diff --git a/CLAUDE.md b/CLAUDE.md index 5c58cc9..7b01e7b 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -8,26 +8,26 @@ Multi-agent workspace for orchestrating multiple AI coding agents working in par | Module | Docs | Path | |--------|------|------| -| Agent (lifecycle, providers, accounts) | [docs/agent.md](docs/agent.md) | `src/agent/` | -| Database (schema, repositories) | [docs/database.md](docs/database.md) | `src/db/` | -| Server & API (tRPC procedures) | [docs/server-api.md](docs/server-api.md) | `src/server/`, `src/trpc/`, `src/coordination/` | -| Frontend (React UI) | [docs/frontend.md](docs/frontend.md) | `packages/web/` | -| CLI & Config | [docs/cli-config.md](docs/cli-config.md) | `src/cli/`, `src/config/` | -| Dispatch & Events | [docs/dispatch-events.md](docs/dispatch-events.md) | `src/dispatch/`, `src/events/` | -| Git, Process, Logging | [docs/git-process-logging.md](docs/git-process-logging.md) | `src/git/`, `src/process/`, `src/logger/`, `src/logging/` | -| Preview (Docker deployments) | [docs/preview.md](docs/preview.md) | `src/preview/` | -| Testing | [docs/testing.md](docs/testing.md) | `src/test/` | +| Agent (lifecycle, providers, accounts) | [docs/agent.md](docs/agent.md) | `apps/server/agent/` | +| Database (schema, repositories) | [docs/database.md](docs/database.md) | `apps/server/db/` | +| Server & API (tRPC procedures) | [docs/server-api.md](docs/server-api.md) | `apps/server/server/`, `apps/server/trpc/`, `apps/server/coordination/` | +| Frontend (React UI) | [docs/frontend.md](docs/frontend.md) | `apps/web/` | +| CLI & Config | [docs/cli-config.md](docs/cli-config.md) | `apps/server/cli/`, `apps/server/config/` | +| Dispatch & Events | [docs/dispatch-events.md](docs/dispatch-events.md) | `apps/server/dispatch/`, `apps/server/events/` | +| Git, Process, Logging | [docs/git-process-logging.md](docs/git-process-logging.md) | `apps/server/git/`, `apps/server/process/`, `apps/server/logger/`, `apps/server/logging/` | +| Preview (Docker deployments) | [docs/preview.md](docs/preview.md) | `apps/server/preview/` | +| Testing | [docs/testing.md](docs/testing.md) | `apps/server/test/` | | Database Migrations | [docs/database-migrations.md](docs/database-migrations.md) | `drizzle/` | -| Logging Guide | [docs/logging.md](docs/logging.md) | `src/logger/` | +| Logging Guide | [docs/logging.md](docs/logging.md) | `apps/server/logger/` | Pre-implementation design docs are archived in `docs/archive/`. ## Key Rules - **Database**: Never use raw SQL for schema initialization. Use `drizzle-kit generate` and the migration system. See [docs/database-migrations.md](docs/database-migrations.md). -- **Logging**: Use `createModuleLogger()` from `src/logger/index.ts`. Keep `console.log` for CLI user-facing output only. -- **Hexagonal architecture**: Repository ports in `src/db/repositories/*.ts`, Drizzle adapters in `src/db/repositories/drizzle/*.ts`. All re-exported from `src/db/index.ts`. -- **tRPC context**: Optional repos accessed via `require*Repository()` helpers in `src/trpc/routers/_helpers.ts`. +- **Logging**: Use `createModuleLogger()` from `apps/server/logger/index.ts`. Keep `console.log` for CLI user-facing output only. +- **Hexagonal architecture**: Repository ports in `apps/server/db/repositories/*.ts`, Drizzle adapters in `apps/server/db/repositories/drizzle/*.ts`. All re-exported from `apps/server/db/index.ts`. +- **tRPC context**: Optional repos accessed via `require*Repository()` helpers in `apps/server/trpc/routers/_helpers.ts`. ## UI Patterns @@ -39,18 +39,18 @@ Pre-implementation design docs are archived in `docs/archive/`. npm run build && npm link ``` -Run after any change to server-side code (`src/**`). +Run after any change to server-side code (`apps/server/**`). ## Testing ```sh npm test # Unit + E2E tests (no API cost) CW_CASSETTE_RECORD=1 npm test -- # Record new cassettes locally -REAL_CLAUDE_TESTS=1 npm test -- src/test/integration/real-providers/ --test-timeout=300000 # Real provider tests (~$0.50) +REAL_CLAUDE_TESTS=1 npm test -- apps/server/test/integration/real-providers/ --test-timeout=300000 # Real provider tests (~$0.50) # Record full-flow cassettes (one-time, costs ~$2–5 in API credits): -CW_CASSETTE_RECORD=1 npm test -- src/test/integration/full-flow/full-flow-cassette.test.ts --test-timeout=3600000 -# Commit the generated src/test/cassettes/.json files afterward. +CW_CASSETTE_RECORD=1 npm test -- apps/server/test/integration/full-flow/full-flow-cassette.test.ts --test-timeout=3600000 +# Commit the generated apps/server/test/cassettes/.json files afterward. # Subsequent runs replay from cassettes at no cost: npm test ``` diff --git a/src/agent/accounts/extractor.ts b/apps/server/agent/accounts/extractor.ts similarity index 100% rename from src/agent/accounts/extractor.ts rename to apps/server/agent/accounts/extractor.ts diff --git a/src/agent/accounts/index.ts b/apps/server/agent/accounts/index.ts similarity index 100% rename from src/agent/accounts/index.ts rename to apps/server/agent/accounts/index.ts diff --git a/src/agent/accounts/paths.ts b/apps/server/agent/accounts/paths.ts similarity index 100% rename from src/agent/accounts/paths.ts rename to apps/server/agent/accounts/paths.ts diff --git a/src/agent/accounts/setup.ts b/apps/server/agent/accounts/setup.ts similarity index 100% rename from src/agent/accounts/setup.ts rename to apps/server/agent/accounts/setup.ts diff --git a/src/agent/accounts/usage.ts b/apps/server/agent/accounts/usage.ts similarity index 100% rename from src/agent/accounts/usage.ts rename to apps/server/agent/accounts/usage.ts diff --git a/src/agent/alias.ts b/apps/server/agent/alias.ts similarity index 100% rename from src/agent/alias.ts rename to apps/server/agent/alias.ts diff --git a/src/agent/cleanup-manager.ts b/apps/server/agent/cleanup-manager.ts similarity index 100% rename from src/agent/cleanup-manager.ts rename to apps/server/agent/cleanup-manager.ts diff --git a/src/agent/content-serializer.ts b/apps/server/agent/content-serializer.ts similarity index 100% rename from src/agent/content-serializer.ts rename to apps/server/agent/content-serializer.ts diff --git a/src/agent/credential-handler.ts b/apps/server/agent/credential-handler.ts similarity index 100% rename from src/agent/credential-handler.ts rename to apps/server/agent/credential-handler.ts diff --git a/src/agent/credentials/default-credential-manager.ts b/apps/server/agent/credentials/default-credential-manager.ts similarity index 100% rename from src/agent/credentials/default-credential-manager.ts rename to apps/server/agent/credentials/default-credential-manager.ts diff --git a/src/agent/credentials/index.ts b/apps/server/agent/credentials/index.ts similarity index 100% rename from src/agent/credentials/index.ts rename to apps/server/agent/credentials/index.ts diff --git a/src/agent/credentials/types.ts b/apps/server/agent/credentials/types.ts similarity index 100% rename from src/agent/credentials/types.ts rename to apps/server/agent/credentials/types.ts diff --git a/src/agent/file-io.test.ts b/apps/server/agent/file-io.test.ts similarity index 100% rename from src/agent/file-io.test.ts rename to apps/server/agent/file-io.test.ts diff --git a/src/agent/file-io.ts b/apps/server/agent/file-io.ts similarity index 100% rename from src/agent/file-io.ts rename to apps/server/agent/file-io.ts diff --git a/src/agent/file-tailer.ts b/apps/server/agent/file-tailer.ts similarity index 100% rename from src/agent/file-tailer.ts rename to apps/server/agent/file-tailer.ts diff --git a/src/agent/index.ts b/apps/server/agent/index.ts similarity index 100% rename from src/agent/index.ts rename to apps/server/agent/index.ts diff --git a/src/agent/lifecycle/cleanup-strategy.ts b/apps/server/agent/lifecycle/cleanup-strategy.ts similarity index 100% rename from src/agent/lifecycle/cleanup-strategy.ts rename to apps/server/agent/lifecycle/cleanup-strategy.ts diff --git a/src/agent/lifecycle/controller.ts b/apps/server/agent/lifecycle/controller.ts similarity index 100% rename from src/agent/lifecycle/controller.ts rename to apps/server/agent/lifecycle/controller.ts diff --git a/src/agent/lifecycle/error-analyzer.test.ts b/apps/server/agent/lifecycle/error-analyzer.test.ts similarity index 100% rename from src/agent/lifecycle/error-analyzer.test.ts rename to apps/server/agent/lifecycle/error-analyzer.test.ts diff --git a/src/agent/lifecycle/error-analyzer.ts b/apps/server/agent/lifecycle/error-analyzer.ts similarity index 100% rename from src/agent/lifecycle/error-analyzer.ts rename to apps/server/agent/lifecycle/error-analyzer.ts diff --git a/src/agent/lifecycle/factory.ts b/apps/server/agent/lifecycle/factory.ts similarity index 100% rename from src/agent/lifecycle/factory.ts rename to apps/server/agent/lifecycle/factory.ts diff --git a/src/agent/lifecycle/index.ts b/apps/server/agent/lifecycle/index.ts similarity index 100% rename from src/agent/lifecycle/index.ts rename to apps/server/agent/lifecycle/index.ts diff --git a/src/agent/lifecycle/instructions.test.ts b/apps/server/agent/lifecycle/instructions.test.ts similarity index 100% rename from src/agent/lifecycle/instructions.test.ts rename to apps/server/agent/lifecycle/instructions.test.ts diff --git a/src/agent/lifecycle/instructions.ts b/apps/server/agent/lifecycle/instructions.ts similarity index 100% rename from src/agent/lifecycle/instructions.ts rename to apps/server/agent/lifecycle/instructions.ts diff --git a/src/agent/lifecycle/retry-policy.test.ts b/apps/server/agent/lifecycle/retry-policy.test.ts similarity index 100% rename from src/agent/lifecycle/retry-policy.test.ts rename to apps/server/agent/lifecycle/retry-policy.test.ts diff --git a/src/agent/lifecycle/retry-policy.ts b/apps/server/agent/lifecycle/retry-policy.ts similarity index 100% rename from src/agent/lifecycle/retry-policy.ts rename to apps/server/agent/lifecycle/retry-policy.ts diff --git a/src/agent/lifecycle/signal-manager.test.ts b/apps/server/agent/lifecycle/signal-manager.test.ts similarity index 100% rename from src/agent/lifecycle/signal-manager.test.ts rename to apps/server/agent/lifecycle/signal-manager.test.ts diff --git a/src/agent/lifecycle/signal-manager.ts b/apps/server/agent/lifecycle/signal-manager.ts similarity index 100% rename from src/agent/lifecycle/signal-manager.ts rename to apps/server/agent/lifecycle/signal-manager.ts diff --git a/src/agent/manager.test.ts b/apps/server/agent/manager.test.ts similarity index 100% rename from src/agent/manager.test.ts rename to apps/server/agent/manager.test.ts diff --git a/src/agent/manager.ts b/apps/server/agent/manager.ts similarity index 100% rename from src/agent/manager.ts rename to apps/server/agent/manager.ts diff --git a/src/agent/markdown-to-tiptap.ts b/apps/server/agent/markdown-to-tiptap.ts similarity index 100% rename from src/agent/markdown-to-tiptap.ts rename to apps/server/agent/markdown-to-tiptap.ts diff --git a/src/agent/mock-manager.test.ts b/apps/server/agent/mock-manager.test.ts similarity index 100% rename from src/agent/mock-manager.test.ts rename to apps/server/agent/mock-manager.test.ts diff --git a/src/agent/mock-manager.ts b/apps/server/agent/mock-manager.ts similarity index 100% rename from src/agent/mock-manager.ts rename to apps/server/agent/mock-manager.ts diff --git a/src/agent/mutex-completion.test.ts b/apps/server/agent/mutex-completion.test.ts similarity index 100% rename from src/agent/mutex-completion.test.ts rename to apps/server/agent/mutex-completion.test.ts diff --git a/src/agent/output-handler.test.ts b/apps/server/agent/output-handler.test.ts similarity index 100% rename from src/agent/output-handler.test.ts rename to apps/server/agent/output-handler.test.ts diff --git a/src/agent/output-handler.ts b/apps/server/agent/output-handler.ts similarity index 100% rename from src/agent/output-handler.ts rename to apps/server/agent/output-handler.ts diff --git a/src/agent/process-manager.test.ts b/apps/server/agent/process-manager.test.ts similarity index 100% rename from src/agent/process-manager.test.ts rename to apps/server/agent/process-manager.test.ts diff --git a/src/agent/process-manager.ts b/apps/server/agent/process-manager.ts similarity index 100% rename from src/agent/process-manager.ts rename to apps/server/agent/process-manager.ts diff --git a/src/agent/prompts/detail.ts b/apps/server/agent/prompts/detail.ts similarity index 100% rename from src/agent/prompts/detail.ts rename to apps/server/agent/prompts/detail.ts diff --git a/src/agent/prompts/discuss.ts b/apps/server/agent/prompts/discuss.ts similarity index 100% rename from src/agent/prompts/discuss.ts rename to apps/server/agent/prompts/discuss.ts diff --git a/src/agent/prompts/execute.ts b/apps/server/agent/prompts/execute.ts similarity index 100% rename from src/agent/prompts/execute.ts rename to apps/server/agent/prompts/execute.ts diff --git a/src/agent/prompts/index.ts b/apps/server/agent/prompts/index.ts similarity index 100% rename from src/agent/prompts/index.ts rename to apps/server/agent/prompts/index.ts diff --git a/src/agent/prompts/plan.ts b/apps/server/agent/prompts/plan.ts similarity index 100% rename from src/agent/prompts/plan.ts rename to apps/server/agent/prompts/plan.ts diff --git a/src/agent/prompts/refine.ts b/apps/server/agent/prompts/refine.ts similarity index 100% rename from src/agent/prompts/refine.ts rename to apps/server/agent/prompts/refine.ts diff --git a/src/agent/prompts/shared.ts b/apps/server/agent/prompts/shared.ts similarity index 100% rename from src/agent/prompts/shared.ts rename to apps/server/agent/prompts/shared.ts diff --git a/src/agent/prompts/workspace.ts b/apps/server/agent/prompts/workspace.ts similarity index 100% rename from src/agent/prompts/workspace.ts rename to apps/server/agent/prompts/workspace.ts diff --git a/src/agent/providers/index.ts b/apps/server/agent/providers/index.ts similarity index 100% rename from src/agent/providers/index.ts rename to apps/server/agent/providers/index.ts diff --git a/src/agent/providers/parsers/claude.ts b/apps/server/agent/providers/parsers/claude.ts similarity index 100% rename from src/agent/providers/parsers/claude.ts rename to apps/server/agent/providers/parsers/claude.ts diff --git a/src/agent/providers/parsers/generic.ts b/apps/server/agent/providers/parsers/generic.ts similarity index 100% rename from src/agent/providers/parsers/generic.ts rename to apps/server/agent/providers/parsers/generic.ts diff --git a/src/agent/providers/parsers/index.ts b/apps/server/agent/providers/parsers/index.ts similarity index 100% rename from src/agent/providers/parsers/index.ts rename to apps/server/agent/providers/parsers/index.ts diff --git a/src/agent/providers/presets.ts b/apps/server/agent/providers/presets.ts similarity index 100% rename from src/agent/providers/presets.ts rename to apps/server/agent/providers/presets.ts diff --git a/src/agent/providers/registry.ts b/apps/server/agent/providers/registry.ts similarity index 100% rename from src/agent/providers/registry.ts rename to apps/server/agent/providers/registry.ts diff --git a/src/agent/providers/stream-types.ts b/apps/server/agent/providers/stream-types.ts similarity index 100% rename from src/agent/providers/stream-types.ts rename to apps/server/agent/providers/stream-types.ts diff --git a/src/agent/providers/types.ts b/apps/server/agent/providers/types.ts similarity index 100% rename from src/agent/providers/types.ts rename to apps/server/agent/providers/types.ts diff --git a/src/agent/schema.ts b/apps/server/agent/schema.ts similarity index 100% rename from src/agent/schema.ts rename to apps/server/agent/schema.ts diff --git a/src/agent/types.ts b/apps/server/agent/types.ts similarity index 100% rename from src/agent/types.ts rename to apps/server/agent/types.ts diff --git a/src/bin/cw.ts b/apps/server/bin/cw.ts similarity index 100% rename from src/bin/cw.ts rename to apps/server/bin/cw.ts diff --git a/src/cli/index.ts b/apps/server/cli/index.ts similarity index 100% rename from src/cli/index.ts rename to apps/server/cli/index.ts diff --git a/src/cli/trpc-client.ts b/apps/server/cli/trpc-client.ts similarity index 100% rename from src/cli/trpc-client.ts rename to apps/server/cli/trpc-client.ts diff --git a/src/config/cwrc.ts b/apps/server/config/cwrc.ts similarity index 100% rename from src/config/cwrc.ts rename to apps/server/config/cwrc.ts diff --git a/src/config/index.ts b/apps/server/config/index.ts similarity index 100% rename from src/config/index.ts rename to apps/server/config/index.ts diff --git a/src/config/types.ts b/apps/server/config/types.ts similarity index 100% rename from src/config/types.ts rename to apps/server/config/types.ts diff --git a/src/container.ts b/apps/server/container.ts similarity index 100% rename from src/container.ts rename to apps/server/container.ts diff --git a/src/coordination/conflict-resolution-service.test.ts b/apps/server/coordination/conflict-resolution-service.test.ts similarity index 100% rename from src/coordination/conflict-resolution-service.test.ts rename to apps/server/coordination/conflict-resolution-service.test.ts diff --git a/src/coordination/conflict-resolution-service.ts b/apps/server/coordination/conflict-resolution-service.ts similarity index 100% rename from src/coordination/conflict-resolution-service.ts rename to apps/server/coordination/conflict-resolution-service.ts diff --git a/src/coordination/index.ts b/apps/server/coordination/index.ts similarity index 100% rename from src/coordination/index.ts rename to apps/server/coordination/index.ts diff --git a/src/coordination/manager.test.ts b/apps/server/coordination/manager.test.ts similarity index 100% rename from src/coordination/manager.test.ts rename to apps/server/coordination/manager.test.ts diff --git a/src/coordination/manager.ts b/apps/server/coordination/manager.ts similarity index 100% rename from src/coordination/manager.ts rename to apps/server/coordination/manager.ts diff --git a/src/coordination/types.ts b/apps/server/coordination/types.ts similarity index 100% rename from src/coordination/types.ts rename to apps/server/coordination/types.ts diff --git a/src/db/config.ts b/apps/server/db/config.ts similarity index 100% rename from src/db/config.ts rename to apps/server/db/config.ts diff --git a/src/db/ensure-schema.ts b/apps/server/db/ensure-schema.ts similarity index 80% rename from src/db/ensure-schema.ts rename to apps/server/db/ensure-schema.ts index b26baab..0cbe4fc 100644 --- a/src/db/ensure-schema.ts +++ b/apps/server/db/ensure-schema.ts @@ -8,6 +8,7 @@ import { migrate } from 'drizzle-orm/better-sqlite3/migrator'; import { join, dirname } from 'node:path'; import { fileURLToPath } from 'node:url'; +import { existsSync } from 'node:fs'; import type { DrizzleDatabase } from './index.js'; import { createModuleLogger } from '../logger/index.js'; @@ -19,7 +20,10 @@ const log = createModuleLogger('db'); */ function getMigrationsPath(): string { const currentDir = dirname(fileURLToPath(import.meta.url)); - // From src/db/ or dist/db/, go up two levels to package root, then into drizzle/ + // In dev (tsx): apps/server/db/ — need 3 levels up to workspace root + // In dist (tsc): dist/db/ — need 2 levels up to workspace root + const upThree = join(currentDir, '..', '..', '..', 'drizzle'); + if (existsSync(upThree)) return upThree; return join(currentDir, '..', '..', 'drizzle'); } diff --git a/src/db/index.ts b/apps/server/db/index.ts similarity index 100% rename from src/db/index.ts rename to apps/server/db/index.ts diff --git a/src/db/repositories/account-repository.ts b/apps/server/db/repositories/account-repository.ts similarity index 100% rename from src/db/repositories/account-repository.ts rename to apps/server/db/repositories/account-repository.ts diff --git a/src/db/repositories/agent-repository.ts b/apps/server/db/repositories/agent-repository.ts similarity index 100% rename from src/db/repositories/agent-repository.ts rename to apps/server/db/repositories/agent-repository.ts diff --git a/src/db/repositories/change-set-repository.ts b/apps/server/db/repositories/change-set-repository.ts similarity index 100% rename from src/db/repositories/change-set-repository.ts rename to apps/server/db/repositories/change-set-repository.ts diff --git a/src/db/repositories/conversation-repository.ts b/apps/server/db/repositories/conversation-repository.ts similarity index 100% rename from src/db/repositories/conversation-repository.ts rename to apps/server/db/repositories/conversation-repository.ts diff --git a/src/db/repositories/drizzle/account.ts b/apps/server/db/repositories/drizzle/account.ts similarity index 100% rename from src/db/repositories/drizzle/account.ts rename to apps/server/db/repositories/drizzle/account.ts diff --git a/src/db/repositories/drizzle/agent.test.ts b/apps/server/db/repositories/drizzle/agent.test.ts similarity index 100% rename from src/db/repositories/drizzle/agent.test.ts rename to apps/server/db/repositories/drizzle/agent.test.ts diff --git a/src/db/repositories/drizzle/agent.ts b/apps/server/db/repositories/drizzle/agent.ts similarity index 100% rename from src/db/repositories/drizzle/agent.ts rename to apps/server/db/repositories/drizzle/agent.ts diff --git a/src/db/repositories/drizzle/cascade.test.ts b/apps/server/db/repositories/drizzle/cascade.test.ts similarity index 100% rename from src/db/repositories/drizzle/cascade.test.ts rename to apps/server/db/repositories/drizzle/cascade.test.ts diff --git a/src/db/repositories/drizzle/change-set.ts b/apps/server/db/repositories/drizzle/change-set.ts similarity index 100% rename from src/db/repositories/drizzle/change-set.ts rename to apps/server/db/repositories/drizzle/change-set.ts diff --git a/src/db/repositories/drizzle/conversation.ts b/apps/server/db/repositories/drizzle/conversation.ts similarity index 100% rename from src/db/repositories/drizzle/conversation.ts rename to apps/server/db/repositories/drizzle/conversation.ts diff --git a/src/db/repositories/drizzle/index.ts b/apps/server/db/repositories/drizzle/index.ts similarity index 100% rename from src/db/repositories/drizzle/index.ts rename to apps/server/db/repositories/drizzle/index.ts diff --git a/src/db/repositories/drizzle/initiative.test.ts b/apps/server/db/repositories/drizzle/initiative.test.ts similarity index 100% rename from src/db/repositories/drizzle/initiative.test.ts rename to apps/server/db/repositories/drizzle/initiative.test.ts diff --git a/src/db/repositories/drizzle/initiative.ts b/apps/server/db/repositories/drizzle/initiative.ts similarity index 100% rename from src/db/repositories/drizzle/initiative.ts rename to apps/server/db/repositories/drizzle/initiative.ts diff --git a/src/db/repositories/drizzle/log-chunk.ts b/apps/server/db/repositories/drizzle/log-chunk.ts similarity index 100% rename from src/db/repositories/drizzle/log-chunk.ts rename to apps/server/db/repositories/drizzle/log-chunk.ts diff --git a/src/db/repositories/drizzle/message.test.ts b/apps/server/db/repositories/drizzle/message.test.ts similarity index 100% rename from src/db/repositories/drizzle/message.test.ts rename to apps/server/db/repositories/drizzle/message.test.ts diff --git a/src/db/repositories/drizzle/message.ts b/apps/server/db/repositories/drizzle/message.ts similarity index 100% rename from src/db/repositories/drizzle/message.ts rename to apps/server/db/repositories/drizzle/message.ts diff --git a/src/db/repositories/drizzle/page.ts b/apps/server/db/repositories/drizzle/page.ts similarity index 100% rename from src/db/repositories/drizzle/page.ts rename to apps/server/db/repositories/drizzle/page.ts diff --git a/src/db/repositories/drizzle/phase.test.ts b/apps/server/db/repositories/drizzle/phase.test.ts similarity index 100% rename from src/db/repositories/drizzle/phase.test.ts rename to apps/server/db/repositories/drizzle/phase.test.ts diff --git a/src/db/repositories/drizzle/phase.ts b/apps/server/db/repositories/drizzle/phase.ts similarity index 100% rename from src/db/repositories/drizzle/phase.ts rename to apps/server/db/repositories/drizzle/phase.ts diff --git a/src/db/repositories/drizzle/project.ts b/apps/server/db/repositories/drizzle/project.ts similarity index 100% rename from src/db/repositories/drizzle/project.ts rename to apps/server/db/repositories/drizzle/project.ts diff --git a/src/db/repositories/drizzle/task.test.ts b/apps/server/db/repositories/drizzle/task.test.ts similarity index 100% rename from src/db/repositories/drizzle/task.test.ts rename to apps/server/db/repositories/drizzle/task.test.ts diff --git a/src/db/repositories/drizzle/task.ts b/apps/server/db/repositories/drizzle/task.ts similarity index 100% rename from src/db/repositories/drizzle/task.ts rename to apps/server/db/repositories/drizzle/task.ts diff --git a/src/db/repositories/drizzle/test-helpers.ts b/apps/server/db/repositories/drizzle/test-helpers.ts similarity index 100% rename from src/db/repositories/drizzle/test-helpers.ts rename to apps/server/db/repositories/drizzle/test-helpers.ts diff --git a/src/db/repositories/index.ts b/apps/server/db/repositories/index.ts similarity index 100% rename from src/db/repositories/index.ts rename to apps/server/db/repositories/index.ts diff --git a/src/db/repositories/initiative-repository.ts b/apps/server/db/repositories/initiative-repository.ts similarity index 100% rename from src/db/repositories/initiative-repository.ts rename to apps/server/db/repositories/initiative-repository.ts diff --git a/src/db/repositories/log-chunk-repository.ts b/apps/server/db/repositories/log-chunk-repository.ts similarity index 100% rename from src/db/repositories/log-chunk-repository.ts rename to apps/server/db/repositories/log-chunk-repository.ts diff --git a/src/db/repositories/message-repository.ts b/apps/server/db/repositories/message-repository.ts similarity index 100% rename from src/db/repositories/message-repository.ts rename to apps/server/db/repositories/message-repository.ts diff --git a/src/db/repositories/page-repository.ts b/apps/server/db/repositories/page-repository.ts similarity index 100% rename from src/db/repositories/page-repository.ts rename to apps/server/db/repositories/page-repository.ts diff --git a/src/db/repositories/phase-repository.ts b/apps/server/db/repositories/phase-repository.ts similarity index 100% rename from src/db/repositories/phase-repository.ts rename to apps/server/db/repositories/phase-repository.ts diff --git a/src/db/repositories/project-repository.ts b/apps/server/db/repositories/project-repository.ts similarity index 100% rename from src/db/repositories/project-repository.ts rename to apps/server/db/repositories/project-repository.ts diff --git a/src/db/repositories/task-repository.ts b/apps/server/db/repositories/task-repository.ts similarity index 100% rename from src/db/repositories/task-repository.ts rename to apps/server/db/repositories/task-repository.ts diff --git a/src/db/schema.ts b/apps/server/db/schema.ts similarity index 100% rename from src/db/schema.ts rename to apps/server/db/schema.ts diff --git a/src/dispatch/index.ts b/apps/server/dispatch/index.ts similarity index 100% rename from src/dispatch/index.ts rename to apps/server/dispatch/index.ts diff --git a/src/dispatch/manager.test.ts b/apps/server/dispatch/manager.test.ts similarity index 100% rename from src/dispatch/manager.test.ts rename to apps/server/dispatch/manager.test.ts diff --git a/src/dispatch/manager.ts b/apps/server/dispatch/manager.ts similarity index 100% rename from src/dispatch/manager.ts rename to apps/server/dispatch/manager.ts diff --git a/src/dispatch/phase-manager.test.ts b/apps/server/dispatch/phase-manager.test.ts similarity index 100% rename from src/dispatch/phase-manager.test.ts rename to apps/server/dispatch/phase-manager.test.ts diff --git a/src/dispatch/phase-manager.ts b/apps/server/dispatch/phase-manager.ts similarity index 100% rename from src/dispatch/phase-manager.ts rename to apps/server/dispatch/phase-manager.ts diff --git a/src/dispatch/types.ts b/apps/server/dispatch/types.ts similarity index 100% rename from src/dispatch/types.ts rename to apps/server/dispatch/types.ts diff --git a/src/events/bus.test.ts b/apps/server/events/bus.test.ts similarity index 100% rename from src/events/bus.test.ts rename to apps/server/events/bus.test.ts diff --git a/src/events/bus.ts b/apps/server/events/bus.ts similarity index 100% rename from src/events/bus.ts rename to apps/server/events/bus.ts diff --git a/src/events/index.ts b/apps/server/events/index.ts similarity index 100% rename from src/events/index.ts rename to apps/server/events/index.ts diff --git a/src/events/types.ts b/apps/server/events/types.ts similarity index 100% rename from src/events/types.ts rename to apps/server/events/types.ts diff --git a/src/execution/orchestrator.ts b/apps/server/execution/orchestrator.ts similarity index 100% rename from src/execution/orchestrator.ts rename to apps/server/execution/orchestrator.ts diff --git a/src/git/branch-manager.ts b/apps/server/git/branch-manager.ts similarity index 100% rename from src/git/branch-manager.ts rename to apps/server/git/branch-manager.ts diff --git a/src/git/branch-naming.ts b/apps/server/git/branch-naming.ts similarity index 100% rename from src/git/branch-naming.ts rename to apps/server/git/branch-naming.ts diff --git a/src/git/clone.ts b/apps/server/git/clone.ts similarity index 100% rename from src/git/clone.ts rename to apps/server/git/clone.ts diff --git a/src/git/index.ts b/apps/server/git/index.ts similarity index 100% rename from src/git/index.ts rename to apps/server/git/index.ts diff --git a/src/git/manager.test.ts b/apps/server/git/manager.test.ts similarity index 100% rename from src/git/manager.test.ts rename to apps/server/git/manager.test.ts diff --git a/src/git/manager.ts b/apps/server/git/manager.ts similarity index 100% rename from src/git/manager.ts rename to apps/server/git/manager.ts diff --git a/src/git/project-clones.ts b/apps/server/git/project-clones.ts similarity index 100% rename from src/git/project-clones.ts rename to apps/server/git/project-clones.ts diff --git a/src/git/simple-git-branch-manager.test.ts b/apps/server/git/simple-git-branch-manager.test.ts similarity index 100% rename from src/git/simple-git-branch-manager.test.ts rename to apps/server/git/simple-git-branch-manager.test.ts diff --git a/src/git/simple-git-branch-manager.ts b/apps/server/git/simple-git-branch-manager.ts similarity index 100% rename from src/git/simple-git-branch-manager.ts rename to apps/server/git/simple-git-branch-manager.ts diff --git a/src/git/types.ts b/apps/server/git/types.ts similarity index 100% rename from src/git/types.ts rename to apps/server/git/types.ts diff --git a/src/index.ts b/apps/server/index.ts similarity index 100% rename from src/index.ts rename to apps/server/index.ts diff --git a/src/logger/index.ts b/apps/server/logger/index.ts similarity index 100% rename from src/logger/index.ts rename to apps/server/logger/index.ts diff --git a/src/logging/index.ts b/apps/server/logging/index.ts similarity index 100% rename from src/logging/index.ts rename to apps/server/logging/index.ts diff --git a/src/logging/manager.test.ts b/apps/server/logging/manager.test.ts similarity index 100% rename from src/logging/manager.test.ts rename to apps/server/logging/manager.test.ts diff --git a/src/logging/manager.ts b/apps/server/logging/manager.ts similarity index 100% rename from src/logging/manager.ts rename to apps/server/logging/manager.ts diff --git a/src/logging/types.ts b/apps/server/logging/types.ts similarity index 100% rename from src/logging/types.ts rename to apps/server/logging/types.ts diff --git a/src/logging/writer.test.ts b/apps/server/logging/writer.test.ts similarity index 100% rename from src/logging/writer.test.ts rename to apps/server/logging/writer.test.ts diff --git a/src/logging/writer.ts b/apps/server/logging/writer.ts similarity index 100% rename from src/logging/writer.ts rename to apps/server/logging/writer.ts diff --git a/src/preview/compose-generator.test.ts b/apps/server/preview/compose-generator.test.ts similarity index 100% rename from src/preview/compose-generator.test.ts rename to apps/server/preview/compose-generator.test.ts diff --git a/src/preview/compose-generator.ts b/apps/server/preview/compose-generator.ts similarity index 100% rename from src/preview/compose-generator.ts rename to apps/server/preview/compose-generator.ts diff --git a/src/preview/config-reader.test.ts b/apps/server/preview/config-reader.test.ts similarity index 96% rename from src/preview/config-reader.test.ts rename to apps/server/preview/config-reader.test.ts index 6454a55..94b6583 100644 --- a/src/preview/config-reader.test.ts +++ b/apps/server/preview/config-reader.test.ts @@ -24,7 +24,7 @@ services: frontend: build: context: "." - dockerfile: packages/web/Dockerfile + dockerfile: apps/web/Dockerfile port: 3000 route: / healthcheck: @@ -62,7 +62,7 @@ services: expect(config.services.frontend.env?.VITE_API_URL).toBe('/api'); expect(config.services.frontend.build).toEqual({ context: '.', - dockerfile: 'packages/web/Dockerfile', + dockerfile: 'apps/web/Dockerfile', }); // Backend diff --git a/src/preview/config-reader.ts b/apps/server/preview/config-reader.ts similarity index 100% rename from src/preview/config-reader.ts rename to apps/server/preview/config-reader.ts diff --git a/src/preview/docker-client.ts b/apps/server/preview/docker-client.ts similarity index 100% rename from src/preview/docker-client.ts rename to apps/server/preview/docker-client.ts diff --git a/src/preview/health-checker.ts b/apps/server/preview/health-checker.ts similarity index 100% rename from src/preview/health-checker.ts rename to apps/server/preview/health-checker.ts diff --git a/src/preview/index.ts b/apps/server/preview/index.ts similarity index 100% rename from src/preview/index.ts rename to apps/server/preview/index.ts diff --git a/src/preview/manager.test.ts b/apps/server/preview/manager.test.ts similarity index 100% rename from src/preview/manager.test.ts rename to apps/server/preview/manager.test.ts diff --git a/src/preview/manager.ts b/apps/server/preview/manager.ts similarity index 100% rename from src/preview/manager.ts rename to apps/server/preview/manager.ts diff --git a/src/preview/port-allocator.test.ts b/apps/server/preview/port-allocator.test.ts similarity index 100% rename from src/preview/port-allocator.test.ts rename to apps/server/preview/port-allocator.test.ts diff --git a/src/preview/port-allocator.ts b/apps/server/preview/port-allocator.ts similarity index 100% rename from src/preview/port-allocator.ts rename to apps/server/preview/port-allocator.ts diff --git a/src/preview/types.ts b/apps/server/preview/types.ts similarity index 100% rename from src/preview/types.ts rename to apps/server/preview/types.ts diff --git a/src/process/index.ts b/apps/server/process/index.ts similarity index 100% rename from src/process/index.ts rename to apps/server/process/index.ts diff --git a/src/process/manager.test.ts b/apps/server/process/manager.test.ts similarity index 100% rename from src/process/manager.test.ts rename to apps/server/process/manager.test.ts diff --git a/src/process/manager.ts b/apps/server/process/manager.ts similarity index 100% rename from src/process/manager.ts rename to apps/server/process/manager.ts diff --git a/src/process/registry.test.ts b/apps/server/process/registry.test.ts similarity index 100% rename from src/process/registry.test.ts rename to apps/server/process/registry.test.ts diff --git a/src/process/registry.ts b/apps/server/process/registry.ts similarity index 100% rename from src/process/registry.ts rename to apps/server/process/registry.ts diff --git a/src/process/types.ts b/apps/server/process/types.ts similarity index 100% rename from src/process/types.ts rename to apps/server/process/types.ts diff --git a/src/server/index.test.ts b/apps/server/server/index.test.ts similarity index 100% rename from src/server/index.test.ts rename to apps/server/server/index.test.ts diff --git a/src/server/index.ts b/apps/server/server/index.ts similarity index 100% rename from src/server/index.ts rename to apps/server/server/index.ts diff --git a/src/server/shutdown.test.ts b/apps/server/server/shutdown.test.ts similarity index 100% rename from src/server/shutdown.test.ts rename to apps/server/server/shutdown.test.ts diff --git a/src/server/shutdown.ts b/apps/server/server/shutdown.ts similarity index 100% rename from src/server/shutdown.ts rename to apps/server/server/shutdown.ts diff --git a/src/server/trpc-adapter.ts b/apps/server/server/trpc-adapter.ts similarity index 100% rename from src/server/trpc-adapter.ts rename to apps/server/server/trpc-adapter.ts diff --git a/src/server/types.ts b/apps/server/server/types.ts similarity index 100% rename from src/server/types.ts rename to apps/server/server/types.ts diff --git a/src/test/cassette/cassette.test.ts b/apps/server/test/cassette/cassette.test.ts similarity index 100% rename from src/test/cassette/cassette.test.ts rename to apps/server/test/cassette/cassette.test.ts diff --git a/src/test/cassette/harness.ts b/apps/server/test/cassette/harness.ts similarity index 100% rename from src/test/cassette/harness.ts rename to apps/server/test/cassette/harness.ts diff --git a/src/test/cassette/index.ts b/apps/server/test/cassette/index.ts similarity index 100% rename from src/test/cassette/index.ts rename to apps/server/test/cassette/index.ts diff --git a/src/test/cassette/key.ts b/apps/server/test/cassette/key.ts similarity index 100% rename from src/test/cassette/key.ts rename to apps/server/test/cassette/key.ts diff --git a/src/test/cassette/normalizer.ts b/apps/server/test/cassette/normalizer.ts similarity index 100% rename from src/test/cassette/normalizer.ts rename to apps/server/test/cassette/normalizer.ts diff --git a/src/test/cassette/process-manager.ts b/apps/server/test/cassette/process-manager.ts similarity index 100% rename from src/test/cassette/process-manager.ts rename to apps/server/test/cassette/process-manager.ts diff --git a/src/test/cassette/replay-worker.mjs b/apps/server/test/cassette/replay-worker.mjs similarity index 100% rename from src/test/cassette/replay-worker.mjs rename to apps/server/test/cassette/replay-worker.mjs diff --git a/src/test/cassette/store.ts b/apps/server/test/cassette/store.ts similarity index 100% rename from src/test/cassette/store.ts rename to apps/server/test/cassette/store.ts diff --git a/src/test/cassette/types.ts b/apps/server/test/cassette/types.ts similarity index 100% rename from src/test/cassette/types.ts rename to apps/server/test/cassette/types.ts diff --git a/src/test/cassettes/.gitkeep b/apps/server/test/cassettes/.gitkeep similarity index 100% rename from src/test/cassettes/.gitkeep rename to apps/server/test/cassettes/.gitkeep diff --git a/src/test/cassettes/1cd13ac7ceb5fffb6a8fd52fe5825dd5.json b/apps/server/test/cassettes/1cd13ac7ceb5fffb6a8fd52fe5825dd5.json similarity index 100% rename from src/test/cassettes/1cd13ac7ceb5fffb6a8fd52fe5825dd5.json rename to apps/server/test/cassettes/1cd13ac7ceb5fffb6a8fd52fe5825dd5.json diff --git a/src/test/cassettes/3ebb6b15ba29592585517881a8deabcd.json b/apps/server/test/cassettes/3ebb6b15ba29592585517881a8deabcd.json similarity index 100% rename from src/test/cassettes/3ebb6b15ba29592585517881a8deabcd.json rename to apps/server/test/cassettes/3ebb6b15ba29592585517881a8deabcd.json diff --git a/src/test/cassettes/80831e59bdc5ad35515a4c68d5d4ed22.json b/apps/server/test/cassettes/80831e59bdc5ad35515a4c68d5d4ed22.json similarity index 100% rename from src/test/cassettes/80831e59bdc5ad35515a4c68d5d4ed22.json rename to apps/server/test/cassettes/80831e59bdc5ad35515a4c68d5d4ed22.json diff --git a/src/test/cassettes/ff2b1ae8f39a02ab1009de52b5fbd8de.json b/apps/server/test/cassettes/ff2b1ae8f39a02ab1009de52b5fbd8de.json similarity index 100% rename from src/test/cassettes/ff2b1ae8f39a02ab1009de52b5fbd8de.json rename to apps/server/test/cassettes/ff2b1ae8f39a02ab1009de52b5fbd8de.json diff --git a/src/test/e2e/architect-workflow.test.ts b/apps/server/test/e2e/architect-workflow.test.ts similarity index 100% rename from src/test/e2e/architect-workflow.test.ts rename to apps/server/test/e2e/architect-workflow.test.ts diff --git a/src/test/e2e/decompose-workflow.test.ts b/apps/server/test/e2e/decompose-workflow.test.ts similarity index 100% rename from src/test/e2e/decompose-workflow.test.ts rename to apps/server/test/e2e/decompose-workflow.test.ts diff --git a/src/test/e2e/edge-cases.test.ts b/apps/server/test/e2e/edge-cases.test.ts similarity index 100% rename from src/test/e2e/edge-cases.test.ts rename to apps/server/test/e2e/edge-cases.test.ts diff --git a/src/test/e2e/extended-scenarios.test.ts b/apps/server/test/e2e/extended-scenarios.test.ts similarity index 100% rename from src/test/e2e/extended-scenarios.test.ts rename to apps/server/test/e2e/extended-scenarios.test.ts diff --git a/src/test/e2e/happy-path.test.ts b/apps/server/test/e2e/happy-path.test.ts similarity index 100% rename from src/test/e2e/happy-path.test.ts rename to apps/server/test/e2e/happy-path.test.ts diff --git a/src/test/e2e/index.ts b/apps/server/test/e2e/index.ts similarity index 100% rename from src/test/e2e/index.ts rename to apps/server/test/e2e/index.ts diff --git a/src/test/e2e/phase-dispatch.test.ts b/apps/server/test/e2e/phase-dispatch.test.ts similarity index 100% rename from src/test/e2e/phase-dispatch.test.ts rename to apps/server/test/e2e/phase-dispatch.test.ts diff --git a/src/test/e2e/recovery-scenarios.test.ts b/apps/server/test/e2e/recovery-scenarios.test.ts similarity index 100% rename from src/test/e2e/recovery-scenarios.test.ts rename to apps/server/test/e2e/recovery-scenarios.test.ts diff --git a/src/test/fixtures.ts b/apps/server/test/fixtures.ts similarity index 100% rename from src/test/fixtures.ts rename to apps/server/test/fixtures.ts diff --git a/src/test/fixtures/todo-api/README.md b/apps/server/test/fixtures/todo-api/README.md similarity index 100% rename from src/test/fixtures/todo-api/README.md rename to apps/server/test/fixtures/todo-api/README.md diff --git a/src/test/fixtures/todo-api/package.json b/apps/server/test/fixtures/todo-api/package.json similarity index 100% rename from src/test/fixtures/todo-api/package.json rename to apps/server/test/fixtures/todo-api/package.json diff --git a/src/test/fixtures/todo-api/src/todo.js b/apps/server/test/fixtures/todo-api/src/todo.js similarity index 100% rename from src/test/fixtures/todo-api/src/todo.js rename to apps/server/test/fixtures/todo-api/src/todo.js diff --git a/src/test/fixtures/todo-api/src/todo.test.js b/apps/server/test/fixtures/todo-api/src/todo.test.js similarity index 100% rename from src/test/fixtures/todo-api/src/todo.test.js rename to apps/server/test/fixtures/todo-api/src/todo.test.js diff --git a/src/test/harness.test.ts b/apps/server/test/harness.test.ts similarity index 100% rename from src/test/harness.test.ts rename to apps/server/test/harness.test.ts diff --git a/src/test/harness.ts b/apps/server/test/harness.ts similarity index 100% rename from src/test/harness.ts rename to apps/server/test/harness.ts diff --git a/src/test/index.ts b/apps/server/test/index.ts similarity index 100% rename from src/test/index.ts rename to apps/server/test/index.ts diff --git a/src/test/integration/agent-workdir-verification.test.ts b/apps/server/test/integration/agent-workdir-verification.test.ts similarity index 100% rename from src/test/integration/agent-workdir-verification.test.ts rename to apps/server/test/integration/agent-workdir-verification.test.ts diff --git a/src/test/integration/crash-race-condition.test.ts b/apps/server/test/integration/crash-race-condition.test.ts similarity index 100% rename from src/test/integration/crash-race-condition.test.ts rename to apps/server/test/integration/crash-race-condition.test.ts diff --git a/src/test/integration/full-flow/full-flow-cassette.test.ts b/apps/server/test/integration/full-flow/full-flow-cassette.test.ts similarity index 100% rename from src/test/integration/full-flow/full-flow-cassette.test.ts rename to apps/server/test/integration/full-flow/full-flow-cassette.test.ts diff --git a/src/test/integration/full-flow/harness.ts b/apps/server/test/integration/full-flow/harness.ts similarity index 100% rename from src/test/integration/full-flow/harness.ts rename to apps/server/test/integration/full-flow/harness.ts diff --git a/src/test/integration/full-flow/report.ts b/apps/server/test/integration/full-flow/report.ts similarity index 100% rename from src/test/integration/full-flow/report.ts rename to apps/server/test/integration/full-flow/report.ts diff --git a/src/test/integration/real-claude.test.ts b/apps/server/test/integration/real-claude.test.ts similarity index 100% rename from src/test/integration/real-claude.test.ts rename to apps/server/test/integration/real-claude.test.ts diff --git a/src/test/integration/real-providers/claude-manager.test.ts b/apps/server/test/integration/real-providers/claude-manager.test.ts similarity index 100% rename from src/test/integration/real-providers/claude-manager.test.ts rename to apps/server/test/integration/real-providers/claude-manager.test.ts diff --git a/src/test/integration/real-providers/codex-manager.test.ts b/apps/server/test/integration/real-providers/codex-manager.test.ts similarity index 100% rename from src/test/integration/real-providers/codex-manager.test.ts rename to apps/server/test/integration/real-providers/codex-manager.test.ts diff --git a/src/test/integration/real-providers/conversation.test.ts b/apps/server/test/integration/real-providers/conversation.test.ts similarity index 100% rename from src/test/integration/real-providers/conversation.test.ts rename to apps/server/test/integration/real-providers/conversation.test.ts diff --git a/src/test/integration/real-providers/crash-recovery.test.ts b/apps/server/test/integration/real-providers/crash-recovery.test.ts similarity index 100% rename from src/test/integration/real-providers/crash-recovery.test.ts rename to apps/server/test/integration/real-providers/crash-recovery.test.ts diff --git a/src/test/integration/real-providers/harness.ts b/apps/server/test/integration/real-providers/harness.ts similarity index 100% rename from src/test/integration/real-providers/harness.ts rename to apps/server/test/integration/real-providers/harness.ts diff --git a/src/test/integration/real-providers/index.ts b/apps/server/test/integration/real-providers/index.ts similarity index 100% rename from src/test/integration/real-providers/index.ts rename to apps/server/test/integration/real-providers/index.ts diff --git a/src/test/integration/real-providers/prompts.ts b/apps/server/test/integration/real-providers/prompts.ts similarity index 100% rename from src/test/integration/real-providers/prompts.ts rename to apps/server/test/integration/real-providers/prompts.ts diff --git a/src/test/integration/real-providers/sample-outputs/README.md b/apps/server/test/integration/real-providers/sample-outputs/README.md similarity index 100% rename from src/test/integration/real-providers/sample-outputs/README.md rename to apps/server/test/integration/real-providers/sample-outputs/README.md diff --git a/src/test/integration/real-providers/sample-outputs/claude-stream-questions.jsonl b/apps/server/test/integration/real-providers/sample-outputs/claude-stream-questions.jsonl similarity index 100% rename from src/test/integration/real-providers/sample-outputs/claude-stream-questions.jsonl rename to apps/server/test/integration/real-providers/sample-outputs/claude-stream-questions.jsonl diff --git a/src/test/integration/real-providers/sample-outputs/claude-stream-success.jsonl b/apps/server/test/integration/real-providers/sample-outputs/claude-stream-success.jsonl similarity index 100% rename from src/test/integration/real-providers/sample-outputs/claude-stream-success.jsonl rename to apps/server/test/integration/real-providers/sample-outputs/claude-stream-success.jsonl diff --git a/src/test/integration/real-providers/sample-outputs/codex-stream-success.jsonl b/apps/server/test/integration/real-providers/sample-outputs/codex-stream-success.jsonl similarity index 100% rename from src/test/integration/real-providers/sample-outputs/codex-stream-success.jsonl rename to apps/server/test/integration/real-providers/sample-outputs/codex-stream-success.jsonl diff --git a/src/test/integration/real-providers/schema-retry.test.ts b/apps/server/test/integration/real-providers/schema-retry.test.ts similarity index 100% rename from src/test/integration/real-providers/schema-retry.test.ts rename to apps/server/test/integration/real-providers/schema-retry.test.ts diff --git a/src/test/topological-sort.test.ts b/apps/server/test/topological-sort.test.ts similarity index 100% rename from src/test/topological-sort.test.ts rename to apps/server/test/topological-sort.test.ts diff --git a/src/trpc/context.ts b/apps/server/trpc/context.ts similarity index 100% rename from src/trpc/context.ts rename to apps/server/trpc/context.ts diff --git a/src/trpc/index.ts b/apps/server/trpc/index.ts similarity index 100% rename from src/trpc/index.ts rename to apps/server/trpc/index.ts diff --git a/src/trpc/router.test.ts b/apps/server/trpc/router.test.ts similarity index 100% rename from src/trpc/router.test.ts rename to apps/server/trpc/router.test.ts diff --git a/src/trpc/router.ts b/apps/server/trpc/router.ts similarity index 100% rename from src/trpc/router.ts rename to apps/server/trpc/router.ts diff --git a/src/trpc/routers/_helpers.ts b/apps/server/trpc/routers/_helpers.ts similarity index 100% rename from src/trpc/routers/_helpers.ts rename to apps/server/trpc/routers/_helpers.ts diff --git a/src/trpc/routers/account.ts b/apps/server/trpc/routers/account.ts similarity index 100% rename from src/trpc/routers/account.ts rename to apps/server/trpc/routers/account.ts diff --git a/src/trpc/routers/agent.ts b/apps/server/trpc/routers/agent.ts similarity index 100% rename from src/trpc/routers/agent.ts rename to apps/server/trpc/routers/agent.ts diff --git a/src/trpc/routers/architect.ts b/apps/server/trpc/routers/architect.ts similarity index 100% rename from src/trpc/routers/architect.ts rename to apps/server/trpc/routers/architect.ts diff --git a/src/trpc/routers/change-set.ts b/apps/server/trpc/routers/change-set.ts similarity index 100% rename from src/trpc/routers/change-set.ts rename to apps/server/trpc/routers/change-set.ts diff --git a/src/trpc/routers/conversation.ts b/apps/server/trpc/routers/conversation.ts similarity index 100% rename from src/trpc/routers/conversation.ts rename to apps/server/trpc/routers/conversation.ts diff --git a/src/trpc/routers/coordination.ts b/apps/server/trpc/routers/coordination.ts similarity index 100% rename from src/trpc/routers/coordination.ts rename to apps/server/trpc/routers/coordination.ts diff --git a/src/trpc/routers/dispatch.ts b/apps/server/trpc/routers/dispatch.ts similarity index 100% rename from src/trpc/routers/dispatch.ts rename to apps/server/trpc/routers/dispatch.ts diff --git a/src/trpc/routers/initiative.ts b/apps/server/trpc/routers/initiative.ts similarity index 100% rename from src/trpc/routers/initiative.ts rename to apps/server/trpc/routers/initiative.ts diff --git a/src/trpc/routers/message.ts b/apps/server/trpc/routers/message.ts similarity index 100% rename from src/trpc/routers/message.ts rename to apps/server/trpc/routers/message.ts diff --git a/src/trpc/routers/page.ts b/apps/server/trpc/routers/page.ts similarity index 100% rename from src/trpc/routers/page.ts rename to apps/server/trpc/routers/page.ts diff --git a/src/trpc/routers/phase-dispatch.ts b/apps/server/trpc/routers/phase-dispatch.ts similarity index 100% rename from src/trpc/routers/phase-dispatch.ts rename to apps/server/trpc/routers/phase-dispatch.ts diff --git a/src/trpc/routers/phase.ts b/apps/server/trpc/routers/phase.ts similarity index 100% rename from src/trpc/routers/phase.ts rename to apps/server/trpc/routers/phase.ts diff --git a/src/trpc/routers/preview.ts b/apps/server/trpc/routers/preview.ts similarity index 100% rename from src/trpc/routers/preview.ts rename to apps/server/trpc/routers/preview.ts diff --git a/src/trpc/routers/project.ts b/apps/server/trpc/routers/project.ts similarity index 100% rename from src/trpc/routers/project.ts rename to apps/server/trpc/routers/project.ts diff --git a/src/trpc/routers/subscription.ts b/apps/server/trpc/routers/subscription.ts similarity index 100% rename from src/trpc/routers/subscription.ts rename to apps/server/trpc/routers/subscription.ts diff --git a/src/trpc/routers/system.ts b/apps/server/trpc/routers/system.ts similarity index 100% rename from src/trpc/routers/system.ts rename to apps/server/trpc/routers/system.ts diff --git a/src/trpc/routers/task.ts b/apps/server/trpc/routers/task.ts similarity index 100% rename from src/trpc/routers/task.ts rename to apps/server/trpc/routers/task.ts diff --git a/src/trpc/subscriptions.ts b/apps/server/trpc/subscriptions.ts similarity index 100% rename from src/trpc/subscriptions.ts rename to apps/server/trpc/subscriptions.ts diff --git a/src/trpc/trpc.ts b/apps/server/trpc/trpc.ts similarity index 100% rename from src/trpc/trpc.ts rename to apps/server/trpc/trpc.ts diff --git a/packages/web/components.json b/apps/web/components.json similarity index 100% rename from packages/web/components.json rename to apps/web/components.json diff --git a/packages/web/index.html b/apps/web/index.html similarity index 100% rename from packages/web/index.html rename to apps/web/index.html diff --git a/packages/web/package.json b/apps/web/package.json similarity index 100% rename from packages/web/package.json rename to apps/web/package.json diff --git a/packages/web/postcss.config.js b/apps/web/postcss.config.js similarity index 100% rename from packages/web/postcss.config.js rename to apps/web/postcss.config.js diff --git a/packages/web/src/App.tsx b/apps/web/src/App.tsx similarity index 100% rename from packages/web/src/App.tsx rename to apps/web/src/App.tsx diff --git a/packages/web/src/components/AccountCard.tsx b/apps/web/src/components/AccountCard.tsx similarity index 100% rename from packages/web/src/components/AccountCard.tsx rename to apps/web/src/components/AccountCard.tsx diff --git a/packages/web/src/components/ActionMenu.tsx b/apps/web/src/components/ActionMenu.tsx similarity index 100% rename from packages/web/src/components/ActionMenu.tsx rename to apps/web/src/components/ActionMenu.tsx diff --git a/packages/web/src/components/AgentActions.tsx b/apps/web/src/components/AgentActions.tsx similarity index 100% rename from packages/web/src/components/AgentActions.tsx rename to apps/web/src/components/AgentActions.tsx diff --git a/packages/web/src/components/AgentOutputViewer.tsx b/apps/web/src/components/AgentOutputViewer.tsx similarity index 100% rename from packages/web/src/components/AgentOutputViewer.tsx rename to apps/web/src/components/AgentOutputViewer.tsx diff --git a/packages/web/src/components/ChangeSetBanner.tsx b/apps/web/src/components/ChangeSetBanner.tsx similarity index 100% rename from packages/web/src/components/ChangeSetBanner.tsx rename to apps/web/src/components/ChangeSetBanner.tsx diff --git a/packages/web/src/components/CreateInitiativeDialog.tsx b/apps/web/src/components/CreateInitiativeDialog.tsx similarity index 100% rename from packages/web/src/components/CreateInitiativeDialog.tsx rename to apps/web/src/components/CreateInitiativeDialog.tsx diff --git a/packages/web/src/components/DecisionList.tsx b/apps/web/src/components/DecisionList.tsx similarity index 100% rename from packages/web/src/components/DecisionList.tsx rename to apps/web/src/components/DecisionList.tsx diff --git a/packages/web/src/components/DependencyIndicator.tsx b/apps/web/src/components/DependencyIndicator.tsx similarity index 100% rename from packages/web/src/components/DependencyIndicator.tsx rename to apps/web/src/components/DependencyIndicator.tsx diff --git a/packages/web/src/components/ErrorBoundary.tsx b/apps/web/src/components/ErrorBoundary.tsx similarity index 100% rename from packages/web/src/components/ErrorBoundary.tsx rename to apps/web/src/components/ErrorBoundary.tsx diff --git a/packages/web/src/components/ExecutionTab.tsx b/apps/web/src/components/ExecutionTab.tsx similarity index 100% rename from packages/web/src/components/ExecutionTab.tsx rename to apps/web/src/components/ExecutionTab.tsx diff --git a/packages/web/src/components/FreeTextInput.tsx b/apps/web/src/components/FreeTextInput.tsx similarity index 100% rename from packages/web/src/components/FreeTextInput.tsx rename to apps/web/src/components/FreeTextInput.tsx diff --git a/packages/web/src/components/InboxDetailPanel.tsx b/apps/web/src/components/InboxDetailPanel.tsx similarity index 100% rename from packages/web/src/components/InboxDetailPanel.tsx rename to apps/web/src/components/InboxDetailPanel.tsx diff --git a/packages/web/src/components/InboxList.tsx b/apps/web/src/components/InboxList.tsx similarity index 100% rename from packages/web/src/components/InboxList.tsx rename to apps/web/src/components/InboxList.tsx diff --git a/packages/web/src/components/InitiativeCard.tsx b/apps/web/src/components/InitiativeCard.tsx similarity index 100% rename from packages/web/src/components/InitiativeCard.tsx rename to apps/web/src/components/InitiativeCard.tsx diff --git a/packages/web/src/components/InitiativeHeader.tsx b/apps/web/src/components/InitiativeHeader.tsx similarity index 100% rename from packages/web/src/components/InitiativeHeader.tsx rename to apps/web/src/components/InitiativeHeader.tsx diff --git a/packages/web/src/components/InitiativeList.tsx b/apps/web/src/components/InitiativeList.tsx similarity index 100% rename from packages/web/src/components/InitiativeList.tsx rename to apps/web/src/components/InitiativeList.tsx diff --git a/packages/web/src/components/MessageCard.tsx b/apps/web/src/components/MessageCard.tsx similarity index 100% rename from packages/web/src/components/MessageCard.tsx rename to apps/web/src/components/MessageCard.tsx diff --git a/packages/web/src/components/OptionGroup.tsx b/apps/web/src/components/OptionGroup.tsx similarity index 100% rename from packages/web/src/components/OptionGroup.tsx rename to apps/web/src/components/OptionGroup.tsx diff --git a/packages/web/src/components/PhaseAccordion.tsx b/apps/web/src/components/PhaseAccordion.tsx similarity index 100% rename from packages/web/src/components/PhaseAccordion.tsx rename to apps/web/src/components/PhaseAccordion.tsx diff --git a/packages/web/src/components/ProgressBar.tsx b/apps/web/src/components/ProgressBar.tsx similarity index 100% rename from packages/web/src/components/ProgressBar.tsx rename to apps/web/src/components/ProgressBar.tsx diff --git a/packages/web/src/components/ProgressPanel.tsx b/apps/web/src/components/ProgressPanel.tsx similarity index 100% rename from packages/web/src/components/ProgressPanel.tsx rename to apps/web/src/components/ProgressPanel.tsx diff --git a/packages/web/src/components/ProjectPicker.tsx b/apps/web/src/components/ProjectPicker.tsx similarity index 100% rename from packages/web/src/components/ProjectPicker.tsx rename to apps/web/src/components/ProjectPicker.tsx diff --git a/packages/web/src/components/QuestionForm.tsx b/apps/web/src/components/QuestionForm.tsx similarity index 100% rename from packages/web/src/components/QuestionForm.tsx rename to apps/web/src/components/QuestionForm.tsx diff --git a/packages/web/src/components/RefineSpawnDialog.tsx b/apps/web/src/components/RefineSpawnDialog.tsx similarity index 100% rename from packages/web/src/components/RefineSpawnDialog.tsx rename to apps/web/src/components/RefineSpawnDialog.tsx diff --git a/packages/web/src/components/RegisterProjectDialog.tsx b/apps/web/src/components/RegisterProjectDialog.tsx similarity index 100% rename from packages/web/src/components/RegisterProjectDialog.tsx rename to apps/web/src/components/RegisterProjectDialog.tsx diff --git a/packages/web/src/components/Skeleton.tsx b/apps/web/src/components/Skeleton.tsx similarity index 100% rename from packages/web/src/components/Skeleton.tsx rename to apps/web/src/components/Skeleton.tsx diff --git a/packages/web/src/components/SpawnArchitectDropdown.tsx b/apps/web/src/components/SpawnArchitectDropdown.tsx similarity index 100% rename from packages/web/src/components/SpawnArchitectDropdown.tsx rename to apps/web/src/components/SpawnArchitectDropdown.tsx diff --git a/packages/web/src/components/StatusBadge.tsx b/apps/web/src/components/StatusBadge.tsx similarity index 100% rename from packages/web/src/components/StatusBadge.tsx rename to apps/web/src/components/StatusBadge.tsx diff --git a/packages/web/src/components/StatusDot.tsx b/apps/web/src/components/StatusDot.tsx similarity index 100% rename from packages/web/src/components/StatusDot.tsx rename to apps/web/src/components/StatusDot.tsx diff --git a/packages/web/src/components/TaskDetailModal.tsx b/apps/web/src/components/TaskDetailModal.tsx similarity index 100% rename from packages/web/src/components/TaskDetailModal.tsx rename to apps/web/src/components/TaskDetailModal.tsx diff --git a/packages/web/src/components/TaskRow.tsx b/apps/web/src/components/TaskRow.tsx similarity index 100% rename from packages/web/src/components/TaskRow.tsx rename to apps/web/src/components/TaskRow.tsx diff --git a/packages/web/src/components/editor/BlockDragHandle.tsx b/apps/web/src/components/editor/BlockDragHandle.tsx similarity index 100% rename from packages/web/src/components/editor/BlockDragHandle.tsx rename to apps/web/src/components/editor/BlockDragHandle.tsx diff --git a/packages/web/src/components/editor/BlockSelectionExtension.ts b/apps/web/src/components/editor/BlockSelectionExtension.ts similarity index 100% rename from packages/web/src/components/editor/BlockSelectionExtension.ts rename to apps/web/src/components/editor/BlockSelectionExtension.ts diff --git a/packages/web/src/components/editor/ContentTab.tsx b/apps/web/src/components/editor/ContentTab.tsx similarity index 100% rename from packages/web/src/components/editor/ContentTab.tsx rename to apps/web/src/components/editor/ContentTab.tsx diff --git a/packages/web/src/components/editor/DeleteSubpageDialog.tsx b/apps/web/src/components/editor/DeleteSubpageDialog.tsx similarity index 100% rename from packages/web/src/components/editor/DeleteSubpageDialog.tsx rename to apps/web/src/components/editor/DeleteSubpageDialog.tsx diff --git a/packages/web/src/components/editor/PageBreadcrumb.tsx b/apps/web/src/components/editor/PageBreadcrumb.tsx similarity index 100% rename from packages/web/src/components/editor/PageBreadcrumb.tsx rename to apps/web/src/components/editor/PageBreadcrumb.tsx diff --git a/packages/web/src/components/editor/PageLinkDeletionDetector.ts b/apps/web/src/components/editor/PageLinkDeletionDetector.ts similarity index 100% rename from packages/web/src/components/editor/PageLinkDeletionDetector.ts rename to apps/web/src/components/editor/PageLinkDeletionDetector.ts diff --git a/packages/web/src/components/editor/PageLinkExtension.tsx b/apps/web/src/components/editor/PageLinkExtension.tsx similarity index 100% rename from packages/web/src/components/editor/PageLinkExtension.tsx rename to apps/web/src/components/editor/PageLinkExtension.tsx diff --git a/packages/web/src/components/editor/PageTitleContext.tsx b/apps/web/src/components/editor/PageTitleContext.tsx similarity index 100% rename from packages/web/src/components/editor/PageTitleContext.tsx rename to apps/web/src/components/editor/PageTitleContext.tsx diff --git a/packages/web/src/components/editor/PageTree.tsx b/apps/web/src/components/editor/PageTree.tsx similarity index 100% rename from packages/web/src/components/editor/PageTree.tsx rename to apps/web/src/components/editor/PageTree.tsx diff --git a/packages/web/src/components/editor/PhaseContentEditor.tsx b/apps/web/src/components/editor/PhaseContentEditor.tsx similarity index 100% rename from packages/web/src/components/editor/PhaseContentEditor.tsx rename to apps/web/src/components/editor/PhaseContentEditor.tsx diff --git a/packages/web/src/components/editor/RefineAgentPanel.tsx b/apps/web/src/components/editor/RefineAgentPanel.tsx similarity index 100% rename from packages/web/src/components/editor/RefineAgentPanel.tsx rename to apps/web/src/components/editor/RefineAgentPanel.tsx diff --git a/packages/web/src/components/editor/SlashCommandList.tsx b/apps/web/src/components/editor/SlashCommandList.tsx similarity index 100% rename from packages/web/src/components/editor/SlashCommandList.tsx rename to apps/web/src/components/editor/SlashCommandList.tsx diff --git a/packages/web/src/components/editor/SlashCommands.ts b/apps/web/src/components/editor/SlashCommands.ts similarity index 100% rename from packages/web/src/components/editor/SlashCommands.ts rename to apps/web/src/components/editor/SlashCommands.ts diff --git a/packages/web/src/components/editor/TiptapEditor.tsx b/apps/web/src/components/editor/TiptapEditor.tsx similarity index 100% rename from packages/web/src/components/editor/TiptapEditor.tsx rename to apps/web/src/components/editor/TiptapEditor.tsx diff --git a/packages/web/src/components/editor/slash-command-items.ts b/apps/web/src/components/editor/slash-command-items.ts similarity index 100% rename from packages/web/src/components/editor/slash-command-items.ts rename to apps/web/src/components/editor/slash-command-items.ts diff --git a/packages/web/src/components/execution/ExecutionContext.tsx b/apps/web/src/components/execution/ExecutionContext.tsx similarity index 100% rename from packages/web/src/components/execution/ExecutionContext.tsx rename to apps/web/src/components/execution/ExecutionContext.tsx diff --git a/packages/web/src/components/execution/PhaseActions.tsx b/apps/web/src/components/execution/PhaseActions.tsx similarity index 100% rename from packages/web/src/components/execution/PhaseActions.tsx rename to apps/web/src/components/execution/PhaseActions.tsx diff --git a/packages/web/src/components/execution/PhaseDetailPanel.tsx b/apps/web/src/components/execution/PhaseDetailPanel.tsx similarity index 100% rename from packages/web/src/components/execution/PhaseDetailPanel.tsx rename to apps/web/src/components/execution/PhaseDetailPanel.tsx diff --git a/packages/web/src/components/execution/PhaseSidebarItem.tsx b/apps/web/src/components/execution/PhaseSidebarItem.tsx similarity index 100% rename from packages/web/src/components/execution/PhaseSidebarItem.tsx rename to apps/web/src/components/execution/PhaseSidebarItem.tsx diff --git a/packages/web/src/components/execution/PhaseWithTasks.tsx b/apps/web/src/components/execution/PhaseWithTasks.tsx similarity index 100% rename from packages/web/src/components/execution/PhaseWithTasks.tsx rename to apps/web/src/components/execution/PhaseWithTasks.tsx diff --git a/packages/web/src/components/execution/PhasesList.tsx b/apps/web/src/components/execution/PhasesList.tsx similarity index 100% rename from packages/web/src/components/execution/PhasesList.tsx rename to apps/web/src/components/execution/PhasesList.tsx diff --git a/packages/web/src/components/execution/PlanSection.tsx b/apps/web/src/components/execution/PlanSection.tsx similarity index 100% rename from packages/web/src/components/execution/PlanSection.tsx rename to apps/web/src/components/execution/PlanSection.tsx diff --git a/packages/web/src/components/execution/ProgressSidebar.tsx b/apps/web/src/components/execution/ProgressSidebar.tsx similarity index 100% rename from packages/web/src/components/execution/ProgressSidebar.tsx rename to apps/web/src/components/execution/ProgressSidebar.tsx diff --git a/packages/web/src/components/execution/TaskModal.tsx b/apps/web/src/components/execution/TaskModal.tsx similarity index 100% rename from packages/web/src/components/execution/TaskModal.tsx rename to apps/web/src/components/execution/TaskModal.tsx diff --git a/packages/web/src/components/execution/index.ts b/apps/web/src/components/execution/index.ts similarity index 100% rename from packages/web/src/components/execution/index.ts rename to apps/web/src/components/execution/index.ts diff --git a/packages/web/src/components/pipeline/PipelineGraph.tsx b/apps/web/src/components/pipeline/PipelineGraph.tsx similarity index 100% rename from packages/web/src/components/pipeline/PipelineGraph.tsx rename to apps/web/src/components/pipeline/PipelineGraph.tsx diff --git a/packages/web/src/components/pipeline/PipelinePhaseGroup.tsx b/apps/web/src/components/pipeline/PipelinePhaseGroup.tsx similarity index 100% rename from packages/web/src/components/pipeline/PipelinePhaseGroup.tsx rename to apps/web/src/components/pipeline/PipelinePhaseGroup.tsx diff --git a/packages/web/src/components/pipeline/PipelineStageColumn.tsx b/apps/web/src/components/pipeline/PipelineStageColumn.tsx similarity index 100% rename from packages/web/src/components/pipeline/PipelineStageColumn.tsx rename to apps/web/src/components/pipeline/PipelineStageColumn.tsx diff --git a/packages/web/src/components/pipeline/PipelineTab.tsx b/apps/web/src/components/pipeline/PipelineTab.tsx similarity index 100% rename from packages/web/src/components/pipeline/PipelineTab.tsx rename to apps/web/src/components/pipeline/PipelineTab.tsx diff --git a/packages/web/src/components/pipeline/PipelineTaskCard.tsx b/apps/web/src/components/pipeline/PipelineTaskCard.tsx similarity index 100% rename from packages/web/src/components/pipeline/PipelineTaskCard.tsx rename to apps/web/src/components/pipeline/PipelineTaskCard.tsx diff --git a/packages/web/src/components/pipeline/index.ts b/apps/web/src/components/pipeline/index.ts similarity index 100% rename from packages/web/src/components/pipeline/index.ts rename to apps/web/src/components/pipeline/index.ts diff --git a/packages/web/src/components/review/CommentForm.tsx b/apps/web/src/components/review/CommentForm.tsx similarity index 100% rename from packages/web/src/components/review/CommentForm.tsx rename to apps/web/src/components/review/CommentForm.tsx diff --git a/packages/web/src/components/review/CommentThread.tsx b/apps/web/src/components/review/CommentThread.tsx similarity index 100% rename from packages/web/src/components/review/CommentThread.tsx rename to apps/web/src/components/review/CommentThread.tsx diff --git a/packages/web/src/components/review/DiffViewer.tsx b/apps/web/src/components/review/DiffViewer.tsx similarity index 100% rename from packages/web/src/components/review/DiffViewer.tsx rename to apps/web/src/components/review/DiffViewer.tsx diff --git a/packages/web/src/components/review/FileCard.tsx b/apps/web/src/components/review/FileCard.tsx similarity index 100% rename from packages/web/src/components/review/FileCard.tsx rename to apps/web/src/components/review/FileCard.tsx diff --git a/packages/web/src/components/review/HunkRows.tsx b/apps/web/src/components/review/HunkRows.tsx similarity index 100% rename from packages/web/src/components/review/HunkRows.tsx rename to apps/web/src/components/review/HunkRows.tsx diff --git a/packages/web/src/components/review/LineWithComments.tsx b/apps/web/src/components/review/LineWithComments.tsx similarity index 100% rename from packages/web/src/components/review/LineWithComments.tsx rename to apps/web/src/components/review/LineWithComments.tsx diff --git a/packages/web/src/components/review/PreviewPanel.tsx b/apps/web/src/components/review/PreviewPanel.tsx similarity index 100% rename from packages/web/src/components/review/PreviewPanel.tsx rename to apps/web/src/components/review/PreviewPanel.tsx diff --git a/packages/web/src/components/review/ReviewSidebar.tsx b/apps/web/src/components/review/ReviewSidebar.tsx similarity index 100% rename from packages/web/src/components/review/ReviewSidebar.tsx rename to apps/web/src/components/review/ReviewSidebar.tsx diff --git a/packages/web/src/components/review/ReviewTab.tsx b/apps/web/src/components/review/ReviewTab.tsx similarity index 100% rename from packages/web/src/components/review/ReviewTab.tsx rename to apps/web/src/components/review/ReviewTab.tsx diff --git a/packages/web/src/components/review/dummy-data.ts b/apps/web/src/components/review/dummy-data.ts similarity index 100% rename from packages/web/src/components/review/dummy-data.ts rename to apps/web/src/components/review/dummy-data.ts diff --git a/packages/web/src/components/review/index.ts b/apps/web/src/components/review/index.ts similarity index 100% rename from packages/web/src/components/review/index.ts rename to apps/web/src/components/review/index.ts diff --git a/packages/web/src/components/review/parse-diff.ts b/apps/web/src/components/review/parse-diff.ts similarity index 100% rename from packages/web/src/components/review/parse-diff.ts rename to apps/web/src/components/review/parse-diff.ts diff --git a/packages/web/src/components/review/types.ts b/apps/web/src/components/review/types.ts similarity index 100% rename from packages/web/src/components/review/types.ts rename to apps/web/src/components/review/types.ts diff --git a/packages/web/src/components/ui/badge.tsx b/apps/web/src/components/ui/badge.tsx similarity index 100% rename from packages/web/src/components/ui/badge.tsx rename to apps/web/src/components/ui/badge.tsx diff --git a/packages/web/src/components/ui/button.tsx b/apps/web/src/components/ui/button.tsx similarity index 100% rename from packages/web/src/components/ui/button.tsx rename to apps/web/src/components/ui/button.tsx diff --git a/packages/web/src/components/ui/card.tsx b/apps/web/src/components/ui/card.tsx similarity index 100% rename from packages/web/src/components/ui/card.tsx rename to apps/web/src/components/ui/card.tsx diff --git a/packages/web/src/components/ui/dialog.tsx b/apps/web/src/components/ui/dialog.tsx similarity index 100% rename from packages/web/src/components/ui/dialog.tsx rename to apps/web/src/components/ui/dialog.tsx diff --git a/packages/web/src/components/ui/dropdown-menu.tsx b/apps/web/src/components/ui/dropdown-menu.tsx similarity index 100% rename from packages/web/src/components/ui/dropdown-menu.tsx rename to apps/web/src/components/ui/dropdown-menu.tsx diff --git a/packages/web/src/components/ui/input.tsx b/apps/web/src/components/ui/input.tsx similarity index 100% rename from packages/web/src/components/ui/input.tsx rename to apps/web/src/components/ui/input.tsx diff --git a/packages/web/src/components/ui/label.tsx b/apps/web/src/components/ui/label.tsx similarity index 100% rename from packages/web/src/components/ui/label.tsx rename to apps/web/src/components/ui/label.tsx diff --git a/packages/web/src/components/ui/select.tsx b/apps/web/src/components/ui/select.tsx similarity index 100% rename from packages/web/src/components/ui/select.tsx rename to apps/web/src/components/ui/select.tsx diff --git a/packages/web/src/components/ui/sonner.tsx b/apps/web/src/components/ui/sonner.tsx similarity index 100% rename from packages/web/src/components/ui/sonner.tsx rename to apps/web/src/components/ui/sonner.tsx diff --git a/packages/web/src/components/ui/textarea.tsx b/apps/web/src/components/ui/textarea.tsx similarity index 100% rename from packages/web/src/components/ui/textarea.tsx rename to apps/web/src/components/ui/textarea.tsx diff --git a/packages/web/src/hooks/index.ts b/apps/web/src/hooks/index.ts similarity index 100% rename from packages/web/src/hooks/index.ts rename to apps/web/src/hooks/index.ts diff --git a/packages/web/src/hooks/useAutoSave.ts b/apps/web/src/hooks/useAutoSave.ts similarity index 100% rename from packages/web/src/hooks/useAutoSave.ts rename to apps/web/src/hooks/useAutoSave.ts diff --git a/packages/web/src/hooks/useDebounce.ts b/apps/web/src/hooks/useDebounce.ts similarity index 100% rename from packages/web/src/hooks/useDebounce.ts rename to apps/web/src/hooks/useDebounce.ts diff --git a/packages/web/src/hooks/useLiveUpdates.ts b/apps/web/src/hooks/useLiveUpdates.ts similarity index 100% rename from packages/web/src/hooks/useLiveUpdates.ts rename to apps/web/src/hooks/useLiveUpdates.ts diff --git a/packages/web/src/hooks/useOptimisticMutation.ts b/apps/web/src/hooks/useOptimisticMutation.ts similarity index 100% rename from packages/web/src/hooks/useOptimisticMutation.ts rename to apps/web/src/hooks/useOptimisticMutation.ts diff --git a/packages/web/src/hooks/usePhaseAutoSave.ts b/apps/web/src/hooks/usePhaseAutoSave.ts similarity index 100% rename from packages/web/src/hooks/usePhaseAutoSave.ts rename to apps/web/src/hooks/usePhaseAutoSave.ts diff --git a/packages/web/src/hooks/useRefineAgent.ts b/apps/web/src/hooks/useRefineAgent.ts similarity index 100% rename from packages/web/src/hooks/useRefineAgent.ts rename to apps/web/src/hooks/useRefineAgent.ts diff --git a/packages/web/src/hooks/useSpawnMutation.ts b/apps/web/src/hooks/useSpawnMutation.ts similarity index 100% rename from packages/web/src/hooks/useSpawnMutation.ts rename to apps/web/src/hooks/useSpawnMutation.ts diff --git a/packages/web/src/hooks/useSubscriptionWithErrorHandling.ts b/apps/web/src/hooks/useSubscriptionWithErrorHandling.ts similarity index 100% rename from packages/web/src/hooks/useSubscriptionWithErrorHandling.ts rename to apps/web/src/hooks/useSubscriptionWithErrorHandling.ts diff --git a/packages/web/src/index.css b/apps/web/src/index.css similarity index 100% rename from packages/web/src/index.css rename to apps/web/src/index.css diff --git a/packages/web/src/layouts/AppLayout.tsx b/apps/web/src/layouts/AppLayout.tsx similarity index 100% rename from packages/web/src/layouts/AppLayout.tsx rename to apps/web/src/layouts/AppLayout.tsx diff --git a/packages/web/src/lib/invalidation.ts b/apps/web/src/lib/invalidation.ts similarity index 100% rename from packages/web/src/lib/invalidation.ts rename to apps/web/src/lib/invalidation.ts diff --git a/packages/web/src/lib/labels.ts b/apps/web/src/lib/labels.ts similarity index 100% rename from packages/web/src/lib/labels.ts rename to apps/web/src/lib/labels.ts diff --git a/packages/web/src/lib/markdown-to-tiptap.ts b/apps/web/src/lib/markdown-to-tiptap.ts similarity index 100% rename from packages/web/src/lib/markdown-to-tiptap.ts rename to apps/web/src/lib/markdown-to-tiptap.ts diff --git a/packages/web/src/lib/parse-agent-output.ts b/apps/web/src/lib/parse-agent-output.ts similarity index 100% rename from packages/web/src/lib/parse-agent-output.ts rename to apps/web/src/lib/parse-agent-output.ts diff --git a/packages/web/src/lib/trpc.ts b/apps/web/src/lib/trpc.ts similarity index 100% rename from packages/web/src/lib/trpc.ts rename to apps/web/src/lib/trpc.ts diff --git a/packages/web/src/lib/utils.ts b/apps/web/src/lib/utils.ts similarity index 100% rename from packages/web/src/lib/utils.ts rename to apps/web/src/lib/utils.ts diff --git a/packages/web/src/main.tsx b/apps/web/src/main.tsx similarity index 100% rename from packages/web/src/main.tsx rename to apps/web/src/main.tsx diff --git a/packages/web/src/routeTree.gen.ts b/apps/web/src/routeTree.gen.ts similarity index 100% rename from packages/web/src/routeTree.gen.ts rename to apps/web/src/routeTree.gen.ts diff --git a/packages/web/src/router.tsx b/apps/web/src/router.tsx similarity index 100% rename from packages/web/src/router.tsx rename to apps/web/src/router.tsx diff --git a/packages/web/src/routes/__root.tsx b/apps/web/src/routes/__root.tsx similarity index 100% rename from packages/web/src/routes/__root.tsx rename to apps/web/src/routes/__root.tsx diff --git a/packages/web/src/routes/agents.tsx b/apps/web/src/routes/agents.tsx similarity index 100% rename from packages/web/src/routes/agents.tsx rename to apps/web/src/routes/agents.tsx diff --git a/packages/web/src/routes/inbox.tsx b/apps/web/src/routes/inbox.tsx similarity index 100% rename from packages/web/src/routes/inbox.tsx rename to apps/web/src/routes/inbox.tsx diff --git a/packages/web/src/routes/index.tsx b/apps/web/src/routes/index.tsx similarity index 100% rename from packages/web/src/routes/index.tsx rename to apps/web/src/routes/index.tsx diff --git a/packages/web/src/routes/initiatives/$id.tsx b/apps/web/src/routes/initiatives/$id.tsx similarity index 100% rename from packages/web/src/routes/initiatives/$id.tsx rename to apps/web/src/routes/initiatives/$id.tsx diff --git a/packages/web/src/routes/initiatives/index.tsx b/apps/web/src/routes/initiatives/index.tsx similarity index 100% rename from packages/web/src/routes/initiatives/index.tsx rename to apps/web/src/routes/initiatives/index.tsx diff --git a/packages/web/src/routes/settings.tsx b/apps/web/src/routes/settings.tsx similarity index 100% rename from packages/web/src/routes/settings.tsx rename to apps/web/src/routes/settings.tsx diff --git a/packages/web/src/routes/settings/health.tsx b/apps/web/src/routes/settings/health.tsx similarity index 100% rename from packages/web/src/routes/settings/health.tsx rename to apps/web/src/routes/settings/health.tsx diff --git a/packages/web/src/routes/settings/index.tsx b/apps/web/src/routes/settings/index.tsx similarity index 100% rename from packages/web/src/routes/settings/index.tsx rename to apps/web/src/routes/settings/index.tsx diff --git a/packages/web/src/routes/settings/projects.tsx b/apps/web/src/routes/settings/projects.tsx similarity index 100% rename from packages/web/src/routes/settings/projects.tsx rename to apps/web/src/routes/settings/projects.tsx diff --git a/packages/web/src/vite-env.d.ts b/apps/web/src/vite-env.d.ts similarity index 100% rename from packages/web/src/vite-env.d.ts rename to apps/web/src/vite-env.d.ts diff --git a/packages/web/tailwind.config.ts b/apps/web/tailwind.config.ts similarity index 100% rename from packages/web/tailwind.config.ts rename to apps/web/tailwind.config.ts diff --git a/packages/web/tsconfig.app.json b/apps/web/tsconfig.app.json similarity index 100% rename from packages/web/tsconfig.app.json rename to apps/web/tsconfig.app.json diff --git a/packages/web/tsconfig.app.tsbuildinfo b/apps/web/tsconfig.app.tsbuildinfo similarity index 100% rename from packages/web/tsconfig.app.tsbuildinfo rename to apps/web/tsconfig.app.tsbuildinfo diff --git a/packages/web/tsconfig.json b/apps/web/tsconfig.json similarity index 100% rename from packages/web/tsconfig.json rename to apps/web/tsconfig.json diff --git a/packages/web/vite.config.ts b/apps/web/vite.config.ts similarity index 100% rename from packages/web/vite.config.ts rename to apps/web/vite.config.ts diff --git a/coverage/base.css b/coverage/base.css new file mode 100644 index 0000000..f418035 --- /dev/null +++ b/coverage/base.css @@ -0,0 +1,224 @@ +body, html { + margin:0; padding: 0; + height: 100%; +} +body { + font-family: Helvetica Neue, Helvetica, Arial; + font-size: 14px; + color:#333; +} +.small { font-size: 12px; } +*, *:after, *:before { + -webkit-box-sizing:border-box; + -moz-box-sizing:border-box; + box-sizing:border-box; + } +h1 { font-size: 20px; margin: 0;} +h2 { font-size: 14px; } +pre { + font: 12px/1.4 Consolas, "Liberation Mono", Menlo, Courier, monospace; + margin: 0; + padding: 0; + -moz-tab-size: 2; + -o-tab-size: 2; + tab-size: 2; +} +a { color:#0074D9; text-decoration:none; } +a:hover { text-decoration:underline; } +.strong { font-weight: bold; } +.space-top1 { padding: 10px 0 0 0; } +.pad2y { padding: 20px 0; } +.pad1y { padding: 10px 0; } +.pad2x { padding: 0 20px; } +.pad2 { padding: 20px; } +.pad1 { padding: 10px; } +.space-left2 { padding-left:55px; } +.space-right2 { padding-right:20px; } +.center { text-align:center; } +.clearfix { display:block; } +.clearfix:after { + content:''; + display:block; + height:0; + clear:both; + visibility:hidden; + } +.fl { float: left; } +@media only screen and (max-width:640px) { + .col3 { width:100%; max-width:100%; } + .hide-mobile { display:none!important; } +} + +.quiet { + color: #7f7f7f; + color: rgba(0,0,0,0.5); +} +.quiet a { opacity: 0.7; } + +.fraction { + font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; + font-size: 10px; + color: #555; + background: #E8E8E8; + padding: 4px 5px; + border-radius: 3px; + vertical-align: middle; +} + +div.path a:link, div.path a:visited { color: #333; } +table.coverage { + border-collapse: collapse; + margin: 10px 0 0 0; + padding: 0; +} + +table.coverage td { + margin: 0; + padding: 0; + vertical-align: top; +} +table.coverage td.line-count { + text-align: right; + padding: 0 5px 0 20px; +} +table.coverage td.line-coverage { + text-align: right; + padding-right: 10px; + min-width:20px; +} + +table.coverage td span.cline-any { + display: inline-block; + padding: 0 5px; + width: 100%; +} +.missing-if-branch { + display: inline-block; + margin-right: 5px; + border-radius: 3px; + position: relative; + padding: 0 4px; + background: #333; + color: yellow; +} + +.skip-if-branch { + display: none; + margin-right: 10px; + position: relative; + padding: 0 4px; + background: #ccc; + color: white; +} +.missing-if-branch .typ, .skip-if-branch .typ { + color: inherit !important; +} +.coverage-summary { + border-collapse: collapse; + width: 100%; +} +.coverage-summary tr { border-bottom: 1px solid #bbb; } +.keyline-all { border: 1px solid #ddd; } +.coverage-summary td, .coverage-summary th { padding: 10px; } +.coverage-summary tbody { border: 1px solid #bbb; } +.coverage-summary td { border-right: 1px solid #bbb; } +.coverage-summary td:last-child { border-right: none; } +.coverage-summary th { + text-align: left; + font-weight: normal; + white-space: nowrap; +} +.coverage-summary th.file { border-right: none !important; } +.coverage-summary th.pct { } +.coverage-summary th.pic, +.coverage-summary th.abs, +.coverage-summary td.pct, +.coverage-summary td.abs { text-align: right; } +.coverage-summary td.file { white-space: nowrap; } +.coverage-summary td.pic { min-width: 120px !important; } +.coverage-summary tfoot td { } + +.coverage-summary .sorter { + height: 10px; + width: 7px; + display: inline-block; + margin-left: 0.5em; + background: url(sort-arrow-sprite.png) no-repeat scroll 0 0 transparent; +} +.coverage-summary .sorted .sorter { + background-position: 0 -20px; +} +.coverage-summary .sorted-desc .sorter { + background-position: 0 -10px; +} +.status-line { height: 10px; } +/* yellow */ +.cbranch-no { background: yellow !important; color: #111; } +/* dark red */ +.red.solid, .status-line.low, .low .cover-fill { background:#C21F39 } +.low .chart { border:1px solid #C21F39 } +.highlighted, +.highlighted .cstat-no, .highlighted .fstat-no, .highlighted .cbranch-no{ + background: #C21F39 !important; +} +/* medium red */ +.cstat-no, .fstat-no, .cbranch-no, .cbranch-no { background:#F6C6CE } +/* light red */ +.low, .cline-no { background:#FCE1E5 } +/* light green */ +.high, .cline-yes { background:rgb(230,245,208) } +/* medium green */ +.cstat-yes { background:rgb(161,215,106) } +/* dark green */ +.status-line.high, .high .cover-fill { background:rgb(77,146,33) } +.high .chart { border:1px solid rgb(77,146,33) } +/* dark yellow (gold) */ +.status-line.medium, .medium .cover-fill { background: #f9cd0b; } +.medium .chart { border:1px solid #f9cd0b; } +/* light yellow */ +.medium { background: #fff4c2; } + +.cstat-skip { background: #ddd; color: #111; } +.fstat-skip { background: #ddd; color: #111 !important; } +.cbranch-skip { background: #ddd !important; color: #111; } + +span.cline-neutral { background: #eaeaea; } + +.coverage-summary td.empty { + opacity: .5; + padding-top: 4px; + padding-bottom: 4px; + line-height: 1; + color: #888; +} + +.cover-fill, .cover-empty { + display:inline-block; + height: 12px; +} +.chart { + line-height: 0; +} +.cover-empty { + background: white; +} +.cover-full { + border-right: none !important; +} +pre.prettyprint { + border: none !important; + padding: 0 !important; + margin: 0 !important; +} +.com { color: #999 !important; } +.ignore-none { color: #999; font-weight: normal; } + +.wrapper { + min-height: 100%; + height: auto !important; + height: 100%; + margin: 0 auto -48px; +} +.footer, .push { + height: 48px; +} diff --git a/coverage/block-navigation.js b/coverage/block-navigation.js new file mode 100644 index 0000000..530d1ed --- /dev/null +++ b/coverage/block-navigation.js @@ -0,0 +1,87 @@ +/* eslint-disable */ +var jumpToCode = (function init() { + // Classes of code we would like to highlight in the file view + var missingCoverageClasses = ['.cbranch-no', '.cstat-no', '.fstat-no']; + + // Elements to highlight in the file listing view + var fileListingElements = ['td.pct.low']; + + // We don't want to select elements that are direct descendants of another match + var notSelector = ':not(' + missingCoverageClasses.join('):not(') + ') > '; // becomes `:not(a):not(b) > ` + + // Selector that finds elements on the page to which we can jump + var selector = + fileListingElements.join(', ') + + ', ' + + notSelector + + missingCoverageClasses.join(', ' + notSelector); // becomes `:not(a):not(b) > a, :not(a):not(b) > b` + + // The NodeList of matching elements + var missingCoverageElements = document.querySelectorAll(selector); + + var currentIndex; + + function toggleClass(index) { + missingCoverageElements + .item(currentIndex) + .classList.remove('highlighted'); + missingCoverageElements.item(index).classList.add('highlighted'); + } + + function makeCurrent(index) { + toggleClass(index); + currentIndex = index; + missingCoverageElements.item(index).scrollIntoView({ + behavior: 'smooth', + block: 'center', + inline: 'center' + }); + } + + function goToPrevious() { + var nextIndex = 0; + if (typeof currentIndex !== 'number' || currentIndex === 0) { + nextIndex = missingCoverageElements.length - 1; + } else if (missingCoverageElements.length > 1) { + nextIndex = currentIndex - 1; + } + + makeCurrent(nextIndex); + } + + function goToNext() { + var nextIndex = 0; + + if ( + typeof currentIndex === 'number' && + currentIndex < missingCoverageElements.length - 1 + ) { + nextIndex = currentIndex + 1; + } + + makeCurrent(nextIndex); + } + + return function jump(event) { + if ( + document.getElementById('fileSearch') === document.activeElement && + document.activeElement != null + ) { + // if we're currently focused on the search input, we don't want to navigate + return; + } + + switch (event.which) { + case 78: // n + case 74: // j + goToNext(); + break; + case 66: // b + case 75: // k + case 80: // p + goToPrevious(); + break; + } + }; +})(); +window.addEventListener('keydown', jumpToCode); diff --git a/coverage/coverage-final.json b/coverage/coverage-final.json new file mode 100644 index 0000000..05e85d5 --- /dev/null +++ b/coverage/coverage-final.json @@ -0,0 +1,122 @@ +{"/Users/lukasmay/development/projects/codewalk-district/packages/shared/src/index.ts": {"path":"/Users/lukasmay/development/projects/codewalk-district/packages/shared/src/index.ts","statementMap":{},"fnMap":{},"branchMap":{},"s":{},"f":{},"b":{},"meta":{"lastBranch":0,"lastFunction":0,"lastStatement":0,"seen":{}}} +,"/Users/lukasmay/development/projects/codewalk-district/packages/shared/src/utils.ts": {"path":"/Users/lukasmay/development/projects/codewalk-district/packages/shared/src/utils.ts","statementMap":{"0":{"start":{"line":13,"column":23},"end":{"line":17,"column":null}},"1":{"start":{"line":25,"column":2},"end":{"line":36,"column":null}},"2":{"start":{"line":27,"column":25},"end":{"line":27,"column":null}},"3":{"start":{"line":28,"column":4},"end":{"line":30,"column":null}},"4":{"start":{"line":29,"column":6},"end":{"line":29,"column":null}},"5":{"start":{"line":33,"column":18},"end":{"line":33,"column":null}},"6":{"start":{"line":34,"column":18},"end":{"line":34,"column":null}},"7":{"start":{"line":35,"column":4},"end":{"line":35,"column":null}},"8":{"start":{"line":62,"column":2},"end":{"line":62,"column":null}},"9":{"start":{"line":62,"column":27},"end":{"line":62,"column":null}},"10":{"start":{"line":64,"column":19},"end":{"line":64,"column":null}},"11":{"start":{"line":64,"column":45},"end":{"line":64,"column":54}},"12":{"start":{"line":65,"column":19},"end":{"line":65,"column":null}},"13":{"start":{"line":66,"column":20},"end":{"line":66,"column":null}},"14":{"start":{"line":68,"column":2},"end":{"line":71,"column":null}},"15":{"start":{"line":69,"column":4},"end":{"line":69,"column":null}},"16":{"start":{"line":70,"column":4},"end":{"line":70,"column":null}},"17":{"start":{"line":73,"column":2},"end":{"line":77,"column":null}},"18":{"start":{"line":74,"column":4},"end":{"line":74,"column":null}},"19":{"start":{"line":74,"column":77},"end":{"line":74,"column":null}},"20":{"start":{"line":75,"column":4},"end":{"line":75,"column":null}},"21":{"start":{"line":76,"column":4},"end":{"line":76,"column":null}},"22":{"start":{"line":80,"column":16},"end":{"line":82,"column":null}},"23":{"start":{"line":81,"column":13},"end":{"line":81,"column":50}},"24":{"start":{"line":82,"column":20},"end":{"line":82,"column":61}},"25":{"start":{"line":84,"column":22},"end":{"line":84,"column":null}},"26":{"start":{"line":86,"column":2},"end":{"line":99,"column":null}},"27":{"start":{"line":88,"column":4},"end":{"line":88,"column":null}},"28":{"start":{"line":88,"column":25},"end":{"line":88,"column":66}},"29":{"start":{"line":89,"column":20},"end":{"line":89,"column":null}},"30":{"start":{"line":90,"column":4},"end":{"line":90,"column":null}},"31":{"start":{"line":92,"column":4},"end":{"line":98,"column":null}},"32":{"start":{"line":93,"column":12},"end":{"line":93,"column":null}},"33":{"start":{"line":94,"column":6},"end":{"line":94,"column":null}},"34":{"start":{"line":95,"column":6},"end":{"line":97,"column":null}},"35":{"start":{"line":96,"column":8},"end":{"line":96,"column":null}},"36":{"start":{"line":102,"column":2},"end":{"line":108,"column":null}},"37":{"start":{"line":103,"column":21},"end":{"line":103,"column":null}},"38":{"start":{"line":103,"column":47},"end":{"line":103,"column":51}},"39":{"start":{"line":104,"column":22},"end":{"line":106,"column":null}},"40":{"start":{"line":105,"column":21},"end":{"line":105,"column":40}},"41":{"start":{"line":106,"column":22},"end":{"line":106,"column":63}},"42":{"start":{"line":107,"column":4},"end":{"line":107,"column":null}},"43":{"start":{"line":110,"column":2},"end":{"line":110,"column":null}},"44":{"start":{"line":114,"column":2},"end":{"line":114,"column":null}},"45":{"start":{"line":136,"column":2},"end":{"line":136,"column":null}},"46":{"start":{"line":136,"column":27},"end":{"line":136,"column":null}},"47":{"start":{"line":138,"column":19},"end":{"line":138,"column":null}},"48":{"start":{"line":138,"column":45},"end":{"line":138,"column":49}},"49":{"start":{"line":141,"column":20},"end":{"line":141,"column":null}},"50":{"start":{"line":142,"column":2},"end":{"line":142,"column":null}},"51":{"start":{"line":142,"column":26},"end":{"line":142,"column":null}},"52":{"start":{"line":143,"column":2},"end":{"line":146,"column":null}},"53":{"start":{"line":144,"column":4},"end":{"line":144,"column":null}},"54":{"start":{"line":144,"column":77},"end":{"line":144,"column":null}},"55":{"start":{"line":145,"column":4},"end":{"line":145,"column":null}},"56":{"start":{"line":149,"column":21},"end":{"line":149,"column":null}},"57":{"start":{"line":150,"column":19},"end":{"line":150,"column":null}},"58":{"start":{"line":153,"column":4},"end":{"line":153,"column":null}},"59":{"start":{"line":153,"column":28},"end":{"line":153,"column":null}},"60":{"start":{"line":154,"column":4},"end":{"line":154,"column":null}},"61":{"start":{"line":154,"column":26},"end":{"line":154,"column":null}},"62":{"start":{"line":156,"column":4},"end":{"line":156,"column":null}},"63":{"start":{"line":157,"column":17},"end":{"line":157,"column":null}},"64":{"start":{"line":158,"column":19},"end":{"line":158,"column":null}},"65":{"start":{"line":159,"column":4},"end":{"line":166,"column":null}},"66":{"start":{"line":160,"column":16},"end":{"line":160,"column":null}},"67":{"start":{"line":161,"column":6},"end":{"line":164,"column":null}},"68":{"start":{"line":162,"column":8},"end":{"line":162,"column":null}},"69":{"start":{"line":163,"column":8},"end":{"line":163,"column":null}},"70":{"start":{"line":165,"column":6},"end":{"line":165,"column":null}},"71":{"start":{"line":167,"column":4},"end":{"line":167,"column":null}},"72":{"start":{"line":168,"column":4},"end":{"line":168,"column":null}},"73":{"start":{"line":169,"column":4},"end":{"line":169,"column":null}},"74":{"start":{"line":173,"column":22},"end":{"line":173,"column":null}},"75":{"start":{"line":174,"column":2},"end":{"line":177,"column":null}},"76":{"start":{"line":175,"column":14},"end":{"line":175,"column":null}},"77":{"start":{"line":176,"column":4},"end":{"line":176,"column":null}},"78":{"start":{"line":176,"column":16},"end":{"line":176,"column":null}},"79":{"start":{"line":180,"column":20},"end":{"line":180,"column":null}},"80":{"start":{"line":181,"column":2},"end":{"line":186,"column":null}},"81":{"start":{"line":182,"column":14},"end":{"line":182,"column":null}},"82":{"start":{"line":183,"column":18},"end":{"line":183,"column":null}},"83":{"start":{"line":184,"column":4},"end":{"line":184,"column":null}},"84":{"start":{"line":184,"column":31},"end":{"line":184,"column":null}},"85":{"start":{"line":185,"column":4},"end":{"line":185,"column":null}},"86":{"start":{"line":189,"column":39},"end":{"line":189,"column":null}},"87":{"start":{"line":190,"column":23},"end":{"line":190,"column":null}},"88":{"start":{"line":190,"column":60},"end":{"line":190,"column":65}},"89":{"start":{"line":191,"column":2},"end":{"line":195,"column":null}},"90":{"start":{"line":192,"column":24},"end":{"line":192,"column":null}},"91":{"start":{"line":193,"column":4},"end":{"line":193,"column":null}},"92":{"start":{"line":193,"column":31},"end":{"line":193,"column":72}},"93":{"start":{"line":194,"column":4},"end":{"line":194,"column":null}},"94":{"start":{"line":197,"column":2},"end":{"line":197,"column":null}}},"fnMap":{"0":{"name":"sortByPriorityAndQueueTime","decl":{"start":{"line":24,"column":16},"end":{"line":24,"column":67}},"loc":{"start":{"line":24,"column":84},"end":{"line":37,"column":null}},"line":24},"1":{"name":"(anonymous_1)","decl":{"start":{"line":25,"column":25},"end":{"line":25,"column":26}},"loc":{"start":{"line":25,"column":35},"end":{"line":36,"column":3}},"line":25},"2":{"name":"topologicalSortPhases","decl":{"start":{"line":58,"column":16},"end":{"line":58,"column":null}},"loc":{"start":{"line":61,"column":7},"end":{"line":111,"column":null}},"line":61},"3":{"name":"(anonymous_3)","decl":{"start":{"line":64,"column":38},"end":{"line":64,"column":39}},"loc":{"start":{"line":64,"column":45},"end":{"line":64,"column":54}},"line":64},"4":{"name":"(anonymous_4)","decl":{"start":{"line":81,"column":12},"end":{"line":81,"column":13}},"loc":{"start":{"line":81,"column":13},"end":{"line":81,"column":50}},"line":81},"5":{"name":"(anonymous_5)","decl":{"start":{"line":82,"column":10},"end":{"line":82,"column":11}},"loc":{"start":{"line":82,"column":20},"end":{"line":82,"column":61}},"line":82},"6":{"name":"(anonymous_6)","decl":{"start":{"line":88,"column":15},"end":{"line":88,"column":16}},"loc":{"start":{"line":88,"column":25},"end":{"line":88,"column":66}},"line":88},"7":{"name":"(anonymous_7)","decl":{"start":{"line":103,"column":40},"end":{"line":103,"column":41}},"loc":{"start":{"line":103,"column":47},"end":{"line":103,"column":51}},"line":103},"8":{"name":"(anonymous_8)","decl":{"start":{"line":105,"column":14},"end":{"line":105,"column":15}},"loc":{"start":{"line":105,"column":21},"end":{"line":105,"column":40}},"line":105},"9":{"name":"(anonymous_9)","decl":{"start":{"line":106,"column":12},"end":{"line":106,"column":13}},"loc":{"start":{"line":106,"column":22},"end":{"line":106,"column":63}},"line":106},"10":{"name":"toTime","decl":{"start":{"line":113,"column":9},"end":{"line":113,"column":16}},"loc":{"start":{"line":113,"column":42},"end":{"line":115,"column":null}},"line":113},"11":{"name":"groupPhasesByDependencyLevel","decl":{"start":{"line":132,"column":16},"end":{"line":132,"column":null}},"loc":{"start":{"line":135,"column":23},"end":{"line":198,"column":null}},"line":135},"12":{"name":"(anonymous_12)","decl":{"start":{"line":138,"column":38},"end":{"line":138,"column":39}},"loc":{"start":{"line":138,"column":45},"end":{"line":138,"column":49}},"line":138},"13":{"name":"computeDepth","decl":{"start":{"line":152,"column":11},"end":{"line":152,"column":24}},"loc":{"start":{"line":152,"column":44},"end":{"line":170,"column":null}},"line":152},"14":{"name":"(anonymous_14)","decl":{"start":{"line":190,"column":50},"end":{"line":190,"column":51}},"loc":{"start":{"line":190,"column":60},"end":{"line":190,"column":65}},"line":190},"15":{"name":"(anonymous_15)","decl":{"start":{"line":193,"column":21},"end":{"line":193,"column":22}},"loc":{"start":{"line":193,"column":31},"end":{"line":193,"column":72}},"line":193}},"branchMap":{"0":{"loc":{"start":{"line":28,"column":4},"end":{"line":30,"column":null}},"type":"if","locations":[{"start":{"line":28,"column":4},"end":{"line":30,"column":null}},{"start":{},"end":{}}],"line":28},"1":{"loc":{"start":{"line":33,"column":18},"end":{"line":33,"column":null}},"type":"cond-expr","locations":[{"start":{"line":33,"column":52},"end":{"line":33,"column":76}},{"start":{"line":33,"column":76},"end":{"line":33,"column":null}}],"line":33},"2":{"loc":{"start":{"line":34,"column":18},"end":{"line":34,"column":null}},"type":"cond-expr","locations":[{"start":{"line":34,"column":52},"end":{"line":34,"column":76}},{"start":{"line":34,"column":76},"end":{"line":34,"column":null}}],"line":34},"3":{"loc":{"start":{"line":62,"column":2},"end":{"line":62,"column":null}},"type":"if","locations":[{"start":{"line":62,"column":2},"end":{"line":62,"column":null}},{"start":{},"end":{}}],"line":62},"4":{"loc":{"start":{"line":74,"column":4},"end":{"line":74,"column":null}},"type":"if","locations":[{"start":{"line":74,"column":4},"end":{"line":74,"column":null}},{"start":{},"end":{}}],"line":74},"5":{"loc":{"start":{"line":74,"column":8},"end":{"line":74,"column":77}},"type":"binary-expr","locations":[{"start":{"line":74,"column":8},"end":{"line":74,"column":39}},{"start":{"line":74,"column":39},"end":{"line":74,"column":77}}],"line":74},"6":{"loc":{"start":{"line":75,"column":32},"end":{"line":75,"column":67}},"type":"binary-expr","locations":[{"start":{"line":75,"column":32},"end":{"line":75,"column":62}},{"start":{"line":75,"column":62},"end":{"line":75,"column":67}}],"line":75},"7":{"loc":{"start":{"line":81,"column":20},"end":{"line":81,"column":49}},"type":"binary-expr","locations":[{"start":{"line":81,"column":20},"end":{"line":81,"column":42}},{"start":{"line":81,"column":42},"end":{"line":81,"column":49}}],"line":81},"8":{"loc":{"start":{"line":92,"column":29},"end":{"line":92,"column":62}},"type":"binary-expr","locations":[{"start":{"line":92,"column":29},"end":{"line":92,"column":58}},{"start":{"line":92,"column":58},"end":{"line":92,"column":62}}],"line":92},"9":{"loc":{"start":{"line":93,"column":22},"end":{"line":93,"column":55}},"type":"binary-expr","locations":[{"start":{"line":93,"column":22},"end":{"line":93,"column":50}},{"start":{"line":93,"column":50},"end":{"line":93,"column":55}}],"line":93},"10":{"loc":{"start":{"line":95,"column":6},"end":{"line":97,"column":null}},"type":"if","locations":[{"start":{"line":95,"column":6},"end":{"line":97,"column":null}},{"start":{},"end":{}}],"line":95},"11":{"loc":{"start":{"line":102,"column":2},"end":{"line":108,"column":null}},"type":"if","locations":[{"start":{"line":102,"column":2},"end":{"line":108,"column":null}},{"start":{},"end":{}}],"line":102},"12":{"loc":{"start":{"line":114,"column":9},"end":{"line":114,"column":null}},"type":"cond-expr","locations":[{"start":{"line":114,"column":33},"end":{"line":114,"column":57}},{"start":{"line":114,"column":57},"end":{"line":114,"column":null}}],"line":114},"13":{"loc":{"start":{"line":136,"column":2},"end":{"line":136,"column":null}},"type":"if","locations":[{"start":{"line":136,"column":2},"end":{"line":136,"column":null}},{"start":{},"end":{}}],"line":136},"14":{"loc":{"start":{"line":144,"column":4},"end":{"line":144,"column":null}},"type":"if","locations":[{"start":{"line":144,"column":4},"end":{"line":144,"column":null}},{"start":{},"end":{}}],"line":144},"15":{"loc":{"start":{"line":144,"column":8},"end":{"line":144,"column":77}},"type":"binary-expr","locations":[{"start":{"line":144,"column":8},"end":{"line":144,"column":39}},{"start":{"line":144,"column":39},"end":{"line":144,"column":77}}],"line":144},"16":{"loc":{"start":{"line":153,"column":4},"end":{"line":153,"column":null}},"type":"if","locations":[{"start":{"line":153,"column":4},"end":{"line":153,"column":null}},{"start":{},"end":{}}],"line":153},"17":{"loc":{"start":{"line":154,"column":4},"end":{"line":154,"column":null}},"type":"if","locations":[{"start":{"line":154,"column":4},"end":{"line":154,"column":null}},{"start":{},"end":{}}],"line":154},"18":{"loc":{"start":{"line":157,"column":17},"end":{"line":157,"column":null}},"type":"binary-expr","locations":[{"start":{"line":157,"column":17},"end":{"line":157,"column":38}},{"start":{"line":157,"column":38},"end":{"line":157,"column":null}}],"line":157},"19":{"loc":{"start":{"line":161,"column":6},"end":{"line":164,"column":null}},"type":"if","locations":[{"start":{"line":161,"column":6},"end":{"line":164,"column":null}},{"start":{},"end":{}}],"line":161},"20":{"loc":{"start":{"line":176,"column":4},"end":{"line":176,"column":null}},"type":"if","locations":[{"start":{"line":176,"column":4},"end":{"line":176,"column":null}},{"start":{},"end":{}}],"line":176},"21":{"loc":{"start":{"line":183,"column":18},"end":{"line":183,"column":null}},"type":"cond-expr","locations":[{"start":{"line":183,"column":40},"end":{"line":183,"column":44}},{"start":{"line":183,"column":44},"end":{"line":183,"column":null}}],"line":183},"22":{"loc":{"start":{"line":183,"column":18},"end":{"line":183,"column":40}},"type":"binary-expr","locations":[{"start":{"line":183,"column":18},"end":{"line":183,"column":31}},{"start":{"line":183,"column":31},"end":{"line":183,"column":40}}],"line":183},"23":{"loc":{"start":{"line":184,"column":4},"end":{"line":184,"column":null}},"type":"if","locations":[{"start":{"line":184,"column":4},"end":{"line":184,"column":null}},{"start":{},"end":{}}],"line":184}},"s":{"0":1,"1":0,"2":0,"3":0,"4":0,"5":0,"6":0,"7":0,"8":10,"9":1,"10":9,"11":23,"12":9,"13":9,"14":9,"15":23,"16":23,"17":9,"18":10,"19":1,"20":9,"21":10,"22":9,"23":23,"24":10,"25":9,"26":9,"27":21,"28":9,"29":21,"30":21,"31":21,"32":7,"33":7,"34":7,"35":6,"36":9,"37":1,"38":1,"39":1,"40":3,"41":1,"42":1,"43":9,"44":40,"45":0,"46":0,"47":0,"48":0,"49":0,"50":0,"51":0,"52":0,"53":0,"54":0,"55":0,"56":0,"57":0,"58":0,"59":0,"60":0,"61":0,"62":0,"63":0,"64":0,"65":0,"66":0,"67":0,"68":0,"69":0,"70":0,"71":0,"72":0,"73":0,"74":0,"75":0,"76":0,"77":0,"78":0,"79":0,"80":0,"81":0,"82":0,"83":0,"84":0,"85":0,"86":0,"87":0,"88":0,"89":0,"90":0,"91":0,"92":0,"93":0,"94":0},"f":{"0":0,"1":0,"2":10,"3":23,"4":23,"5":10,"6":9,"7":1,"8":3,"9":1,"10":40,"11":0,"12":0,"13":0,"14":0,"15":0},"b":{"0":[0,0],"1":[0,0],"2":[0,0],"3":[1,9],"4":[1,9],"5":[10,10],"6":[9,0],"7":[23,0],"8":[21,0],"9":[7,0],"10":[6,1],"11":[1,8],"12":[40,0],"13":[0,0],"14":[0,0],"15":[0,0],"16":[0,0],"17":[0,0],"18":[0,0],"19":[0,0],"20":[0,0],"21":[0,0],"22":[0,0],"23":[0,0]},"meta":{"lastBranch":24,"lastFunction":16,"lastStatement":95,"seen":{"s:13:23:17:Infinity":0,"f:24:16:24:67":0,"s:25:2:36:Infinity":1,"f:25:25:25:26":1,"s:27:25:27:Infinity":2,"b:28:4:30:Infinity:undefined:undefined:undefined:undefined":0,"s:28:4:30:Infinity":3,"s:29:6:29:Infinity":4,"s:33:18:33:Infinity":5,"b:33:52:33:76:33:76:33:Infinity":1,"s:34:18:34:Infinity":6,"b:34:52:34:76:34:76:34:Infinity":2,"s:35:4:35:Infinity":7,"f:58:16:58:Infinity":2,"b:62:2:62:Infinity:undefined:undefined:undefined:undefined":3,"s:62:2:62:Infinity":8,"s:62:27:62:Infinity":9,"s:64:19:64:Infinity":10,"f:64:38:64:39":3,"s:64:45:64:54":11,"s:65:19:65:Infinity":12,"s:66:20:66:Infinity":13,"s:68:2:71:Infinity":14,"s:69:4:69:Infinity":15,"s:70:4:70:Infinity":16,"s:73:2:77:Infinity":17,"b:74:4:74:Infinity:undefined:undefined:undefined:undefined":4,"s:74:4:74:Infinity":18,"b:74:8:74:39:74:39:74:77":5,"s:74:77:74:Infinity":19,"s:75:4:75:Infinity":20,"b:75:32:75:62:75:62:75:67":6,"s:76:4:76:Infinity":21,"s:80:16:82:Infinity":22,"f:81:12:81:13":4,"s:81:13:81:50":23,"b:81:20:81:42:81:42:81:49":7,"f:82:10:82:11":5,"s:82:20:82:61":24,"s:84:22:84:Infinity":25,"s:86:2:99:Infinity":26,"s:88:4:88:Infinity":27,"f:88:15:88:16":6,"s:88:25:88:66":28,"s:89:20:89:Infinity":29,"s:90:4:90:Infinity":30,"s:92:4:98:Infinity":31,"b:92:29:92:58:92:58:92:62":8,"s:93:12:93:Infinity":32,"b:93:22:93:50:93:50:93:55":9,"s:94:6:94:Infinity":33,"b:95:6:97:Infinity:undefined:undefined:undefined:undefined":10,"s:95:6:97:Infinity":34,"s:96:8:96:Infinity":35,"b:102:2:108:Infinity:undefined:undefined:undefined:undefined":11,"s:102:2:108:Infinity":36,"s:103:21:103:Infinity":37,"f:103:40:103:41":7,"s:103:47:103:51":38,"s:104:22:106:Infinity":39,"f:105:14:105:15":8,"s:105:21:105:40":40,"f:106:12:106:13":9,"s:106:22:106:63":41,"s:107:4:107:Infinity":42,"s:110:2:110:Infinity":43,"f:113:9:113:16":10,"s:114:2:114:Infinity":44,"b:114:33:114:57:114:57:114:Infinity":12,"f:132:16:132:Infinity":11,"b:136:2:136:Infinity:undefined:undefined:undefined:undefined":13,"s:136:2:136:Infinity":45,"s:136:27:136:Infinity":46,"s:138:19:138:Infinity":47,"f:138:38:138:39":12,"s:138:45:138:49":48,"s:141:20:141:Infinity":49,"s:142:2:142:Infinity":50,"s:142:26:142:Infinity":51,"s:143:2:146:Infinity":52,"b:144:4:144:Infinity:undefined:undefined:undefined:undefined":14,"s:144:4:144:Infinity":53,"b:144:8:144:39:144:39:144:77":15,"s:144:77:144:Infinity":54,"s:145:4:145:Infinity":55,"s:149:21:149:Infinity":56,"s:150:19:150:Infinity":57,"f:152:11:152:24":13,"b:153:4:153:Infinity:undefined:undefined:undefined:undefined":16,"s:153:4:153:Infinity":58,"s:153:28:153:Infinity":59,"b:154:4:154:Infinity:undefined:undefined:undefined:undefined":17,"s:154:4:154:Infinity":60,"s:154:26:154:Infinity":61,"s:156:4:156:Infinity":62,"s:157:17:157:Infinity":63,"b:157:17:157:38:157:38:157:Infinity":18,"s:158:19:158:Infinity":64,"s:159:4:166:Infinity":65,"s:160:16:160:Infinity":66,"b:161:6:164:Infinity:undefined:undefined:undefined:undefined":19,"s:161:6:164:Infinity":67,"s:162:8:162:Infinity":68,"s:163:8:163:Infinity":69,"s:165:6:165:Infinity":70,"s:167:4:167:Infinity":71,"s:168:4:168:Infinity":72,"s:169:4:169:Infinity":73,"s:173:22:173:Infinity":74,"s:174:2:177:Infinity":75,"s:175:14:175:Infinity":76,"b:176:4:176:Infinity:undefined:undefined:undefined:undefined":20,"s:176:4:176:Infinity":77,"s:176:16:176:Infinity":78,"s:180:20:180:Infinity":79,"s:181:2:186:Infinity":80,"s:182:14:182:Infinity":81,"s:183:18:183:Infinity":82,"b:183:40:183:44:183:44:183:Infinity":21,"b:183:18:183:31:183:31:183:40":22,"b:184:4:184:Infinity:undefined:undefined:undefined:undefined":23,"s:184:4:184:Infinity":83,"s:184:31:184:Infinity":84,"s:185:4:185:Infinity":85,"s:189:39:189:Infinity":86,"s:190:23:190:Infinity":87,"f:190:50:190:51":14,"s:190:60:190:65":88,"s:191:2:195:Infinity":89,"s:192:24:192:Infinity":90,"s:193:4:193:Infinity":91,"f:193:21:193:22":15,"s:193:31:193:72":92,"s:194:4:194:Infinity":93,"s:197:2:197:Infinity":94}}} +,"/Users/lukasmay/development/projects/codewalk-district/src/container.ts": {"path":"/Users/lukasmay/development/projects/codewalk-district/src/container.ts","statementMap":{"0":{"start":{"line":80,"column":2},"end":{"line":92,"column":null}},"1":{"start":{"line":135,"column":8},"end":{"line":135,"column":null}},"2":{"start":{"line":138,"column":19},"end":{"line":138,"column":null}},"3":{"start":{"line":139,"column":8},"end":{"line":139,"column":null}},"4":{"start":{"line":140,"column":25},"end":{"line":140,"column":null}},"5":{"start":{"line":141,"column":21},"end":{"line":141,"column":null}},"6":{"start":{"line":144,"column":8},"end":{"line":144,"column":null}},"7":{"start":{"line":145,"column":2},"end":{"line":145,"column":null}},"8":{"start":{"line":146,"column":2},"end":{"line":146,"column":null}},"9":{"start":{"line":149,"column":16},"end":{"line":149,"column":null}},"10":{"start":{"line":150,"column":2},"end":{"line":150,"column":null}},"11":{"start":{"line":153,"column":8},"end":{"line":153,"column":null}},"12":{"start":{"line":154,"column":2},"end":{"line":154,"column":null}},"13":{"start":{"line":157,"column":28},"end":{"line":157,"column":null}},"14":{"start":{"line":158,"column":2},"end":{"line":158,"column":null}},"15":{"start":{"line":161,"column":23},"end":{"line":174,"column":null}},"16":{"start":{"line":175,"column":2},"end":{"line":175,"column":null}},"17":{"start":{"line":178,"column":2},"end":{"line":178,"column":null}},"18":{"start":{"line":179,"column":2},"end":{"line":179,"column":null}},"19":{"start":{"line":182,"column":24},"end":{"line":182,"column":null}},"20":{"start":{"line":183,"column":2},"end":{"line":183,"column":null}},"21":{"start":{"line":186,"column":26},"end":{"line":193,"column":null}},"22":{"start":{"line":194,"column":31},"end":{"line":203,"column":null}},"23":{"start":{"line":204,"column":2},"end":{"line":204,"column":null}},"24":{"start":{"line":207,"column":36},"end":{"line":212,"column":null}},"25":{"start":{"line":215,"column":32},"end":{"line":225,"column":null}},"26":{"start":{"line":226,"column":2},"end":{"line":226,"column":null}},"27":{"start":{"line":227,"column":2},"end":{"line":227,"column":null}},"28":{"start":{"line":230,"column":25},"end":{"line":234,"column":null}},"29":{"start":{"line":235,"column":2},"end":{"line":235,"column":null}},"30":{"start":{"line":237,"column":2},"end":{"line":265,"column":null}},"31":{"start":{"line":253,"column":6},"end":{"line":263,"column":null}}},"fnMap":{"0":{"name":"createRepositories","decl":{"start":{"line":79,"column":16},"end":{"line":79,"column":35}},"loc":{"start":{"line":79,"column":70},"end":{"line":93,"column":null}},"line":79},"1":{"name":"createContainer","decl":{"start":{"line":134,"column":22},"end":{"line":134,"column":38}},"loc":{"start":{"line":134,"column":86},"end":{"line":266,"column":null}},"line":134},"2":{"name":"(anonymous_2)","decl":{"start":{"line":252,"column":4},"end":{"line":252,"column":39}},"loc":{"start":{"line":252,"column":39},"end":{"line":264,"column":null}},"line":252}},"branchMap":{"0":{"loc":{"start":{"line":153,"column":8},"end":{"line":153,"column":null}},"type":"binary-expr","locations":[{"start":{"line":153,"column":8},"end":{"line":153,"column":60}},{"start":{"line":153,"column":60},"end":{"line":153,"column":null}}],"line":153},"1":{"loc":{"start":{"line":173,"column":4},"end":{"line":173,"column":null}},"type":"binary-expr","locations":[{"start":{"line":173,"column":4},"end":{"line":173,"column":22}},{"start":{"line":173,"column":22},"end":{"line":173,"column":null}}],"line":173}},"s":{"0":80,"1":0,"2":0,"3":0,"4":0,"5":0,"6":0,"7":0,"8":0,"9":0,"10":0,"11":0,"12":0,"13":0,"14":0,"15":0,"16":0,"17":0,"18":0,"19":0,"20":0,"21":0,"22":0,"23":0,"24":0,"25":0,"26":0,"27":0,"28":0,"29":0,"30":0,"31":0},"f":{"0":80,"1":0,"2":0},"b":{"0":[0,0],"1":[0,0]},"meta":{"lastBranch":2,"lastFunction":3,"lastStatement":32,"seen":{"f:79:16:79:35":0,"s:80:2:92:Infinity":0,"f:134:22:134:38":1,"s:135:8:135:Infinity":1,"s:138:19:138:Infinity":2,"s:139:8:139:Infinity":3,"s:140:25:140:Infinity":4,"s:141:21:141:Infinity":5,"s:144:8:144:Infinity":6,"s:145:2:145:Infinity":7,"s:146:2:146:Infinity":8,"s:149:16:149:Infinity":9,"s:150:2:150:Infinity":10,"s:153:8:153:Infinity":11,"b:153:8:153:60:153:60:153:Infinity":0,"s:154:2:154:Infinity":12,"s:157:28:157:Infinity":13,"s:158:2:158:Infinity":14,"s:161:23:174:Infinity":15,"b:173:4:173:22:173:22:173:Infinity":1,"s:175:2:175:Infinity":16,"s:178:2:178:Infinity":17,"s:179:2:179:Infinity":18,"s:182:24:182:Infinity":19,"s:183:2:183:Infinity":20,"s:186:26:193:Infinity":21,"s:194:31:203:Infinity":22,"s:204:2:204:Infinity":23,"s:207:36:212:Infinity":24,"s:215:32:225:Infinity":25,"s:226:2:226:Infinity":26,"s:227:2:227:Infinity":27,"s:230:25:234:Infinity":28,"s:235:2:235:Infinity":29,"s:237:2:265:Infinity":30,"f:252:4:252:39":2,"s:253:6:263:Infinity":31}}} +,"/Users/lukasmay/development/projects/codewalk-district/src/agent/alias.ts": {"path":"/Users/lukasmay/development/projects/codewalk-district/src/agent/alias.ts","statementMap":{"0":{"start":{"line":11,"column":20},"end":{"line":11,"column":null}},"1":{"start":{"line":20,"column":2},"end":{"line":31,"column":null}},"2":{"start":{"line":20,"column":15},"end":{"line":20,"column":18}},"3":{"start":{"line":21,"column":10},"end":{"line":25,"column":null}},"4":{"start":{"line":27,"column":21},"end":{"line":27,"column":null}},"5":{"start":{"line":28,"column":4},"end":{"line":30,"column":null}},"6":{"start":{"line":29,"column":6},"end":{"line":29,"column":null}},"7":{"start":{"line":33,"column":2},"end":{"line":33,"column":null}}},"fnMap":{"0":{"name":"generateUniqueAlias","decl":{"start":{"line":19,"column":22},"end":{"line":19,"column":42}},"loc":{"start":{"line":19,"column":88},"end":{"line":34,"column":null}},"line":19}},"branchMap":{"0":{"loc":{"start":{"line":28,"column":4},"end":{"line":30,"column":null}},"type":"if","locations":[{"start":{"line":28,"column":4},"end":{"line":30,"column":null}},{"start":{},"end":{}}],"line":28}},"s":{"0":15,"1":0,"2":0,"3":0,"4":0,"5":0,"6":0,"7":0},"f":{"0":0},"b":{"0":[0,0]},"meta":{"lastBranch":1,"lastFunction":1,"lastStatement":8,"seen":{"s:11:20:11:Infinity":0,"f:19:22:19:42":0,"s:20:2:31:Infinity":1,"s:20:15:20:18":2,"s:21:10:25:Infinity":3,"s:27:21:27:Infinity":4,"b:28:4:30:Infinity:undefined:undefined:undefined:undefined":0,"s:28:4:30:Infinity":5,"s:29:6:29:Infinity":6,"s:33:2:33:Infinity":7}}} +,"/Users/lukasmay/development/projects/codewalk-district/src/agent/cleanup-manager.ts": {"path":"/Users/lukasmay/development/projects/codewalk-district/src/agent/cleanup-manager.ts","statementMap":{"0":{"start":{"line":26,"column":6},"end":{"line":26,"column":null}},"1":{"start":{"line":27,"column":6},"end":{"line":27,"column":null}},"2":{"start":{"line":31,"column":12},"end":{"line":31,"column":null}},"3":{"start":{"line":32,"column":12},"end":{"line":32,"column":null}},"4":{"start":{"line":33,"column":12},"end":{"line":33,"column":null}},"5":{"start":{"line":34,"column":12},"end":{"line":34,"column":null}},"6":{"start":{"line":35,"column":12},"end":{"line":35,"column":29}},"7":{"start":{"line":36,"column":12},"end":{"line":36,"column":null}},"8":{"start":{"line":43,"column":4},"end":{"line":43,"column":null}},"9":{"start":{"line":51,"column":17},"end":{"line":51,"column":null}},"10":{"start":{"line":52,"column":10},"end":{"line":52,"column":null}},"11":{"start":{"line":53,"column":4},"end":{"line":55,"column":null}},"12":{"start":{"line":54,"column":6},"end":{"line":54,"column":null}},"13":{"start":{"line":56,"column":4},"end":{"line":56,"column":null}},"14":{"start":{"line":64,"column":25},"end":{"line":64,"column":null}},"15":{"start":{"line":66,"column":4},"end":{"line":70,"column":null}},"16":{"start":{"line":67,"column":6},"end":{"line":67,"column":null}},"17":{"start":{"line":69,"column":6},"end":{"line":69,"column":null}},"18":{"start":{"line":72,"column":4},"end":{"line":90,"column":null}},"19":{"start":{"line":73,"column":23},"end":{"line":73,"column":null}},"20":{"start":{"line":74,"column":6},"end":{"line":82,"column":null}},"21":{"start":{"line":75,"column":8},"end":{"line":81,"column":null}},"22":{"start":{"line":76,"column":16},"end":{"line":76,"column":null}},"23":{"start":{"line":77,"column":21},"end":{"line":77,"column":null}},"24":{"start":{"line":78,"column":10},"end":{"line":78,"column":null}},"25":{"start":{"line":80,"column":10},"end":{"line":80,"column":null}},"26":{"start":{"line":84,"column":6},"end":{"line":89,"column":null}},"27":{"start":{"line":85,"column":19},"end":{"line":85,"column":null}},"28":{"start":{"line":86,"column":8},"end":{"line":86,"column":null}},"29":{"start":{"line":88,"column":8},"end":{"line":88,"column":null}},"30":{"start":{"line":92,"column":4},"end":{"line":92,"column":null}},"31":{"start":{"line":93,"column":4},"end":{"line":93,"column":null}},"32":{"start":{"line":100,"column":23},"end":{"line":100,"column":null}},"33":{"start":{"line":101,"column":32},"end":{"line":101,"column":null}},"34":{"start":{"line":103,"column":4},"end":{"line":110,"column":null}},"35":{"start":{"line":104,"column":23},"end":{"line":104,"column":null}},"36":{"start":{"line":105,"column":6},"end":{"line":107,"column":null}},"37":{"start":{"line":106,"column":8},"end":{"line":106,"column":null}},"38":{"start":{"line":109,"column":6},"end":{"line":109,"column":null}},"39":{"start":{"line":112,"column":4},"end":{"line":118,"column":null}},"40":{"start":{"line":113,"column":6},"end":{"line":117,"column":null}},"41":{"start":{"line":114,"column":8},"end":{"line":114,"column":null}},"42":{"start":{"line":125,"column":10},"end":{"line":125,"column":null}},"43":{"start":{"line":126,"column":4},"end":{"line":126,"column":null}},"44":{"start":{"line":133,"column":32},"end":{"line":133,"column":null}},"45":{"start":{"line":135,"column":4},"end":{"line":142,"column":null}},"46":{"start":{"line":136,"column":23},"end":{"line":136,"column":null}},"47":{"start":{"line":137,"column":6},"end":{"line":139,"column":null}},"48":{"start":{"line":138,"column":8},"end":{"line":138,"column":null}},"49":{"start":{"line":141,"column":6},"end":{"line":141,"column":null}},"50":{"start":{"line":144,"column":4},"end":{"line":150,"column":null}},"51":{"start":{"line":145,"column":6},"end":{"line":149,"column":null}},"52":{"start":{"line":146,"column":8},"end":{"line":146,"column":null}},"53":{"start":{"line":148,"column":8},"end":{"line":148,"column":null}},"54":{"start":{"line":157,"column":10},"end":{"line":157,"column":null}},"55":{"start":{"line":159,"column":4},"end":{"line":163,"column":null}},"56":{"start":{"line":160,"column":6},"end":{"line":160,"column":null}},"57":{"start":{"line":162,"column":6},"end":{"line":162,"column":null}},"58":{"start":{"line":165,"column":19},"end":{"line":165,"column":null}},"59":{"start":{"line":166,"column":25},"end":{"line":166,"column":null}},"60":{"start":{"line":166,"column":49},"end":{"line":166,"column":55}},"61":{"start":{"line":168,"column":4},"end":{"line":177,"column":null}},"62":{"start":{"line":169,"column":6},"end":{"line":176,"column":null}},"63":{"start":{"line":170,"column":8},"end":{"line":170,"column":null}},"64":{"start":{"line":171,"column":8},"end":{"line":175,"column":null}},"65":{"start":{"line":172,"column":10},"end":{"line":172,"column":null}},"66":{"start":{"line":174,"column":10},"end":{"line":174,"column":null}},"67":{"start":{"line":179,"column":4},"end":{"line":181,"column":null}},"68":{"start":{"line":180,"column":6},"end":{"line":180,"column":null}},"69":{"start":{"line":183,"column":10},"end":{"line":183,"column":null}},"70":{"start":{"line":184,"column":4},"end":{"line":191,"column":null}},"71":{"start":{"line":185,"column":23},"end":{"line":185,"column":null}},"72":{"start":{"line":186,"column":6},"end":{"line":190,"column":null}},"73":{"start":{"line":187,"column":8},"end":{"line":189,"column":null}},"74":{"start":{"line":188,"column":10},"end":{"line":188,"column":null}},"75":{"start":{"line":198,"column":10},"end":{"line":198,"column":null}},"76":{"start":{"line":200,"column":4},"end":{"line":204,"column":null}},"77":{"start":{"line":201,"column":6},"end":{"line":201,"column":null}},"78":{"start":{"line":203,"column":6},"end":{"line":203,"column":null}},"79":{"start":{"line":206,"column":19},"end":{"line":206,"column":null}},"80":{"start":{"line":207,"column":23},"end":{"line":207,"column":null}},"81":{"start":{"line":207,"column":47},"end":{"line":207,"column":53}},"82":{"start":{"line":209,"column":4},"end":{"line":218,"column":null}},"83":{"start":{"line":210,"column":6},"end":{"line":217,"column":null}},"84":{"start":{"line":211,"column":8},"end":{"line":211,"column":null}},"85":{"start":{"line":212,"column":8},"end":{"line":216,"column":null}},"86":{"start":{"line":213,"column":10},"end":{"line":213,"column":null}},"87":{"start":{"line":215,"column":10},"end":{"line":215,"column":null}},"88":{"start":{"line":226,"column":25},"end":{"line":226,"column":null}},"89":{"start":{"line":228,"column":4},"end":{"line":232,"column":null}},"90":{"start":{"line":229,"column":6},"end":{"line":229,"column":null}},"91":{"start":{"line":231,"column":6},"end":{"line":231,"column":null}},"92":{"start":{"line":234,"column":63},"end":{"line":234,"column":null}},"93":{"start":{"line":236,"column":4},"end":{"line":243,"column":null}},"94":{"start":{"line":237,"column":23},"end":{"line":237,"column":null}},"95":{"start":{"line":238,"column":6},"end":{"line":240,"column":null}},"96":{"start":{"line":239,"column":8},"end":{"line":239,"column":null}},"97":{"start":{"line":242,"column":6},"end":{"line":242,"column":null}},"98":{"start":{"line":245,"column":28},"end":{"line":245,"column":null}},"99":{"start":{"line":246,"column":4},"end":{"line":253,"column":null}},"100":{"start":{"line":247,"column":6},"end":{"line":252,"column":null}},"101":{"start":{"line":248,"column":27},"end":{"line":248,"column":null}},"102":{"start":{"line":249,"column":8},"end":{"line":249,"column":null}},"103":{"start":{"line":249,"column":38},"end":{"line":249,"column":null}},"104":{"start":{"line":251,"column":8},"end":{"line":251,"column":null}},"105":{"start":{"line":254,"column":4},"end":{"line":254,"column":null}},"106":{"start":{"line":261,"column":18},"end":{"line":261,"column":null}},"107":{"start":{"line":262,"column":4},"end":{"line":264,"column":null}},"108":{"start":{"line":263,"column":6},"end":{"line":263,"column":null}},"109":{"start":{"line":265,"column":4},"end":{"line":265,"column":null}},"110":{"start":{"line":272,"column":25},"end":{"line":272,"column":null}},"111":{"start":{"line":273,"column":10},"end":{"line":273,"column":null}},"112":{"start":{"line":274,"column":10},"end":{"line":274,"column":null}},"113":{"start":{"line":275,"column":10},"end":{"line":275,"column":null}},"114":{"start":{"line":277,"column":4},"end":{"line":285,"column":null}},"115":{"start":{"line":278,"column":6},"end":{"line":282,"column":null}},"116":{"start":{"line":279,"column":8},"end":{"line":279,"column":null}},"117":{"start":{"line":280,"column":8},"end":{"line":280,"column":null}},"118":{"start":{"line":281,"column":8},"end":{"line":281,"column":null}},"119":{"start":{"line":284,"column":6},"end":{"line":284,"column":null}},"120":{"start":{"line":287,"column":4},"end":{"line":295,"column":null}},"121":{"start":{"line":288,"column":6},"end":{"line":292,"column":null}},"122":{"start":{"line":289,"column":8},"end":{"line":289,"column":null}},"123":{"start":{"line":290,"column":8},"end":{"line":290,"column":null}},"124":{"start":{"line":291,"column":8},"end":{"line":291,"column":null}},"125":{"start":{"line":294,"column":6},"end":{"line":294,"column":null}},"126":{"start":{"line":307,"column":25},"end":{"line":307,"column":null}},"127":{"start":{"line":310,"column":4},"end":{"line":312,"column":null}},"128":{"start":{"line":311,"column":6},"end":{"line":311,"column":null}},"129":{"start":{"line":314,"column":18},"end":{"line":314,"column":null}},"130":{"start":{"line":315,"column":4},"end":{"line":317,"column":null}},"131":{"start":{"line":316,"column":6},"end":{"line":316,"column":null}},"132":{"start":{"line":319,"column":4},"end":{"line":321,"column":null}},"133":{"start":{"line":320,"column":6},"end":{"line":320,"column":null}},"134":{"start":{"line":323,"column":4},"end":{"line":327,"column":null}},"135":{"start":{"line":324,"column":6},"end":{"line":324,"column":null}},"136":{"start":{"line":326,"column":6},"end":{"line":326,"column":null}},"137":{"start":{"line":329,"column":4},"end":{"line":333,"column":null}},"138":{"start":{"line":330,"column":6},"end":{"line":330,"column":null}},"139":{"start":{"line":332,"column":6},"end":{"line":332,"column":null}},"140":{"start":{"line":335,"column":4},"end":{"line":335,"column":null}},"141":{"start":{"line":336,"column":4},"end":{"line":336,"column":null}},"142":{"start":{"line":364,"column":26},"end":{"line":364,"column":null}},"143":{"start":{"line":365,"column":4},"end":{"line":365,"column":null}},"144":{"start":{"line":367,"column":4},"end":{"line":468,"column":null}},"145":{"start":{"line":368,"column":20},"end":{"line":368,"column":null}},"146":{"start":{"line":369,"column":6},"end":{"line":369,"column":null}},"147":{"start":{"line":371,"column":6},"end":{"line":467,"column":null}},"148":{"start":{"line":372,"column":8},"end":{"line":372,"column":null}},"149":{"start":{"line":374,"column":14},"end":{"line":374,"column":null}},"150":{"start":{"line":375,"column":23},"end":{"line":384,"column":null}},"151":{"start":{"line":379,"column":30},"end":{"line":379,"column":null}},"152":{"start":{"line":382,"column":27},"end":{"line":382,"column":null}},"153":{"start":{"line":386,"column":8},"end":{"line":388,"column":null}},"154":{"start":{"line":387,"column":10},"end":{"line":387,"column":null}},"155":{"start":{"line":390,"column":20},"end":{"line":390,"column":null}},"156":{"start":{"line":393,"column":28},"end":{"line":393,"column":null}},"157":{"start":{"line":395,"column":8},"end":{"line":401,"column":null}},"158":{"start":{"line":403,"column":8},"end":{"line":403,"column":null}},"159":{"start":{"line":404,"column":6},"end":{"line":467,"column":null}},"160":{"start":{"line":407,"column":29},"end":{"line":407,"column":null}},"161":{"start":{"line":408,"column":31},"end":{"line":408,"column":null}},"162":{"start":{"line":410,"column":8},"end":{"line":427,"column":null}},"163":{"start":{"line":411,"column":10},"end":{"line":411,"column":null}},"164":{"start":{"line":412,"column":10},"end":{"line":426,"column":null}},"165":{"start":{"line":413,"column":18},"end":{"line":413,"column":null}},"166":{"start":{"line":414,"column":34},"end":{"line":414,"column":null}},"167":{"start":{"line":415,"column":18},"end":{"line":415,"column":null}},"168":{"start":{"line":416,"column":12},"end":{"line":419,"column":null}},"169":{"start":{"line":417,"column":14},"end":{"line":417,"column":null}},"170":{"start":{"line":418,"column":14},"end":{"line":418,"column":null}},"171":{"start":{"line":421,"column":12},"end":{"line":424,"column":null}},"172":{"start":{"line":429,"column":8},"end":{"line":459,"column":null}},"173":{"start":{"line":430,"column":28},"end":{"line":430,"column":null}},"174":{"start":{"line":431,"column":10},"end":{"line":453,"column":null}},"175":{"start":{"line":432,"column":18},"end":{"line":432,"column":null}},"176":{"start":{"line":433,"column":12},"end":{"line":452,"column":null}},"177":{"start":{"line":435,"column":42},"end":{"line":435,"column":null}},"178":{"start":{"line":436,"column":14},"end":{"line":451,"column":null}},"179":{"start":{"line":437,"column":16},"end":{"line":437,"column":null}},"180":{"start":{"line":438,"column":16},"end":{"line":450,"column":null}},"181":{"start":{"line":439,"column":18},"end":{"line":439,"column":null}},"182":{"start":{"line":440,"column":18},"end":{"line":440,"column":null}},"183":{"start":{"line":442,"column":18},"end":{"line":445,"column":null}},"184":{"start":{"line":447,"column":18},"end":{"line":447,"column":null}},"185":{"start":{"line":448,"column":18},"end":{"line":448,"column":null}},"186":{"start":{"line":449,"column":18},"end":{"line":449,"column":null}},"187":{"start":{"line":455,"column":10},"end":{"line":458,"column":null}},"188":{"start":{"line":460,"column":8},"end":{"line":460,"column":null}},"189":{"start":{"line":461,"column":8},"end":{"line":461,"column":null}},"190":{"start":{"line":462,"column":8},"end":{"line":462,"column":null}},"191":{"start":{"line":464,"column":8},"end":{"line":464,"column":null}},"192":{"start":{"line":465,"column":8},"end":{"line":465,"column":null}},"193":{"start":{"line":466,"column":8},"end":{"line":466,"column":null}},"194":{"start":{"line":470,"column":4},"end":{"line":474,"column":null}},"195":{"start":{"line":471,"column":6},"end":{"line":471,"column":null}},"196":{"start":{"line":473,"column":6},"end":{"line":473,"column":null}},"197":{"start":{"line":475,"column":4},"end":{"line":479,"column":null}},"198":{"start":{"line":476,"column":6},"end":{"line":476,"column":null}},"199":{"start":{"line":478,"column":6},"end":{"line":478,"column":null}},"200":{"start":{"line":487,"column":4},"end":{"line":502,"column":null}},"201":{"start":{"line":488,"column":20},"end":{"line":488,"column":null}},"202":{"start":{"line":489,"column":6},"end":{"line":501,"column":null}},"203":{"start":{"line":490,"column":8},"end":{"line":500,"column":null}},"204":{"start":{"line":491,"column":25},"end":{"line":491,"column":null}},"205":{"start":{"line":493,"column":10},"end":{"line":495,"column":null}},"206":{"start":{"line":494,"column":12},"end":{"line":494,"column":null}},"207":{"start":{"line":497,"column":10},"end":{"line":499,"column":null}},"208":{"start":{"line":498,"column":12},"end":{"line":498,"column":null}},"209":{"start":{"line":503,"column":4},"end":{"line":503,"column":null}},"210":{"start":{"line":510,"column":4},"end":{"line":522,"column":null}},"211":{"start":{"line":511,"column":39},"end":{"line":520,"column":null}},"212":{"start":{"line":521,"column":6},"end":{"line":521,"column":null}}},"fnMap":{"0":{"name":"(anonymous_0)","decl":{"start":{"line":30,"column":2},"end":{"line":30,"column":null}},"loc":{"start":{"line":37,"column":4},"end":{"line":37,"column":null}},"line":37},"1":{"name":"(anonymous_1)","decl":{"start":{"line":42,"column":10},"end":{"line":42,"column":26}},"loc":{"start":{"line":42,"column":49},"end":{"line":44,"column":null}},"line":42},"2":{"name":"(anonymous_2)","decl":{"start":{"line":50,"column":10},"end":{"line":50,"column":26}},"loc":{"start":{"line":50,"column":54},"end":{"line":57,"column":null}},"line":50},"3":{"name":"(anonymous_3)","decl":{"start":{"line":63,"column":8},"end":{"line":63,"column":29}},"loc":{"start":{"line":63,"column":88},"end":{"line":94,"column":null}},"line":63},"4":{"name":"(anonymous_4)","decl":{"start":{"line":99,"column":8},"end":{"line":99,"column":28}},"loc":{"start":{"line":99,"column":87},"end":{"line":119,"column":null}},"line":99},"5":{"name":"(anonymous_5)","decl":{"start":{"line":124,"column":8},"end":{"line":124,"column":24}},"loc":{"start":{"line":124,"column":58},"end":{"line":127,"column":null}},"line":124},"6":{"name":"(anonymous_6)","decl":{"start":{"line":132,"column":8},"end":{"line":132,"column":23}},"loc":{"start":{"line":132,"column":67},"end":{"line":151,"column":null}},"line":132},"7":{"name":"(anonymous_7)","decl":{"start":{"line":156,"column":8},"end":{"line":156,"column":49}},"loc":{"start":{"line":156,"column":49},"end":{"line":192,"column":null}},"line":156},"8":{"name":"(anonymous_8)","decl":{"start":{"line":166,"column":44},"end":{"line":166,"column":49}},"loc":{"start":{"line":166,"column":49},"end":{"line":166,"column":55}},"line":166},"9":{"name":"(anonymous_9)","decl":{"start":{"line":197,"column":8},"end":{"line":197,"column":45}},"loc":{"start":{"line":197,"column":45},"end":{"line":219,"column":null}},"line":197},"10":{"name":"(anonymous_10)","decl":{"start":{"line":207,"column":42},"end":{"line":207,"column":47}},"loc":{"start":{"line":207,"column":47},"end":{"line":207,"column":53}},"line":207},"11":{"name":"(anonymous_11)","decl":{"start":{"line":225,"column":8},"end":{"line":225,"column":30}},"loc":{"start":{"line":225,"column":93},"end":{"line":255,"column":null}},"line":225},"12":{"name":"(anonymous_12)","decl":{"start":{"line":260,"column":8},"end":{"line":260,"column":23}},"loc":{"start":{"line":260,"column":85},"end":{"line":266,"column":null}},"line":260},"13":{"name":"(anonymous_13)","decl":{"start":{"line":271,"column":8},"end":{"line":271,"column":24}},"loc":{"start":{"line":271,"column":71},"end":{"line":296,"column":null}},"line":271},"14":{"name":"(anonymous_14)","decl":{"start":{"line":302,"column":8},"end":{"line":302,"column":null}},"loc":{"start":{"line":306,"column":51},"end":{"line":337,"column":null}},"line":306},"15":{"name":"(anonymous_15)","decl":{"start":{"line":351,"column":8},"end":{"line":351,"column":null}},"loc":{"start":{"line":363,"column":19},"end":{"line":480,"column":null}},"line":363},"16":{"name":"(anonymous_16)","decl":{"start":{"line":379,"column":19},"end":{"line":379,"column":20}},"loc":{"start":{"line":379,"column":30},"end":{"line":379,"column":null}},"line":379},"17":{"name":"(anonymous_17)","decl":{"start":{"line":382,"column":14},"end":{"line":382,"column":15}},"loc":{"start":{"line":382,"column":27},"end":{"line":382,"column":null}},"line":382},"18":{"name":"(anonymous_18)","decl":{"start":{"line":386,"column":29},"end":{"line":386,"column":30}},"loc":{"start":{"line":386,"column":38},"end":{"line":388,"column":9}},"line":386},"19":{"name":"(anonymous_19)","decl":{"start":{"line":486,"column":10},"end":{"line":486,"column":35}},"loc":{"start":{"line":486,"column":63},"end":{"line":504,"column":null}},"line":486},"20":{"name":"(anonymous_20)","decl":{"start":{"line":509,"column":10},"end":{"line":509,"column":22}},"loc":{"start":{"line":509,"column":103},"end":{"line":523,"column":null}},"line":509}},"branchMap":{"0":{"loc":{"start":{"line":35,"column":12},"end":{"line":35,"column":null}},"type":"default-arg","locations":[{"start":{"line":35,"column":29},"end":{"line":35,"column":null}}],"line":35},"1":{"loc":{"start":{"line":53,"column":4},"end":{"line":55,"column":null}},"type":"if","locations":[{"start":{"line":53,"column":4},"end":{"line":55,"column":null}},{"start":{},"end":{}}],"line":53},"2":{"loc":{"start":{"line":53,"column":8},"end":{"line":53,"column":91}},"type":"binary-expr","locations":[{"start":{"line":53,"column":8},"end":{"line":53,"column":52}},{"start":{"line":53,"column":47},"end":{"line":53,"column":91}}],"line":53},"3":{"loc":{"start":{"line":72,"column":4},"end":{"line":90,"column":null}},"type":"if","locations":[{"start":{"line":72,"column":4},"end":{"line":90,"column":null}},{"start":{"line":83,"column":11},"end":{"line":90,"column":null}}],"line":72},"4":{"loc":{"start":{"line":80,"column":56},"end":{"line":80,"column":105}},"type":"cond-expr","locations":[{"start":{"line":80,"column":79},"end":{"line":80,"column":93}},{"start":{"line":80,"column":93},"end":{"line":80,"column":105}}],"line":80},"5":{"loc":{"start":{"line":88,"column":31},"end":{"line":88,"column":80}},"type":"cond-expr","locations":[{"start":{"line":88,"column":54},"end":{"line":88,"column":68}},{"start":{"line":88,"column":68},"end":{"line":88,"column":80}}],"line":88},"6":{"loc":{"start":{"line":103,"column":4},"end":{"line":110,"column":null}},"type":"if","locations":[{"start":{"line":103,"column":4},"end":{"line":110,"column":null}},{"start":{"line":108,"column":11},"end":{"line":110,"column":null}}],"line":103},"7":{"loc":{"start":{"line":135,"column":4},"end":{"line":142,"column":null}},"type":"if","locations":[{"start":{"line":135,"column":4},"end":{"line":142,"column":null}},{"start":{"line":140,"column":11},"end":{"line":142,"column":null}}],"line":135},"8":{"loc":{"start":{"line":148,"column":34},"end":{"line":148,"column":83}},"type":"cond-expr","locations":[{"start":{"line":148,"column":57},"end":{"line":148,"column":71}},{"start":{"line":148,"column":71},"end":{"line":148,"column":83}}],"line":148},"9":{"loc":{"start":{"line":169,"column":6},"end":{"line":176,"column":null}},"type":"if","locations":[{"start":{"line":169,"column":6},"end":{"line":176,"column":null}},{"start":{},"end":{}}],"line":169},"10":{"loc":{"start":{"line":174,"column":41},"end":{"line":174,"column":90}},"type":"cond-expr","locations":[{"start":{"line":174,"column":64},"end":{"line":174,"column":78}},{"start":{"line":174,"column":78},"end":{"line":174,"column":90}}],"line":174},"11":{"loc":{"start":{"line":210,"column":6},"end":{"line":217,"column":null}},"type":"if","locations":[{"start":{"line":210,"column":6},"end":{"line":217,"column":null}},{"start":{},"end":{}}],"line":210},"12":{"loc":{"start":{"line":215,"column":41},"end":{"line":215,"column":90}},"type":"cond-expr","locations":[{"start":{"line":215,"column":64},"end":{"line":215,"column":78}},{"start":{"line":215,"column":78},"end":{"line":215,"column":90}}],"line":215},"13":{"loc":{"start":{"line":236,"column":4},"end":{"line":243,"column":null}},"type":"if","locations":[{"start":{"line":236,"column":4},"end":{"line":243,"column":null}},{"start":{"line":241,"column":11},"end":{"line":243,"column":null}}],"line":236},"14":{"loc":{"start":{"line":249,"column":8},"end":{"line":249,"column":null}},"type":"if","locations":[{"start":{"line":249,"column":8},"end":{"line":249,"column":null}},{"start":{},"end":{}}],"line":249},"15":{"loc":{"start":{"line":262,"column":4},"end":{"line":264,"column":null}},"type":"if","locations":[{"start":{"line":262,"column":4},"end":{"line":264,"column":null}},{"start":{},"end":{}}],"line":262},"16":{"loc":{"start":{"line":278,"column":6},"end":{"line":282,"column":null}},"type":"if","locations":[{"start":{"line":278,"column":6},"end":{"line":282,"column":null}},{"start":{},"end":{}}],"line":278},"17":{"loc":{"start":{"line":284,"column":29},"end":{"line":284,"column":78}},"type":"cond-expr","locations":[{"start":{"line":284,"column":52},"end":{"line":284,"column":66}},{"start":{"line":284,"column":66},"end":{"line":284,"column":78}}],"line":284},"18":{"loc":{"start":{"line":288,"column":6},"end":{"line":292,"column":null}},"type":"if","locations":[{"start":{"line":288,"column":6},"end":{"line":292,"column":null}},{"start":{},"end":{}}],"line":288},"19":{"loc":{"start":{"line":294,"column":31},"end":{"line":294,"column":80}},"type":"cond-expr","locations":[{"start":{"line":294,"column":54},"end":{"line":294,"column":68}},{"start":{"line":294,"column":68},"end":{"line":294,"column":80}}],"line":294},"20":{"loc":{"start":{"line":310,"column":4},"end":{"line":312,"column":null}},"type":"if","locations":[{"start":{"line":310,"column":4},"end":{"line":312,"column":null}},{"start":{},"end":{}}],"line":310},"21":{"loc":{"start":{"line":315,"column":4},"end":{"line":317,"column":null}},"type":"if","locations":[{"start":{"line":315,"column":4},"end":{"line":317,"column":null}},{"start":{},"end":{}}],"line":315},"22":{"loc":{"start":{"line":319,"column":4},"end":{"line":321,"column":null}},"type":"if","locations":[{"start":{"line":319,"column":4},"end":{"line":321,"column":null}},{"start":{},"end":{}}],"line":319},"23":{"loc":{"start":{"line":326,"column":38},"end":{"line":326,"column":87}},"type":"cond-expr","locations":[{"start":{"line":326,"column":61},"end":{"line":326,"column":75}},{"start":{"line":326,"column":75},"end":{"line":326,"column":87}}],"line":326},"24":{"loc":{"start":{"line":332,"column":31},"end":{"line":332,"column":80}},"type":"cond-expr","locations":[{"start":{"line":332,"column":54},"end":{"line":332,"column":68}},{"start":{"line":332,"column":68},"end":{"line":332,"column":80}}],"line":332},"25":{"loc":{"start":{"line":368,"column":20},"end":{"line":368,"column":null}},"type":"cond-expr","locations":[{"start":{"line":368,"column":26},"end":{"line":368,"column":56}},{"start":{"line":368,"column":56},"end":{"line":368,"column":null}}],"line":368},"26":{"loc":{"start":{"line":371,"column":6},"end":{"line":467,"column":null}},"type":"if","locations":[{"start":{"line":371,"column":6},"end":{"line":467,"column":null}},{"start":{"line":404,"column":6},"end":{"line":467,"column":null}}],"line":371},"27":{"loc":{"start":{"line":371,"column":10},"end":{"line":371,"column":41}},"type":"binary-expr","locations":[{"start":{"line":371,"column":10},"end":{"line":371,"column":19}},{"start":{"line":371,"column":19},"end":{"line":371,"column":41}}],"line":371},"28":{"loc":{"start":{"line":381,"column":24},"end":{"line":383,"column":null}},"type":"cond-expr","locations":[{"start":{"line":382,"column":14},"end":{"line":382,"column":null}},{"start":{"line":383,"column":14},"end":{"line":383,"column":null}}],"line":381},"29":{"loc":{"start":{"line":387,"column":45},"end":{"line":387,"column":94}},"type":"cond-expr","locations":[{"start":{"line":387,"column":68},"end":{"line":387,"column":82}},{"start":{"line":387,"column":82},"end":{"line":387,"column":94}}],"line":387},"30":{"loc":{"start":{"line":404,"column":6},"end":{"line":467,"column":null}},"type":"if","locations":[{"start":{"line":404,"column":6},"end":{"line":467,"column":null}},{"start":{"line":463,"column":13},"end":{"line":467,"column":null}}],"line":404},"31":{"loc":{"start":{"line":408,"column":31},"end":{"line":408,"column":null}},"type":"cond-expr","locations":[{"start":{"line":408,"column":52},"end":{"line":408,"column":104}},{"start":{"line":408,"column":104},"end":{"line":408,"column":null}}],"line":408},"32":{"loc":{"start":{"line":410,"column":8},"end":{"line":427,"column":null}},"type":"if","locations":[{"start":{"line":410,"column":8},"end":{"line":427,"column":null}},{"start":{},"end":{}}],"line":410},"33":{"loc":{"start":{"line":416,"column":12},"end":{"line":419,"column":null}},"type":"if","locations":[{"start":{"line":416,"column":12},"end":{"line":419,"column":null}},{"start":{},"end":{}}],"line":416},"34":{"loc":{"start":{"line":423,"column":19},"end":{"line":423,"column":null}},"type":"cond-expr","locations":[{"start":{"line":423,"column":42},"end":{"line":423,"column":56}},{"start":{"line":423,"column":56},"end":{"line":423,"column":null}}],"line":423},"35":{"loc":{"start":{"line":431,"column":10},"end":{"line":453,"column":null}},"type":"if","locations":[{"start":{"line":431,"column":10},"end":{"line":453,"column":null}},{"start":{},"end":{}}],"line":431},"36":{"loc":{"start":{"line":433,"column":12},"end":{"line":452,"column":null}},"type":"if","locations":[{"start":{"line":433,"column":12},"end":{"line":452,"column":null}},{"start":{},"end":{}}],"line":433},"37":{"loc":{"start":{"line":436,"column":14},"end":{"line":451,"column":null}},"type":"if","locations":[{"start":{"line":436,"column":14},"end":{"line":451,"column":null}},{"start":{},"end":{}}],"line":436},"38":{"loc":{"start":{"line":444,"column":25},"end":{"line":444,"column":null}},"type":"cond-expr","locations":[{"start":{"line":444,"column":48},"end":{"line":444,"column":62}},{"start":{"line":444,"column":62},"end":{"line":444,"column":null}}],"line":444},"39":{"loc":{"start":{"line":448,"column":71},"end":{"line":448,"column":119}},"type":"cond-expr","locations":[{"start":{"line":448,"column":94},"end":{"line":448,"column":108}},{"start":{"line":448,"column":108},"end":{"line":448,"column":119}}],"line":448},"40":{"loc":{"start":{"line":457,"column":17},"end":{"line":457,"column":null}},"type":"cond-expr","locations":[{"start":{"line":457,"column":44},"end":{"line":457,"column":62}},{"start":{"line":457,"column":62},"end":{"line":457,"column":null}}],"line":457},"41":{"loc":{"start":{"line":473,"column":22},"end":{"line":473,"column":71}},"type":"cond-expr","locations":[{"start":{"line":473,"column":45},"end":{"line":473,"column":59}},{"start":{"line":473,"column":59},"end":{"line":473,"column":71}}],"line":473},"42":{"loc":{"start":{"line":478,"column":22},"end":{"line":478,"column":71}},"type":"cond-expr","locations":[{"start":{"line":478,"column":45},"end":{"line":478,"column":59}},{"start":{"line":478,"column":59},"end":{"line":478,"column":71}}],"line":478},"43":{"loc":{"start":{"line":493,"column":10},"end":{"line":495,"column":null}},"type":"if","locations":[{"start":{"line":493,"column":10},"end":{"line":495,"column":null}},{"start":{},"end":{}}],"line":493},"44":{"loc":{"start":{"line":493,"column":14},"end":{"line":493,"column":72}},"type":"binary-expr","locations":[{"start":{"line":493,"column":14},"end":{"line":493,"column":42}},{"start":{"line":493,"column":42},"end":{"line":493,"column":72}}],"line":493},"45":{"loc":{"start":{"line":497,"column":10},"end":{"line":499,"column":null}},"type":"if","locations":[{"start":{"line":497,"column":10},"end":{"line":499,"column":null}},{"start":{},"end":{}}],"line":497},"46":{"loc":{"start":{"line":497,"column":14},"end":{"line":497,"column":73}},"type":"binary-expr","locations":[{"start":{"line":497,"column":14},"end":{"line":497,"column":42}},{"start":{"line":497,"column":42},"end":{"line":497,"column":73}}],"line":497},"47":{"loc":{"start":{"line":510,"column":4},"end":{"line":522,"column":null}},"type":"if","locations":[{"start":{"line":510,"column":4},"end":{"line":522,"column":null}},{"start":{},"end":{}}],"line":510},"48":{"loc":{"start":{"line":517,"column":18},"end":{"line":517,"column":null}},"type":"binary-expr","locations":[{"start":{"line":517,"column":18},"end":{"line":517,"column":34}},{"start":{"line":517,"column":34},"end":{"line":517,"column":null}}],"line":517}},"s":{"0":15,"1":15,"2":23,"3":23,"4":23,"5":23,"6":23,"7":23,"8":3,"9":0,"10":0,"11":0,"12":0,"13":0,"14":3,"15":3,"16":3,"17":3,"18":0,"19":0,"20":0,"21":0,"22":0,"23":0,"24":0,"25":0,"26":0,"27":0,"28":0,"29":0,"30":0,"31":0,"32":3,"33":3,"34":3,"35":0,"36":0,"37":0,"38":3,"39":3,"40":3,"41":3,"42":3,"43":3,"44":0,"45":0,"46":0,"47":0,"48":0,"49":0,"50":0,"51":0,"52":0,"53":0,"54":0,"55":0,"56":0,"57":0,"58":0,"59":0,"60":0,"61":0,"62":0,"63":0,"64":0,"65":0,"66":0,"67":0,"68":0,"69":0,"70":0,"71":0,"72":0,"73":0,"74":0,"75":0,"76":0,"77":0,"78":0,"79":0,"80":0,"81":0,"82":0,"83":0,"84":0,"85":0,"86":0,"87":0,"88":0,"89":0,"90":0,"91":0,"92":0,"93":0,"94":0,"95":0,"96":0,"97":0,"98":0,"99":0,"100":0,"101":0,"102":0,"103":0,"104":0,"105":0,"106":0,"107":0,"108":0,"109":0,"110":0,"111":0,"112":0,"113":0,"114":0,"115":0,"116":0,"117":0,"118":0,"119":0,"120":0,"121":0,"122":0,"123":0,"124":0,"125":0,"126":0,"127":0,"128":0,"129":0,"130":0,"131":0,"132":0,"133":0,"134":0,"135":0,"136":0,"137":0,"138":0,"139":0,"140":0,"141":0,"142":0,"143":0,"144":0,"145":0,"146":0,"147":0,"148":0,"149":0,"150":0,"151":0,"152":0,"153":0,"154":0,"155":0,"156":0,"157":0,"158":0,"159":0,"160":0,"161":0,"162":0,"163":0,"164":0,"165":0,"166":0,"167":0,"168":0,"169":0,"170":0,"171":0,"172":0,"173":0,"174":0,"175":0,"176":0,"177":0,"178":0,"179":0,"180":0,"181":0,"182":0,"183":0,"184":0,"185":0,"186":0,"187":0,"188":0,"189":0,"190":0,"191":0,"192":0,"193":0,"194":0,"195":0,"196":0,"197":0,"198":0,"199":0,"200":0,"201":0,"202":0,"203":0,"204":0,"205":0,"206":0,"207":0,"208":0,"209":0,"210":0,"211":0,"212":0},"f":{"0":23,"1":3,"2":0,"3":3,"4":3,"5":3,"6":0,"7":0,"8":0,"9":0,"10":0,"11":0,"12":0,"13":0,"14":0,"15":0,"16":0,"17":0,"18":0,"19":0,"20":0},"b":{"0":[23],"1":[0,0],"2":[0,0],"3":[0,0],"4":[0,0],"5":[0,0],"6":[0,3],"7":[0,0],"8":[0,0],"9":[0,0],"10":[0,0],"11":[0,0],"12":[0,0],"13":[0,0],"14":[0,0],"15":[0,0],"16":[0,0],"17":[0,0],"18":[0,0],"19":[0,0],"20":[0,0],"21":[0,0],"22":[0,0],"23":[0,0],"24":[0,0],"25":[0,0],"26":[0,0],"27":[0,0],"28":[0,0],"29":[0,0],"30":[0,0],"31":[0,0],"32":[0,0],"33":[0,0],"34":[0,0],"35":[0,0],"36":[0,0],"37":[0,0],"38":[0,0],"39":[0,0],"40":[0,0],"41":[0,0],"42":[0,0],"43":[0,0],"44":[0,0],"45":[0,0],"46":[0,0],"47":[0,0],"48":[0,0]},"meta":{"lastBranch":49,"lastFunction":21,"lastStatement":213,"seen":{"s:26:6:26:Infinity":0,"s:27:6:27:Infinity":1,"f:30:2:30:Infinity":0,"b:35:29:35:Infinity":0,"s:31:12:31:Infinity":2,"s:32:12:32:Infinity":3,"s:33:12:33:Infinity":4,"s:34:12:34:Infinity":5,"s:35:12:35:29":6,"s:36:12:36:Infinity":7,"f:42:10:42:26":1,"s:43:4:43:Infinity":8,"f:50:10:50:26":2,"s:51:17:51:Infinity":9,"s:52:10:52:Infinity":10,"b:53:4:55:Infinity:undefined:undefined:undefined:undefined":1,"s:53:4:55:Infinity":11,"b:53:8:53:52:53:47:53:91":2,"s:54:6:54:Infinity":12,"s:56:4:56:Infinity":13,"f:63:8:63:29":3,"s:64:25:64:Infinity":14,"s:66:4:70:Infinity":15,"s:67:6:67:Infinity":16,"s:69:6:69:Infinity":17,"b:72:4:90:Infinity:83:11:90:Infinity":3,"s:72:4:90:Infinity":18,"s:73:23:73:Infinity":19,"s:74:6:82:Infinity":20,"s:75:8:81:Infinity":21,"s:76:16:76:Infinity":22,"s:77:21:77:Infinity":23,"s:78:10:78:Infinity":24,"s:80:10:80:Infinity":25,"b:80:79:80:93:80:93:80:105":4,"s:84:6:89:Infinity":26,"s:85:19:85:Infinity":27,"s:86:8:86:Infinity":28,"s:88:8:88:Infinity":29,"b:88:54:88:68:88:68:88:80":5,"s:92:4:92:Infinity":30,"s:93:4:93:Infinity":31,"f:99:8:99:28":4,"s:100:23:100:Infinity":32,"s:101:32:101:Infinity":33,"b:103:4:110:Infinity:108:11:110:Infinity":6,"s:103:4:110:Infinity":34,"s:104:23:104:Infinity":35,"s:105:6:107:Infinity":36,"s:106:8:106:Infinity":37,"s:109:6:109:Infinity":38,"s:112:4:118:Infinity":39,"s:113:6:117:Infinity":40,"s:114:8:114:Infinity":41,"f:124:8:124:24":5,"s:125:10:125:Infinity":42,"s:126:4:126:Infinity":43,"f:132:8:132:23":6,"s:133:32:133:Infinity":44,"b:135:4:142:Infinity:140:11:142:Infinity":7,"s:135:4:142:Infinity":45,"s:136:23:136:Infinity":46,"s:137:6:139:Infinity":47,"s:138:8:138:Infinity":48,"s:141:6:141:Infinity":49,"s:144:4:150:Infinity":50,"s:145:6:149:Infinity":51,"s:146:8:146:Infinity":52,"s:148:8:148:Infinity":53,"b:148:57:148:71:148:71:148:83":8,"f:156:8:156:49":7,"s:157:10:157:Infinity":54,"s:159:4:163:Infinity":55,"s:160:6:160:Infinity":56,"s:162:6:162:Infinity":57,"s:165:19:165:Infinity":58,"s:166:25:166:Infinity":59,"f:166:44:166:49":8,"s:166:49:166:55":60,"s:168:4:177:Infinity":61,"b:169:6:176:Infinity:undefined:undefined:undefined:undefined":9,"s:169:6:176:Infinity":62,"s:170:8:170:Infinity":63,"s:171:8:175:Infinity":64,"s:172:10:172:Infinity":65,"s:174:10:174:Infinity":66,"b:174:64:174:78:174:78:174:90":10,"s:179:4:181:Infinity":67,"s:180:6:180:Infinity":68,"s:183:10:183:Infinity":69,"s:184:4:191:Infinity":70,"s:185:23:185:Infinity":71,"s:186:6:190:Infinity":72,"s:187:8:189:Infinity":73,"s:188:10:188:Infinity":74,"f:197:8:197:45":9,"s:198:10:198:Infinity":75,"s:200:4:204:Infinity":76,"s:201:6:201:Infinity":77,"s:203:6:203:Infinity":78,"s:206:19:206:Infinity":79,"s:207:23:207:Infinity":80,"f:207:42:207:47":10,"s:207:47:207:53":81,"s:209:4:218:Infinity":82,"b:210:6:217:Infinity:undefined:undefined:undefined:undefined":11,"s:210:6:217:Infinity":83,"s:211:8:211:Infinity":84,"s:212:8:216:Infinity":85,"s:213:10:213:Infinity":86,"s:215:10:215:Infinity":87,"b:215:64:215:78:215:78:215:90":12,"f:225:8:225:30":11,"s:226:25:226:Infinity":88,"s:228:4:232:Infinity":89,"s:229:6:229:Infinity":90,"s:231:6:231:Infinity":91,"s:234:63:234:Infinity":92,"b:236:4:243:Infinity:241:11:243:Infinity":13,"s:236:4:243:Infinity":93,"s:237:23:237:Infinity":94,"s:238:6:240:Infinity":95,"s:239:8:239:Infinity":96,"s:242:6:242:Infinity":97,"s:245:28:245:Infinity":98,"s:246:4:253:Infinity":99,"s:247:6:252:Infinity":100,"s:248:27:248:Infinity":101,"b:249:8:249:Infinity:undefined:undefined:undefined:undefined":14,"s:249:8:249:Infinity":102,"s:249:38:249:Infinity":103,"s:251:8:251:Infinity":104,"s:254:4:254:Infinity":105,"f:260:8:260:23":12,"s:261:18:261:Infinity":106,"b:262:4:264:Infinity:undefined:undefined:undefined:undefined":15,"s:262:4:264:Infinity":107,"s:263:6:263:Infinity":108,"s:265:4:265:Infinity":109,"f:271:8:271:24":13,"s:272:25:272:Infinity":110,"s:273:10:273:Infinity":111,"s:274:10:274:Infinity":112,"s:275:10:275:Infinity":113,"s:277:4:285:Infinity":114,"b:278:6:282:Infinity:undefined:undefined:undefined:undefined":16,"s:278:6:282:Infinity":115,"s:279:8:279:Infinity":116,"s:280:8:280:Infinity":117,"s:281:8:281:Infinity":118,"s:284:6:284:Infinity":119,"b:284:52:284:66:284:66:284:78":17,"s:287:4:295:Infinity":120,"b:288:6:292:Infinity:undefined:undefined:undefined:undefined":18,"s:288:6:292:Infinity":121,"s:289:8:289:Infinity":122,"s:290:8:290:Infinity":123,"s:291:8:291:Infinity":124,"s:294:6:294:Infinity":125,"b:294:54:294:68:294:68:294:80":19,"f:302:8:302:Infinity":14,"s:307:25:307:Infinity":126,"b:310:4:312:Infinity:undefined:undefined:undefined:undefined":20,"s:310:4:312:Infinity":127,"s:311:6:311:Infinity":128,"s:314:18:314:Infinity":129,"b:315:4:317:Infinity:undefined:undefined:undefined:undefined":21,"s:315:4:317:Infinity":130,"s:316:6:316:Infinity":131,"b:319:4:321:Infinity:undefined:undefined:undefined:undefined":22,"s:319:4:321:Infinity":132,"s:320:6:320:Infinity":133,"s:323:4:327:Infinity":134,"s:324:6:324:Infinity":135,"s:326:6:326:Infinity":136,"b:326:61:326:75:326:75:326:87":23,"s:329:4:333:Infinity":137,"s:330:6:330:Infinity":138,"s:332:6:332:Infinity":139,"b:332:54:332:68:332:68:332:80":24,"s:335:4:335:Infinity":140,"s:336:4:336:Infinity":141,"f:351:8:351:Infinity":15,"s:364:26:364:Infinity":142,"s:365:4:365:Infinity":143,"s:367:4:468:Infinity":144,"s:368:20:368:Infinity":145,"b:368:26:368:56:368:56:368:Infinity":25,"s:369:6:369:Infinity":146,"b:371:6:467:Infinity:404:6:467:Infinity":26,"s:371:6:467:Infinity":147,"b:371:10:371:19:371:19:371:41":27,"s:372:8:372:Infinity":148,"s:374:14:374:Infinity":149,"s:375:23:384:Infinity":150,"f:379:19:379:20":16,"s:379:30:379:Infinity":151,"b:382:14:382:Infinity:383:14:383:Infinity":28,"f:382:14:382:15":17,"s:382:27:382:Infinity":152,"s:386:8:388:Infinity":153,"f:386:29:386:30":18,"s:387:10:387:Infinity":154,"b:387:68:387:82:387:82:387:94":29,"s:390:20:390:Infinity":155,"s:393:28:393:Infinity":156,"s:395:8:401:Infinity":157,"s:403:8:403:Infinity":158,"b:404:6:467:Infinity:463:13:467:Infinity":30,"s:404:6:467:Infinity":159,"s:407:29:407:Infinity":160,"s:408:31:408:Infinity":161,"b:408:52:408:104:408:104:408:Infinity":31,"b:410:8:427:Infinity:undefined:undefined:undefined:undefined":32,"s:410:8:427:Infinity":162,"s:411:10:411:Infinity":163,"s:412:10:426:Infinity":164,"s:413:18:413:Infinity":165,"s:414:34:414:Infinity":166,"s:415:18:415:Infinity":167,"b:416:12:419:Infinity:undefined:undefined:undefined:undefined":33,"s:416:12:419:Infinity":168,"s:417:14:417:Infinity":169,"s:418:14:418:Infinity":170,"s:421:12:424:Infinity":171,"b:423:42:423:56:423:56:423:Infinity":34,"s:429:8:459:Infinity":172,"s:430:28:430:Infinity":173,"b:431:10:453:Infinity:undefined:undefined:undefined:undefined":35,"s:431:10:453:Infinity":174,"s:432:18:432:Infinity":175,"b:433:12:452:Infinity:undefined:undefined:undefined:undefined":36,"s:433:12:452:Infinity":176,"s:435:42:435:Infinity":177,"b:436:14:451:Infinity:undefined:undefined:undefined:undefined":37,"s:436:14:451:Infinity":178,"s:437:16:437:Infinity":179,"s:438:16:450:Infinity":180,"s:439:18:439:Infinity":181,"s:440:18:440:Infinity":182,"s:442:18:445:Infinity":183,"b:444:48:444:62:444:62:444:Infinity":38,"s:447:18:447:Infinity":184,"s:448:18:448:Infinity":185,"b:448:94:448:108:448:108:448:119":39,"s:449:18:449:Infinity":186,"s:455:10:458:Infinity":187,"b:457:44:457:62:457:62:457:Infinity":40,"s:460:8:460:Infinity":188,"s:461:8:461:Infinity":189,"s:462:8:462:Infinity":190,"s:464:8:464:Infinity":191,"s:465:8:465:Infinity":192,"s:466:8:466:Infinity":193,"s:470:4:474:Infinity":194,"s:471:6:471:Infinity":195,"s:473:6:473:Infinity":196,"b:473:45:473:59:473:59:473:71":41,"s:475:4:479:Infinity":197,"s:476:6:476:Infinity":198,"s:478:6:478:Infinity":199,"b:478:45:478:59:478:59:478:71":42,"f:486:10:486:35":19,"s:487:4:502:Infinity":200,"s:488:20:488:Infinity":201,"s:489:6:501:Infinity":202,"s:490:8:500:Infinity":203,"s:491:25:491:Infinity":204,"b:493:10:495:Infinity:undefined:undefined:undefined:undefined":43,"s:493:10:495:Infinity":205,"b:493:14:493:42:493:42:493:72":44,"s:494:12:494:Infinity":206,"b:497:10:499:Infinity:undefined:undefined:undefined:undefined":45,"s:497:10:499:Infinity":207,"b:497:14:497:42:497:42:497:73":46,"s:498:12:498:Infinity":208,"s:503:4:503:Infinity":209,"f:509:10:509:22":20,"b:510:4:522:Infinity:undefined:undefined:undefined:undefined":47,"s:510:4:522:Infinity":210,"s:511:39:520:Infinity":211,"b:517:18:517:34:517:34:517:Infinity":48,"s:521:6:521:Infinity":212}}} +,"/Users/lukasmay/development/projects/codewalk-district/src/agent/content-serializer.ts": {"path":"/Users/lukasmay/development/projects/codewalk-district/src/agent/content-serializer.ts","statementMap":{"0":{"start":{"line":28,"column":23},"end":{"line":43,"column":null}},"1":{"start":{"line":34,"column":4},"end":{"line":36,"column":null}},"2":{"start":{"line":40,"column":20},"end":{"line":40,"column":null}},"3":{"start":{"line":41,"column":4},"end":{"line":41,"column":null}},"4":{"start":{"line":45,"column":39},"end":{"line":45,"column":null}},"5":{"start":{"line":48,"column":2},"end":{"line":52,"column":null}},"6":{"start":{"line":49,"column":4},"end":{"line":51,"column":null}},"7":{"start":{"line":53,"column":2},"end":{"line":53,"column":null}},"8":{"start":{"line":60,"column":2},"end":{"line":60,"column":null}},"9":{"start":{"line":60,"column":41},"end":{"line":60,"column":null}},"10":{"start":{"line":62,"column":14},"end":{"line":62,"column":null}},"11":{"start":{"line":63,"column":2},"end":{"line":63,"column":null}},"12":{"start":{"line":63,"column":57},"end":{"line":63,"column":null}},"13":{"start":{"line":65,"column":2},"end":{"line":65,"column":null}},"14":{"start":{"line":75,"column":2},"end":{"line":75,"column":null}},"15":{"start":{"line":75,"column":26},"end":{"line":75,"column":null}},"16":{"start":{"line":78,"column":22},"end":{"line":78,"column":null}},"17":{"start":{"line":79,"column":2},"end":{"line":85,"column":null}},"18":{"start":{"line":80,"column":22},"end":{"line":80,"column":null}},"19":{"start":{"line":81,"column":4},"end":{"line":83,"column":null}},"20":{"start":{"line":82,"column":6},"end":{"line":82,"column":null}},"21":{"start":{"line":84,"column":4},"end":{"line":84,"column":null}},"22":{"start":{"line":88,"column":2},"end":{"line":90,"column":null}},"23":{"start":{"line":89,"column":4},"end":{"line":89,"column":null}},"24":{"start":{"line":89,"column":28},"end":{"line":89,"column":53}},"25":{"start":{"line":93,"column":29},"end":{"line":93,"column":null}},"26":{"start":{"line":96,"column":25},"end":{"line":96,"column":null}},"27":{"start":{"line":97,"column":18},"end":{"line":97,"column":null}},"28":{"start":{"line":99,"column":4},"end":{"line":109,"column":null}},"29":{"start":{"line":100,"column":6},"end":{"line":108,"column":null}},"30":{"start":{"line":101,"column":23},"end":{"line":101,"column":null}},"31":{"start":{"line":102,"column":19},"end":{"line":102,"column":null}},"32":{"start":{"line":103,"column":8},"end":{"line":105,"column":null}},"33":{"start":{"line":104,"column":10},"end":{"line":104,"column":null}},"34":{"start":{"line":111,"column":4},"end":{"line":111,"column":null}},"35":{"start":{"line":113,"column":21},"end":{"line":113,"column":null}},"36":{"start":{"line":114,"column":4},"end":{"line":116,"column":null}},"37":{"start":{"line":115,"column":6},"end":{"line":115,"column":null}},"38":{"start":{"line":120,"column":16},"end":{"line":120,"column":null}},"39":{"start":{"line":121,"column":2},"end":{"line":123,"column":null}},"40":{"start":{"line":122,"column":4},"end":{"line":122,"column":null}},"41":{"start":{"line":125,"column":2},"end":{"line":125,"column":null}}},"fnMap":{"0":{"name":"(anonymous_0)","decl":{"start":{"line":33,"column":2},"end":{"line":33,"column":18}},"loc":{"start":{"line":33,"column":18},"end":{"line":37,"column":null}},"line":33},"1":{"name":"(anonymous_1)","decl":{"start":{"line":39,"column":2},"end":{"line":39,"column":17}},"loc":{"start":{"line":39,"column":36},"end":{"line":42,"column":null}},"line":39},"2":{"name":"getManager","decl":{"start":{"line":47,"column":9},"end":{"line":47,"column":39}},"loc":{"start":{"line":47,"column":39},"end":{"line":54,"column":null}},"line":47},"3":{"name":"tiptapJsonToMarkdown","decl":{"start":{"line":59,"column":16},"end":{"line":59,"column":37}},"loc":{"start":{"line":59,"column":60},"end":{"line":66,"column":null}},"line":59},"4":{"name":"serializePageTree","decl":{"start":{"line":74,"column":16},"end":{"line":74,"column":34}},"loc":{"start":{"line":74,"column":73},"end":{"line":126,"column":null}},"line":74},"5":{"name":"(anonymous_5)","decl":{"start":{"line":89,"column":18},"end":{"line":89,"column":19}},"loc":{"start":{"line":89,"column":28},"end":{"line":89,"column":53}},"line":89},"6":{"name":"renderPage","decl":{"start":{"line":95,"column":11},"end":{"line":95,"column":22}},"loc":{"start":{"line":95,"column":71},"end":{"line":117,"column":null}},"line":95}},"branchMap":{"0":{"loc":{"start":{"line":40,"column":20},"end":{"line":40,"column":null}},"type":"binary-expr","locations":[{"start":{"line":40,"column":20},"end":{"line":40,"column":53}},{"start":{"line":40,"column":53},"end":{"line":40,"column":null}}],"line":40},"1":{"loc":{"start":{"line":48,"column":2},"end":{"line":52,"column":null}},"type":"if","locations":[{"start":{"line":48,"column":2},"end":{"line":52,"column":null}},{"start":{},"end":{}}],"line":48},"2":{"loc":{"start":{"line":60,"column":2},"end":{"line":60,"column":null}},"type":"if","locations":[{"start":{"line":60,"column":2},"end":{"line":60,"column":null}},{"start":{},"end":{}}],"line":60},"3":{"loc":{"start":{"line":60,"column":6},"end":{"line":60,"column":41}},"type":"binary-expr","locations":[{"start":{"line":60,"column":6},"end":{"line":60,"column":15}},{"start":{"line":60,"column":15},"end":{"line":60,"column":41}}],"line":60},"4":{"loc":{"start":{"line":63,"column":2},"end":{"line":63,"column":null}},"type":"if","locations":[{"start":{"line":63,"column":2},"end":{"line":63,"column":null}},{"start":{},"end":{}}],"line":63},"5":{"loc":{"start":{"line":63,"column":6},"end":{"line":63,"column":57}},"type":"binary-expr","locations":[{"start":{"line":63,"column":6},"end":{"line":63,"column":28}},{"start":{"line":63,"column":28},"end":{"line":63,"column":57}}],"line":63},"6":{"loc":{"start":{"line":75,"column":2},"end":{"line":75,"column":null}},"type":"if","locations":[{"start":{"line":75,"column":2},"end":{"line":75,"column":null}},{"start":{},"end":{}}],"line":75},"7":{"loc":{"start":{"line":81,"column":4},"end":{"line":83,"column":null}},"type":"if","locations":[{"start":{"line":81,"column":4},"end":{"line":83,"column":null}},{"start":{},"end":{}}],"line":81},"8":{"loc":{"start":{"line":99,"column":4},"end":{"line":109,"column":null}},"type":"if","locations":[{"start":{"line":99,"column":4},"end":{"line":109,"column":null}},{"start":{},"end":{}}],"line":99},"9":{"loc":{"start":{"line":103,"column":8},"end":{"line":105,"column":null}},"type":"if","locations":[{"start":{"line":103,"column":8},"end":{"line":105,"column":null}},{"start":{},"end":{}}],"line":103},"10":{"loc":{"start":{"line":113,"column":21},"end":{"line":113,"column":null}},"type":"binary-expr","locations":[{"start":{"line":113,"column":21},"end":{"line":113,"column":49}},{"start":{"line":113,"column":49},"end":{"line":113,"column":null}}],"line":113},"11":{"loc":{"start":{"line":120,"column":16},"end":{"line":120,"column":null}},"type":"binary-expr","locations":[{"start":{"line":120,"column":16},"end":{"line":120,"column":41}},{"start":{"line":120,"column":41},"end":{"line":120,"column":null}}],"line":120}},"s":{"0":21,"1":0,"2":0,"3":0,"4":21,"5":0,"6":0,"7":0,"8":0,"9":0,"10":0,"11":0,"12":0,"13":0,"14":0,"15":0,"16":0,"17":0,"18":0,"19":0,"20":0,"21":0,"22":0,"23":0,"24":0,"25":0,"26":0,"27":0,"28":0,"29":0,"30":0,"31":0,"32":0,"33":0,"34":0,"35":0,"36":0,"37":0,"38":0,"39":0,"40":0,"41":0},"f":{"0":0,"1":0,"2":0,"3":0,"4":0,"5":0,"6":0},"b":{"0":[0,0],"1":[0,0],"2":[0,0],"3":[0,0],"4":[0,0],"5":[0,0],"6":[0,0],"7":[0,0],"8":[0,0],"9":[0,0],"10":[0,0],"11":[0,0]},"meta":{"lastBranch":12,"lastFunction":7,"lastStatement":42,"seen":{"s:28:23:43:Infinity":0,"f:33:2:33:18":0,"s:34:4:36:Infinity":1,"f:39:2:39:17":1,"s:40:20:40:Infinity":2,"b:40:20:40:53:40:53:40:Infinity":0,"s:41:4:41:Infinity":3,"s:45:39:45:Infinity":4,"f:47:9:47:39":2,"b:48:2:52:Infinity:undefined:undefined:undefined:undefined":1,"s:48:2:52:Infinity":5,"s:49:4:51:Infinity":6,"s:53:2:53:Infinity":7,"f:59:16:59:37":3,"b:60:2:60:Infinity:undefined:undefined:undefined:undefined":2,"s:60:2:60:Infinity":8,"b:60:6:60:15:60:15:60:41":3,"s:60:41:60:Infinity":9,"s:62:14:62:Infinity":10,"b:63:2:63:Infinity:undefined:undefined:undefined:undefined":4,"s:63:2:63:Infinity":11,"b:63:6:63:28:63:28:63:57":5,"s:63:57:63:Infinity":12,"s:65:2:65:Infinity":13,"f:74:16:74:34":4,"b:75:2:75:Infinity:undefined:undefined:undefined:undefined":6,"s:75:2:75:Infinity":14,"s:75:26:75:Infinity":15,"s:78:22:78:Infinity":16,"s:79:2:85:Infinity":17,"s:80:22:80:Infinity":18,"b:81:4:83:Infinity:undefined:undefined:undefined:undefined":7,"s:81:4:83:Infinity":19,"s:82:6:82:Infinity":20,"s:84:4:84:Infinity":21,"s:88:2:90:Infinity":22,"s:89:4:89:Infinity":23,"f:89:18:89:19":5,"s:89:28:89:53":24,"s:93:29:93:Infinity":25,"f:95:11:95:22":6,"s:96:25:96:Infinity":26,"s:97:18:97:Infinity":27,"b:99:4:109:Infinity:undefined:undefined:undefined:undefined":8,"s:99:4:109:Infinity":28,"s:100:6:108:Infinity":29,"s:101:23:101:Infinity":30,"s:102:19:102:Infinity":31,"b:103:8:105:Infinity:undefined:undefined:undefined:undefined":9,"s:103:8:105:Infinity":32,"s:104:10:104:Infinity":33,"s:111:4:111:Infinity":34,"s:113:21:113:Infinity":35,"b:113:21:113:49:113:49:113:Infinity":10,"s:114:4:116:Infinity":36,"s:115:6:115:Infinity":37,"s:120:16:120:Infinity":38,"b:120:16:120:41:120:41:120:Infinity":11,"s:121:2:123:Infinity":39,"s:122:4:122:Infinity":40,"s:125:2:125:Infinity":41}}} +,"/Users/lukasmay/development/projects/codewalk-district/src/agent/credential-handler.ts": {"path":"/Users/lukasmay/development/projects/codewalk-district/src/agent/credential-handler.ts","statementMap":{"0":{"start":{"line":19,"column":6},"end":{"line":19,"column":null}},"1":{"start":{"line":22,"column":33},"end":{"line":22,"column":null}},"2":{"start":{"line":26,"column":12},"end":{"line":26,"column":null}},"3":{"start":{"line":27,"column":12},"end":{"line":27,"column":null}},"4":{"start":{"line":28,"column":12},"end":{"line":28,"column":null}},"5":{"start":{"line":37,"column":4},"end":{"line":37,"column":null}},"6":{"start":{"line":37,"column":33},"end":{"line":37,"column":null}},"7":{"start":{"line":39,"column":4},"end":{"line":39,"column":null}},"8":{"start":{"line":40,"column":20},"end":{"line":40,"column":null}},"9":{"start":{"line":41,"column":4},"end":{"line":41,"column":null}},"10":{"start":{"line":41,"column":18},"end":{"line":41,"column":null}},"11":{"start":{"line":43,"column":10},"end":{"line":43,"column":null}},"12":{"start":{"line":44,"column":4},"end":{"line":44,"column":null}},"13":{"start":{"line":46,"column":4},"end":{"line":46,"column":null}},"14":{"start":{"line":54,"column":4},"end":{"line":62,"column":null}},"15":{"start":{"line":55,"column":6},"end":{"line":58,"column":null}},"16":{"start":{"line":59,"column":6},"end":{"line":59,"column":null}},"17":{"start":{"line":61,"column":6},"end":{"line":61,"column":null}},"18":{"start":{"line":70,"column":4},"end":{"line":70,"column":null}},"19":{"start":{"line":70,"column":33},"end":{"line":70,"column":null}},"20":{"start":{"line":71,"column":4},"end":{"line":78,"column":null}},"21":{"start":{"line":72,"column":12},"end":{"line":72,"column":null}},"22":{"start":{"line":73,"column":12},"end":{"line":73,"column":null}},"23":{"start":{"line":74,"column":6},"end":{"line":74,"column":null}},"24":{"start":{"line":75,"column":6},"end":{"line":75,"column":null}},"25":{"start":{"line":77,"column":6},"end":{"line":77,"column":null}},"26":{"start":{"line":87,"column":4},"end":{"line":90,"column":null}},"27":{"start":{"line":88,"column":21},"end":{"line":88,"column":null}},"28":{"start":{"line":89,"column":6},"end":{"line":89,"column":null}},"29":{"start":{"line":91,"column":18},"end":{"line":91,"column":null}},"30":{"start":{"line":92,"column":4},"end":{"line":92,"column":null}},"31":{"start":{"line":101,"column":4},"end":{"line":109,"column":null}},"32":{"start":{"line":102,"column":12},"end":{"line":102,"column":null}},"33":{"start":{"line":103,"column":6},"end":{"line":103,"column":null}},"34":{"start":{"line":103,"column":33},"end":{"line":103,"column":null}},"35":{"start":{"line":104,"column":12},"end":{"line":104,"column":null}},"36":{"start":{"line":105,"column":21},"end":{"line":105,"column":null}},"37":{"start":{"line":106,"column":6},"end":{"line":106,"column":null}},"38":{"start":{"line":108,"column":6},"end":{"line":108,"column":null}},"39":{"start":{"line":122,"column":47},"end":{"line":122,"column":null}},"40":{"start":{"line":123,"column":42},"end":{"line":123,"column":null}},"41":{"start":{"line":125,"column":4},"end":{"line":146,"column":null}},"42":{"start":{"line":126,"column":6},"end":{"line":126,"column":null}},"43":{"start":{"line":127,"column":22},"end":{"line":127,"column":null}},"44":{"start":{"line":128,"column":6},"end":{"line":130,"column":null}},"45":{"start":{"line":129,"column":8},"end":{"line":129,"column":null}},"46":{"start":{"line":131,"column":6},"end":{"line":131,"column":null}},"47":{"start":{"line":133,"column":35},"end":{"line":133,"column":null}},"48":{"start":{"line":134,"column":6},"end":{"line":136,"column":null}},"49":{"start":{"line":135,"column":8},"end":{"line":135,"column":null}},"50":{"start":{"line":137,"column":6},"end":{"line":139,"column":null}},"51":{"start":{"line":138,"column":8},"end":{"line":138,"column":null}},"52":{"start":{"line":141,"column":26},"end":{"line":141,"column":null}},"53":{"start":{"line":142,"column":6},"end":{"line":145,"column":null}},"54":{"start":{"line":143,"column":8},"end":{"line":143,"column":null}},"55":{"start":{"line":144,"column":8},"end":{"line":144,"column":null}},"56":{"start":{"line":148,"column":4},"end":{"line":148,"column":null}},"57":{"start":{"line":155,"column":21},"end":{"line":162,"column":null}},"58":{"start":{"line":163,"column":18},"end":{"line":163,"column":null}},"59":{"start":{"line":164,"column":4},"end":{"line":164,"column":null}},"60":{"start":{"line":164,"column":32},"end":{"line":164,"column":49}},"61":{"start":{"line":176,"column":4},"end":{"line":176,"column":null}},"62":{"start":{"line":176,"column":33},"end":{"line":176,"column":null}},"63":{"start":{"line":178,"column":4},"end":{"line":178,"column":null}},"64":{"start":{"line":181,"column":27},"end":{"line":181,"column":null}},"65":{"start":{"line":182,"column":4},"end":{"line":182,"column":null}},"66":{"start":{"line":185,"column":24},"end":{"line":185,"column":null}},"67":{"start":{"line":186,"column":4},"end":{"line":189,"column":null}},"68":{"start":{"line":187,"column":6},"end":{"line":187,"column":null}},"69":{"start":{"line":188,"column":6},"end":{"line":188,"column":null}},"70":{"start":{"line":190,"column":4},"end":{"line":190,"column":null}},"71":{"start":{"line":193,"column":10},"end":{"line":193,"column":null}},"72":{"start":{"line":194,"column":4},"end":{"line":194,"column":null}},"73":{"start":{"line":195,"column":33},"end":{"line":195,"column":null}},"74":{"start":{"line":196,"column":4},"end":{"line":199,"column":null}},"75":{"start":{"line":197,"column":6},"end":{"line":197,"column":null}},"76":{"start":{"line":198,"column":6},"end":{"line":198,"column":null}},"77":{"start":{"line":200,"column":4},"end":{"line":202,"column":null}},"78":{"start":{"line":201,"column":6},"end":{"line":201,"column":null}},"79":{"start":{"line":204,"column":4},"end":{"line":204,"column":null}},"80":{"start":{"line":206,"column":4},"end":{"line":206,"column":null}}},"fnMap":{"0":{"name":"(anonymous_0)","decl":{"start":{"line":25,"column":2},"end":{"line":25,"column":null}},"loc":{"start":{"line":29,"column":4},"end":{"line":29,"column":null}},"line":29},"1":{"name":"(anonymous_1)","decl":{"start":{"line":36,"column":8},"end":{"line":36,"column":22}},"loc":{"start":{"line":36,"column":120},"end":{"line":47,"column":null}},"line":36},"2":{"name":"(anonymous_2)","decl":{"start":{"line":53,"column":2},"end":{"line":53,"column":25}},"loc":{"start":{"line":53,"column":68},"end":{"line":63,"column":null}},"line":53},"3":{"name":"(anonymous_3)","decl":{"start":{"line":69,"column":8},"end":{"line":69,"column":36}},"loc":{"start":{"line":69,"column":89},"end":{"line":79,"column":null}},"line":69},"4":{"name":"(anonymous_4)","decl":{"start":{"line":86,"column":8},"end":{"line":86,"column":26}},"loc":{"start":{"line":86,"column":114},"end":{"line":93,"column":null}},"line":86},"5":{"name":"(anonymous_5)","decl":{"start":{"line":100,"column":2},"end":{"line":100,"column":18}},"loc":{"start":{"line":100,"column":52},"end":{"line":110,"column":null}},"line":100},"6":{"name":"(anonymous_6)","decl":{"start":{"line":117,"column":8},"end":{"line":117,"column":null}},"loc":{"start":{"line":121,"column":86},"end":{"line":149,"column":null}},"line":121},"7":{"name":"(anonymous_7)","decl":{"start":{"line":154,"column":2},"end":{"line":154,"column":20}},"loc":{"start":{"line":154,"column":51},"end":{"line":165,"column":null}},"line":154},"8":{"name":"(anonymous_8)","decl":{"start":{"line":164,"column":25},"end":{"line":164,"column":26}},"loc":{"start":{"line":164,"column":32},"end":{"line":164,"column":49}},"line":164},"9":{"name":"(anonymous_9)","decl":{"start":{"line":172,"column":8},"end":{"line":172,"column":null}},"loc":{"start":{"line":175,"column":80},"end":{"line":207,"column":null}},"line":175}},"branchMap":{"0":{"loc":{"start":{"line":37,"column":4},"end":{"line":37,"column":null}},"type":"if","locations":[{"start":{"line":37,"column":4},"end":{"line":37,"column":null}},{"start":{},"end":{}}],"line":37},"1":{"loc":{"start":{"line":41,"column":4},"end":{"line":41,"column":null}},"type":"if","locations":[{"start":{"line":41,"column":4},"end":{"line":41,"column":null}},{"start":{},"end":{}}],"line":41},"2":{"loc":{"start":{"line":54,"column":4},"end":{"line":62,"column":null}},"type":"if","locations":[{"start":{"line":54,"column":4},"end":{"line":62,"column":null}},{"start":{"line":60,"column":11},"end":{"line":62,"column":null}}],"line":54},"3":{"loc":{"start":{"line":54,"column":8},"end":{"line":54,"column":51}},"type":"binary-expr","locations":[{"start":{"line":54,"column":8},"end":{"line":54,"column":30}},{"start":{"line":54,"column":30},"end":{"line":54,"column":51}}],"line":54},"4":{"loc":{"start":{"line":70,"column":4},"end":{"line":70,"column":null}},"type":"if","locations":[{"start":{"line":70,"column":4},"end":{"line":70,"column":null}},{"start":{},"end":{}}],"line":70},"5":{"loc":{"start":{"line":77,"column":33},"end":{"line":77,"column":82}},"type":"cond-expr","locations":[{"start":{"line":77,"column":56},"end":{"line":77,"column":70}},{"start":{"line":77,"column":70},"end":{"line":77,"column":82}}],"line":77},"6":{"loc":{"start":{"line":87,"column":4},"end":{"line":90,"column":null}},"type":"if","locations":[{"start":{"line":87,"column":4},"end":{"line":90,"column":null}},{"start":{},"end":{}}],"line":87},"7":{"loc":{"start":{"line":103,"column":6},"end":{"line":103,"column":null}},"type":"if","locations":[{"start":{"line":103,"column":6},"end":{"line":103,"column":null}},{"start":{},"end":{}}],"line":103},"8":{"loc":{"start":{"line":106,"column":13},"end":{"line":106,"column":null}},"type":"binary-expr","locations":[{"start":{"line":106,"column":13},"end":{"line":106,"column":50}},{"start":{"line":106,"column":50},"end":{"line":106,"column":null}}],"line":106},"9":{"loc":{"start":{"line":125,"column":4},"end":{"line":146,"column":null}},"type":"if","locations":[{"start":{"line":125,"column":4},"end":{"line":146,"column":null}},{"start":{},"end":{}}],"line":125},"10":{"loc":{"start":{"line":125,"column":8},"end":{"line":125,"column":70}},"type":"binary-expr","locations":[{"start":{"line":125,"column":8},"end":{"line":125,"column":21}},{"start":{"line":125,"column":21},"end":{"line":125,"column":46}},{"start":{"line":125,"column":46},"end":{"line":125,"column":70}}],"line":125},"11":{"loc":{"start":{"line":128,"column":6},"end":{"line":130,"column":null}},"type":"if","locations":[{"start":{"line":128,"column":6},"end":{"line":130,"column":null}},{"start":{},"end":{}}],"line":128},"12":{"loc":{"start":{"line":134,"column":6},"end":{"line":136,"column":null}},"type":"if","locations":[{"start":{"line":134,"column":6},"end":{"line":136,"column":null}},{"start":{},"end":{}}],"line":134},"13":{"loc":{"start":{"line":137,"column":6},"end":{"line":139,"column":null}},"type":"if","locations":[{"start":{"line":137,"column":6},"end":{"line":139,"column":null}},{"start":{},"end":{}}],"line":137},"14":{"loc":{"start":{"line":142,"column":6},"end":{"line":145,"column":null}},"type":"if","locations":[{"start":{"line":142,"column":6},"end":{"line":145,"column":null}},{"start":{},"end":{}}],"line":142},"15":{"loc":{"start":{"line":176,"column":4},"end":{"line":176,"column":null}},"type":"if","locations":[{"start":{"line":176,"column":4},"end":{"line":176,"column":null}},{"start":{},"end":{}}],"line":176},"16":{"loc":{"start":{"line":186,"column":4},"end":{"line":189,"column":null}},"type":"if","locations":[{"start":{"line":186,"column":4},"end":{"line":189,"column":null}},{"start":{},"end":{}}],"line":186},"17":{"loc":{"start":{"line":196,"column":4},"end":{"line":199,"column":null}},"type":"if","locations":[{"start":{"line":196,"column":4},"end":{"line":199,"column":null}},{"start":{},"end":{}}],"line":196},"18":{"loc":{"start":{"line":200,"column":4},"end":{"line":202,"column":null}},"type":"if","locations":[{"start":{"line":200,"column":4},"end":{"line":202,"column":null}},{"start":{},"end":{}}],"line":200}},"s":{"0":15,"1":15,"2":23,"3":23,"4":23,"5":8,"6":8,"7":0,"8":0,"9":0,"10":0,"11":0,"12":0,"13":0,"14":0,"15":0,"16":0,"17":0,"18":0,"19":0,"20":0,"21":0,"22":0,"23":0,"24":0,"25":0,"26":0,"27":0,"28":0,"29":0,"30":0,"31":0,"32":0,"33":0,"34":0,"35":0,"36":0,"37":0,"38":0,"39":10,"40":10,"41":10,"42":0,"43":0,"44":0,"45":0,"46":0,"47":0,"48":0,"49":0,"50":0,"51":0,"52":0,"53":0,"54":0,"55":0,"56":10,"57":0,"58":0,"59":0,"60":0,"61":0,"62":0,"63":0,"64":0,"65":0,"66":0,"67":0,"68":0,"69":0,"70":0,"71":0,"72":0,"73":0,"74":0,"75":0,"76":0,"77":0,"78":0,"79":0,"80":0},"f":{"0":23,"1":8,"2":0,"3":0,"4":0,"5":0,"6":10,"7":0,"8":0,"9":0},"b":{"0":[8,0],"1":[0,0],"2":[0,0],"3":[0,0],"4":[0,0],"5":[0,0],"6":[0,0],"7":[0,0],"8":[0,0],"9":[0,10],"10":[10,0,0],"11":[0,0],"12":[0,0],"13":[0,0],"14":[0,0],"15":[0,0],"16":[0,0],"17":[0,0],"18":[0,0]},"meta":{"lastBranch":19,"lastFunction":10,"lastStatement":81,"seen":{"s:19:6:19:Infinity":0,"s:22:33:22:Infinity":1,"f:25:2:25:Infinity":0,"s:26:12:26:Infinity":2,"s:27:12:27:Infinity":3,"s:28:12:28:Infinity":4,"f:36:8:36:22":1,"b:37:4:37:Infinity:undefined:undefined:undefined:undefined":0,"s:37:4:37:Infinity":5,"s:37:33:37:Infinity":6,"s:39:4:39:Infinity":7,"s:40:20:40:Infinity":8,"b:41:4:41:Infinity:undefined:undefined:undefined:undefined":1,"s:41:4:41:Infinity":9,"s:41:18:41:Infinity":10,"s:43:10:43:Infinity":11,"s:44:4:44:Infinity":12,"s:46:4:46:Infinity":13,"f:53:2:53:25":2,"b:54:4:62:Infinity:60:11:62:Infinity":2,"s:54:4:62:Infinity":14,"b:54:8:54:30:54:30:54:51":3,"s:55:6:58:Infinity":15,"s:59:6:59:Infinity":16,"s:61:6:61:Infinity":17,"f:69:8:69:36":3,"b:70:4:70:Infinity:undefined:undefined:undefined:undefined":4,"s:70:4:70:Infinity":18,"s:70:33:70:Infinity":19,"s:71:4:78:Infinity":20,"s:72:12:72:Infinity":21,"s:73:12:73:Infinity":22,"s:74:6:74:Infinity":23,"s:75:6:75:Infinity":24,"s:77:6:77:Infinity":25,"b:77:56:77:70:77:70:77:82":5,"f:86:8:86:26":4,"b:87:4:90:Infinity:undefined:undefined:undefined:undefined":6,"s:87:4:90:Infinity":26,"s:88:21:88:Infinity":27,"s:89:6:89:Infinity":28,"s:91:18:91:Infinity":29,"s:92:4:92:Infinity":30,"f:100:2:100:18":5,"s:101:4:109:Infinity":31,"s:102:12:102:Infinity":32,"b:103:6:103:Infinity:undefined:undefined:undefined:undefined":7,"s:103:6:103:Infinity":33,"s:103:33:103:Infinity":34,"s:104:12:104:Infinity":35,"s:105:21:105:Infinity":36,"s:106:6:106:Infinity":37,"b:106:13:106:50:106:50:106:Infinity":8,"s:108:6:108:Infinity":38,"f:117:8:117:Infinity":6,"s:122:47:122:Infinity":39,"s:123:42:123:Infinity":40,"b:125:4:146:Infinity:undefined:undefined:undefined:undefined":9,"s:125:4:146:Infinity":41,"b:125:8:125:21:125:21:125:46:125:46:125:70":10,"s:126:6:126:Infinity":42,"s:127:22:127:Infinity":43,"b:128:6:130:Infinity:undefined:undefined:undefined:undefined":11,"s:128:6:130:Infinity":44,"s:129:8:129:Infinity":45,"s:131:6:131:Infinity":46,"s:133:35:133:Infinity":47,"b:134:6:136:Infinity:undefined:undefined:undefined:undefined":12,"s:134:6:136:Infinity":48,"s:135:8:135:Infinity":49,"b:137:6:139:Infinity:undefined:undefined:undefined:undefined":13,"s:137:6:139:Infinity":50,"s:138:8:138:Infinity":51,"s:141:26:141:Infinity":52,"b:142:6:145:Infinity:undefined:undefined:undefined:undefined":14,"s:142:6:145:Infinity":53,"s:143:8:143:Infinity":54,"s:144:8:144:Infinity":55,"s:148:4:148:Infinity":56,"f:154:2:154:20":7,"s:155:21:162:Infinity":57,"s:163:18:163:Infinity":58,"s:164:4:164:Infinity":59,"f:164:25:164:26":8,"s:164:32:164:49":60,"f:172:8:172:Infinity":9,"b:176:4:176:Infinity:undefined:undefined:undefined:undefined":15,"s:176:4:176:Infinity":61,"s:176:33:176:Infinity":62,"s:178:4:178:Infinity":63,"s:181:27:181:Infinity":64,"s:182:4:182:Infinity":65,"s:185:24:185:Infinity":66,"b:186:4:189:Infinity:undefined:undefined:undefined:undefined":16,"s:186:4:189:Infinity":67,"s:187:6:187:Infinity":68,"s:188:6:188:Infinity":69,"s:190:4:190:Infinity":70,"s:193:10:193:Infinity":71,"s:194:4:194:Infinity":72,"s:195:33:195:Infinity":73,"b:196:4:199:Infinity:undefined:undefined:undefined:undefined":17,"s:196:4:199:Infinity":74,"s:197:6:197:Infinity":75,"s:198:6:198:Infinity":76,"b:200:4:202:Infinity:undefined:undefined:undefined:undefined":18,"s:200:4:202:Infinity":77,"s:201:6:201:Infinity":78,"s:204:4:204:Infinity":79,"s:206:4:206:Infinity":80}}} +,"/Users/lukasmay/development/projects/codewalk-district/src/agent/file-io.ts": {"path":"/Users/lukasmay/development/projects/codewalk-district/src/agent/file-io.ts","statementMap":{"0":{"start":{"line":71,"column":2},"end":{"line":71,"column":null}},"1":{"start":{"line":79,"column":26},"end":{"line":79,"column":null}},"2":{"start":{"line":80,"column":2},"end":{"line":98,"column":null}},"3":{"start":{"line":81,"column":4},"end":{"line":81,"column":null}},"4":{"start":{"line":81,"column":47},"end":{"line":81,"column":null}},"5":{"start":{"line":82,"column":4},"end":{"line":97,"column":null}},"6":{"start":{"line":83,"column":6},"end":{"line":90,"column":null}},"7":{"start":{"line":84,"column":8},"end":{"line":84,"column":null}},"8":{"start":{"line":86,"column":8},"end":{"line":86,"column":null}},"9":{"start":{"line":87,"column":8},"end":{"line":89,"column":null}},"10":{"start":{"line":88,"column":10},"end":{"line":88,"column":null}},"11":{"start":{"line":91,"column":4},"end":{"line":97,"column":null}},"12":{"start":{"line":92,"column":6},"end":{"line":92,"column":null}},"13":{"start":{"line":93,"column":4},"end":{"line":97,"column":null}},"14":{"start":{"line":94,"column":6},"end":{"line":94,"column":null}},"15":{"start":{"line":96,"column":6},"end":{"line":96,"column":null}},"16":{"start":{"line":99,"column":2},"end":{"line":99,"column":null}},"17":{"start":{"line":100,"column":2},"end":{"line":103,"column":null}},"18":{"start":{"line":101,"column":4},"end":{"line":101,"column":null}},"19":{"start":{"line":102,"column":4},"end":{"line":102,"column":null}},"20":{"start":{"line":104,"column":2},"end":{"line":104,"column":null}},"21":{"start":{"line":108,"column":8},"end":{"line":108,"column":null}},"22":{"start":{"line":109,"column":2},"end":{"line":109,"column":null}},"23":{"start":{"line":112,"column":2},"end":{"line":116,"column":null}},"24":{"start":{"line":118,"column":34},"end":{"line":118,"column":null}},"25":{"start":{"line":120,"column":2},"end":{"line":134,"column":null}},"26":{"start":{"line":121,"column":16},"end":{"line":121,"column":null}},"27":{"start":{"line":122,"column":20},"end":{"line":131,"column":null}},"28":{"start":{"line":132,"column":4},"end":{"line":132,"column":null}},"29":{"start":{"line":133,"column":4},"end":{"line":133,"column":null}},"30":{"start":{"line":136,"column":2},"end":{"line":163,"column":null}},"31":{"start":{"line":137,"column":10},"end":{"line":137,"column":null}},"32":{"start":{"line":138,"column":4},"end":{"line":138,"column":null}},"33":{"start":{"line":140,"column":4},"end":{"line":162,"column":null}},"34":{"start":{"line":141,"column":25},"end":{"line":141,"column":null}},"35":{"start":{"line":142,"column":6},"end":{"line":149,"column":null}},"36":{"start":{"line":143,"column":8},"end":{"line":148,"column":null}},"37":{"start":{"line":144,"column":25},"end":{"line":144,"column":null}},"38":{"start":{"line":145,"column":10},"end":{"line":145,"column":null}},"39":{"start":{"line":151,"column":22},"end":{"line":158,"column":null}},"40":{"start":{"line":159,"column":23},"end":{"line":159,"column":null}},"41":{"start":{"line":160,"column":6},"end":{"line":160,"column":null}},"42":{"start":{"line":161,"column":6},"end":{"line":161,"column":null}},"43":{"start":{"line":165,"column":2},"end":{"line":185,"column":null}},"44":{"start":{"line":166,"column":15},"end":{"line":166,"column":null}},"45":{"start":{"line":167,"column":23},"end":{"line":167,"column":null}},"46":{"start":{"line":168,"column":4},"end":{"line":174,"column":null}},"47":{"start":{"line":169,"column":6},"end":{"line":173,"column":null}},"48":{"start":{"line":170,"column":8},"end":{"line":170,"column":null}},"49":{"start":{"line":175,"column":20},"end":{"line":182,"column":null}},"50":{"start":{"line":183,"column":4},"end":{"line":183,"column":null}},"51":{"start":{"line":184,"column":4},"end":{"line":184,"column":null}},"52":{"start":{"line":187,"column":2},"end":{"line":202,"column":null}},"53":{"start":{"line":188,"column":14},"end":{"line":188,"column":null}},"54":{"start":{"line":189,"column":20},"end":{"line":199,"column":null}},"55":{"start":{"line":200,"column":4},"end":{"line":200,"column":null}},"56":{"start":{"line":201,"column":4},"end":{"line":201,"column":null}},"57":{"start":{"line":205,"column":33},"end":{"line":205,"column":null}},"58":{"start":{"line":207,"column":2},"end":{"line":233,"column":null}},"59":{"start":{"line":208,"column":10},"end":{"line":208,"column":null}},"60":{"start":{"line":209,"column":4},"end":{"line":209,"column":null}},"61":{"start":{"line":211,"column":4},"end":{"line":232,"column":null}},"62":{"start":{"line":212,"column":25},"end":{"line":212,"column":null}},"63":{"start":{"line":213,"column":6},"end":{"line":219,"column":null}},"64":{"start":{"line":214,"column":8},"end":{"line":218,"column":null}},"65":{"start":{"line":215,"column":10},"end":{"line":215,"column":null}},"66":{"start":{"line":220,"column":22},"end":{"line":228,"column":null}},"67":{"start":{"line":229,"column":23},"end":{"line":229,"column":null}},"68":{"start":{"line":230,"column":6},"end":{"line":230,"column":null}},"69":{"start":{"line":231,"column":6},"end":{"line":231,"column":null}},"70":{"start":{"line":235,"column":2},"end":{"line":257,"column":null}},"71":{"start":{"line":236,"column":10},"end":{"line":236,"column":null}},"72":{"start":{"line":237,"column":4},"end":{"line":237,"column":null}},"73":{"start":{"line":239,"column":4},"end":{"line":256,"column":null}},"74":{"start":{"line":240,"column":22},"end":{"line":252,"column":null}},"75":{"start":{"line":253,"column":23},"end":{"line":253,"column":null}},"76":{"start":{"line":254,"column":6},"end":{"line":254,"column":null}},"77":{"start":{"line":255,"column":6},"end":{"line":255,"column":null}},"78":{"start":{"line":260,"column":2},"end":{"line":269,"column":null}},"79":{"start":{"line":277,"column":2},"end":{"line":283,"column":null}},"80":{"start":{"line":278,"column":10},"end":{"line":278,"column":null}},"81":{"start":{"line":279,"column":10},"end":{"line":279,"column":null}},"82":{"start":{"line":280,"column":4},"end":{"line":280,"column":null}},"83":{"start":{"line":282,"column":4},"end":{"line":282,"column":null}},"84":{"start":{"line":290,"column":2},"end":{"line":290,"column":null}},"85":{"start":{"line":290,"column":28},"end":{"line":290,"column":null}},"86":{"start":{"line":292,"column":23},"end":{"line":292,"column":null}},"87":{"start":{"line":293,"column":2},"end":{"line":305,"column":null}},"88":{"start":{"line":294,"column":10},"end":{"line":294,"column":null}},"89":{"start":{"line":295,"column":4},"end":{"line":302,"column":null}},"90":{"start":{"line":296,"column":6},"end":{"line":296,"column":null}},"91":{"start":{"line":296,"column":34},"end":{"line":296,"column":null}},"92":{"start":{"line":297,"column":12},"end":{"line":297,"column":null}},"93":{"start":{"line":298,"column":21},"end":{"line":298,"column":null}},"94":{"start":{"line":299,"column":6},"end":{"line":299,"column":null}},"95":{"start":{"line":299,"column":19},"end":{"line":299,"column":null}},"96":{"start":{"line":300,"column":21},"end":{"line":300,"column":null}},"97":{"start":{"line":301,"column":6},"end":{"line":301,"column":null}},"98":{"start":{"line":301,"column":18},"end":{"line":301,"column":null}},"99":{"start":{"line":306,"column":2},"end":{"line":306,"column":null}},"100":{"start":{"line":310,"column":8},"end":{"line":310,"column":null}},"101":{"start":{"line":311,"column":17},"end":{"line":311,"column":null}},"102":{"start":{"line":312,"column":2},"end":{"line":312,"column":null}},"103":{"start":{"line":312,"column":15},"end":{"line":312,"column":null}},"104":{"start":{"line":314,"column":24},"end":{"line":314,"column":null}},"105":{"start":{"line":315,"column":2},"end":{"line":318,"column":null}},"106":{"start":{"line":322,"column":8},"end":{"line":322,"column":null}},"107":{"start":{"line":323,"column":2},"end":{"line":332,"column":null}},"108":{"start":{"line":324,"column":15},"end":{"line":324,"column":null}},"109":{"start":{"line":325,"column":17},"end":{"line":325,"column":null}},"110":{"start":{"line":326,"column":4},"end":{"line":331,"column":null}},"111":{"start":{"line":336,"column":8},"end":{"line":336,"column":null}},"112":{"start":{"line":337,"column":2},"end":{"line":348,"column":null}},"113":{"start":{"line":338,"column":15},"end":{"line":338,"column":null}},"114":{"start":{"line":339,"column":17},"end":{"line":339,"column":null}},"115":{"start":{"line":340,"column":4},"end":{"line":347,"column":null}},"116":{"start":{"line":352,"column":8},"end":{"line":352,"column":null}},"117":{"start":{"line":353,"column":2},"end":{"line":362,"column":null}},"118":{"start":{"line":354,"column":15},"end":{"line":354,"column":null}},"119":{"start":{"line":355,"column":4},"end":{"line":361,"column":null}},"120":{"start":{"line":366,"column":8},"end":{"line":366,"column":null}},"121":{"start":{"line":367,"column":2},"end":{"line":375,"column":null}},"122":{"start":{"line":368,"column":19},"end":{"line":368,"column":null}},"123":{"start":{"line":369,"column":4},"end":{"line":374,"column":null}}},"fnMap":{"0":{"name":"generateId","decl":{"start":{"line":70,"column":16},"end":{"line":70,"column":37}},"loc":{"start":{"line":70,"column":37},"end":{"line":72,"column":null}},"line":70},"1":{"name":"formatFrontmatter","decl":{"start":{"line":78,"column":9},"end":{"line":78,"column":27}},"loc":{"start":{"line":78,"column":85},"end":{"line":105,"column":null}},"line":78},"2":{"name":"writeInputFiles","decl":{"start":{"line":107,"column":16},"end":{"line":107,"column":32}},"loc":{"start":{"line":107,"column":71},"end":{"line":270,"column":null}},"line":107},"3":{"name":"readFrontmatterFile","decl":{"start":{"line":276,"column":16},"end":{"line":276,"column":36}},"loc":{"start":{"line":276,"column":110},"end":{"line":284,"column":null}},"line":276},"4":{"name":"readFrontmatterDir","decl":{"start":{"line":286,"column":9},"end":{"line":286,"column":null}},"loc":{"start":{"line":289,"column":7},"end":{"line":307,"column":null}},"line":289},"5":{"name":"readSummary","decl":{"start":{"line":309,"column":16},"end":{"line":309,"column":28}},"loc":{"start":{"line":309,"column":72},"end":{"line":319,"column":null}},"line":309},"6":{"name":"readPhaseFiles","decl":{"start":{"line":321,"column":16},"end":{"line":321,"column":31}},"loc":{"start":{"line":321,"column":72},"end":{"line":333,"column":null}},"line":321},"7":{"name":"(anonymous_7)","decl":{"start":{"line":323,"column":37},"end":{"line":323,"column":38}},"loc":{"start":{"line":323,"column":63},"end":{"line":332,"column":3}},"line":323},"8":{"name":"readTaskFiles","decl":{"start":{"line":335,"column":16},"end":{"line":335,"column":30}},"loc":{"start":{"line":335,"column":70},"end":{"line":349,"column":null}},"line":335},"9":{"name":"(anonymous_9)","decl":{"start":{"line":337,"column":37},"end":{"line":337,"column":38}},"loc":{"start":{"line":337,"column":63},"end":{"line":348,"column":3}},"line":337},"10":{"name":"readDecisionFiles","decl":{"start":{"line":351,"column":16},"end":{"line":351,"column":34}},"loc":{"start":{"line":351,"column":78},"end":{"line":363,"column":null}},"line":351},"11":{"name":"(anonymous_11)","decl":{"start":{"line":353,"column":37},"end":{"line":353,"column":38}},"loc":{"start":{"line":353,"column":63},"end":{"line":362,"column":3}},"line":353},"12":{"name":"readPageFiles","decl":{"start":{"line":365,"column":16},"end":{"line":365,"column":30}},"loc":{"start":{"line":365,"column":70},"end":{"line":376,"column":null}},"line":365},"13":{"name":"(anonymous_13)","decl":{"start":{"line":367,"column":37},"end":{"line":367,"column":38}},"loc":{"start":{"line":367,"column":63},"end":{"line":375,"column":3}},"line":367}},"branchMap":{"0":{"loc":{"start":{"line":78,"column":58},"end":{"line":78,"column":85}},"type":"default-arg","locations":[{"start":{"line":78,"column":73},"end":{"line":78,"column":85}}],"line":78},"1":{"loc":{"start":{"line":81,"column":4},"end":{"line":81,"column":null}},"type":"if","locations":[{"start":{"line":81,"column":4},"end":{"line":81,"column":null}},{"start":{},"end":{}}],"line":81},"2":{"loc":{"start":{"line":81,"column":8},"end":{"line":81,"column":47}},"type":"binary-expr","locations":[{"start":{"line":81,"column":8},"end":{"line":81,"column":31}},{"start":{"line":81,"column":31},"end":{"line":81,"column":47}}],"line":81},"3":{"loc":{"start":{"line":82,"column":4},"end":{"line":97,"column":null}},"type":"if","locations":[{"start":{"line":82,"column":4},"end":{"line":97,"column":null}},{"start":{"line":91,"column":4},"end":{"line":97,"column":null}}],"line":82},"4":{"loc":{"start":{"line":83,"column":6},"end":{"line":90,"column":null}},"type":"if","locations":[{"start":{"line":83,"column":6},"end":{"line":90,"column":null}},{"start":{"line":85,"column":13},"end":{"line":90,"column":null}}],"line":83},"5":{"loc":{"start":{"line":91,"column":4},"end":{"line":97,"column":null}},"type":"if","locations":[{"start":{"line":91,"column":4},"end":{"line":97,"column":null}},{"start":{"line":93,"column":4},"end":{"line":97,"column":null}}],"line":91},"6":{"loc":{"start":{"line":93,"column":4},"end":{"line":97,"column":null}},"type":"if","locations":[{"start":{"line":93,"column":4},"end":{"line":97,"column":null}},{"start":{"line":95,"column":11},"end":{"line":97,"column":null}}],"line":93},"7":{"loc":{"start":{"line":93,"column":15},"end":{"line":93,"column":91}},"type":"binary-expr","locations":[{"start":{"line":93,"column":15},"end":{"line":93,"column":45}},{"start":{"line":93,"column":45},"end":{"line":93,"column":69}},{"start":{"line":93,"column":69},"end":{"line":93,"column":91}}],"line":93},"8":{"loc":{"start":{"line":100,"column":2},"end":{"line":103,"column":null}},"type":"if","locations":[{"start":{"line":100,"column":2},"end":{"line":103,"column":null}},{"start":{},"end":{}}],"line":100},"9":{"loc":{"start":{"line":120,"column":2},"end":{"line":134,"column":null}},"type":"if","locations":[{"start":{"line":120,"column":2},"end":{"line":134,"column":null}},{"start":{},"end":{}}],"line":120},"10":{"loc":{"start":{"line":136,"column":2},"end":{"line":163,"column":null}},"type":"if","locations":[{"start":{"line":136,"column":2},"end":{"line":163,"column":null}},{"start":{},"end":{}}],"line":136},"11":{"loc":{"start":{"line":136,"column":6},"end":{"line":136,"column":49}},"type":"binary-expr","locations":[{"start":{"line":136,"column":6},"end":{"line":136,"column":23}},{"start":{"line":136,"column":23},"end":{"line":136,"column":49}}],"line":136},"12":{"loc":{"start":{"line":142,"column":6},"end":{"line":149,"column":null}},"type":"if","locations":[{"start":{"line":142,"column":6},"end":{"line":149,"column":null}},{"start":{},"end":{}}],"line":142},"13":{"loc":{"start":{"line":165,"column":2},"end":{"line":185,"column":null}},"type":"if","locations":[{"start":{"line":165,"column":2},"end":{"line":185,"column":null}},{"start":{},"end":{}}],"line":165},"14":{"loc":{"start":{"line":168,"column":4},"end":{"line":174,"column":null}},"type":"if","locations":[{"start":{"line":168,"column":4},"end":{"line":174,"column":null}},{"start":{},"end":{}}],"line":168},"15":{"loc":{"start":{"line":187,"column":2},"end":{"line":202,"column":null}},"type":"if","locations":[{"start":{"line":187,"column":2},"end":{"line":202,"column":null}},{"start":{},"end":{}}],"line":187},"16":{"loc":{"start":{"line":198,"column":6},"end":{"line":198,"column":null}},"type":"binary-expr","locations":[{"start":{"line":198,"column":6},"end":{"line":198,"column":23}},{"start":{"line":198,"column":23},"end":{"line":198,"column":null}}],"line":198},"17":{"loc":{"start":{"line":207,"column":2},"end":{"line":233,"column":null}},"type":"if","locations":[{"start":{"line":207,"column":2},"end":{"line":233,"column":null}},{"start":{},"end":{}}],"line":207},"18":{"loc":{"start":{"line":207,"column":6},"end":{"line":207,"column":51}},"type":"binary-expr","locations":[{"start":{"line":207,"column":6},"end":{"line":207,"column":24}},{"start":{"line":207,"column":24},"end":{"line":207,"column":51}}],"line":207},"19":{"loc":{"start":{"line":213,"column":6},"end":{"line":219,"column":null}},"type":"if","locations":[{"start":{"line":213,"column":6},"end":{"line":219,"column":null}},{"start":{},"end":{}}],"line":213},"20":{"loc":{"start":{"line":225,"column":21},"end":{"line":225,"column":null}},"type":"binary-expr","locations":[{"start":{"line":225,"column":21},"end":{"line":225,"column":37}},{"start":{"line":225,"column":37},"end":{"line":225,"column":null}}],"line":225},"21":{"loc":{"start":{"line":235,"column":2},"end":{"line":257,"column":null}},"type":"if","locations":[{"start":{"line":235,"column":2},"end":{"line":257,"column":null}},{"start":{},"end":{}}],"line":235},"22":{"loc":{"start":{"line":235,"column":6},"end":{"line":235,"column":49}},"type":"binary-expr","locations":[{"start":{"line":235,"column":6},"end":{"line":235,"column":23}},{"start":{"line":235,"column":23},"end":{"line":235,"column":49}}],"line":235},"23":{"loc":{"start":{"line":251,"column":8},"end":{"line":251,"column":null}},"type":"binary-expr","locations":[{"start":{"line":251,"column":8},"end":{"line":251,"column":25}},{"start":{"line":251,"column":25},"end":{"line":251,"column":null}}],"line":251},"24":{"loc":{"start":{"line":265,"column":15},"end":{"line":265,"column":null}},"type":"binary-expr","locations":[{"start":{"line":265,"column":15},"end":{"line":265,"column":34}},{"start":{"line":265,"column":34},"end":{"line":265,"column":null}}],"line":265},"25":{"loc":{"start":{"line":266,"column":17},"end":{"line":266,"column":null}},"type":"binary-expr","locations":[{"start":{"line":266,"column":17},"end":{"line":266,"column":38}},{"start":{"line":266,"column":38},"end":{"line":266,"column":null}}],"line":266},"26":{"loc":{"start":{"line":290,"column":2},"end":{"line":290,"column":null}},"type":"if","locations":[{"start":{"line":290,"column":2},"end":{"line":290,"column":null}},{"start":{},"end":{}}],"line":290},"27":{"loc":{"start":{"line":296,"column":6},"end":{"line":296,"column":null}},"type":"if","locations":[{"start":{"line":296,"column":6},"end":{"line":296,"column":null}},{"start":{},"end":{}}],"line":296},"28":{"loc":{"start":{"line":299,"column":6},"end":{"line":299,"column":null}},"type":"if","locations":[{"start":{"line":299,"column":6},"end":{"line":299,"column":null}},{"start":{},"end":{}}],"line":299},"29":{"loc":{"start":{"line":301,"column":6},"end":{"line":301,"column":null}},"type":"if","locations":[{"start":{"line":301,"column":6},"end":{"line":301,"column":null}},{"start":{},"end":{}}],"line":301},"30":{"loc":{"start":{"line":312,"column":2},"end":{"line":312,"column":null}},"type":"if","locations":[{"start":{"line":312,"column":2},"end":{"line":312,"column":null}},{"start":{},"end":{}}],"line":312},"31":{"loc":{"start":{"line":317,"column":19},"end":{"line":317,"column":null}},"type":"cond-expr","locations":[{"start":{"line":317,"column":50},"end":{"line":317,"column":78}},{"start":{"line":317,"column":78},"end":{"line":317,"column":null}}],"line":317},"32":{"loc":{"start":{"line":325,"column":17},"end":{"line":325,"column":null}},"type":"cond-expr","locations":[{"start":{"line":325,"column":52},"end":{"line":325,"column":84}},{"start":{"line":325,"column":84},"end":{"line":325,"column":null}}],"line":325},"33":{"loc":{"start":{"line":328,"column":20},"end":{"line":328,"column":36}},"type":"binary-expr","locations":[{"start":{"line":328,"column":20},"end":{"line":328,"column":34}},{"start":{"line":328,"column":34},"end":{"line":328,"column":36}}],"line":328},"34":{"loc":{"start":{"line":339,"column":17},"end":{"line":339,"column":null}},"type":"cond-expr","locations":[{"start":{"line":339,"column":52},"end":{"line":339,"column":84}},{"start":{"line":339,"column":84},"end":{"line":339,"column":null}}],"line":339},"35":{"loc":{"start":{"line":342,"column":20},"end":{"line":342,"column":36}},"type":"binary-expr","locations":[{"start":{"line":342,"column":20},"end":{"line":342,"column":34}},{"start":{"line":342,"column":34},"end":{"line":342,"column":36}}],"line":342},"36":{"loc":{"start":{"line":343,"column":23},"end":{"line":343,"column":49}},"type":"binary-expr","locations":[{"start":{"line":343,"column":23},"end":{"line":343,"column":40}},{"start":{"line":343,"column":40},"end":{"line":343,"column":49}}],"line":343},"37":{"loc":{"start":{"line":344,"column":19},"end":{"line":344,"column":38}},"type":"binary-expr","locations":[{"start":{"line":344,"column":19},"end":{"line":344,"column":32}},{"start":{"line":344,"column":32},"end":{"line":344,"column":38}}],"line":344},"38":{"loc":{"start":{"line":357,"column":20},"end":{"line":357,"column":36}},"type":"binary-expr","locations":[{"start":{"line":357,"column":20},"end":{"line":357,"column":34}},{"start":{"line":357,"column":34},"end":{"line":357,"column":36}}],"line":357},"39":{"loc":{"start":{"line":358,"column":23},"end":{"line":358,"column":42}},"type":"binary-expr","locations":[{"start":{"line":358,"column":23},"end":{"line":358,"column":40}},{"start":{"line":358,"column":40},"end":{"line":358,"column":42}}],"line":358},"40":{"loc":{"start":{"line":359,"column":21},"end":{"line":359,"column":38}},"type":"binary-expr","locations":[{"start":{"line":359,"column":21},"end":{"line":359,"column":36}},{"start":{"line":359,"column":36},"end":{"line":359,"column":38}}],"line":359},"41":{"loc":{"start":{"line":371,"column":20},"end":{"line":371,"column":36}},"type":"binary-expr","locations":[{"start":{"line":371,"column":20},"end":{"line":371,"column":34}},{"start":{"line":371,"column":34},"end":{"line":371,"column":36}}],"line":371},"42":{"loc":{"start":{"line":372,"column":22},"end":{"line":372,"column":40}},"type":"binary-expr","locations":[{"start":{"line":372,"column":22},"end":{"line":372,"column":38}},{"start":{"line":372,"column":38},"end":{"line":372,"column":40}}],"line":372}},"s":{"0":101,"1":5,"2":5,"3":20,"4":1,"5":19,"6":0,"7":0,"8":0,"9":0,"10":0,"11":19,"12":0,"13":19,"14":0,"15":19,"16":5,"17":5,"18":1,"19":1,"20":5,"21":5,"22":5,"23":5,"24":5,"25":5,"26":1,"27":1,"28":1,"29":1,"30":5,"31":1,"32":1,"33":1,"34":2,"35":2,"36":0,"37":0,"38":0,"39":2,"40":2,"41":2,"42":2,"43":5,"44":1,"45":1,"46":1,"47":1,"48":1,"49":1,"50":1,"51":1,"52":5,"53":1,"54":1,"55":1,"56":1,"57":5,"58":5,"59":0,"60":0,"61":0,"62":0,"63":0,"64":0,"65":0,"66":0,"67":0,"68":0,"69":0,"70":5,"71":0,"72":0,"73":0,"74":0,"75":0,"76":0,"77":0,"78":5,"79":14,"80":14,"81":14,"82":14,"83":4,"84":14,"85":7,"86":7,"87":7,"88":7,"89":7,"90":8,"91":1,"92":7,"93":7,"94":7,"95":0,"96":7,"97":7,"98":7,"99":7,"100":7,"101":7,"102":7,"103":4,"104":3,"105":3,"106":3,"107":3,"108":2,"109":2,"110":2,"111":3,"112":3,"113":2,"114":2,"115":2,"116":2,"117":2,"118":1,"119":1,"120":6,"121":6,"122":2,"123":2},"f":{"0":101,"1":5,"2":5,"3":14,"4":14,"5":7,"6":3,"7":2,"8":3,"9":2,"10":2,"11":1,"12":6,"13":2},"b":{"0":[5],"1":[1,19],"2":[20,20],"3":[0,19],"4":[0,0],"5":[0,19],"6":[0,19],"7":[19,16,16],"8":[1,4],"9":[1,4],"10":[1,4],"11":[5,1],"12":[0,2],"13":[1,4],"14":[1,0],"15":[1,4],"16":[1,0],"17":[0,5],"18":[5,0],"19":[0,0],"20":[0,0],"21":[0,5],"22":[5,0],"23":[0,0],"24":[5,5],"25":[5,5],"26":[7,7],"27":[1,7],"28":[0,7],"29":[7,0],"30":[4,3],"31":[2,1],"32":[1,1],"33":[2,0],"34":[1,1],"35":[2,0],"36":[2,1],"37":[2,1],"38":[1,0],"39":[1,0],"40":[1,0],"41":[2,0],"42":[2,1]},"meta":{"lastBranch":43,"lastFunction":14,"lastStatement":124,"seen":{"f:70:16:70:37":0,"s:71:2:71:Infinity":0,"f:78:9:78:27":1,"b:78:73:78:85":0,"s:79:26:79:Infinity":1,"s:80:2:98:Infinity":2,"b:81:4:81:Infinity:undefined:undefined:undefined:undefined":1,"s:81:4:81:Infinity":3,"b:81:8:81:31:81:31:81:47":2,"s:81:47:81:Infinity":4,"b:82:4:97:Infinity:91:4:97:Infinity":3,"s:82:4:97:Infinity":5,"b:83:6:90:Infinity:85:13:90:Infinity":4,"s:83:6:90:Infinity":6,"s:84:8:84:Infinity":7,"s:86:8:86:Infinity":8,"s:87:8:89:Infinity":9,"s:88:10:88:Infinity":10,"b:91:4:97:Infinity:93:4:97:Infinity":5,"s:91:4:97:Infinity":11,"s:92:6:92:Infinity":12,"b:93:4:97:Infinity:95:11:97:Infinity":6,"s:93:4:97:Infinity":13,"b:93:15:93:45:93:45:93:69:93:69:93:91":7,"s:94:6:94:Infinity":14,"s:96:6:96:Infinity":15,"s:99:2:99:Infinity":16,"b:100:2:103:Infinity:undefined:undefined:undefined:undefined":8,"s:100:2:103:Infinity":17,"s:101:4:101:Infinity":18,"s:102:4:102:Infinity":19,"s:104:2:104:Infinity":20,"f:107:16:107:32":2,"s:108:8:108:Infinity":21,"s:109:2:109:Infinity":22,"s:112:2:116:Infinity":23,"s:118:34:118:Infinity":24,"b:120:2:134:Infinity:undefined:undefined:undefined:undefined":9,"s:120:2:134:Infinity":25,"s:121:16:121:Infinity":26,"s:122:20:131:Infinity":27,"s:132:4:132:Infinity":28,"s:133:4:133:Infinity":29,"b:136:2:163:Infinity:undefined:undefined:undefined:undefined":10,"s:136:2:163:Infinity":30,"b:136:6:136:23:136:23:136:49":11,"s:137:10:137:Infinity":31,"s:138:4:138:Infinity":32,"s:140:4:162:Infinity":33,"s:141:25:141:Infinity":34,"b:142:6:149:Infinity:undefined:undefined:undefined:undefined":12,"s:142:6:149:Infinity":35,"s:143:8:148:Infinity":36,"s:144:25:144:Infinity":37,"s:145:10:145:Infinity":38,"s:151:22:158:Infinity":39,"s:159:23:159:Infinity":40,"s:160:6:160:Infinity":41,"s:161:6:161:Infinity":42,"b:165:2:185:Infinity:undefined:undefined:undefined:undefined":13,"s:165:2:185:Infinity":43,"s:166:15:166:Infinity":44,"s:167:23:167:Infinity":45,"b:168:4:174:Infinity:undefined:undefined:undefined:undefined":14,"s:168:4:174:Infinity":46,"s:169:6:173:Infinity":47,"s:170:8:170:Infinity":48,"s:175:20:182:Infinity":49,"s:183:4:183:Infinity":50,"s:184:4:184:Infinity":51,"b:187:2:202:Infinity:undefined:undefined:undefined:undefined":15,"s:187:2:202:Infinity":52,"s:188:14:188:Infinity":53,"s:189:20:199:Infinity":54,"b:198:6:198:23:198:23:198:Infinity":16,"s:200:4:200:Infinity":55,"s:201:4:201:Infinity":56,"s:205:33:205:Infinity":57,"b:207:2:233:Infinity:undefined:undefined:undefined:undefined":17,"s:207:2:233:Infinity":58,"b:207:6:207:24:207:24:207:51":18,"s:208:10:208:Infinity":59,"s:209:4:209:Infinity":60,"s:211:4:232:Infinity":61,"s:212:25:212:Infinity":62,"b:213:6:219:Infinity:undefined:undefined:undefined:undefined":19,"s:213:6:219:Infinity":63,"s:214:8:218:Infinity":64,"s:215:10:215:Infinity":65,"s:220:22:228:Infinity":66,"b:225:21:225:37:225:37:225:Infinity":20,"s:229:23:229:Infinity":67,"s:230:6:230:Infinity":68,"s:231:6:231:Infinity":69,"b:235:2:257:Infinity:undefined:undefined:undefined:undefined":21,"s:235:2:257:Infinity":70,"b:235:6:235:23:235:23:235:49":22,"s:236:10:236:Infinity":71,"s:237:4:237:Infinity":72,"s:239:4:256:Infinity":73,"s:240:22:252:Infinity":74,"b:251:8:251:25:251:25:251:Infinity":23,"s:253:23:253:Infinity":75,"s:254:6:254:Infinity":76,"s:255:6:255:Infinity":77,"s:260:2:269:Infinity":78,"b:265:15:265:34:265:34:265:Infinity":24,"b:266:17:266:38:266:38:266:Infinity":25,"f:276:16:276:36":3,"s:277:2:283:Infinity":79,"s:278:10:278:Infinity":80,"s:279:10:279:Infinity":81,"s:280:4:280:Infinity":82,"s:282:4:282:Infinity":83,"f:286:9:286:Infinity":4,"b:290:2:290:Infinity:undefined:undefined:undefined:undefined":26,"s:290:2:290:Infinity":84,"s:290:28:290:Infinity":85,"s:292:23:292:Infinity":86,"s:293:2:305:Infinity":87,"s:294:10:294:Infinity":88,"s:295:4:302:Infinity":89,"b:296:6:296:Infinity:undefined:undefined:undefined:undefined":27,"s:296:6:296:Infinity":90,"s:296:34:296:Infinity":91,"s:297:12:297:Infinity":92,"s:298:21:298:Infinity":93,"b:299:6:299:Infinity:undefined:undefined:undefined:undefined":28,"s:299:6:299:Infinity":94,"s:299:19:299:Infinity":95,"s:300:21:300:Infinity":96,"b:301:6:301:Infinity:undefined:undefined:undefined:undefined":29,"s:301:6:301:Infinity":97,"s:301:18:301:Infinity":98,"s:306:2:306:Infinity":99,"f:309:16:309:28":5,"s:310:8:310:Infinity":100,"s:311:17:311:Infinity":101,"b:312:2:312:Infinity:undefined:undefined:undefined:undefined":30,"s:312:2:312:Infinity":102,"s:312:15:312:Infinity":103,"s:314:24:314:Infinity":104,"s:315:2:318:Infinity":105,"b:317:50:317:78:317:78:317:Infinity":31,"f:321:16:321:31":6,"s:322:8:322:Infinity":106,"s:323:2:332:Infinity":107,"f:323:37:323:38":7,"s:324:15:324:Infinity":108,"s:325:17:325:Infinity":109,"b:325:52:325:84:325:84:325:Infinity":32,"s:326:4:331:Infinity":110,"b:328:20:328:34:328:34:328:36":33,"f:335:16:335:30":8,"s:336:8:336:Infinity":111,"s:337:2:348:Infinity":112,"f:337:37:337:38":9,"s:338:15:338:Infinity":113,"s:339:17:339:Infinity":114,"b:339:52:339:84:339:84:339:Infinity":34,"s:340:4:347:Infinity":115,"b:342:20:342:34:342:34:342:36":35,"b:343:23:343:40:343:40:343:49":36,"b:344:19:344:32:344:32:344:38":37,"f:351:16:351:34":10,"s:352:8:352:Infinity":116,"s:353:2:362:Infinity":117,"f:353:37:353:38":11,"s:354:15:354:Infinity":118,"s:355:4:361:Infinity":119,"b:357:20:357:34:357:34:357:36":38,"b:358:23:358:40:358:40:358:42":39,"b:359:21:359:36:359:36:359:38":40,"f:365:16:365:30":12,"s:366:8:366:Infinity":120,"s:367:2:375:Infinity":121,"f:367:37:367:38":13,"s:368:19:368:Infinity":122,"s:369:4:374:Infinity":123,"b:371:20:371:34:371:34:371:36":41,"b:372:22:372:38:372:38:372:40":42}}} +,"/Users/lukasmay/development/projects/codewalk-district/src/agent/file-tailer.ts": {"path":"/Users/lukasmay/development/projects/codewalk-district/src/agent/file-tailer.ts","statementMap":{"0":{"start":{"line":18,"column":6},"end":{"line":18,"column":null}},"1":{"start":{"line":21,"column":25},"end":{"line":21,"column":null}},"2":{"start":{"line":24,"column":25},"end":{"line":24,"column":null}},"3":{"start":{"line":52,"column":21},"end":{"line":52,"column":null}},"4":{"start":{"line":53,"column":38},"end":{"line":53,"column":null}},"5":{"start":{"line":54,"column":48},"end":{"line":54,"column":null}},"6":{"start":{"line":55,"column":42},"end":{"line":55,"column":null}},"7":{"start":{"line":56,"column":20},"end":{"line":56,"column":null}},"8":{"start":{"line":57,"column":24},"end":{"line":57,"column":null}},"9":{"start":{"line":58,"column":20},"end":{"line":58,"column":null}},"10":{"start":{"line":68,"column":4},"end":{"line":68,"column":null}},"11":{"start":{"line":69,"column":4},"end":{"line":69,"column":null}},"12":{"start":{"line":70,"column":4},"end":{"line":70,"column":null}},"13":{"start":{"line":71,"column":4},"end":{"line":71,"column":null}},"14":{"start":{"line":72,"column":4},"end":{"line":72,"column":null}},"15":{"start":{"line":73,"column":4},"end":{"line":73,"column":null}},"16":{"start":{"line":81,"column":4},"end":{"line":81,"column":null}},"17":{"start":{"line":81,"column":22},"end":{"line":81,"column":null}},"18":{"start":{"line":83,"column":4},"end":{"line":83,"column":null}},"19":{"start":{"line":85,"column":4},"end":{"line":126,"column":null}},"20":{"start":{"line":87,"column":6},"end":{"line":87,"column":null}},"21":{"start":{"line":90,"column":6},"end":{"line":96,"column":null}},"22":{"start":{"line":91,"column":8},"end":{"line":91,"column":null}},"23":{"start":{"line":94,"column":22},"end":{"line":94,"column":null}},"24":{"start":{"line":95,"column":8},"end":{"line":95,"column":null}},"25":{"start":{"line":99,"column":6},"end":{"line":105,"column":null}},"26":{"start":{"line":100,"column":8},"end":{"line":104,"column":null}},"27":{"start":{"line":101,"column":10},"end":{"line":103,"column":null}},"28":{"start":{"line":102,"column":12},"end":{"line":102,"column":null}},"29":{"start":{"line":107,"column":6},"end":{"line":109,"column":null}},"30":{"start":{"line":108,"column":8},"end":{"line":108,"column":null}},"31":{"start":{"line":112,"column":6},"end":{"line":118,"column":null}},"32":{"start":{"line":113,"column":8},"end":{"line":117,"column":null}},"33":{"start":{"line":114,"column":10},"end":{"line":116,"column":null}},"34":{"start":{"line":115,"column":12},"end":{"line":115,"column":null}},"35":{"start":{"line":121,"column":6},"end":{"line":123,"column":null}},"36":{"start":{"line":122,"column":8},"end":{"line":122,"column":null}},"37":{"start":{"line":125,"column":6},"end":{"line":125,"column":null}},"38":{"start":{"line":134,"column":4},"end":{"line":134,"column":null}},"39":{"start":{"line":134,"column":58},"end":{"line":134,"column":null}},"40":{"start":{"line":136,"column":4},"end":{"line":136,"column":null}},"41":{"start":{"line":137,"column":4},"end":{"line":181,"column":null}},"42":{"start":{"line":139,"column":20},"end":{"line":139,"column":null}},"43":{"start":{"line":140,"column":6},"end":{"line":142,"column":null}},"44":{"start":{"line":141,"column":8},"end":{"line":141,"column":null}},"45":{"start":{"line":145,"column":26},"end":{"line":145,"column":null}},"46":{"start":{"line":146,"column":21},"end":{"line":146,"column":null}},"47":{"start":{"line":147,"column":28},"end":{"line":147,"column":null}},"48":{"start":{"line":149,"column":6},"end":{"line":149,"column":null}},"49":{"start":{"line":149,"column":27},"end":{"line":149,"column":null}},"50":{"start":{"line":151,"column":6},"end":{"line":151,"column":null}},"51":{"start":{"line":154,"column":23},"end":{"line":154,"column":null}},"52":{"start":{"line":155,"column":6},"end":{"line":157,"column":null}},"53":{"start":{"line":156,"column":8},"end":{"line":156,"column":null}},"54":{"start":{"line":160,"column":22},"end":{"line":160,"column":null}},"55":{"start":{"line":161,"column":20},"end":{"line":161,"column":null}},"56":{"start":{"line":164,"column":6},"end":{"line":164,"column":null}},"57":{"start":{"line":167,"column":6},"end":{"line":171,"column":null}},"58":{"start":{"line":168,"column":8},"end":{"line":170,"column":null}},"59":{"start":{"line":169,"column":10},"end":{"line":169,"column":null}},"60":{"start":{"line":174,"column":6},"end":{"line":178,"column":null}},"61":{"start":{"line":175,"column":8},"end":{"line":177,"column":null}},"62":{"start":{"line":176,"column":10},"end":{"line":176,"column":null}},"63":{"start":{"line":180,"column":6},"end":{"line":180,"column":null}},"64":{"start":{"line":188,"column":19},"end":{"line":188,"column":null}},"65":{"start":{"line":190,"column":4},"end":{"line":194,"column":null}},"66":{"start":{"line":191,"column":6},"end":{"line":193,"column":null}},"67":{"start":{"line":192,"column":8},"end":{"line":192,"column":null}},"68":{"start":{"line":202,"column":4},"end":{"line":202,"column":null}},"69":{"start":{"line":202,"column":22},"end":{"line":202,"column":null}},"70":{"start":{"line":204,"column":4},"end":{"line":204,"column":null}},"71":{"start":{"line":205,"column":4},"end":{"line":205,"column":null}},"72":{"start":{"line":208,"column":4},"end":{"line":211,"column":null}},"73":{"start":{"line":209,"column":6},"end":{"line":209,"column":null}},"74":{"start":{"line":210,"column":6},"end":{"line":210,"column":null}},"75":{"start":{"line":214,"column":4},"end":{"line":217,"column":null}},"76":{"start":{"line":215,"column":6},"end":{"line":215,"column":null}},"77":{"start":{"line":216,"column":6},"end":{"line":216,"column":null}},"78":{"start":{"line":220,"column":4},"end":{"line":238,"column":null}},"79":{"start":{"line":221,"column":6},"end":{"line":221,"column":null}},"80":{"start":{"line":224,"column":6},"end":{"line":227,"column":null}},"81":{"start":{"line":225,"column":8},"end":{"line":225,"column":null}},"82":{"start":{"line":226,"column":8},"end":{"line":226,"column":null}},"83":{"start":{"line":230,"column":24},"end":{"line":230,"column":null}},"84":{"start":{"line":231,"column":6},"end":{"line":235,"column":null}},"85":{"start":{"line":232,"column":8},"end":{"line":234,"column":null}},"86":{"start":{"line":233,"column":10},"end":{"line":233,"column":null}},"87":{"start":{"line":241,"column":4},"end":{"line":248,"column":null}},"88":{"start":{"line":242,"column":6},"end":{"line":246,"column":null}},"89":{"start":{"line":243,"column":8},"end":{"line":243,"column":null}},"90":{"start":{"line":247,"column":6},"end":{"line":247,"column":null}},"91":{"start":{"line":255,"column":4},"end":{"line":255,"column":null}}},"fnMap":{"0":{"name":"(anonymous_0)","decl":{"start":{"line":67,"column":2},"end":{"line":67,"column":14}},"loc":{"start":{"line":67,"column":42},"end":{"line":74,"column":null}},"line":67},"1":{"name":"(anonymous_1)","decl":{"start":{"line":80,"column":8},"end":{"line":80,"column":31}},"loc":{"start":{"line":80,"column":31},"end":{"line":127,"column":null}},"line":80},"2":{"name":"(anonymous_2)","decl":{"start":{"line":99,"column":42},"end":{"line":99,"column":43}},"loc":{"start":{"line":99,"column":57},"end":{"line":105,"column":7}},"line":99},"3":{"name":"(anonymous_3)","decl":{"start":{"line":101,"column":38},"end":{"line":101,"column":39}},"loc":{"start":{"line":101,"column":47},"end":{"line":103,"column":11}},"line":101},"4":{"name":"(anonymous_4)","decl":{"start":{"line":107,"column":31},"end":{"line":107,"column":32}},"loc":{"start":{"line":107,"column":40},"end":{"line":109,"column":7}},"line":107},"5":{"name":"(anonymous_5)","decl":{"start":{"line":112,"column":38},"end":{"line":112,"column":44}},"loc":{"start":{"line":112,"column":44},"end":{"line":118,"column":9}},"line":112},"6":{"name":"(anonymous_6)","decl":{"start":{"line":114,"column":38},"end":{"line":114,"column":39}},"loc":{"start":{"line":114,"column":47},"end":{"line":116,"column":11}},"line":114},"7":{"name":"(anonymous_7)","decl":{"start":{"line":133,"column":16},"end":{"line":133,"column":48}},"loc":{"start":{"line":133,"column":48},"end":{"line":182,"column":null}},"line":133},"8":{"name":"(anonymous_8)","decl":{"start":{"line":175,"column":21},"end":{"line":175,"column":27}},"loc":{"start":{"line":175,"column":27},"end":{"line":177,"column":9}},"line":175},"9":{"name":"(anonymous_9)","decl":{"start":{"line":176,"column":38},"end":{"line":176,"column":44}},"loc":{"start":{"line":176,"column":44},"end":{"line":176,"column":46}},"line":176},"10":{"name":"(anonymous_10)","decl":{"start":{"line":187,"column":10},"end":{"line":187,"column":22}},"loc":{"start":{"line":187,"column":42},"end":{"line":195,"column":null}},"line":187},"11":{"name":"(anonymous_11)","decl":{"start":{"line":201,"column":8},"end":{"line":201,"column":30}},"loc":{"start":{"line":201,"column":30},"end":{"line":249,"column":null}},"line":201},"12":{"name":"(anonymous_12)","decl":{"start":{"line":254,"column":6},"end":{"line":254,"column":27}},"loc":{"start":{"line":254,"column":27},"end":{"line":256,"column":null}},"line":254}},"branchMap":{"0":{"loc":{"start":{"line":72,"column":30},"end":{"line":72,"column":null}},"type":"binary-expr","locations":[{"start":{"line":72,"column":30},"end":{"line":72,"column":60}},{"start":{"line":72,"column":60},"end":{"line":72,"column":null}}],"line":72},"1":{"loc":{"start":{"line":81,"column":4},"end":{"line":81,"column":null}},"type":"if","locations":[{"start":{"line":81,"column":4},"end":{"line":81,"column":null}},{"start":{},"end":{}}],"line":81},"2":{"loc":{"start":{"line":90,"column":6},"end":{"line":96,"column":null}},"type":"if","locations":[{"start":{"line":90,"column":6},"end":{"line":96,"column":null}},{"start":{"line":92,"column":13},"end":{"line":96,"column":null}}],"line":90},"3":{"loc":{"start":{"line":100,"column":8},"end":{"line":104,"column":null}},"type":"if","locations":[{"start":{"line":100,"column":8},"end":{"line":104,"column":null}},{"start":{},"end":{}}],"line":100},"4":{"loc":{"start":{"line":100,"column":12},"end":{"line":100,"column":53}},"type":"binary-expr","locations":[{"start":{"line":100,"column":12},"end":{"line":100,"column":38}},{"start":{"line":100,"column":38},"end":{"line":100,"column":53}}],"line":100},"5":{"loc":{"start":{"line":102,"column":28},"end":{"line":102,"column":78}},"type":"cond-expr","locations":[{"start":{"line":102,"column":51},"end":{"line":102,"column":65}},{"start":{"line":102,"column":65},"end":{"line":102,"column":78}}],"line":102},"6":{"loc":{"start":{"line":108,"column":24},"end":{"line":108,"column":74}},"type":"cond-expr","locations":[{"start":{"line":108,"column":47},"end":{"line":108,"column":61}},{"start":{"line":108,"column":61},"end":{"line":108,"column":74}}],"line":108},"7":{"loc":{"start":{"line":113,"column":8},"end":{"line":117,"column":null}},"type":"if","locations":[{"start":{"line":113,"column":8},"end":{"line":117,"column":null}},{"start":{},"end":{}}],"line":113},"8":{"loc":{"start":{"line":115,"column":28},"end":{"line":115,"column":78}},"type":"cond-expr","locations":[{"start":{"line":115,"column":51},"end":{"line":115,"column":65}},{"start":{"line":115,"column":65},"end":{"line":115,"column":78}}],"line":115},"9":{"loc":{"start":{"line":121,"column":6},"end":{"line":123,"column":null}},"type":"if","locations":[{"start":{"line":121,"column":6},"end":{"line":123,"column":null}},{"start":{},"end":{}}],"line":121},"10":{"loc":{"start":{"line":125,"column":23},"end":{"line":125,"column":73}},"type":"cond-expr","locations":[{"start":{"line":125,"column":46},"end":{"line":125,"column":60}},{"start":{"line":125,"column":60},"end":{"line":125,"column":73}}],"line":125},"11":{"loc":{"start":{"line":134,"column":4},"end":{"line":134,"column":null}},"type":"if","locations":[{"start":{"line":134,"column":4},"end":{"line":134,"column":null}},{"start":{},"end":{}}],"line":134},"12":{"loc":{"start":{"line":134,"column":8},"end":{"line":134,"column":58}},"type":"binary-expr","locations":[{"start":{"line":134,"column":8},"end":{"line":134,"column":24}},{"start":{"line":134,"column":24},"end":{"line":134,"column":44}},{"start":{"line":134,"column":44},"end":{"line":134,"column":58}}],"line":134},"13":{"loc":{"start":{"line":140,"column":6},"end":{"line":142,"column":null}},"type":"if","locations":[{"start":{"line":140,"column":6},"end":{"line":142,"column":null}},{"start":{},"end":{}}],"line":140},"14":{"loc":{"start":{"line":149,"column":6},"end":{"line":149,"column":null}},"type":"if","locations":[{"start":{"line":149,"column":6},"end":{"line":149,"column":null}},{"start":{},"end":{}}],"line":149},"15":{"loc":{"start":{"line":155,"column":6},"end":{"line":157,"column":null}},"type":"if","locations":[{"start":{"line":155,"column":6},"end":{"line":157,"column":null}},{"start":{},"end":{}}],"line":155},"16":{"loc":{"start":{"line":164,"column":25},"end":{"line":164,"column":null}},"type":"binary-expr","locations":[{"start":{"line":164,"column":25},"end":{"line":164,"column":40}},{"start":{"line":164,"column":40},"end":{"line":164,"column":null}}],"line":164},"17":{"loc":{"start":{"line":168,"column":8},"end":{"line":170,"column":null}},"type":"if","locations":[{"start":{"line":168,"column":8},"end":{"line":170,"column":null}},{"start":{},"end":{}}],"line":168},"18":{"loc":{"start":{"line":174,"column":6},"end":{"line":178,"column":null}},"type":"if","locations":[{"start":{"line":174,"column":6},"end":{"line":178,"column":null}},{"start":{},"end":{}}],"line":174},"19":{"loc":{"start":{"line":191,"column":6},"end":{"line":193,"column":null}},"type":"if","locations":[{"start":{"line":191,"column":6},"end":{"line":193,"column":null}},{"start":{},"end":{}}],"line":191},"20":{"loc":{"start":{"line":202,"column":4},"end":{"line":202,"column":null}},"type":"if","locations":[{"start":{"line":202,"column":4},"end":{"line":202,"column":null}},{"start":{},"end":{}}],"line":202},"21":{"loc":{"start":{"line":208,"column":4},"end":{"line":211,"column":null}},"type":"if","locations":[{"start":{"line":208,"column":4},"end":{"line":211,"column":null}},{"start":{},"end":{}}],"line":208},"22":{"loc":{"start":{"line":214,"column":4},"end":{"line":217,"column":null}},"type":"if","locations":[{"start":{"line":214,"column":4},"end":{"line":217,"column":null}},{"start":{},"end":{}}],"line":214},"23":{"loc":{"start":{"line":224,"column":6},"end":{"line":227,"column":null}},"type":"if","locations":[{"start":{"line":224,"column":6},"end":{"line":227,"column":null}},{"start":{},"end":{}}],"line":224},"24":{"loc":{"start":{"line":232,"column":8},"end":{"line":234,"column":null}},"type":"if","locations":[{"start":{"line":232,"column":8},"end":{"line":234,"column":null}},{"start":{},"end":{}}],"line":232},"25":{"loc":{"start":{"line":241,"column":4},"end":{"line":248,"column":null}},"type":"if","locations":[{"start":{"line":241,"column":4},"end":{"line":248,"column":null}},{"start":{},"end":{}}],"line":241}},"s":{"0":14,"1":14,"2":14,"3":0,"4":0,"5":0,"6":0,"7":0,"8":0,"9":0,"10":0,"11":0,"12":0,"13":0,"14":0,"15":0,"16":0,"17":0,"18":0,"19":0,"20":0,"21":0,"22":0,"23":0,"24":0,"25":0,"26":0,"27":0,"28":0,"29":0,"30":0,"31":0,"32":0,"33":0,"34":0,"35":0,"36":0,"37":0,"38":0,"39":0,"40":0,"41":0,"42":0,"43":0,"44":0,"45":0,"46":0,"47":0,"48":0,"49":0,"50":0,"51":0,"52":0,"53":0,"54":0,"55":0,"56":0,"57":0,"58":0,"59":0,"60":0,"61":0,"62":0,"63":0,"64":0,"65":0,"66":0,"67":0,"68":0,"69":0,"70":0,"71":0,"72":0,"73":0,"74":0,"75":0,"76":0,"77":0,"78":0,"79":0,"80":0,"81":0,"82":0,"83":0,"84":0,"85":0,"86":0,"87":0,"88":0,"89":0,"90":0,"91":0},"f":{"0":0,"1":0,"2":0,"3":0,"4":0,"5":0,"6":0,"7":0,"8":0,"9":0,"10":0,"11":0,"12":0},"b":{"0":[0,0],"1":[0,0],"2":[0,0],"3":[0,0],"4":[0,0],"5":[0,0],"6":[0,0],"7":[0,0],"8":[0,0],"9":[0,0],"10":[0,0],"11":[0,0],"12":[0,0,0],"13":[0,0],"14":[0,0],"15":[0,0],"16":[0,0],"17":[0,0],"18":[0,0],"19":[0,0],"20":[0,0],"21":[0,0],"22":[0,0],"23":[0,0],"24":[0,0],"25":[0,0]},"meta":{"lastBranch":26,"lastFunction":13,"lastStatement":92,"seen":{"s:18:6:18:Infinity":0,"s:21:25:21:Infinity":1,"s:24:25:24:Infinity":2,"s:52:21:52:Infinity":3,"s:53:38:53:Infinity":4,"s:54:48:54:Infinity":5,"s:55:42:55:Infinity":6,"s:56:20:56:Infinity":7,"s:57:24:57:Infinity":8,"s:58:20:58:Infinity":9,"f:67:2:67:14":0,"s:68:4:68:Infinity":10,"s:69:4:69:Infinity":11,"s:70:4:70:Infinity":12,"s:71:4:71:Infinity":13,"s:72:4:72:Infinity":14,"b:72:30:72:60:72:60:72:Infinity":0,"s:73:4:73:Infinity":15,"f:80:8:80:31":1,"b:81:4:81:Infinity:undefined:undefined:undefined:undefined":1,"s:81:4:81:Infinity":16,"s:81:22:81:Infinity":17,"s:83:4:83:Infinity":18,"s:85:4:126:Infinity":19,"s:87:6:87:Infinity":20,"b:90:6:96:Infinity:92:13:96:Infinity":2,"s:90:6:96:Infinity":21,"s:91:8:91:Infinity":22,"s:94:22:94:Infinity":23,"s:95:8:95:Infinity":24,"s:99:6:105:Infinity":25,"f:99:42:99:43":2,"b:100:8:104:Infinity:undefined:undefined:undefined:undefined":3,"s:100:8:104:Infinity":26,"b:100:12:100:38:100:38:100:53":4,"s:101:10:103:Infinity":27,"f:101:38:101:39":3,"s:102:12:102:Infinity":28,"b:102:51:102:65:102:65:102:78":5,"s:107:6:109:Infinity":29,"f:107:31:107:32":4,"s:108:8:108:Infinity":30,"b:108:47:108:61:108:61:108:74":6,"s:112:6:118:Infinity":31,"f:112:38:112:44":5,"b:113:8:117:Infinity:undefined:undefined:undefined:undefined":7,"s:113:8:117:Infinity":32,"s:114:10:116:Infinity":33,"f:114:38:114:39":6,"s:115:12:115:Infinity":34,"b:115:51:115:65:115:65:115:78":8,"b:121:6:123:Infinity:undefined:undefined:undefined:undefined":9,"s:121:6:123:Infinity":35,"s:122:8:122:Infinity":36,"s:125:6:125:Infinity":37,"b:125:46:125:60:125:60:125:73":10,"f:133:16:133:48":7,"b:134:4:134:Infinity:undefined:undefined:undefined:undefined":11,"s:134:4:134:Infinity":38,"b:134:8:134:24:134:24:134:44:134:44:134:58":12,"s:134:58:134:Infinity":39,"s:136:4:136:Infinity":40,"s:137:4:181:Infinity":41,"s:139:20:139:Infinity":42,"b:140:6:142:Infinity:undefined:undefined:undefined:undefined":13,"s:140:6:142:Infinity":43,"s:141:8:141:Infinity":44,"s:145:26:145:Infinity":45,"s:146:21:146:Infinity":46,"s:147:28:147:Infinity":47,"b:149:6:149:Infinity:undefined:undefined:undefined:undefined":14,"s:149:6:149:Infinity":48,"s:149:27:149:Infinity":49,"s:151:6:151:Infinity":50,"s:154:23:154:Infinity":51,"b:155:6:157:Infinity:undefined:undefined:undefined:undefined":15,"s:155:6:157:Infinity":52,"s:156:8:156:Infinity":53,"s:160:22:160:Infinity":54,"s:161:20:161:Infinity":55,"s:164:6:164:Infinity":56,"b:164:25:164:40:164:40:164:Infinity":16,"s:167:6:171:Infinity":57,"b:168:8:170:Infinity:undefined:undefined:undefined:undefined":17,"s:168:8:170:Infinity":58,"s:169:10:169:Infinity":59,"b:174:6:178:Infinity:undefined:undefined:undefined:undefined":18,"s:174:6:178:Infinity":60,"s:175:8:177:Infinity":61,"f:175:21:175:27":8,"s:176:10:176:Infinity":62,"f:176:38:176:44":9,"s:180:6:180:Infinity":63,"f:187:10:187:22":10,"s:188:19:188:Infinity":64,"s:190:4:194:Infinity":65,"b:191:6:193:Infinity:undefined:undefined:undefined:undefined":19,"s:191:6:193:Infinity":66,"s:192:8:192:Infinity":67,"f:201:8:201:30":11,"b:202:4:202:Infinity:undefined:undefined:undefined:undefined":20,"s:202:4:202:Infinity":68,"s:202:22:202:Infinity":69,"s:204:4:204:Infinity":70,"s:205:4:205:Infinity":71,"b:208:4:211:Infinity:undefined:undefined:undefined:undefined":21,"s:208:4:211:Infinity":72,"s:209:6:209:Infinity":73,"s:210:6:210:Infinity":74,"b:214:4:217:Infinity:undefined:undefined:undefined:undefined":22,"s:214:4:217:Infinity":75,"s:215:6:215:Infinity":76,"s:216:6:216:Infinity":77,"s:220:4:238:Infinity":78,"s:221:6:221:Infinity":79,"b:224:6:227:Infinity:undefined:undefined:undefined:undefined":23,"s:224:6:227:Infinity":80,"s:225:8:225:Infinity":81,"s:226:8:226:Infinity":82,"s:230:24:230:Infinity":83,"s:231:6:235:Infinity":84,"b:232:8:234:Infinity:undefined:undefined:undefined:undefined":24,"s:232:8:234:Infinity":85,"s:233:10:233:Infinity":86,"b:241:4:248:Infinity:undefined:undefined:undefined:undefined":25,"s:241:4:248:Infinity":87,"s:242:6:246:Infinity":88,"s:243:8:243:Infinity":89,"s:247:6:247:Infinity":90,"f:254:6:254:27":12,"s:255:4:255:Infinity":91}}} +,"/Users/lukasmay/development/projects/codewalk-district/src/agent/index.ts": {"path":"/Users/lukasmay/development/projects/codewalk-district/src/agent/index.ts","statementMap":{},"fnMap":{},"branchMap":{},"s":{},"f":{},"b":{},"meta":{"lastBranch":0,"lastFunction":0,"lastStatement":0,"seen":{}}} +,"/Users/lukasmay/development/projects/codewalk-district/src/agent/manager.ts": {"path":"/Users/lukasmay/development/projects/codewalk-district/src/agent/manager.ts","statementMap":{"0":{"start":{"line":56,"column":6},"end":{"line":56,"column":null}},"1":{"start":{"line":59,"column":47},"end":{"line":59,"column":null}},"2":{"start":{"line":61,"column":51},"end":{"line":61,"column":null}},"3":{"start":{"line":62,"column":50},"end":{"line":62,"column":null}},"4":{"start":{"line":71,"column":12},"end":{"line":71,"column":null}},"5":{"start":{"line":72,"column":12},"end":{"line":72,"column":null}},"6":{"start":{"line":73,"column":12},"end":{"line":73,"column":null}},"7":{"start":{"line":74,"column":12},"end":{"line":74,"column":null}},"8":{"start":{"line":75,"column":12},"end":{"line":75,"column":null}},"9":{"start":{"line":76,"column":12},"end":{"line":76,"column":null}},"10":{"start":{"line":77,"column":12},"end":{"line":77,"column":null}},"11":{"start":{"line":78,"column":12},"end":{"line":78,"column":null}},"12":{"start":{"line":79,"column":12},"end":{"line":79,"column":null}},"13":{"start":{"line":80,"column":12},"end":{"line":80,"column":null}},"14":{"start":{"line":81,"column":12},"end":{"line":81,"column":null}},"15":{"start":{"line":82,"column":12},"end":{"line":82,"column":29}},"16":{"start":{"line":84,"column":4},"end":{"line":84,"column":null}},"17":{"start":{"line":85,"column":4},"end":{"line":85,"column":null}},"18":{"start":{"line":86,"column":4},"end":{"line":86,"column":null}},"19":{"start":{"line":87,"column":4},"end":{"line":87,"column":null}},"20":{"start":{"line":88,"column":4},"end":{"line":88,"column":null}},"21":{"start":{"line":89,"column":4},"end":{"line":95,"column":null}},"22":{"start":{"line":98,"column":4},"end":{"line":102,"column":null}},"23":{"start":{"line":99,"column":6},"end":{"line":101,"column":null}},"24":{"start":{"line":100,"column":8},"end":{"line":100,"column":null}},"25":{"start":{"line":110,"column":19},"end":{"line":110,"column":null}},"26":{"start":{"line":111,"column":4},"end":{"line":111,"column":null}},"27":{"start":{"line":111,"column":28},"end":{"line":111,"column":null}},"28":{"start":{"line":112,"column":4},"end":{"line":112,"column":null}},"29":{"start":{"line":113,"column":4},"end":{"line":113,"column":null}},"30":{"start":{"line":125,"column":17},"end":{"line":125,"column":null}},"31":{"start":{"line":126,"column":4},"end":{"line":126,"column":null}},"32":{"start":{"line":126,"column":15},"end":{"line":126,"column":null}},"33":{"start":{"line":128,"column":4},"end":{"line":140,"column":null}},"34":{"start":{"line":129,"column":6},"end":{"line":139,"column":null}},"35":{"start":{"line":131,"column":10},"end":{"line":137,"column":null}},"36":{"start":{"line":132,"column":12},"end":{"line":136,"column":null}},"37":{"start":{"line":139,"column":22},"end":{"line":139,"column":129}},"38":{"start":{"line":148,"column":4},"end":{"line":153,"column":null}},"39":{"start":{"line":156,"column":4},"end":{"line":163,"column":null}},"40":{"start":{"line":158,"column":22},"end":{"line":158,"column":null}},"41":{"start":{"line":159,"column":8},"end":{"line":159,"column":null}},"42":{"start":{"line":160,"column":8},"end":{"line":160,"column":null}},"43":{"start":{"line":164,"column":4},"end":{"line":164,"column":null}},"44":{"start":{"line":172,"column":4},"end":{"line":172,"column":null}},"45":{"start":{"line":180,"column":119},"end":{"line":180,"column":null}},"46":{"start":{"line":181,"column":21},"end":{"line":181,"column":null}},"47":{"start":{"line":182,"column":4},"end":{"line":182,"column":null}},"48":{"start":{"line":184,"column":10},"end":{"line":184,"column":null}},"49":{"start":{"line":185,"column":4},"end":{"line":187,"column":null}},"50":{"start":{"line":186,"column":6},"end":{"line":186,"column":null}},"51":{"start":{"line":191,"column":4},"end":{"line":199,"column":null}},"52":{"start":{"line":192,"column":6},"end":{"line":192,"column":null}},"53":{"start":{"line":193,"column":23},"end":{"line":193,"column":null}},"54":{"start":{"line":194,"column":6},"end":{"line":196,"column":null}},"55":{"start":{"line":195,"column":8},"end":{"line":195,"column":null}},"56":{"start":{"line":198,"column":6},"end":{"line":198,"column":null}},"57":{"start":{"line":200,"column":18},"end":{"line":200,"column":null}},"58":{"start":{"line":201,"column":4},"end":{"line":201,"column":null}},"59":{"start":{"line":204,"column":35},"end":{"line":204,"column":null}},"60":{"start":{"line":205,"column":42},"end":{"line":205,"column":null}},"61":{"start":{"line":207,"column":26},"end":{"line":207,"column":null}},"62":{"start":{"line":208,"column":4},"end":{"line":220,"column":null}},"63":{"start":{"line":209,"column":6},"end":{"line":209,"column":null}},"64":{"start":{"line":210,"column":6},"end":{"line":210,"column":null}},"65":{"start":{"line":212,"column":6},"end":{"line":212,"column":null}},"66":{"start":{"line":213,"column":35},"end":{"line":213,"column":null}},"67":{"start":{"line":214,"column":6},"end":{"line":216,"column":null}},"68":{"start":{"line":215,"column":8},"end":{"line":215,"column":null}},"69":{"start":{"line":217,"column":6},"end":{"line":219,"column":null}},"70":{"start":{"line":218,"column":8},"end":{"line":218,"column":null}},"71":{"start":{"line":222,"column":4},"end":{"line":226,"column":null}},"72":{"start":{"line":223,"column":6},"end":{"line":223,"column":null}},"73":{"start":{"line":225,"column":6},"end":{"line":225,"column":null}},"74":{"start":{"line":230,"column":4},"end":{"line":247,"column":null}},"75":{"start":{"line":231,"column":6},"end":{"line":231,"column":null}},"76":{"start":{"line":232,"column":6},"end":{"line":232,"column":null}},"77":{"start":{"line":235,"column":23},"end":{"line":235,"column":null}},"78":{"start":{"line":236,"column":6},"end":{"line":242,"column":null}},"79":{"start":{"line":240,"column":37},"end":{"line":240,"column":66}},"80":{"start":{"line":244,"column":6},"end":{"line":244,"column":null}},"81":{"start":{"line":245,"column":6},"end":{"line":245,"column":null}},"82":{"start":{"line":246,"column":6},"end":{"line":246,"column":null}},"83":{"start":{"line":250,"column":10},"end":{"line":250,"column":null}},"84":{"start":{"line":251,"column":4},"end":{"line":256,"column":null}},"85":{"start":{"line":259,"column":10},"end":{"line":259,"column":null}},"86":{"start":{"line":260,"column":4},"end":{"line":262,"column":null}},"87":{"start":{"line":261,"column":6},"end":{"line":261,"column":null}},"88":{"start":{"line":265,"column":18},"end":{"line":275,"column":null}},"89":{"start":{"line":276,"column":20},"end":{"line":276,"column":null}},"90":{"start":{"line":279,"column":4},"end":{"line":279,"column":null}},"91":{"start":{"line":282,"column":4},"end":{"line":285,"column":null}},"92":{"start":{"line":283,"column":6},"end":{"line":283,"column":null}},"93":{"start":{"line":284,"column":6},"end":{"line":284,"column":null}},"94":{"start":{"line":288,"column":48},"end":{"line":288,"column":null}},"95":{"start":{"line":289,"column":21},"end":{"line":289,"column":null}},"96":{"start":{"line":291,"column":4},"end":{"line":299,"column":null}},"97":{"start":{"line":302,"column":27},"end":{"line":302,"column":null}},"98":{"start":{"line":304,"column":4},"end":{"line":309,"column":null}},"99":{"start":{"line":312,"column":44},"end":{"line":316,"column":null}},"100":{"start":{"line":314,"column":17},"end":{"line":314,"column":null}},"101":{"start":{"line":318,"column":4},"end":{"line":318,"column":null}},"102":{"start":{"line":321,"column":23},"end":{"line":335,"column":null}},"103":{"start":{"line":337,"column":4},"end":{"line":341,"column":null}},"104":{"start":{"line":343,"column":37},"end":{"line":343,"column":null}},"105":{"start":{"line":344,"column":4},"end":{"line":344,"column":null}},"106":{"start":{"line":345,"column":4},"end":{"line":345,"column":null}},"107":{"start":{"line":348,"column":4},"end":{"line":355,"column":null}},"108":{"start":{"line":349,"column":39},"end":{"line":353,"column":null}},"109":{"start":{"line":354,"column":6},"end":{"line":354,"column":null}},"110":{"start":{"line":358,"column":23},"end":{"line":362,"column":null}},"111":{"start":{"line":360,"column":12},"end":{"line":360,"column":null}},"112":{"start":{"line":361,"column":12},"end":{"line":361,"column":null}},"113":{"start":{"line":363,"column":4},"end":{"line":363,"column":null}},"114":{"start":{"line":365,"column":4},"end":{"line":365,"column":null}},"115":{"start":{"line":372,"column":4},"end":{"line":372,"column":null}},"116":{"start":{"line":372,"column":41},"end":{"line":372,"column":null}},"117":{"start":{"line":374,"column":19},"end":{"line":374,"column":null}},"118":{"start":{"line":375,"column":4},"end":{"line":379,"column":null}},"119":{"start":{"line":378,"column":17},"end":{"line":378,"column":null}},"120":{"start":{"line":382,"column":4},"end":{"line":382,"column":null}},"121":{"start":{"line":384,"column":4},"end":{"line":384,"column":null}},"122":{"start":{"line":387,"column":4},"end":{"line":387,"column":null}},"123":{"start":{"line":395,"column":4},"end":{"line":425,"column":null}},"124":{"start":{"line":396,"column":20},"end":{"line":396,"column":null}},"125":{"start":{"line":397,"column":6},"end":{"line":397,"column":null}},"126":{"start":{"line":397,"column":45},"end":{"line":397,"column":null}},"127":{"start":{"line":399,"column":33},"end":{"line":401,"column":null}},"128":{"start":{"line":403,"column":6},"end":{"line":407,"column":null}},"129":{"start":{"line":404,"column":8},"end":{"line":404,"column":null}},"130":{"start":{"line":405,"column":8},"end":{"line":405,"column":null}},"131":{"start":{"line":406,"column":8},"end":{"line":406,"column":null}},"132":{"start":{"line":409,"column":6},"end":{"line":421,"column":null}},"133":{"start":{"line":410,"column":24},"end":{"line":410,"column":null}},"134":{"start":{"line":411,"column":8},"end":{"line":418,"column":null}},"135":{"start":{"line":412,"column":10},"end":{"line":412,"column":null}},"136":{"start":{"line":413,"column":26},"end":{"line":413,"column":null}},"137":{"start":{"line":414,"column":10},"end":{"line":417,"column":null}},"138":{"start":{"line":415,"column":12},"end":{"line":415,"column":null}},"139":{"start":{"line":416,"column":12},"end":{"line":416,"column":null}},"140":{"start":{"line":419,"column":8},"end":{"line":419,"column":null}},"141":{"start":{"line":420,"column":8},"end":{"line":420,"column":null}},"142":{"start":{"line":423,"column":6},"end":{"line":423,"column":null}},"143":{"start":{"line":424,"column":6},"end":{"line":424,"column":null}},"144":{"start":{"line":433,"column":18},"end":{"line":433,"column":null}},"145":{"start":{"line":434,"column":4},"end":{"line":434,"column":null}},"146":{"start":{"line":434,"column":27},"end":{"line":434,"column":null}},"147":{"start":{"line":436,"column":10},"end":{"line":436,"column":null}},"148":{"start":{"line":437,"column":4},"end":{"line":437,"column":null}},"149":{"start":{"line":437,"column":54},"end":{"line":437,"column":null}},"150":{"start":{"line":440,"column":23},"end":{"line":440,"column":null}},"151":{"start":{"line":441,"column":4},"end":{"line":441,"column":null}},"152":{"start":{"line":441,"column":33},"end":{"line":441,"column":null}},"153":{"start":{"line":443,"column":22},"end":{"line":443,"column":null}},"154":{"start":{"line":443,"column":42},"end":{"line":443,"column":55}},"155":{"start":{"line":445,"column":6},"end":{"line":446,"column":null}},"156":{"start":{"line":450,"column":4},"end":{"line":450,"column":null}},"157":{"start":{"line":452,"column":21},"end":{"line":452,"column":null}},"158":{"start":{"line":453,"column":48},"end":{"line":453,"column":null}},"159":{"start":{"line":455,"column":27},"end":{"line":455,"column":null}},"160":{"start":{"line":457,"column":23},"end":{"line":457,"column":null}},"161":{"start":{"line":458,"column":4},"end":{"line":458,"column":null}},"162":{"start":{"line":459,"column":4},"end":{"line":461,"column":null}},"163":{"start":{"line":460,"column":6},"end":{"line":460,"column":null}},"164":{"start":{"line":464,"column":30},"end":{"line":464,"column":null}},"165":{"start":{"line":465,"column":4},"end":{"line":467,"column":null}},"166":{"start":{"line":466,"column":6},"end":{"line":466,"column":null}},"167":{"start":{"line":469,"column":44},"end":{"line":473,"column":null}},"168":{"start":{"line":471,"column":17},"end":{"line":471,"column":null}},"169":{"start":{"line":475,"column":4},"end":{"line":475,"column":null}},"170":{"start":{"line":476,"column":43},"end":{"line":476,"column":null}},"171":{"start":{"line":477,"column":4},"end":{"line":477,"column":null}},"172":{"start":{"line":479,"column":37},"end":{"line":483,"column":null}},"173":{"start":{"line":481,"column":12},"end":{"line":481,"column":null}},"174":{"start":{"line":482,"column":12},"end":{"line":482,"column":null}},"175":{"start":{"line":484,"column":4},"end":{"line":484,"column":null}},"176":{"start":{"line":486,"column":4},"end":{"line":486,"column":null}},"177":{"start":{"line":495,"column":4},"end":{"line":495,"column":null}},"178":{"start":{"line":495,"column":33},"end":{"line":495,"column":null}},"179":{"start":{"line":497,"column":4},"end":{"line":507,"column":null}},"180":{"start":{"line":498,"column":20},"end":{"line":498,"column":null}},"181":{"start":{"line":499,"column":6},"end":{"line":499,"column":null}},"182":{"start":{"line":499,"column":29},"end":{"line":499,"column":null}},"183":{"start":{"line":501,"column":38},"end":{"line":501,"column":null}},"184":{"start":{"line":502,"column":24},"end":{"line":502,"column":null}},"185":{"start":{"line":503,"column":6},"end":{"line":503,"column":null}},"186":{"start":{"line":504,"column":6},"end":{"line":504,"column":null}},"187":{"start":{"line":506,"column":6},"end":{"line":506,"column":null}},"188":{"start":{"line":514,"column":18},"end":{"line":514,"column":null}},"189":{"start":{"line":515,"column":4},"end":{"line":515,"column":null}},"190":{"start":{"line":515,"column":16},"end":{"line":515,"column":null}},"191":{"start":{"line":516,"column":4},"end":{"line":516,"column":null}},"192":{"start":{"line":518,"column":19},"end":{"line":518,"column":null}},"193":{"start":{"line":519,"column":4},"end":{"line":522,"column":null}},"194":{"start":{"line":520,"column":6},"end":{"line":520,"column":null}},"195":{"start":{"line":520,"column":12},"end":{"line":520,"column":49}},"196":{"start":{"line":521,"column":6},"end":{"line":521,"column":null}},"197":{"start":{"line":523,"column":4},"end":{"line":523,"column":null}},"198":{"start":{"line":526,"column":4},"end":{"line":526,"column":null}},"199":{"start":{"line":528,"column":4},"end":{"line":528,"column":null}},"200":{"start":{"line":530,"column":4},"end":{"line":537,"column":null}},"201":{"start":{"line":531,"column":39},"end":{"line":535,"column":null}},"202":{"start":{"line":536,"column":6},"end":{"line":536,"column":null}},"203":{"start":{"line":544,"column":19},"end":{"line":544,"column":null}},"204":{"start":{"line":545,"column":4},"end":{"line":545,"column":null}},"205":{"start":{"line":545,"column":29},"end":{"line":545,"column":48}},"206":{"start":{"line":552,"column":18},"end":{"line":552,"column":null}},"207":{"start":{"line":553,"column":4},"end":{"line":553,"column":null}},"208":{"start":{"line":560,"column":18},"end":{"line":560,"column":null}},"209":{"start":{"line":561,"column":4},"end":{"line":561,"column":null}},"210":{"start":{"line":569,"column":4},"end":{"line":572,"column":null}},"211":{"start":{"line":574,"column":4},"end":{"line":577,"column":null}},"212":{"start":{"line":575,"column":31},"end":{"line":575,"column":null}},"213":{"start":{"line":585,"column":4},"end":{"line":585,"column":null}},"214":{"start":{"line":593,"column":18},"end":{"line":593,"column":null}},"215":{"start":{"line":594,"column":4},"end":{"line":594,"column":null}},"216":{"start":{"line":594,"column":16},"end":{"line":594,"column":null}},"217":{"start":{"line":595,"column":4},"end":{"line":597,"column":null}},"218":{"start":{"line":596,"column":6},"end":{"line":596,"column":null}},"219":{"start":{"line":598,"column":4},"end":{"line":600,"column":null}},"220":{"start":{"line":599,"column":6},"end":{"line":599,"column":null}},"221":{"start":{"line":601,"column":4},"end":{"line":601,"column":null}},"222":{"start":{"line":603,"column":10},"end":{"line":603,"column":null}},"223":{"start":{"line":604,"column":4},"end":{"line":604,"column":null}},"224":{"start":{"line":604,"column":19},"end":{"line":604,"column":null}},"225":{"start":{"line":605,"column":4},"end":{"line":607,"column":null}},"226":{"start":{"line":606,"column":6},"end":{"line":606,"column":null}},"227":{"start":{"line":609,"column":21},"end":{"line":609,"column":null}},"228":{"start":{"line":610,"column":19},"end":{"line":610,"column":null}},"229":{"start":{"line":613,"column":10},"end":{"line":613,"column":null}},"230":{"start":{"line":614,"column":4},"end":{"line":619,"column":null}},"231":{"start":{"line":615,"column":6},"end":{"line":615,"column":null}},"232":{"start":{"line":616,"column":6},"end":{"line":616,"column":null}},"233":{"start":{"line":621,"column":4},"end":{"line":621,"column":null}},"234":{"start":{"line":623,"column":48},"end":{"line":623,"column":null}},"235":{"start":{"line":624,"column":4},"end":{"line":624,"column":null}},"236":{"start":{"line":627,"column":27},"end":{"line":627,"column":null}},"237":{"start":{"line":630,"column":23},"end":{"line":630,"column":null}},"238":{"start":{"line":631,"column":4},"end":{"line":631,"column":null}},"239":{"start":{"line":632,"column":4},"end":{"line":634,"column":null}},"240":{"start":{"line":633,"column":6},"end":{"line":633,"column":null}},"241":{"start":{"line":637,"column":30},"end":{"line":637,"column":null}},"242":{"start":{"line":638,"column":4},"end":{"line":640,"column":null}},"243":{"start":{"line":639,"column":6},"end":{"line":639,"column":null}},"244":{"start":{"line":642,"column":44},"end":{"line":646,"column":null}},"245":{"start":{"line":644,"column":17},"end":{"line":644,"column":null}},"246":{"start":{"line":648,"column":4},"end":{"line":648,"column":null}},"247":{"start":{"line":650,"column":43},"end":{"line":650,"column":null}},"248":{"start":{"line":651,"column":4},"end":{"line":651,"column":null}},"249":{"start":{"line":652,"column":4},"end":{"line":652,"column":null}},"250":{"start":{"line":654,"column":4},"end":{"line":661,"column":null}},"251":{"start":{"line":655,"column":39},"end":{"line":659,"column":null}},"252":{"start":{"line":660,"column":6},"end":{"line":660,"column":null}},"253":{"start":{"line":663,"column":37},"end":{"line":667,"column":null}},"254":{"start":{"line":665,"column":12},"end":{"line":665,"column":null}},"255":{"start":{"line":666,"column":12},"end":{"line":666,"column":null}},"256":{"start":{"line":668,"column":4},"end":{"line":668,"column":null}},"257":{"start":{"line":675,"column":4},"end":{"line":675,"column":null}},"258":{"start":{"line":682,"column":4},"end":{"line":682,"column":null}},"259":{"start":{"line":689,"column":18},"end":{"line":689,"column":null}},"260":{"start":{"line":690,"column":4},"end":{"line":690,"column":null}},"261":{"start":{"line":690,"column":16},"end":{"line":690,"column":null}},"262":{"start":{"line":691,"column":4},"end":{"line":691,"column":null}},"263":{"start":{"line":694,"column":19},"end":{"line":694,"column":null}},"264":{"start":{"line":695,"column":4},"end":{"line":698,"column":null}},"265":{"start":{"line":696,"column":6},"end":{"line":696,"column":null}},"266":{"start":{"line":696,"column":12},"end":{"line":696,"column":49}},"267":{"start":{"line":697,"column":6},"end":{"line":697,"column":null}},"268":{"start":{"line":699,"column":4},"end":{"line":699,"column":null}},"269":{"start":{"line":702,"column":4},"end":{"line":703,"column":null}},"270":{"start":{"line":702,"column":10},"end":{"line":702,"column":90}},"271":{"start":{"line":703,"column":18},"end":{"line":703,"column":126}},"272":{"start":{"line":705,"column":4},"end":{"line":706,"column":null}},"273":{"start":{"line":705,"column":10},"end":{"line":705,"column":89}},"274":{"start":{"line":706,"column":18},"end":{"line":706,"column":125}},"275":{"start":{"line":708,"column":4},"end":{"line":709,"column":null}},"276":{"start":{"line":708,"column":10},"end":{"line":708,"column":65}},"277":{"start":{"line":709,"column":18},"end":{"line":709,"column":121}},"278":{"start":{"line":712,"column":4},"end":{"line":715,"column":null}},"279":{"start":{"line":713,"column":6},"end":{"line":714,"column":null}},"280":{"start":{"line":713,"column":12},"end":{"line":713,"column":68}},"281":{"start":{"line":714,"column":20},"end":{"line":714,"column":129}},"282":{"start":{"line":718,"column":4},"end":{"line":718,"column":null}},"283":{"start":{"line":721,"column":4},"end":{"line":728,"column":null}},"284":{"start":{"line":722,"column":39},"end":{"line":726,"column":null}},"285":{"start":{"line":727,"column":6},"end":{"line":727,"column":null}},"286":{"start":{"line":729,"column":4},"end":{"line":729,"column":null}},"287":{"start":{"line":736,"column":18},"end":{"line":736,"column":null}},"288":{"start":{"line":737,"column":4},"end":{"line":737,"column":null}},"289":{"start":{"line":737,"column":16},"end":{"line":737,"column":null}},"290":{"start":{"line":738,"column":4},"end":{"line":738,"column":null}},"291":{"start":{"line":740,"column":4},"end":{"line":740,"column":null}},"292":{"start":{"line":742,"column":4},"end":{"line":745,"column":null}},"293":{"start":{"line":747,"column":4},"end":{"line":747,"column":null}},"294":{"start":{"line":754,"column":4},"end":{"line":754,"column":null}},"295":{"start":{"line":761,"column":4},"end":{"line":761,"column":null}},"296":{"start":{"line":768,"column":34},"end":{"line":768,"column":null}},"297":{"start":{"line":769,"column":4},"end":{"line":795,"column":null}},"298":{"start":{"line":771,"column":26},"end":{"line":771,"column":null}},"299":{"start":{"line":772,"column":40},"end":{"line":772,"column":null}},"300":{"start":{"line":772,"column":119},"end":{"line":772,"column":161}},"301":{"start":{"line":774,"column":27},"end":{"line":778,"column":null}},"302":{"start":{"line":776,"column":16},"end":{"line":776,"column":null}},"303":{"start":{"line":777,"column":16},"end":{"line":777,"column":null}},"304":{"start":{"line":779,"column":23},"end":{"line":779,"column":null}},"305":{"start":{"line":780,"column":8},"end":{"line":780,"column":null}},"306":{"start":{"line":780,"column":20},"end":{"line":780,"column":null}},"307":{"start":{"line":785,"column":12},"end":{"line":792,"column":null}},"308":{"start":{"line":786,"column":14},"end":{"line":791,"column":null}},"309":{"start":{"line":792,"column":28},"end":{"line":792,"column":157}},"310":{"start":{"line":803,"column":4},"end":{"line":870,"column":null}},"311":{"start":{"line":805,"column":20},"end":{"line":805,"column":null}},"312":{"start":{"line":806,"column":6},"end":{"line":808,"column":null}},"313":{"start":{"line":807,"column":8},"end":{"line":807,"column":null}},"314":{"start":{"line":811,"column":6},"end":{"line":811,"column":null}},"315":{"start":{"line":813,"column":6},"end":{"line":819,"column":null}},"316":{"start":{"line":822,"column":6},"end":{"line":862,"column":null}},"317":{"start":{"line":823,"column":30},"end":{"line":823,"column":null}},"318":{"start":{"line":824,"column":8},"end":{"line":852,"column":null}},"319":{"start":{"line":825,"column":10},"end":{"line":830,"column":null}},"320":{"start":{"line":836,"column":10},"end":{"line":840,"column":null}},"321":{"start":{"line":842,"column":10},"end":{"line":848,"column":null}},"322":{"start":{"line":851,"column":10},"end":{"line":851,"column":null}},"323":{"start":{"line":854,"column":8},"end":{"line":859,"column":null}},"324":{"start":{"line":861,"column":8},"end":{"line":861,"column":null}},"325":{"start":{"line":864,"column":6},"end":{"line":869,"column":null}},"326":{"start":{"line":878,"column":4},"end":{"line":910,"column":null}},"327":{"start":{"line":880,"column":25},"end":{"line":880,"column":null}},"328":{"start":{"line":881,"column":12},"end":{"line":881,"column":null}},"329":{"start":{"line":882,"column":6},"end":{"line":884,"column":null}},"330":{"start":{"line":883,"column":8},"end":{"line":883,"column":null}},"331":{"start":{"line":886,"column":12},"end":{"line":886,"column":null}},"332":{"start":{"line":888,"column":6},"end":{"line":891,"column":null}},"333":{"start":{"line":889,"column":8},"end":{"line":889,"column":null}},"334":{"start":{"line":890,"column":8},"end":{"line":890,"column":null}},"335":{"start":{"line":893,"column":28},"end":{"line":893,"column":null}},"336":{"start":{"line":894,"column":21},"end":{"line":894,"column":null}},"337":{"start":{"line":897,"column":24},"end":{"line":897,"column":null}},"338":{"start":{"line":899,"column":6},"end":{"line":903,"column":null}},"339":{"start":{"line":900,"column":8},"end":{"line":900,"column":null}},"340":{"start":{"line":902,"column":8},"end":{"line":902,"column":null}},"341":{"start":{"line":905,"column":6},"end":{"line":905,"column":null}},"342":{"start":{"line":908,"column":6},"end":{"line":908,"column":null}},"343":{"start":{"line":909,"column":6},"end":{"line":909,"column":null}},"344":{"start":{"line":931,"column":4},"end":{"line":945,"column":null}}},"fnMap":{"0":{"name":"(anonymous_0)","decl":{"start":{"line":70,"column":2},"end":{"line":70,"column":null}},"loc":{"start":{"line":83,"column":4},"end":{"line":103,"column":null}},"line":83},"1":{"name":"(anonymous_1)","decl":{"start":{"line":99,"column":37},"end":{"line":99,"column":44}},"loc":{"start":{"line":99,"column":75},"end":{"line":101,"column":7}},"line":99},"2":{"name":"(anonymous_2)","decl":{"start":{"line":109,"column":10},"end":{"line":109,"column":28}},"loc":{"start":{"line":109,"column":51},"end":{"line":114,"column":null}},"line":109},"3":{"name":"(anonymous_3)","decl":{"start":{"line":120,"column":10},"end":{"line":120,"column":null}},"loc":{"start":{"line":124,"column":45},"end":{"line":141,"column":null}},"line":124},"4":{"name":"(anonymous_4)","decl":{"start":{"line":128,"column":11},"end":{"line":128,"column":12}},"loc":{"start":{"line":128,"column":24},"end":{"line":140,"column":null}},"line":128},"5":{"name":"(anonymous_5)","decl":{"start":{"line":130,"column":14},"end":{"line":130,"column":20}},"loc":{"start":{"line":130,"column":20},"end":{"line":138,"column":9}},"line":130},"6":{"name":"(anonymous_6)","decl":{"start":{"line":139,"column":15},"end":{"line":139,"column":22}},"loc":{"start":{"line":139,"column":22},"end":{"line":139,"column":129}},"line":139},"7":{"name":"(anonymous_7)","decl":{"start":{"line":147,"column":8},"end":{"line":147,"column":27}},"loc":{"start":{"line":147,"column":75},"end":{"line":165,"column":null}},"line":147},"8":{"name":"(anonymous_8)","decl":{"start":{"line":157,"column":6},"end":{"line":157,"column":13}},"loc":{"start":{"line":157,"column":22},"end":{"line":161,"column":null}},"line":157},"9":{"name":"(anonymous_9)","decl":{"start":{"line":171,"column":8},"end":{"line":171,"column":14}},"loc":{"start":{"line":171,"column":62},"end":{"line":173,"column":null}},"line":171},"10":{"name":"(anonymous_10)","decl":{"start":{"line":179,"column":16},"end":{"line":179,"column":30}},"loc":{"start":{"line":179,"column":78},"end":{"line":366,"column":null}},"line":179},"11":{"name":"(anonymous_11)","decl":{"start":{"line":240,"column":31},"end":{"line":240,"column":37}},"loc":{"start":{"line":240,"column":37},"end":{"line":240,"column":66}},"line":240},"12":{"name":"(anonymous_12)","decl":{"start":{"line":314,"column":6},"end":{"line":314,"column":7}},"loc":{"start":{"line":314,"column":17},"end":{"line":314,"column":null}},"line":314},"13":{"name":"(anonymous_13)","decl":{"start":{"line":360,"column":6},"end":{"line":360,"column":12}},"loc":{"start":{"line":360,"column":12},"end":{"line":360,"column":null}},"line":360},"14":{"name":"(anonymous_14)","decl":{"start":{"line":361,"column":6},"end":{"line":361,"column":12}},"loc":{"start":{"line":361,"column":12},"end":{"line":361,"column":null}},"line":361},"15":{"name":"(anonymous_15)","decl":{"start":{"line":371,"column":16},"end":{"line":371,"column":46}},"loc":{"start":{"line":371,"column":78},"end":{"line":388,"column":null}},"line":371},"16":{"name":"(anonymous_16)","decl":{"start":{"line":378,"column":6},"end":{"line":378,"column":7}},"loc":{"start":{"line":378,"column":17},"end":{"line":378,"column":null}},"line":378},"17":{"name":"(anonymous_17)","decl":{"start":{"line":394,"column":16},"end":{"line":394,"column":31}},"loc":{"start":{"line":394,"column":63},"end":{"line":426,"column":null}},"line":394},"18":{"name":"(anonymous_18)","decl":{"start":{"line":432,"column":16},"end":{"line":432,"column":32}},"loc":{"start":{"line":432,"column":67},"end":{"line":487,"column":null}},"line":432},"19":{"name":"(anonymous_19)","decl":{"start":{"line":443,"column":37},"end":{"line":443,"column":42}},"loc":{"start":{"line":443,"column":42},"end":{"line":443,"column":55}},"line":443},"20":{"name":"(anonymous_20)","decl":{"start":{"line":471,"column":6},"end":{"line":471,"column":7}},"loc":{"start":{"line":471,"column":17},"end":{"line":471,"column":null}},"line":471},"21":{"name":"(anonymous_21)","decl":{"start":{"line":481,"column":6},"end":{"line":481,"column":12}},"loc":{"start":{"line":481,"column":12},"end":{"line":481,"column":null}},"line":481},"22":{"name":"(anonymous_22)","decl":{"start":{"line":482,"column":6},"end":{"line":482,"column":12}},"loc":{"start":{"line":482,"column":12},"end":{"line":482,"column":null}},"line":482},"23":{"name":"(anonymous_23)","decl":{"start":{"line":494,"column":16},"end":{"line":494,"column":46}},"loc":{"start":{"line":494,"column":78},"end":{"line":508,"column":null}},"line":494},"24":{"name":"(anonymous_24)","decl":{"start":{"line":513,"column":8},"end":{"line":513,"column":13}},"loc":{"start":{"line":513,"column":45},"end":{"line":538,"column":null}},"line":513},"25":{"name":"(anonymous_25)","decl":{"start":{"line":543,"column":8},"end":{"line":543,"column":37}},"loc":{"start":{"line":543,"column":37},"end":{"line":546,"column":null}},"line":543},"26":{"name":"(anonymous_26)","decl":{"start":{"line":545,"column":22},"end":{"line":545,"column":23}},"loc":{"start":{"line":545,"column":29},"end":{"line":545,"column":48}},"line":545},"27":{"name":"(anonymous_27)","decl":{"start":{"line":551,"column":8},"end":{"line":551,"column":12}},"loc":{"start":{"line":551,"column":56},"end":{"line":554,"column":null}},"line":551},"28":{"name":"(anonymous_28)","decl":{"start":{"line":559,"column":8},"end":{"line":559,"column":18}},"loc":{"start":{"line":559,"column":59},"end":{"line":562,"column":null}},"line":559},"29":{"name":"(anonymous_29)","decl":{"start":{"line":568,"column":8},"end":{"line":568,"column":28}},"loc":{"start":{"line":568,"column":93},"end":{"line":578,"column":null}},"line":568},"30":{"name":"(anonymous_30)","decl":{"start":{"line":575,"column":6},"end":{"line":575,"column":7}},"loc":{"start":{"line":575,"column":31},"end":{"line":575,"column":null}},"line":575},"31":{"name":"(anonymous_31)","decl":{"start":{"line":584,"column":8},"end":{"line":584,"column":15}},"loc":{"start":{"line":584,"column":80},"end":{"line":586,"column":null}},"line":584},"32":{"name":"(anonymous_32)","decl":{"start":{"line":592,"column":16},"end":{"line":592,"column":31}},"loc":{"start":{"line":592,"column":96},"end":{"line":669,"column":null}},"line":592},"33":{"name":"(anonymous_33)","decl":{"start":{"line":644,"column":6},"end":{"line":644,"column":7}},"loc":{"start":{"line":644,"column":17},"end":{"line":644,"column":null}},"line":644},"34":{"name":"(anonymous_34)","decl":{"start":{"line":665,"column":6},"end":{"line":665,"column":12}},"loc":{"start":{"line":665,"column":12},"end":{"line":665,"column":null}},"line":665},"35":{"name":"(anonymous_35)","decl":{"start":{"line":666,"column":6},"end":{"line":666,"column":12}},"loc":{"start":{"line":666,"column":12},"end":{"line":666,"column":null}},"line":666},"36":{"name":"(anonymous_36)","decl":{"start":{"line":674,"column":8},"end":{"line":674,"column":18}},"loc":{"start":{"line":674,"column":64},"end":{"line":676,"column":null}},"line":674},"37":{"name":"(anonymous_37)","decl":{"start":{"line":681,"column":8},"end":{"line":681,"column":28}},"loc":{"start":{"line":681,"column":79},"end":{"line":683,"column":null}},"line":681},"38":{"name":"(anonymous_38)","decl":{"start":{"line":688,"column":8},"end":{"line":688,"column":15}},"loc":{"start":{"line":688,"column":47},"end":{"line":730,"column":null}},"line":688},"39":{"name":"(anonymous_39)","decl":{"start":{"line":735,"column":8},"end":{"line":735,"column":16}},"loc":{"start":{"line":735,"column":48},"end":{"line":748,"column":null}},"line":735},"40":{"name":"(anonymous_40)","decl":{"start":{"line":753,"column":8},"end":{"line":753,"column":49}},"loc":{"start":{"line":753,"column":49},"end":{"line":755,"column":null}},"line":753},"41":{"name":"(anonymous_41)","decl":{"start":{"line":760,"column":8},"end":{"line":760,"column":45}},"loc":{"start":{"line":760,"column":45},"end":{"line":762,"column":null}},"line":760},"42":{"name":"(anonymous_42)","decl":{"start":{"line":767,"column":8},"end":{"line":767,"column":47}},"loc":{"start":{"line":767,"column":47},"end":{"line":796,"column":null}},"line":767},"43":{"name":"(anonymous_43)","decl":{"start":{"line":771,"column":6},"end":{"line":771,"column":7}},"loc":{"start":{"line":771,"column":26},"end":{"line":771,"column":null}},"line":771},"44":{"name":"(anonymous_44)","decl":{"start":{"line":772,"column":6},"end":{"line":772,"column":7}},"loc":{"start":{"line":772,"column":40},"end":{"line":772,"column":null}},"line":772},"45":{"name":"(anonymous_45)","decl":{"start":{"line":772,"column":108},"end":{"line":772,"column":109}},"loc":{"start":{"line":772,"column":119},"end":{"line":772,"column":161}},"line":772},"46":{"name":"(anonymous_46)","decl":{"start":{"line":773,"column":6},"end":{"line":773,"column":7}},"loc":{"start":{"line":773,"column":24},"end":{"line":781,"column":null}},"line":773},"47":{"name":"(anonymous_47)","decl":{"start":{"line":776,"column":10},"end":{"line":776,"column":16}},"loc":{"start":{"line":776,"column":16},"end":{"line":776,"column":null}},"line":776},"48":{"name":"(anonymous_48)","decl":{"start":{"line":777,"column":10},"end":{"line":777,"column":16}},"loc":{"start":{"line":777,"column":16},"end":{"line":777,"column":null}},"line":777},"49":{"name":"(anonymous_49)","decl":{"start":{"line":783,"column":10},"end":{"line":783,"column":11}},"loc":{"start":{"line":783,"column":43},"end":{"line":793,"column":null}},"line":783},"50":{"name":"(anonymous_50)","decl":{"start":{"line":785,"column":64},"end":{"line":785,"column":73}},"loc":{"start":{"line":785,"column":73},"end":{"line":792,"column":13}},"line":785},"51":{"name":"(anonymous_51)","decl":{"start":{"line":792,"column":21},"end":{"line":792,"column":28}},"loc":{"start":{"line":792,"column":28},"end":{"line":792,"column":157}},"line":792},"52":{"name":"(anonymous_52)","decl":{"start":{"line":802,"column":16},"end":{"line":802,"column":37}},"loc":{"start":{"line":802,"column":119},"end":{"line":871,"column":null}},"line":802},"53":{"name":"(anonymous_53)","decl":{"start":{"line":877,"column":16},"end":{"line":877,"column":43}},"loc":{"start":{"line":877,"column":81},"end":{"line":911,"column":null}},"line":877},"54":{"name":"(anonymous_54)","decl":{"start":{"line":916,"column":10},"end":{"line":916,"column":22}},"loc":{"start":{"line":930,"column":16},"end":{"line":946,"column":null}},"line":930}},"branchMap":{"0":{"loc":{"start":{"line":82,"column":12},"end":{"line":82,"column":null}},"type":"default-arg","locations":[{"start":{"line":82,"column":29},"end":{"line":82,"column":null}}],"line":82},"1":{"loc":{"start":{"line":98,"column":4},"end":{"line":102,"column":null}},"type":"if","locations":[{"start":{"line":98,"column":4},"end":{"line":102,"column":null}},{"start":{},"end":{}}],"line":98},"2":{"loc":{"start":{"line":111,"column":4},"end":{"line":111,"column":null}},"type":"if","locations":[{"start":{"line":111,"column":4},"end":{"line":111,"column":null}},{"start":{},"end":{}}],"line":111},"3":{"loc":{"start":{"line":126,"column":4},"end":{"line":126,"column":null}},"type":"if","locations":[{"start":{"line":126,"column":4},"end":{"line":126,"column":null}},{"start":{},"end":{}}],"line":126},"4":{"loc":{"start":{"line":131,"column":10},"end":{"line":137,"column":null}},"type":"if","locations":[{"start":{"line":131,"column":10},"end":{"line":137,"column":null}},{"start":{},"end":{}}],"line":131},"5":{"loc":{"start":{"line":139,"column":47},"end":{"line":139,"column":96}},"type":"cond-expr","locations":[{"start":{"line":139,"column":70},"end":{"line":139,"column":84}},{"start":{"line":139,"column":84},"end":{"line":139,"column":96}}],"line":139},"6":{"loc":{"start":{"line":180,"column":25},"end":{"line":180,"column":43}},"type":"default-arg","locations":[{"start":{"line":180,"column":32},"end":{"line":180,"column":43}}],"line":180},"7":{"loc":{"start":{"line":180,"column":53},"end":{"line":180,"column":78}},"type":"default-arg","locations":[{"start":{"line":180,"column":68},"end":{"line":180,"column":78}}],"line":180},"8":{"loc":{"start":{"line":185,"column":4},"end":{"line":187,"column":null}},"type":"if","locations":[{"start":{"line":185,"column":4},"end":{"line":187,"column":null}},{"start":{},"end":{}}],"line":185},"9":{"loc":{"start":{"line":191,"column":4},"end":{"line":199,"column":null}},"type":"if","locations":[{"start":{"line":191,"column":4},"end":{"line":199,"column":null}},{"start":{"line":197,"column":11},"end":{"line":199,"column":null}}],"line":191},"10":{"loc":{"start":{"line":194,"column":6},"end":{"line":196,"column":null}},"type":"if","locations":[{"start":{"line":194,"column":6},"end":{"line":196,"column":null}},{"start":{},"end":{}}],"line":194},"11":{"loc":{"start":{"line":208,"column":4},"end":{"line":220,"column":null}},"type":"if","locations":[{"start":{"line":208,"column":4},"end":{"line":220,"column":null}},{"start":{},"end":{}}],"line":208},"12":{"loc":{"start":{"line":214,"column":6},"end":{"line":216,"column":null}},"type":"if","locations":[{"start":{"line":214,"column":6},"end":{"line":216,"column":null}},{"start":{},"end":{}}],"line":214},"13":{"loc":{"start":{"line":217,"column":6},"end":{"line":219,"column":null}},"type":"if","locations":[{"start":{"line":217,"column":6},"end":{"line":219,"column":null}},{"start":{},"end":{}}],"line":217},"14":{"loc":{"start":{"line":222,"column":4},"end":{"line":226,"column":null}},"type":"if","locations":[{"start":{"line":222,"column":4},"end":{"line":226,"column":null}},{"start":{"line":224,"column":11},"end":{"line":226,"column":null}}],"line":222},"15":{"loc":{"start":{"line":230,"column":4},"end":{"line":247,"column":null}},"type":"if","locations":[{"start":{"line":230,"column":4},"end":{"line":247,"column":null}},{"start":{"line":243,"column":11},"end":{"line":247,"column":null}}],"line":230},"16":{"loc":{"start":{"line":260,"column":4},"end":{"line":262,"column":null}},"type":"if","locations":[{"start":{"line":260,"column":4},"end":{"line":262,"column":null}},{"start":{},"end":{}}],"line":260},"17":{"loc":{"start":{"line":267,"column":14},"end":{"line":267,"column":null}},"type":"binary-expr","locations":[{"start":{"line":267,"column":14},"end":{"line":267,"column":24}},{"start":{"line":267,"column":24},"end":{"line":267,"column":null}}],"line":267},"18":{"loc":{"start":{"line":268,"column":20},"end":{"line":268,"column":null}},"type":"binary-expr","locations":[{"start":{"line":268,"column":20},"end":{"line":268,"column":36}},{"start":{"line":268,"column":36},"end":{"line":268,"column":null}}],"line":268},"19":{"loc":{"start":{"line":282,"column":4},"end":{"line":285,"column":null}},"type":"if","locations":[{"start":{"line":282,"column":4},"end":{"line":285,"column":null}},{"start":{},"end":{}}],"line":282},"20":{"loc":{"start":{"line":289,"column":21},"end":{"line":289,"column":null}},"type":"binary-expr","locations":[{"start":{"line":289,"column":21},"end":{"line":289,"column":28}},{"start":{"line":289,"column":28},"end":{"line":289,"column":null}}],"line":289},"21":{"loc":{"start":{"line":313,"column":37},"end":{"line":313,"column":54}},"type":"binary-expr","locations":[{"start":{"line":313,"column":37},"end":{"line":313,"column":44}},{"start":{"line":313,"column":44},"end":{"line":313,"column":54}}],"line":313},"22":{"loc":{"start":{"line":332,"column":20},"end":{"line":332,"column":null}},"type":"binary-expr","locations":[{"start":{"line":332,"column":20},"end":{"line":332,"column":36}},{"start":{"line":332,"column":36},"end":{"line":332,"column":null}}],"line":332},"23":{"loc":{"start":{"line":334,"column":17},"end":{"line":334,"column":null}},"type":"binary-expr","locations":[{"start":{"line":334,"column":17},"end":{"line":334,"column":30}},{"start":{"line":334,"column":30},"end":{"line":334,"column":null}}],"line":334},"24":{"loc":{"start":{"line":348,"column":4},"end":{"line":355,"column":null}},"type":"if","locations":[{"start":{"line":348,"column":4},"end":{"line":355,"column":null}},{"start":{},"end":{}}],"line":348},"25":{"loc":{"start":{"line":352,"column":49},"end":{"line":352,"column":65}},"type":"binary-expr","locations":[{"start":{"line":352,"column":49},"end":{"line":352,"column":59}},{"start":{"line":352,"column":59},"end":{"line":352,"column":65}}],"line":352},"26":{"loc":{"start":{"line":372,"column":4},"end":{"line":372,"column":null}},"type":"if","locations":[{"start":{"line":372,"column":4},"end":{"line":372,"column":null}},{"start":{},"end":{}}],"line":372},"27":{"loc":{"start":{"line":397,"column":6},"end":{"line":397,"column":null}},"type":"if","locations":[{"start":{"line":397,"column":6},"end":{"line":397,"column":null}},{"start":{},"end":{}}],"line":397},"28":{"loc":{"start":{"line":397,"column":10},"end":{"line":397,"column":45}},"type":"binary-expr","locations":[{"start":{"line":397,"column":10},"end":{"line":397,"column":20}},{"start":{"line":397,"column":20},"end":{"line":397,"column":45}}],"line":397},"29":{"loc":{"start":{"line":403,"column":6},"end":{"line":407,"column":null}},"type":"if","locations":[{"start":{"line":403,"column":6},"end":{"line":407,"column":null}},{"start":{},"end":{}}],"line":403},"30":{"loc":{"start":{"line":409,"column":6},"end":{"line":421,"column":null}},"type":"if","locations":[{"start":{"line":409,"column":6},"end":{"line":421,"column":null}},{"start":{},"end":{}}],"line":409},"31":{"loc":{"start":{"line":410,"column":24},"end":{"line":410,"column":null}},"type":"binary-expr","locations":[{"start":{"line":410,"column":24},"end":{"line":410,"column":62}},{"start":{"line":410,"column":62},"end":{"line":410,"column":null}}],"line":410},"32":{"loc":{"start":{"line":411,"column":8},"end":{"line":418,"column":null}},"type":"if","locations":[{"start":{"line":411,"column":8},"end":{"line":418,"column":null}},{"start":{},"end":{}}],"line":411},"33":{"loc":{"start":{"line":414,"column":10},"end":{"line":417,"column":null}},"type":"if","locations":[{"start":{"line":414,"column":10},"end":{"line":417,"column":null}},{"start":{},"end":{}}],"line":414},"34":{"loc":{"start":{"line":423,"column":31},"end":{"line":423,"column":80}},"type":"cond-expr","locations":[{"start":{"line":423,"column":54},"end":{"line":423,"column":68}},{"start":{"line":423,"column":68},"end":{"line":423,"column":80}}],"line":423},"35":{"loc":{"start":{"line":434,"column":4},"end":{"line":434,"column":null}},"type":"if","locations":[{"start":{"line":434,"column":4},"end":{"line":434,"column":null}},{"start":{},"end":{}}],"line":434},"36":{"loc":{"start":{"line":437,"column":4},"end":{"line":437,"column":null}},"type":"if","locations":[{"start":{"line":437,"column":4},"end":{"line":437,"column":null}},{"start":{},"end":{}}],"line":437},"37":{"loc":{"start":{"line":437,"column":8},"end":{"line":437,"column":54}},"type":"binary-expr","locations":[{"start":{"line":437,"column":8},"end":{"line":437,"column":21}},{"start":{"line":437,"column":21},"end":{"line":437,"column":54}}],"line":437},"38":{"loc":{"start":{"line":441,"column":4},"end":{"line":441,"column":null}},"type":"if","locations":[{"start":{"line":441,"column":4},"end":{"line":441,"column":null}},{"start":{},"end":{}}],"line":441},"39":{"loc":{"start":{"line":459,"column":4},"end":{"line":461,"column":null}},"type":"if","locations":[{"start":{"line":459,"column":4},"end":{"line":461,"column":null}},{"start":{},"end":{}}],"line":459},"40":{"loc":{"start":{"line":465,"column":4},"end":{"line":467,"column":null}},"type":"if","locations":[{"start":{"line":465,"column":4},"end":{"line":467,"column":null}},{"start":{},"end":{}}],"line":465},"41":{"loc":{"start":{"line":495,"column":4},"end":{"line":495,"column":null}},"type":"if","locations":[{"start":{"line":495,"column":4},"end":{"line":495,"column":null}},{"start":{},"end":{}}],"line":495},"42":{"loc":{"start":{"line":499,"column":6},"end":{"line":499,"column":null}},"type":"if","locations":[{"start":{"line":499,"column":6},"end":{"line":499,"column":null}},{"start":{},"end":{}}],"line":499},"43":{"loc":{"start":{"line":506,"column":31},"end":{"line":506,"column":80}},"type":"cond-expr","locations":[{"start":{"line":506,"column":54},"end":{"line":506,"column":68}},{"start":{"line":506,"column":68},"end":{"line":506,"column":80}}],"line":506},"44":{"loc":{"start":{"line":515,"column":4},"end":{"line":515,"column":null}},"type":"if","locations":[{"start":{"line":515,"column":4},"end":{"line":515,"column":null}},{"start":{},"end":{}}],"line":515},"45":{"loc":{"start":{"line":519,"column":4},"end":{"line":522,"column":null}},"type":"if","locations":[{"start":{"line":519,"column":4},"end":{"line":522,"column":null}},{"start":{},"end":{}}],"line":519},"46":{"loc":{"start":{"line":530,"column":4},"end":{"line":537,"column":null}},"type":"if","locations":[{"start":{"line":530,"column":4},"end":{"line":537,"column":null}},{"start":{},"end":{}}],"line":530},"47":{"loc":{"start":{"line":534,"column":54},"end":{"line":534,"column":74}},"type":"binary-expr","locations":[{"start":{"line":534,"column":54},"end":{"line":534,"column":70}},{"start":{"line":534,"column":70},"end":{"line":534,"column":74}}],"line":534},"48":{"loc":{"start":{"line":553,"column":11},"end":{"line":553,"column":null}},"type":"cond-expr","locations":[{"start":{"line":553,"column":19},"end":{"line":553,"column":45}},{"start":{"line":553,"column":45},"end":{"line":553,"column":null}}],"line":553},"49":{"loc":{"start":{"line":561,"column":11},"end":{"line":561,"column":null}},"type":"cond-expr","locations":[{"start":{"line":561,"column":19},"end":{"line":561,"column":45}},{"start":{"line":561,"column":45},"end":{"line":561,"column":null}}],"line":561},"50":{"loc":{"start":{"line":594,"column":4},"end":{"line":594,"column":null}},"type":"if","locations":[{"start":{"line":594,"column":4},"end":{"line":594,"column":null}},{"start":{},"end":{}}],"line":594},"51":{"loc":{"start":{"line":595,"column":4},"end":{"line":597,"column":null}},"type":"if","locations":[{"start":{"line":595,"column":4},"end":{"line":597,"column":null}},{"start":{},"end":{}}],"line":595},"52":{"loc":{"start":{"line":598,"column":4},"end":{"line":600,"column":null}},"type":"if","locations":[{"start":{"line":598,"column":4},"end":{"line":600,"column":null}},{"start":{},"end":{}}],"line":598},"53":{"loc":{"start":{"line":604,"column":4},"end":{"line":604,"column":null}},"type":"if","locations":[{"start":{"line":604,"column":4},"end":{"line":604,"column":null}},{"start":{},"end":{}}],"line":604},"54":{"loc":{"start":{"line":605,"column":4},"end":{"line":607,"column":null}},"type":"if","locations":[{"start":{"line":605,"column":4},"end":{"line":607,"column":null}},{"start":{},"end":{}}],"line":605},"55":{"loc":{"start":{"line":632,"column":4},"end":{"line":634,"column":null}},"type":"if","locations":[{"start":{"line":632,"column":4},"end":{"line":634,"column":null}},{"start":{},"end":{}}],"line":632},"56":{"loc":{"start":{"line":638,"column":4},"end":{"line":640,"column":null}},"type":"if","locations":[{"start":{"line":638,"column":4},"end":{"line":640,"column":null}},{"start":{},"end":{}}],"line":638},"57":{"loc":{"start":{"line":654,"column":4},"end":{"line":661,"column":null}},"type":"if","locations":[{"start":{"line":654,"column":4},"end":{"line":661,"column":null}},{"start":{},"end":{}}],"line":654},"58":{"loc":{"start":{"line":658,"column":54},"end":{"line":658,"column":74}},"type":"binary-expr","locations":[{"start":{"line":658,"column":54},"end":{"line":658,"column":70}},{"start":{"line":658,"column":70},"end":{"line":658,"column":74}}],"line":658},"59":{"loc":{"start":{"line":690,"column":4},"end":{"line":690,"column":null}},"type":"if","locations":[{"start":{"line":690,"column":4},"end":{"line":690,"column":null}},{"start":{},"end":{}}],"line":690},"60":{"loc":{"start":{"line":695,"column":4},"end":{"line":698,"column":null}},"type":"if","locations":[{"start":{"line":695,"column":4},"end":{"line":698,"column":null}},{"start":{},"end":{}}],"line":695},"61":{"loc":{"start":{"line":703,"column":43},"end":{"line":703,"column":92}},"type":"cond-expr","locations":[{"start":{"line":703,"column":66},"end":{"line":703,"column":80}},{"start":{"line":703,"column":80},"end":{"line":703,"column":92}}],"line":703},"62":{"loc":{"start":{"line":706,"column":43},"end":{"line":706,"column":92}},"type":"cond-expr","locations":[{"start":{"line":706,"column":66},"end":{"line":706,"column":80}},{"start":{"line":706,"column":80},"end":{"line":706,"column":92}}],"line":706},"63":{"loc":{"start":{"line":709,"column":43},"end":{"line":709,"column":92}},"type":"cond-expr","locations":[{"start":{"line":709,"column":66},"end":{"line":709,"column":80}},{"start":{"line":709,"column":80},"end":{"line":709,"column":92}}],"line":709},"64":{"loc":{"start":{"line":712,"column":4},"end":{"line":715,"column":null}},"type":"if","locations":[{"start":{"line":712,"column":4},"end":{"line":715,"column":null}},{"start":{},"end":{}}],"line":712},"65":{"loc":{"start":{"line":714,"column":45},"end":{"line":714,"column":94}},"type":"cond-expr","locations":[{"start":{"line":714,"column":68},"end":{"line":714,"column":82}},{"start":{"line":714,"column":82},"end":{"line":714,"column":94}}],"line":714},"66":{"loc":{"start":{"line":721,"column":4},"end":{"line":728,"column":null}},"type":"if","locations":[{"start":{"line":721,"column":4},"end":{"line":728,"column":null}},{"start":{},"end":{}}],"line":721},"67":{"loc":{"start":{"line":737,"column":4},"end":{"line":737,"column":null}},"type":"if","locations":[{"start":{"line":737,"column":4},"end":{"line":737,"column":null}},{"start":{},"end":{}}],"line":737},"68":{"loc":{"start":{"line":780,"column":8},"end":{"line":780,"column":null}},"type":"if","locations":[{"start":{"line":780,"column":8},"end":{"line":780,"column":null}},{"start":{},"end":{}}],"line":780},"69":{"loc":{"start":{"line":782,"column":6},"end":{"line":794,"column":null}},"type":"cond-expr","locations":[{"start":{"line":783,"column":10},"end":{"line":793,"column":null}},{"start":{"line":794,"column":10},"end":{"line":794,"column":null}}],"line":782},"70":{"loc":{"start":{"line":792,"column":53},"end":{"line":792,"column":102}},"type":"cond-expr","locations":[{"start":{"line":792,"column":76},"end":{"line":792,"column":90}},{"start":{"line":792,"column":90},"end":{"line":792,"column":102}}],"line":792},"71":{"loc":{"start":{"line":806,"column":6},"end":{"line":808,"column":null}},"type":"if","locations":[{"start":{"line":806,"column":6},"end":{"line":808,"column":null}},{"start":{},"end":{}}],"line":806},"72":{"loc":{"start":{"line":822,"column":6},"end":{"line":862,"column":null}},"type":"if","locations":[{"start":{"line":822,"column":6},"end":{"line":862,"column":null}},{"start":{"line":853,"column":13},"end":{"line":862,"column":null}}],"line":822},"73":{"loc":{"start":{"line":824,"column":8},"end":{"line":852,"column":null}},"type":"if","locations":[{"start":{"line":824,"column":8},"end":{"line":852,"column":null}},{"start":{"line":841,"column":15},"end":{"line":852,"column":null}}],"line":824},"74":{"loc":{"start":{"line":868,"column":13},"end":{"line":868,"column":null}},"type":"cond-expr","locations":[{"start":{"line":868,"column":36},"end":{"line":868,"column":50}},{"start":{"line":868,"column":50},"end":{"line":868,"column":null}}],"line":868},"75":{"loc":{"start":{"line":882,"column":6},"end":{"line":884,"column":null}},"type":"if","locations":[{"start":{"line":882,"column":6},"end":{"line":884,"column":null}},{"start":{},"end":{}}],"line":882},"76":{"loc":{"start":{"line":882,"column":10},"end":{"line":882,"column":101}},"type":"binary-expr","locations":[{"start":{"line":882,"column":10},"end":{"line":882,"column":62}},{"start":{"line":882,"column":57},"end":{"line":882,"column":101}}],"line":882},"77":{"loc":{"start":{"line":888,"column":6},"end":{"line":891,"column":null}},"type":"if","locations":[{"start":{"line":888,"column":6},"end":{"line":891,"column":null}},{"start":{},"end":{}}],"line":888},"78":{"loc":{"start":{"line":897,"column":24},"end":{"line":897,"column":null}},"type":"binary-expr","locations":[{"start":{"line":897,"column":24},"end":{"line":897,"column":52}},{"start":{"line":897,"column":52},"end":{"line":897,"column":85}},{"start":{"line":897,"column":85},"end":{"line":897,"column":null}}],"line":897},"79":{"loc":{"start":{"line":899,"column":6},"end":{"line":903,"column":null}},"type":"if","locations":[{"start":{"line":899,"column":6},"end":{"line":903,"column":null}},{"start":{"line":901,"column":13},"end":{"line":903,"column":null}}],"line":899},"80":{"loc":{"start":{"line":908,"column":34},"end":{"line":908,"column":83}},"type":"cond-expr","locations":[{"start":{"line":908,"column":57},"end":{"line":908,"column":71}},{"start":{"line":908,"column":71},"end":{"line":908,"column":83}}],"line":908},"81":{"loc":{"start":{"line":934,"column":14},"end":{"line":934,"column":null}},"type":"binary-expr","locations":[{"start":{"line":934,"column":14},"end":{"line":934,"column":30}},{"start":{"line":934,"column":30},"end":{"line":934,"column":null}}],"line":934}},"s":{"0":15,"1":38,"2":38,"3":38,"4":23,"5":23,"6":23,"7":23,"8":23,"9":23,"10":23,"11":23,"12":23,"13":23,"14":23,"15":23,"16":23,"17":23,"18":23,"19":23,"20":23,"21":23,"22":23,"23":23,"24":0,"25":6,"26":6,"27":4,"28":6,"29":6,"30":10,"31":10,"32":10,"33":0,"34":0,"35":0,"36":0,"37":0,"38":0,"39":0,"40":0,"41":0,"42":0,"43":0,"44":9,"45":9,"46":9,"47":9,"48":9,"49":9,"50":0,"51":9,"52":9,"53":9,"54":9,"55":1,"56":0,"57":8,"58":8,"59":8,"60":8,"61":8,"62":8,"63":0,"64":0,"65":0,"66":0,"67":0,"68":0,"69":0,"70":0,"71":8,"72":0,"73":8,"74":8,"75":0,"76":0,"77":0,"78":0,"79":0,"80":8,"81":8,"82":8,"83":8,"84":8,"85":8,"86":8,"87":0,"88":8,"89":8,"90":8,"91":8,"92":0,"93":0,"94":8,"95":8,"96":9,"97":9,"98":8,"99":8,"100":0,"101":9,"102":8,"103":9,"104":9,"105":9,"106":9,"107":9,"108":8,"109":8,"110":8,"111":0,"112":8,"113":8,"114":8,"115":0,"116":0,"117":0,"118":0,"119":0,"120":0,"121":0,"122":0,"123":0,"124":0,"125":0,"126":0,"127":0,"128":0,"129":0,"130":0,"131":0,"132":0,"133":0,"134":0,"135":0,"136":0,"137":0,"138":0,"139":0,"140":0,"141":0,"142":0,"143":0,"144":0,"145":0,"146":0,"147":0,"148":0,"149":0,"150":0,"151":0,"152":0,"153":0,"154":0,"155":0,"156":0,"157":0,"158":0,"159":0,"160":0,"161":0,"162":0,"163":0,"164":0,"165":0,"166":0,"167":0,"168":0,"169":0,"170":0,"171":0,"172":0,"173":0,"174":0,"175":0,"176":0,"177":3,"178":3,"179":0,"180":0,"181":0,"182":0,"183":0,"184":0,"185":0,"186":0,"187":0,"188":4,"189":4,"190":1,"191":3,"192":3,"193":3,"194":2,"195":2,"196":2,"197":3,"198":3,"199":3,"200":3,"201":3,"202":3,"203":1,"204":1,"205":1,"206":2,"207":2,"208":2,"209":2,"210":0,"211":0,"212":0,"213":4,"214":4,"215":4,"216":0,"217":4,"218":1,"219":3,"220":1,"221":2,"222":2,"223":2,"224":0,"225":2,"226":0,"227":2,"228":2,"229":2,"230":2,"231":2,"232":0,"233":2,"234":2,"235":2,"236":2,"237":2,"238":2,"239":4,"240":0,"241":2,"242":2,"243":0,"244":2,"245":0,"246":2,"247":2,"248":2,"249":2,"250":2,"251":2,"252":2,"253":2,"254":0,"255":2,"256":2,"257":1,"258":0,"259":4,"260":4,"261":1,"262":3,"263":3,"264":3,"265":2,"266":2,"267":2,"268":3,"269":3,"270":3,"271":0,"272":3,"273":3,"274":0,"275":3,"276":3,"277":0,"278":3,"279":0,"280":0,"281":0,"282":3,"283":3,"284":3,"285":3,"286":3,"287":0,"288":0,"289":0,"290":0,"291":0,"292":0,"293":0,"294":0,"295":0,"296":0,"297":0,"298":0,"299":0,"300":0,"301":0,"302":0,"303":0,"304":0,"305":0,"306":0,"307":0,"308":0,"309":0,"310":0,"311":0,"312":0,"313":0,"314":0,"315":0,"316":0,"317":0,"318":0,"319":0,"320":0,"321":0,"322":0,"323":0,"324":0,"325":0,"326":0,"327":0,"328":0,"329":0,"330":0,"331":0,"332":0,"333":0,"334":0,"335":0,"336":0,"337":0,"338":0,"339":0,"340":0,"341":0,"342":0,"343":0,"344":11},"f":{"0":23,"1":0,"2":6,"3":10,"4":0,"5":0,"6":0,"7":0,"8":0,"9":9,"10":9,"11":0,"12":0,"13":0,"14":8,"15":0,"16":0,"17":0,"18":0,"19":0,"20":0,"21":0,"22":0,"23":3,"24":4,"25":1,"26":1,"27":2,"28":2,"29":0,"30":0,"31":4,"32":4,"33":0,"34":0,"35":2,"36":1,"37":0,"38":4,"39":0,"40":0,"41":0,"42":0,"43":0,"44":0,"45":0,"46":0,"47":0,"48":0,"49":0,"50":0,"51":0,"52":0,"53":0,"54":11},"b":{"0":[23],"1":[23,0],"2":[4,2],"3":[10,0],"4":[0,0],"5":[0,0],"6":[9],"7":[9],"8":[0,9],"9":[9,0],"10":[1,8],"11":[0,8],"12":[0,0],"13":[0,0],"14":[0,8],"15":[0,8],"16":[0,8],"17":[8,0],"18":[9,8],"19":[0,8],"20":[8,7],"21":[8,7],"22":[8,8],"23":[9,8],"24":[8,1],"25":[8,0],"26":[0,0],"27":[0,0],"28":[0,0],"29":[0,0],"30":[0,0],"31":[0,0],"32":[0,0],"33":[0,0],"34":[0,0],"35":[0,0],"36":[0,0],"37":[0,0],"38":[0,0],"39":[0,0],"40":[0,0],"41":[3,0],"42":[0,0],"43":[0,0],"44":[1,3],"45":[2,1],"46":[3,0],"47":[3,0],"48":[1,1],"49":[1,1],"50":[0,4],"51":[1,3],"52":[1,2],"53":[0,2],"54":[0,2],"55":[0,4],"56":[0,2],"57":[2,0],"58":[2,0],"59":[1,3],"60":[2,1],"61":[0,0],"62":[0,0],"63":[0,0],"64":[0,3],"65":[0,0],"66":[3,0],"67":[0,0],"68":[0,0],"69":[0,0],"70":[0,0],"71":[0,0],"72":[0,0],"73":[0,0],"74":[0,0],"75":[0,0],"76":[0,0],"77":[0,0],"78":[0,0,0],"79":[0,0],"80":[0,0],"81":[11,0]},"meta":{"lastBranch":82,"lastFunction":55,"lastStatement":345,"seen":{"s:56:6:56:Infinity":0,"s:59:47:59:Infinity":1,"s:61:51:61:Infinity":2,"s:62:50:62:Infinity":3,"f:70:2:70:Infinity":0,"b:82:29:82:Infinity":0,"s:71:12:71:Infinity":4,"s:72:12:72:Infinity":5,"s:73:12:73:Infinity":6,"s:74:12:74:Infinity":7,"s:75:12:75:Infinity":8,"s:76:12:76:Infinity":9,"s:77:12:77:Infinity":10,"s:78:12:78:Infinity":11,"s:79:12:79:Infinity":12,"s:80:12:80:Infinity":13,"s:81:12:81:Infinity":14,"s:82:12:82:29":15,"s:84:4:84:Infinity":16,"s:85:4:85:Infinity":17,"s:86:4:86:Infinity":18,"s:87:4:87:Infinity":19,"s:88:4:88:Infinity":20,"s:89:4:95:Infinity":21,"b:98:4:102:Infinity:undefined:undefined:undefined:undefined":1,"s:98:4:102:Infinity":22,"s:99:6:101:Infinity":23,"f:99:37:99:44":1,"s:100:8:100:Infinity":24,"f:109:10:109:28":2,"s:110:19:110:Infinity":25,"b:111:4:111:Infinity:undefined:undefined:undefined:undefined":2,"s:111:4:111:Infinity":26,"s:111:28:111:Infinity":27,"s:112:4:112:Infinity":28,"s:113:4:113:Infinity":29,"f:120:10:120:Infinity":3,"s:125:17:125:Infinity":30,"b:126:4:126:Infinity:undefined:undefined:undefined:undefined":3,"s:126:4:126:Infinity":31,"s:126:15:126:Infinity":32,"s:128:4:140:Infinity":33,"f:128:11:128:12":4,"s:129:6:139:Infinity":34,"f:130:14:130:20":5,"b:131:10:137:Infinity:undefined:undefined:undefined:undefined":4,"s:131:10:137:Infinity":35,"s:132:12:136:Infinity":36,"f:139:15:139:22":6,"s:139:22:139:129":37,"b:139:70:139:84:139:84:139:96":5,"f:147:8:147:27":7,"s:148:4:153:Infinity":38,"s:156:4:163:Infinity":39,"f:157:6:157:13":8,"s:158:22:158:Infinity":40,"s:159:8:159:Infinity":41,"s:160:8:160:Infinity":42,"s:164:4:164:Infinity":43,"f:171:8:171:14":9,"s:172:4:172:Infinity":44,"f:179:16:179:30":10,"s:180:119:180:Infinity":45,"b:180:32:180:43":6,"b:180:68:180:78":7,"s:181:21:181:Infinity":46,"s:182:4:182:Infinity":47,"s:184:10:184:Infinity":48,"b:185:4:187:Infinity:undefined:undefined:undefined:undefined":8,"s:185:4:187:Infinity":49,"s:186:6:186:Infinity":50,"b:191:4:199:Infinity:197:11:199:Infinity":9,"s:191:4:199:Infinity":51,"s:192:6:192:Infinity":52,"s:193:23:193:Infinity":53,"b:194:6:196:Infinity:undefined:undefined:undefined:undefined":10,"s:194:6:196:Infinity":54,"s:195:8:195:Infinity":55,"s:198:6:198:Infinity":56,"s:200:18:200:Infinity":57,"s:201:4:201:Infinity":58,"s:204:35:204:Infinity":59,"s:205:42:205:Infinity":60,"s:207:26:207:Infinity":61,"b:208:4:220:Infinity:undefined:undefined:undefined:undefined":11,"s:208:4:220:Infinity":62,"s:209:6:209:Infinity":63,"s:210:6:210:Infinity":64,"s:212:6:212:Infinity":65,"s:213:35:213:Infinity":66,"b:214:6:216:Infinity:undefined:undefined:undefined:undefined":12,"s:214:6:216:Infinity":67,"s:215:8:215:Infinity":68,"b:217:6:219:Infinity:undefined:undefined:undefined:undefined":13,"s:217:6:219:Infinity":69,"s:218:8:218:Infinity":70,"b:222:4:226:Infinity:224:11:226:Infinity":14,"s:222:4:226:Infinity":71,"s:223:6:223:Infinity":72,"s:225:6:225:Infinity":73,"b:230:4:247:Infinity:243:11:247:Infinity":15,"s:230:4:247:Infinity":74,"s:231:6:231:Infinity":75,"s:232:6:232:Infinity":76,"s:235:23:235:Infinity":77,"s:236:6:242:Infinity":78,"f:240:31:240:37":11,"s:240:37:240:66":79,"s:244:6:244:Infinity":80,"s:245:6:245:Infinity":81,"s:246:6:246:Infinity":82,"s:250:10:250:Infinity":83,"s:251:4:256:Infinity":84,"s:259:10:259:Infinity":85,"b:260:4:262:Infinity:undefined:undefined:undefined:undefined":16,"s:260:4:262:Infinity":86,"s:261:6:261:Infinity":87,"s:265:18:275:Infinity":88,"b:267:14:267:24:267:24:267:Infinity":17,"b:268:20:268:36:268:36:268:Infinity":18,"s:276:20:276:Infinity":89,"s:279:4:279:Infinity":90,"b:282:4:285:Infinity:undefined:undefined:undefined:undefined":19,"s:282:4:285:Infinity":91,"s:283:6:283:Infinity":92,"s:284:6:284:Infinity":93,"s:288:48:288:Infinity":94,"s:289:21:289:Infinity":95,"b:289:21:289:28:289:28:289:Infinity":20,"s:291:4:299:Infinity":96,"s:302:27:302:Infinity":97,"s:304:4:309:Infinity":98,"s:312:44:316:Infinity":99,"b:313:37:313:44:313:44:313:54":21,"f:314:6:314:7":12,"s:314:17:314:Infinity":100,"s:318:4:318:Infinity":101,"s:321:23:335:Infinity":102,"b:332:20:332:36:332:36:332:Infinity":22,"b:334:17:334:30:334:30:334:Infinity":23,"s:337:4:341:Infinity":103,"s:343:37:343:Infinity":104,"s:344:4:344:Infinity":105,"s:345:4:345:Infinity":106,"b:348:4:355:Infinity:undefined:undefined:undefined:undefined":24,"s:348:4:355:Infinity":107,"s:349:39:353:Infinity":108,"b:352:49:352:59:352:59:352:65":25,"s:354:6:354:Infinity":109,"s:358:23:362:Infinity":110,"f:360:6:360:12":13,"s:360:12:360:Infinity":111,"f:361:6:361:12":14,"s:361:12:361:Infinity":112,"s:363:4:363:Infinity":113,"s:365:4:365:Infinity":114,"f:371:16:371:46":15,"b:372:4:372:Infinity:undefined:undefined:undefined:undefined":26,"s:372:4:372:Infinity":115,"s:372:41:372:Infinity":116,"s:374:19:374:Infinity":117,"s:375:4:379:Infinity":118,"f:378:6:378:7":16,"s:378:17:378:Infinity":119,"s:382:4:382:Infinity":120,"s:384:4:384:Infinity":121,"s:387:4:387:Infinity":122,"f:394:16:394:31":17,"s:395:4:425:Infinity":123,"s:396:20:396:Infinity":124,"b:397:6:397:Infinity:undefined:undefined:undefined:undefined":27,"s:397:6:397:Infinity":125,"b:397:10:397:20:397:20:397:45":28,"s:397:45:397:Infinity":126,"s:399:33:401:Infinity":127,"b:403:6:407:Infinity:undefined:undefined:undefined:undefined":29,"s:403:6:407:Infinity":128,"s:404:8:404:Infinity":129,"s:405:8:405:Infinity":130,"s:406:8:406:Infinity":131,"b:409:6:421:Infinity:undefined:undefined:undefined:undefined":30,"s:409:6:421:Infinity":132,"s:410:24:410:Infinity":133,"b:410:24:410:62:410:62:410:Infinity":31,"b:411:8:418:Infinity:undefined:undefined:undefined:undefined":32,"s:411:8:418:Infinity":134,"s:412:10:412:Infinity":135,"s:413:26:413:Infinity":136,"b:414:10:417:Infinity:undefined:undefined:undefined:undefined":33,"s:414:10:417:Infinity":137,"s:415:12:415:Infinity":138,"s:416:12:416:Infinity":139,"s:419:8:419:Infinity":140,"s:420:8:420:Infinity":141,"s:423:6:423:Infinity":142,"b:423:54:423:68:423:68:423:80":34,"s:424:6:424:Infinity":143,"f:432:16:432:32":18,"s:433:18:433:Infinity":144,"b:434:4:434:Infinity:undefined:undefined:undefined:undefined":35,"s:434:4:434:Infinity":145,"s:434:27:434:Infinity":146,"s:436:10:436:Infinity":147,"b:437:4:437:Infinity:undefined:undefined:undefined:undefined":36,"s:437:4:437:Infinity":148,"b:437:8:437:21:437:21:437:54":37,"s:437:54:437:Infinity":149,"s:440:23:440:Infinity":150,"b:441:4:441:Infinity:undefined:undefined:undefined:undefined":38,"s:441:4:441:Infinity":151,"s:441:33:441:Infinity":152,"s:443:22:443:Infinity":153,"f:443:37:443:42":19,"s:443:42:443:55":154,"s:445:6:446:Infinity":155,"s:450:4:450:Infinity":156,"s:452:21:452:Infinity":157,"s:453:48:453:Infinity":158,"s:455:27:455:Infinity":159,"s:457:23:457:Infinity":160,"s:458:4:458:Infinity":161,"b:459:4:461:Infinity:undefined:undefined:undefined:undefined":39,"s:459:4:461:Infinity":162,"s:460:6:460:Infinity":163,"s:464:30:464:Infinity":164,"b:465:4:467:Infinity:undefined:undefined:undefined:undefined":40,"s:465:4:467:Infinity":165,"s:466:6:466:Infinity":166,"s:469:44:473:Infinity":167,"f:471:6:471:7":20,"s:471:17:471:Infinity":168,"s:475:4:475:Infinity":169,"s:476:43:476:Infinity":170,"s:477:4:477:Infinity":171,"s:479:37:483:Infinity":172,"f:481:6:481:12":21,"s:481:12:481:Infinity":173,"f:482:6:482:12":22,"s:482:12:482:Infinity":174,"s:484:4:484:Infinity":175,"s:486:4:486:Infinity":176,"f:494:16:494:46":23,"b:495:4:495:Infinity:undefined:undefined:undefined:undefined":41,"s:495:4:495:Infinity":177,"s:495:33:495:Infinity":178,"s:497:4:507:Infinity":179,"s:498:20:498:Infinity":180,"b:499:6:499:Infinity:undefined:undefined:undefined:undefined":42,"s:499:6:499:Infinity":181,"s:499:29:499:Infinity":182,"s:501:38:501:Infinity":183,"s:502:24:502:Infinity":184,"s:503:6:503:Infinity":185,"s:504:6:504:Infinity":186,"s:506:6:506:Infinity":187,"b:506:54:506:68:506:68:506:80":43,"f:513:8:513:13":24,"s:514:18:514:Infinity":188,"b:515:4:515:Infinity:undefined:undefined:undefined:undefined":44,"s:515:4:515:Infinity":189,"s:515:16:515:Infinity":190,"s:516:4:516:Infinity":191,"s:518:19:518:Infinity":192,"b:519:4:522:Infinity:undefined:undefined:undefined:undefined":45,"s:519:4:522:Infinity":193,"s:520:6:520:Infinity":194,"s:520:12:520:49":195,"s:521:6:521:Infinity":196,"s:523:4:523:Infinity":197,"s:526:4:526:Infinity":198,"s:528:4:528:Infinity":199,"b:530:4:537:Infinity:undefined:undefined:undefined:undefined":46,"s:530:4:537:Infinity":200,"s:531:39:535:Infinity":201,"b:534:54:534:70:534:70:534:74":47,"s:536:6:536:Infinity":202,"f:543:8:543:37":25,"s:544:19:544:Infinity":203,"s:545:4:545:Infinity":204,"f:545:22:545:23":26,"s:545:29:545:48":205,"f:551:8:551:12":27,"s:552:18:552:Infinity":206,"s:553:4:553:Infinity":207,"b:553:19:553:45:553:45:553:Infinity":48,"f:559:8:559:18":28,"s:560:18:560:Infinity":208,"s:561:4:561:Infinity":209,"b:561:19:561:45:561:45:561:Infinity":49,"f:568:8:568:28":29,"s:569:4:572:Infinity":210,"s:574:4:577:Infinity":211,"f:575:6:575:7":30,"s:575:31:575:Infinity":212,"f:584:8:584:15":31,"s:585:4:585:Infinity":213,"f:592:16:592:31":32,"s:593:18:593:Infinity":214,"b:594:4:594:Infinity:undefined:undefined:undefined:undefined":50,"s:594:4:594:Infinity":215,"s:594:16:594:Infinity":216,"b:595:4:597:Infinity:undefined:undefined:undefined:undefined":51,"s:595:4:597:Infinity":217,"s:596:6:596:Infinity":218,"b:598:4:600:Infinity:undefined:undefined:undefined:undefined":52,"s:598:4:600:Infinity":219,"s:599:6:599:Infinity":220,"s:601:4:601:Infinity":221,"s:603:10:603:Infinity":222,"b:604:4:604:Infinity:undefined:undefined:undefined:undefined":53,"s:604:4:604:Infinity":223,"s:604:19:604:Infinity":224,"b:605:4:607:Infinity:undefined:undefined:undefined:undefined":54,"s:605:4:607:Infinity":225,"s:606:6:606:Infinity":226,"s:609:21:609:Infinity":227,"s:610:19:610:Infinity":228,"s:613:10:613:Infinity":229,"s:614:4:619:Infinity":230,"s:615:6:615:Infinity":231,"s:616:6:616:Infinity":232,"s:621:4:621:Infinity":233,"s:623:48:623:Infinity":234,"s:624:4:624:Infinity":235,"s:627:27:627:Infinity":236,"s:630:23:630:Infinity":237,"s:631:4:631:Infinity":238,"b:632:4:634:Infinity:undefined:undefined:undefined:undefined":55,"s:632:4:634:Infinity":239,"s:633:6:633:Infinity":240,"s:637:30:637:Infinity":241,"b:638:4:640:Infinity:undefined:undefined:undefined:undefined":56,"s:638:4:640:Infinity":242,"s:639:6:639:Infinity":243,"s:642:44:646:Infinity":244,"f:644:6:644:7":33,"s:644:17:644:Infinity":245,"s:648:4:648:Infinity":246,"s:650:43:650:Infinity":247,"s:651:4:651:Infinity":248,"s:652:4:652:Infinity":249,"b:654:4:661:Infinity:undefined:undefined:undefined:undefined":57,"s:654:4:661:Infinity":250,"s:655:39:659:Infinity":251,"b:658:54:658:70:658:70:658:74":58,"s:660:6:660:Infinity":252,"s:663:37:667:Infinity":253,"f:665:6:665:12":34,"s:665:12:665:Infinity":254,"f:666:6:666:12":35,"s:666:12:666:Infinity":255,"s:668:4:668:Infinity":256,"f:674:8:674:18":36,"s:675:4:675:Infinity":257,"f:681:8:681:28":37,"s:682:4:682:Infinity":258,"f:688:8:688:15":38,"s:689:18:689:Infinity":259,"b:690:4:690:Infinity:undefined:undefined:undefined:undefined":59,"s:690:4:690:Infinity":260,"s:690:16:690:Infinity":261,"s:691:4:691:Infinity":262,"s:694:19:694:Infinity":263,"b:695:4:698:Infinity:undefined:undefined:undefined:undefined":60,"s:695:4:698:Infinity":264,"s:696:6:696:Infinity":265,"s:696:12:696:49":266,"s:697:6:697:Infinity":267,"s:699:4:699:Infinity":268,"s:702:4:703:Infinity":269,"s:702:10:702:90":270,"s:703:18:703:126":271,"b:703:66:703:80:703:80:703:92":61,"s:705:4:706:Infinity":272,"s:705:10:705:89":273,"s:706:18:706:125":274,"b:706:66:706:80:706:80:706:92":62,"s:708:4:709:Infinity":275,"s:708:10:708:65":276,"s:709:18:709:121":277,"b:709:66:709:80:709:80:709:92":63,"b:712:4:715:Infinity:undefined:undefined:undefined:undefined":64,"s:712:4:715:Infinity":278,"s:713:6:714:Infinity":279,"s:713:12:713:68":280,"s:714:20:714:129":281,"b:714:68:714:82:714:82:714:94":65,"s:718:4:718:Infinity":282,"b:721:4:728:Infinity:undefined:undefined:undefined:undefined":66,"s:721:4:728:Infinity":283,"s:722:39:726:Infinity":284,"s:727:6:727:Infinity":285,"s:729:4:729:Infinity":286,"f:735:8:735:16":39,"s:736:18:736:Infinity":287,"b:737:4:737:Infinity:undefined:undefined:undefined:undefined":67,"s:737:4:737:Infinity":288,"s:737:16:737:Infinity":289,"s:738:4:738:Infinity":290,"s:740:4:740:Infinity":291,"s:742:4:745:Infinity":292,"s:747:4:747:Infinity":293,"f:753:8:753:49":40,"s:754:4:754:Infinity":294,"f:760:8:760:45":41,"s:761:4:761:Infinity":295,"f:767:8:767:47":42,"s:768:34:768:Infinity":296,"s:769:4:795:Infinity":297,"f:771:6:771:7":43,"s:771:26:771:Infinity":298,"f:772:6:772:7":44,"s:772:40:772:Infinity":299,"f:772:108:772:109":45,"s:772:119:772:161":300,"f:773:6:773:7":46,"s:774:27:778:Infinity":301,"f:776:10:776:16":47,"s:776:16:776:Infinity":302,"f:777:10:777:16":48,"s:777:16:777:Infinity":303,"s:779:23:779:Infinity":304,"b:780:8:780:Infinity:undefined:undefined:undefined:undefined":68,"s:780:8:780:Infinity":305,"s:780:20:780:Infinity":306,"b:783:10:793:Infinity:794:10:794:Infinity":69,"f:783:10:783:11":49,"s:785:12:792:Infinity":307,"f:785:64:785:73":50,"s:786:14:791:Infinity":308,"f:792:21:792:28":51,"s:792:28:792:157":309,"b:792:76:792:90:792:90:792:102":70,"f:802:16:802:37":52,"s:803:4:870:Infinity":310,"s:805:20:805:Infinity":311,"b:806:6:808:Infinity:undefined:undefined:undefined:undefined":71,"s:806:6:808:Infinity":312,"s:807:8:807:Infinity":313,"s:811:6:811:Infinity":314,"s:813:6:819:Infinity":315,"b:822:6:862:Infinity:853:13:862:Infinity":72,"s:822:6:862:Infinity":316,"s:823:30:823:Infinity":317,"b:824:8:852:Infinity:841:15:852:Infinity":73,"s:824:8:852:Infinity":318,"s:825:10:830:Infinity":319,"s:836:10:840:Infinity":320,"s:842:10:848:Infinity":321,"s:851:10:851:Infinity":322,"s:854:8:859:Infinity":323,"s:861:8:861:Infinity":324,"s:864:6:869:Infinity":325,"b:868:36:868:50:868:50:868:Infinity":74,"f:877:16:877:43":53,"s:878:4:910:Infinity":326,"s:880:25:880:Infinity":327,"s:881:12:881:Infinity":328,"b:882:6:884:Infinity:undefined:undefined:undefined:undefined":75,"s:882:6:884:Infinity":329,"b:882:10:882:62:882:57:882:101":76,"s:883:8:883:Infinity":330,"s:886:12:886:Infinity":331,"b:888:6:891:Infinity:undefined:undefined:undefined:undefined":77,"s:888:6:891:Infinity":332,"s:889:8:889:Infinity":333,"s:890:8:890:Infinity":334,"s:893:28:893:Infinity":335,"s:894:21:894:Infinity":336,"s:897:24:897:Infinity":337,"b:897:24:897:52:897:52:897:85:897:85:897:Infinity":78,"b:899:6:903:Infinity:901:13:903:Infinity":79,"s:899:6:903:Infinity":338,"s:900:8:900:Infinity":339,"s:902:8:902:Infinity":340,"s:905:6:905:Infinity":341,"s:908:6:908:Infinity":342,"b:908:57:908:71:908:71:908:83":80,"s:909:6:909:Infinity":343,"f:916:10:916:22":54,"s:931:4:945:Infinity":344,"b:934:14:934:30:934:30:934:Infinity":81}}} +,"/Users/lukasmay/development/projects/codewalk-district/src/agent/markdown-to-tiptap.ts": {"path":"/Users/lukasmay/development/projects/codewalk-district/src/agent/markdown-to-tiptap.ts","statementMap":{"0":{"start":{"line":13,"column":39},"end":{"line":13,"column":null}},"1":{"start":{"line":16,"column":2},"end":{"line":20,"column":null}},"2":{"start":{"line":17,"column":4},"end":{"line":19,"column":null}},"3":{"start":{"line":21,"column":2},"end":{"line":21,"column":null}},"4":{"start":{"line":28,"column":2},"end":{"line":30,"column":null}},"5":{"start":{"line":29,"column":4},"end":{"line":29,"column":null}},"6":{"start":{"line":31,"column":2},"end":{"line":31,"column":null}}},"fnMap":{"0":{"name":"getManager","decl":{"start":{"line":15,"column":9},"end":{"line":15,"column":39}},"loc":{"start":{"line":15,"column":39},"end":{"line":22,"column":null}},"line":15},"1":{"name":"markdownToTiptapJson","decl":{"start":{"line":27,"column":16},"end":{"line":27,"column":37}},"loc":{"start":{"line":27,"column":63},"end":{"line":32,"column":null}},"line":27}},"branchMap":{"0":{"loc":{"start":{"line":16,"column":2},"end":{"line":20,"column":null}},"type":"if","locations":[{"start":{"line":16,"column":2},"end":{"line":20,"column":null}},{"start":{},"end":{}}],"line":16},"1":{"loc":{"start":{"line":28,"column":2},"end":{"line":30,"column":null}},"type":"if","locations":[{"start":{"line":28,"column":2},"end":{"line":30,"column":null}},{"start":{},"end":{}}],"line":28}},"s":{"0":20,"1":0,"2":0,"3":0,"4":0,"5":0,"6":0},"f":{"0":0,"1":0},"b":{"0":[0,0],"1":[0,0]},"meta":{"lastBranch":2,"lastFunction":2,"lastStatement":7,"seen":{"s:13:39:13:Infinity":0,"f:15:9:15:39":0,"b:16:2:20:Infinity:undefined:undefined:undefined:undefined":0,"s:16:2:20:Infinity":1,"s:17:4:19:Infinity":2,"s:21:2:21:Infinity":3,"f:27:16:27:37":1,"b:28:2:30:Infinity:undefined:undefined:undefined:undefined":1,"s:28:2:30:Infinity":4,"s:29:4:29:Infinity":5,"s:31:2:31:Infinity":6}}} +,"/Users/lukasmay/development/projects/codewalk-district/src/agent/mock-manager.ts": {"path":"/Users/lukasmay/development/projects/codewalk-district/src/agent/mock-manager.ts","statementMap":{"0":{"start":{"line":67,"column":44},"end":{"line":72,"column":null}},"1":{"start":{"line":82,"column":49},"end":{"line":82,"column":null}},"2":{"start":{"line":83,"column":62},"end":{"line":83,"column":null}},"3":{"start":{"line":88,"column":4},"end":{"line":88,"column":null}},"4":{"start":{"line":89,"column":4},"end":{"line":89,"column":null}},"5":{"start":{"line":97,"column":4},"end":{"line":97,"column":null}},"6":{"start":{"line":104,"column":4},"end":{"line":104,"column":null}},"7":{"start":{"line":114,"column":31},"end":{"line":114,"column":null}},"8":{"start":{"line":115,"column":17},"end":{"line":115,"column":null}},"9":{"start":{"line":118,"column":4},"end":{"line":122,"column":null}},"10":{"start":{"line":119,"column":6},"end":{"line":121,"column":null}},"11":{"start":{"line":120,"column":8},"end":{"line":120,"column":null}},"12":{"start":{"line":124,"column":10},"end":{"line":124,"column":null}},"13":{"start":{"line":125,"column":10},"end":{"line":125,"column":null}},"14":{"start":{"line":126,"column":10},"end":{"line":126,"column":null}},"15":{"start":{"line":127,"column":16},"end":{"line":127,"column":null}},"16":{"start":{"line":130,"column":21},"end":{"line":130,"column":null}},"17":{"start":{"line":132,"column":28},"end":{"line":145,"column":null}},"18":{"start":{"line":147,"column":36},"end":{"line":150,"column":null}},"19":{"start":{"line":152,"column":4},"end":{"line":152,"column":null}},"20":{"start":{"line":155,"column":4},"end":{"line":168,"column":null}},"21":{"start":{"line":156,"column":39},"end":{"line":166,"column":null}},"22":{"start":{"line":167,"column":6},"end":{"line":167,"column":null}},"23":{"start":{"line":171,"column":4},"end":{"line":171,"column":null}},"24":{"start":{"line":173,"column":4},"end":{"line":173,"column":null}},"25":{"start":{"line":180,"column":18},"end":{"line":180,"column":null}},"26":{"start":{"line":182,"column":18},"end":{"line":184,"column":null}},"27":{"start":{"line":183,"column":6},"end":{"line":183,"column":null}},"28":{"start":{"line":186,"column":19},"end":{"line":186,"column":null}},"29":{"start":{"line":187,"column":4},"end":{"line":189,"column":null}},"30":{"start":{"line":188,"column":6},"end":{"line":188,"column":null}},"31":{"start":{"line":196,"column":4},"end":{"line":202,"column":null}},"32":{"start":{"line":197,"column":22},"end":{"line":197,"column":null}},"33":{"start":{"line":198,"column":19},"end":{"line":198,"column":null}},"34":{"start":{"line":199,"column":21},"end":{"line":199,"column":null}},"35":{"start":{"line":200,"column":21},"end":{"line":200,"column":null}},"36":{"start":{"line":201,"column":15},"end":{"line":201,"column":null}},"37":{"start":{"line":209,"column":19},"end":{"line":209,"column":null}},"38":{"start":{"line":210,"column":4},"end":{"line":210,"column":null}},"39":{"start":{"line":210,"column":17},"end":{"line":210,"column":null}},"40":{"start":{"line":212,"column":21},"end":{"line":212,"column":null}},"41":{"start":{"line":214,"column":4},"end":{"line":285,"column":null}},"42":{"start":{"line":216,"column":8},"end":{"line":220,"column":null}},"43":{"start":{"line":221,"column":8},"end":{"line":221,"column":null}},"44":{"start":{"line":222,"column":8},"end":{"line":222,"column":null}},"45":{"start":{"line":224,"column":8},"end":{"line":237,"column":null}},"46":{"start":{"line":225,"column":25},"end":{"line":225,"column":null}},"47":{"start":{"line":226,"column":43},"end":{"line":235,"column":null}},"48":{"start":{"line":236,"column":10},"end":{"line":236,"column":null}},"49":{"start":{"line":238,"column":8},"end":{"line":238,"column":null}},"50":{"start":{"line":241,"column":8},"end":{"line":244,"column":null}},"51":{"start":{"line":245,"column":8},"end":{"line":245,"column":null}},"52":{"start":{"line":246,"column":8},"end":{"line":246,"column":null}},"53":{"start":{"line":248,"column":8},"end":{"line":260,"column":null}},"54":{"start":{"line":249,"column":43},"end":{"line":258,"column":null}},"55":{"start":{"line":259,"column":10},"end":{"line":259,"column":null}},"56":{"start":{"line":261,"column":8},"end":{"line":261,"column":null}},"57":{"start":{"line":264,"column":8},"end":{"line":264,"column":null}},"58":{"start":{"line":265,"column":8},"end":{"line":265,"column":null}},"59":{"start":{"line":266,"column":8},"end":{"line":268,"column":null}},"60":{"start":{"line":270,"column":8},"end":{"line":283,"column":null}},"61":{"start":{"line":271,"column":43},"end":{"line":281,"column":null}},"62":{"start":{"line":282,"column":10},"end":{"line":282,"column":null}},"63":{"start":{"line":284,"column":8},"end":{"line":284,"column":null}},"64":{"start":{"line":294,"column":19},"end":{"line":294,"column":null}},"65":{"start":{"line":295,"column":4},"end":{"line":297,"column":null}},"66":{"start":{"line":296,"column":6},"end":{"line":296,"column":null}},"67":{"start":{"line":300,"column":4},"end":{"line":303,"column":null}},"68":{"start":{"line":301,"column":6},"end":{"line":301,"column":null}},"69":{"start":{"line":302,"column":6},"end":{"line":302,"column":null}},"70":{"start":{"line":305,"column":4},"end":{"line":305,"column":null}},"71":{"start":{"line":306,"column":4},"end":{"line":306,"column":null}},"72":{"start":{"line":308,"column":4},"end":{"line":320,"column":null}},"73":{"start":{"line":309,"column":39},"end":{"line":318,"column":null}},"74":{"start":{"line":319,"column":6},"end":{"line":319,"column":null}},"75":{"start":{"line":328,"column":19},"end":{"line":328,"column":null}},"76":{"start":{"line":329,"column":4},"end":{"line":331,"column":null}},"77":{"start":{"line":330,"column":6},"end":{"line":330,"column":null}},"78":{"start":{"line":334,"column":4},"end":{"line":337,"column":null}},"79":{"start":{"line":335,"column":6},"end":{"line":335,"column":null}},"80":{"start":{"line":336,"column":6},"end":{"line":336,"column":null}},"81":{"start":{"line":339,"column":17},"end":{"line":339,"column":null}},"82":{"start":{"line":340,"column":4},"end":{"line":340,"column":null}},"83":{"start":{"line":342,"column":4},"end":{"line":352,"column":null}},"84":{"start":{"line":343,"column":39},"end":{"line":350,"column":null}},"85":{"start":{"line":351,"column":6},"end":{"line":351,"column":null}},"86":{"start":{"line":359,"column":4},"end":{"line":359,"column":null}},"87":{"start":{"line":359,"column":60},"end":{"line":359,"column":71}},"88":{"start":{"line":366,"column":19},"end":{"line":366,"column":null}},"89":{"start":{"line":367,"column":4},"end":{"line":367,"column":null}},"90":{"start":{"line":374,"column":4},"end":{"line":378,"column":null}},"91":{"start":{"line":375,"column":6},"end":{"line":377,"column":null}},"92":{"start":{"line":376,"column":8},"end":{"line":376,"column":null}},"93":{"start":{"line":379,"column":4},"end":{"line":379,"column":null}},"94":{"start":{"line":392,"column":19},"end":{"line":392,"column":null}},"95":{"start":{"line":393,"column":4},"end":{"line":395,"column":null}},"96":{"start":{"line":394,"column":6},"end":{"line":394,"column":null}},"97":{"start":{"line":397,"column":4},"end":{"line":401,"column":null}},"98":{"start":{"line":398,"column":6},"end":{"line":400,"column":null}},"99":{"start":{"line":403,"column":4},"end":{"line":405,"column":null}},"100":{"start":{"line":404,"column":6},"end":{"line":404,"column":null}},"101":{"start":{"line":408,"column":4},"end":{"line":408,"column":null}},"102":{"start":{"line":409,"column":4},"end":{"line":409,"column":null}},"103":{"start":{"line":410,"column":4},"end":{"line":410,"column":null}},"104":{"start":{"line":413,"column":4},"end":{"line":425,"column":null}},"105":{"start":{"line":414,"column":39},"end":{"line":423,"column":null}},"106":{"start":{"line":424,"column":6},"end":{"line":424,"column":null}},"107":{"start":{"line":431,"column":6},"end":{"line":431,"column":null}},"108":{"start":{"line":432,"column":46},"end":{"line":437,"column":null}},"109":{"start":{"line":439,"column":4},"end":{"line":439,"column":null}},"110":{"start":{"line":448,"column":19},"end":{"line":448,"column":null}},"111":{"start":{"line":449,"column":4},"end":{"line":449,"column":null}},"112":{"start":{"line":456,"column":19},"end":{"line":456,"column":null}},"113":{"start":{"line":457,"column":4},"end":{"line":457,"column":null}},"114":{"start":{"line":465,"column":19},"end":{"line":465,"column":null}},"115":{"start":{"line":466,"column":4},"end":{"line":468,"column":null}},"116":{"start":{"line":467,"column":6},"end":{"line":467,"column":null}},"117":{"start":{"line":469,"column":16},"end":{"line":469,"column":null}},"118":{"start":{"line":470,"column":4},"end":{"line":470,"column":null}},"119":{"start":{"line":471,"column":4},"end":{"line":471,"column":null}},"120":{"start":{"line":479,"column":4},"end":{"line":483,"column":null}},"121":{"start":{"line":480,"column":6},"end":{"line":482,"column":null}},"122":{"start":{"line":481,"column":8},"end":{"line":481,"column":null}},"123":{"start":{"line":484,"column":4},"end":{"line":484,"column":null}},"124":{"start":{"line":485,"column":4},"end":{"line":485,"column":null}}},"fnMap":{"0":{"name":"(anonymous_0)","decl":{"start":{"line":87,"column":2},"end":{"line":87,"column":14}},"loc":{"start":{"line":87,"column":86},"end":{"line":90,"column":null}},"line":87},"1":{"name":"(anonymous_1)","decl":{"start":{"line":96,"column":2},"end":{"line":96,"column":14}},"loc":{"start":{"line":96,"column":68},"end":{"line":98,"column":null}},"line":96},"2":{"name":"(anonymous_2)","decl":{"start":{"line":103,"column":2},"end":{"line":103,"column":16}},"loc":{"start":{"line":103,"column":41},"end":{"line":105,"column":null}},"line":103},"3":{"name":"(anonymous_3)","decl":{"start":{"line":113,"column":8},"end":{"line":113,"column":14}},"loc":{"start":{"line":113,"column":62},"end":{"line":174,"column":null}},"line":113},"4":{"name":"(anonymous_4)","decl":{"start":{"line":179,"column":10},"end":{"line":179,"column":29}},"loc":{"start":{"line":179,"column":81},"end":{"line":190,"column":null}},"line":179},"5":{"name":"(anonymous_5)","decl":{"start":{"line":182,"column":29},"end":{"line":182,"column":35}},"loc":{"start":{"line":182,"column":35},"end":{"line":184,"column":7}},"line":182},"6":{"name":"(anonymous_6)","decl":{"start":{"line":195,"column":10},"end":{"line":195,"column":27}},"loc":{"start":{"line":195,"column":84},"end":{"line":203,"column":null}},"line":195},"7":{"name":"(anonymous_7)","decl":{"start":{"line":208,"column":10},"end":{"line":208,"column":24}},"loc":{"start":{"line":208,"column":76},"end":{"line":286,"column":null}},"line":208},"8":{"name":"(anonymous_8)","decl":{"start":{"line":293,"column":8},"end":{"line":293,"column":13}},"loc":{"start":{"line":293,"column":45},"end":{"line":321,"column":null}},"line":293},"9":{"name":"(anonymous_9)","decl":{"start":{"line":327,"column":8},"end":{"line":327,"column":15}},"loc":{"start":{"line":327,"column":47},"end":{"line":353,"column":null}},"line":327},"10":{"name":"(anonymous_10)","decl":{"start":{"line":358,"column":8},"end":{"line":358,"column":37}},"loc":{"start":{"line":358,"column":37},"end":{"line":360,"column":null}},"line":358},"11":{"name":"(anonymous_11)","decl":{"start":{"line":359,"column":48},"end":{"line":359,"column":49}},"loc":{"start":{"line":359,"column":60},"end":{"line":359,"column":71}},"line":359},"12":{"name":"(anonymous_12)","decl":{"start":{"line":365,"column":8},"end":{"line":365,"column":12}},"loc":{"start":{"line":365,"column":56},"end":{"line":368,"column":null}},"line":365},"13":{"name":"(anonymous_13)","decl":{"start":{"line":373,"column":8},"end":{"line":373,"column":18}},"loc":{"start":{"line":373,"column":59},"end":{"line":380,"column":null}},"line":373},"14":{"name":"(anonymous_14)","decl":{"start":{"line":391,"column":8},"end":{"line":391,"column":15}},"loc":{"start":{"line":391,"column":80},"end":{"line":440,"column":null}},"line":391},"15":{"name":"(anonymous_15)","decl":{"start":{"line":447,"column":8},"end":{"line":447,"column":18}},"loc":{"start":{"line":447,"column":64},"end":{"line":450,"column":null}},"line":447},"16":{"name":"(anonymous_16)","decl":{"start":{"line":455,"column":8},"end":{"line":455,"column":28}},"loc":{"start":{"line":455,"column":79},"end":{"line":458,"column":null}},"line":455},"17":{"name":"(anonymous_17)","decl":{"start":{"line":464,"column":8},"end":{"line":464,"column":16}},"loc":{"start":{"line":464,"column":48},"end":{"line":472,"column":null}},"line":464},"18":{"name":"(anonymous_18)","decl":{"start":{"line":478,"column":2},"end":{"line":478,"column":16}},"loc":{"start":{"line":478,"column":16},"end":{"line":486,"column":null}},"line":478}},"branchMap":{"0":{"loc":{"start":{"line":89,"column":27},"end":{"line":89,"column":null}},"type":"binary-expr","locations":[{"start":{"line":89,"column":27},"end":{"line":89,"column":55}},{"start":{"line":89,"column":55},"end":{"line":89,"column":null}}],"line":89},"1":{"loc":{"start":{"line":115,"column":17},"end":{"line":115,"column":null}},"type":"binary-expr","locations":[{"start":{"line":115,"column":17},"end":{"line":115,"column":33}},{"start":{"line":115,"column":33},"end":{"line":115,"column":null}}],"line":115},"2":{"loc":{"start":{"line":115,"column":42},"end":{"line":115,"column":73}},"type":"binary-expr","locations":[{"start":{"line":115,"column":42},"end":{"line":115,"column":65}},{"start":{"line":115,"column":65},"end":{"line":115,"column":73}}],"line":115},"3":{"loc":{"start":{"line":119,"column":6},"end":{"line":121,"column":null}},"type":"if","locations":[{"start":{"line":119,"column":6},"end":{"line":121,"column":null}},{"start":{},"end":{}}],"line":119},"4":{"loc":{"start":{"line":130,"column":21},"end":{"line":130,"column":null}},"type":"binary-expr","locations":[{"start":{"line":130,"column":21},"end":{"line":130,"column":57}},{"start":{"line":130,"column":57},"end":{"line":130,"column":null}}],"line":130},"5":{"loc":{"start":{"line":134,"column":12},"end":{"line":134,"column":null}},"type":"binary-expr","locations":[{"start":{"line":134,"column":12},"end":{"line":134,"column":20}},{"start":{"line":134,"column":20},"end":{"line":134,"column":null}}],"line":134},"6":{"loc":{"start":{"line":135,"column":14},"end":{"line":135,"column":null}},"type":"binary-expr","locations":[{"start":{"line":135,"column":14},"end":{"line":135,"column":24}},{"start":{"line":135,"column":24},"end":{"line":135,"column":null}}],"line":135},"7":{"loc":{"start":{"line":136,"column":20},"end":{"line":136,"column":null}},"type":"binary-expr","locations":[{"start":{"line":136,"column":20},"end":{"line":136,"column":44}},{"start":{"line":136,"column":44},"end":{"line":136,"column":null}}],"line":136},"8":{"loc":{"start":{"line":140,"column":12},"end":{"line":140,"column":null}},"type":"binary-expr","locations":[{"start":{"line":140,"column":12},"end":{"line":140,"column":28}},{"start":{"line":140,"column":28},"end":{"line":140,"column":null}}],"line":140},"9":{"loc":{"start":{"line":141,"column":16},"end":{"line":141,"column":null}},"type":"binary-expr","locations":[{"start":{"line":141,"column":16},"end":{"line":141,"column":36}},{"start":{"line":141,"column":36},"end":{"line":141,"column":null}}],"line":141},"10":{"loc":{"start":{"line":155,"column":4},"end":{"line":168,"column":null}},"type":"if","locations":[{"start":{"line":155,"column":4},"end":{"line":168,"column":null}},{"start":{},"end":{}}],"line":155},"11":{"loc":{"start":{"line":162,"column":18},"end":{"line":162,"column":null}},"type":"binary-expr","locations":[{"start":{"line":162,"column":18},"end":{"line":162,"column":28}},{"start":{"line":162,"column":28},"end":{"line":162,"column":null}}],"line":162},"12":{"loc":{"start":{"line":164,"column":20},"end":{"line":164,"column":null}},"type":"binary-expr","locations":[{"start":{"line":164,"column":20},"end":{"line":164,"column":40}},{"start":{"line":164,"column":40},"end":{"line":164,"column":null}}],"line":164},"13":{"loc":{"start":{"line":180,"column":18},"end":{"line":180,"column":null}},"type":"binary-expr","locations":[{"start":{"line":180,"column":18},"end":{"line":180,"column":36}},{"start":{"line":180,"column":36},"end":{"line":180,"column":null}}],"line":180},"14":{"loc":{"start":{"line":187,"column":4},"end":{"line":189,"column":null}},"type":"if","locations":[{"start":{"line":187,"column":4},"end":{"line":189,"column":null}},{"start":{},"end":{}}],"line":187},"15":{"loc":{"start":{"line":196,"column":4},"end":{"line":202,"column":null}},"type":"switch","locations":[{"start":{"line":197,"column":6},"end":{"line":197,"column":null}},{"start":{"line":198,"column":6},"end":{"line":198,"column":null}},{"start":{"line":199,"column":6},"end":{"line":199,"column":null}},{"start":{"line":200,"column":6},"end":{"line":200,"column":null}},{"start":{"line":201,"column":6},"end":{"line":201,"column":null}}],"line":196},"16":{"loc":{"start":{"line":210,"column":4},"end":{"line":210,"column":null}},"type":"if","locations":[{"start":{"line":210,"column":4},"end":{"line":210,"column":null}},{"start":{},"end":{}}],"line":210},"17":{"loc":{"start":{"line":214,"column":4},"end":{"line":285,"column":null}},"type":"switch","locations":[{"start":{"line":215,"column":6},"end":{"line":238,"column":null}},{"start":{"line":240,"column":6},"end":{"line":261,"column":null}},{"start":{"line":263,"column":6},"end":{"line":284,"column":null}}],"line":214},"18":{"loc":{"start":{"line":218,"column":19},"end":{"line":218,"column":null}},"type":"binary-expr","locations":[{"start":{"line":218,"column":19},"end":{"line":218,"column":38}},{"start":{"line":218,"column":38},"end":{"line":218,"column":null}}],"line":218},"19":{"loc":{"start":{"line":224,"column":8},"end":{"line":237,"column":null}},"type":"if","locations":[{"start":{"line":224,"column":8},"end":{"line":237,"column":null}},{"start":{},"end":{}}],"line":224},"20":{"loc":{"start":{"line":248,"column":8},"end":{"line":260,"column":null}},"type":"if","locations":[{"start":{"line":248,"column":8},"end":{"line":260,"column":null}},{"start":{},"end":{}}],"line":248},"21":{"loc":{"start":{"line":270,"column":8},"end":{"line":283,"column":null}},"type":"if","locations":[{"start":{"line":270,"column":8},"end":{"line":283,"column":null}},{"start":{},"end":{}}],"line":270},"22":{"loc":{"start":{"line":278,"column":25},"end":{"line":278,"column":null}},"type":"binary-expr","locations":[{"start":{"line":278,"column":25},"end":{"line":278,"column":43}},{"start":{"line":278,"column":43},"end":{"line":278,"column":null}}],"line":278},"23":{"loc":{"start":{"line":295,"column":4},"end":{"line":297,"column":null}},"type":"if","locations":[{"start":{"line":295,"column":4},"end":{"line":297,"column":null}},{"start":{},"end":{}}],"line":295},"24":{"loc":{"start":{"line":300,"column":4},"end":{"line":303,"column":null}},"type":"if","locations":[{"start":{"line":300,"column":4},"end":{"line":303,"column":null}},{"start":{},"end":{}}],"line":300},"25":{"loc":{"start":{"line":308,"column":4},"end":{"line":320,"column":null}},"type":"if","locations":[{"start":{"line":308,"column":4},"end":{"line":320,"column":null}},{"start":{},"end":{}}],"line":308},"26":{"loc":{"start":{"line":329,"column":4},"end":{"line":331,"column":null}},"type":"if","locations":[{"start":{"line":329,"column":4},"end":{"line":331,"column":null}},{"start":{},"end":{}}],"line":329},"27":{"loc":{"start":{"line":334,"column":4},"end":{"line":337,"column":null}},"type":"if","locations":[{"start":{"line":334,"column":4},"end":{"line":337,"column":null}},{"start":{},"end":{}}],"line":334},"28":{"loc":{"start":{"line":342,"column":4},"end":{"line":352,"column":null}},"type":"if","locations":[{"start":{"line":342,"column":4},"end":{"line":352,"column":null}},{"start":{},"end":{}}],"line":342},"29":{"loc":{"start":{"line":367,"column":11},"end":{"line":367,"column":null}},"type":"cond-expr","locations":[{"start":{"line":367,"column":20},"end":{"line":367,"column":34}},{"start":{"line":367,"column":34},"end":{"line":367,"column":null}}],"line":367},"30":{"loc":{"start":{"line":375,"column":6},"end":{"line":377,"column":null}},"type":"if","locations":[{"start":{"line":375,"column":6},"end":{"line":377,"column":null}},{"start":{},"end":{}}],"line":375},"31":{"loc":{"start":{"line":393,"column":4},"end":{"line":395,"column":null}},"type":"if","locations":[{"start":{"line":393,"column":4},"end":{"line":395,"column":null}},{"start":{},"end":{}}],"line":393},"32":{"loc":{"start":{"line":397,"column":4},"end":{"line":401,"column":null}},"type":"if","locations":[{"start":{"line":397,"column":4},"end":{"line":401,"column":null}},{"start":{},"end":{}}],"line":397},"33":{"loc":{"start":{"line":403,"column":4},"end":{"line":405,"column":null}},"type":"if","locations":[{"start":{"line":403,"column":4},"end":{"line":405,"column":null}},{"start":{},"end":{}}],"line":403},"34":{"loc":{"start":{"line":413,"column":4},"end":{"line":425,"column":null}},"type":"if","locations":[{"start":{"line":413,"column":4},"end":{"line":425,"column":null}},{"start":{},"end":{}}],"line":413},"35":{"loc":{"start":{"line":431,"column":6},"end":{"line":431,"column":null}},"type":"cond-expr","locations":[{"start":{"line":431,"column":42},"end":{"line":431,"column":74}},{"start":{"line":431,"column":74},"end":{"line":431,"column":null}}],"line":431},"36":{"loc":{"start":{"line":434,"column":13},"end":{"line":434,"column":null}},"type":"binary-expr","locations":[{"start":{"line":434,"column":13},"end":{"line":434,"column":38}},{"start":{"line":434,"column":38},"end":{"line":434,"column":null}}],"line":434},"37":{"loc":{"start":{"line":449,"column":11},"end":{"line":449,"column":null}},"type":"binary-expr","locations":[{"start":{"line":449,"column":11},"end":{"line":449,"column":29}},{"start":{"line":449,"column":29},"end":{"line":449,"column":null}}],"line":449},"38":{"loc":{"start":{"line":457,"column":11},"end":{"line":457,"column":null}},"type":"binary-expr","locations":[{"start":{"line":457,"column":11},"end":{"line":457,"column":39}},{"start":{"line":457,"column":39},"end":{"line":457,"column":null}}],"line":457},"39":{"loc":{"start":{"line":466,"column":4},"end":{"line":468,"column":null}},"type":"if","locations":[{"start":{"line":466,"column":4},"end":{"line":468,"column":null}},{"start":{},"end":{}}],"line":466},"40":{"loc":{"start":{"line":480,"column":6},"end":{"line":482,"column":null}},"type":"if","locations":[{"start":{"line":480,"column":6},"end":{"line":482,"column":null}},{"start":{},"end":{}}],"line":480}},"s":{"0":9,"1":126,"2":126,"3":126,"4":126,"5":63,"6":1,"7":126,"8":126,"9":126,"10":79,"11":1,"12":125,"13":125,"14":125,"15":125,"16":125,"17":126,"18":126,"19":126,"20":126,"21":124,"22":124,"23":125,"24":125,"25":137,"26":137,"27":107,"28":137,"29":137,"30":137,"31":74,"32":4,"33":3,"34":7,"35":0,"36":60,"37":107,"38":107,"39":0,"40":107,"41":107,"42":74,"43":74,"44":74,"45":74,"46":74,"47":74,"48":74,"49":74,"50":13,"51":13,"52":13,"53":13,"54":13,"55":13,"56":13,"57":20,"58":20,"59":20,"60":20,"61":20,"62":20,"63":20,"64":2,"65":2,"66":1,"67":1,"68":1,"69":1,"70":1,"71":1,"72":1,"73":1,"74":1,"75":0,"76":0,"77":0,"78":0,"79":0,"80":0,"81":0,"82":0,"83":0,"84":0,"85":0,"86":59,"87":79,"88":31,"89":31,"90":12,"91":11,"92":11,"93":1,"94":14,"95":14,"96":1,"97":13,"98":1,"99":12,"100":0,"101":12,"102":12,"103":12,"104":12,"105":12,"106":12,"107":12,"108":14,"109":14,"110":9,"111":9,"112":15,"113":15,"114":2,"115":2,"116":0,"117":2,"118":2,"119":2,"120":129,"121":125,"122":124,"123":129,"124":129},"f":{"0":126,"1":63,"2":1,"3":126,"4":137,"5":107,"6":74,"7":107,"8":2,"9":0,"10":59,"11":79,"12":31,"13":12,"14":14,"15":9,"16":15,"17":2,"18":129},"b":{"0":[126,125],"1":[126,33],"2":[33,0],"3":[1,78],"4":[125,66],"5":[126,0],"6":[126,0],"7":[126,73],"8":[126,97],"9":[126,125],"10":[124,2],"11":[124,0],"12":[124,124],"13":[137,25],"14":[137,0],"15":[4,3,7,0,60],"16":[0,107],"17":[74,13,20],"18":[74,0],"19":[74,0],"20":[13,0],"21":[20,0],"22":[20,0],"23":[1,1],"24":[1,0],"25":[1,0],"26":[0,0],"27":[0,0],"28":[0,0],"29":[30,1],"30":[11,0],"31":[1,13],"32":[1,12],"33":[0,12],"34":[12,0],"35":[0,12],"36":[14,8],"37":[9,0],"38":[15,5],"39":[0,2],"40":[124,1]},"meta":{"lastBranch":41,"lastFunction":19,"lastStatement":125,"seen":{"s:67:44:72:Infinity":0,"s:82:49:82:Infinity":1,"s:83:62:83:Infinity":2,"f:87:2:87:14":0,"s:88:4:88:Infinity":3,"s:89:4:89:Infinity":4,"b:89:27:89:55:89:55:89:Infinity":0,"f:96:2:96:14":1,"s:97:4:97:Infinity":5,"f:103:2:103:16":2,"s:104:4:104:Infinity":6,"f:113:8:113:14":3,"s:114:31:114:Infinity":7,"s:115:17:115:Infinity":8,"b:115:17:115:33:115:33:115:Infinity":1,"b:115:42:115:65:115:65:115:73":2,"s:118:4:122:Infinity":9,"b:119:6:121:Infinity:undefined:undefined:undefined:undefined":3,"s:119:6:121:Infinity":10,"s:120:8:120:Infinity":11,"s:124:10:124:Infinity":12,"s:125:10:125:Infinity":13,"s:126:10:126:Infinity":14,"s:127:16:127:Infinity":15,"s:130:21:130:Infinity":16,"b:130:21:130:57:130:57:130:Infinity":4,"s:132:28:145:Infinity":17,"b:134:12:134:20:134:20:134:Infinity":5,"b:135:14:135:24:135:24:135:Infinity":6,"b:136:20:136:44:136:44:136:Infinity":7,"b:140:12:140:28:140:28:140:Infinity":8,"b:141:16:141:36:141:36:141:Infinity":9,"s:147:36:150:Infinity":18,"s:152:4:152:Infinity":19,"b:155:4:168:Infinity:undefined:undefined:undefined:undefined":10,"s:155:4:168:Infinity":20,"s:156:39:166:Infinity":21,"b:162:18:162:28:162:28:162:Infinity":11,"b:164:20:164:40:164:40:164:Infinity":12,"s:167:6:167:Infinity":22,"s:171:4:171:Infinity":23,"s:173:4:173:Infinity":24,"f:179:10:179:29":4,"s:180:18:180:Infinity":25,"b:180:18:180:36:180:36:180:Infinity":13,"s:182:18:184:Infinity":26,"f:182:29:182:35":5,"s:183:6:183:Infinity":27,"s:186:19:186:Infinity":28,"b:187:4:189:Infinity:undefined:undefined:undefined:undefined":14,"s:187:4:189:Infinity":29,"s:188:6:188:Infinity":30,"f:195:10:195:27":6,"b:197:6:197:Infinity:198:6:198:Infinity:199:6:199:Infinity:200:6:200:Infinity:201:6:201:Infinity":15,"s:196:4:202:Infinity":31,"s:197:22:197:Infinity":32,"s:198:19:198:Infinity":33,"s:199:21:199:Infinity":34,"s:200:21:200:Infinity":35,"s:201:15:201:Infinity":36,"f:208:10:208:24":7,"s:209:19:209:Infinity":37,"b:210:4:210:Infinity:undefined:undefined:undefined:undefined":16,"s:210:4:210:Infinity":38,"s:210:17:210:Infinity":39,"s:212:21:212:Infinity":40,"b:215:6:238:Infinity:240:6:261:Infinity:263:6:284:Infinity":17,"s:214:4:285:Infinity":41,"s:216:8:220:Infinity":42,"b:218:19:218:38:218:38:218:Infinity":18,"s:221:8:221:Infinity":43,"s:222:8:222:Infinity":44,"b:224:8:237:Infinity:undefined:undefined:undefined:undefined":19,"s:224:8:237:Infinity":45,"s:225:25:225:Infinity":46,"s:226:43:235:Infinity":47,"s:236:10:236:Infinity":48,"s:238:8:238:Infinity":49,"s:241:8:244:Infinity":50,"s:245:8:245:Infinity":51,"s:246:8:246:Infinity":52,"b:248:8:260:Infinity:undefined:undefined:undefined:undefined":20,"s:248:8:260:Infinity":53,"s:249:43:258:Infinity":54,"s:259:10:259:Infinity":55,"s:261:8:261:Infinity":56,"s:264:8:264:Infinity":57,"s:265:8:265:Infinity":58,"s:266:8:268:Infinity":59,"b:270:8:283:Infinity:undefined:undefined:undefined:undefined":21,"s:270:8:283:Infinity":60,"s:271:43:281:Infinity":61,"b:278:25:278:43:278:43:278:Infinity":22,"s:282:10:282:Infinity":62,"s:284:8:284:Infinity":63,"f:293:8:293:13":8,"s:294:19:294:Infinity":64,"b:295:4:297:Infinity:undefined:undefined:undefined:undefined":23,"s:295:4:297:Infinity":65,"s:296:6:296:Infinity":66,"b:300:4:303:Infinity:undefined:undefined:undefined:undefined":24,"s:300:4:303:Infinity":67,"s:301:6:301:Infinity":68,"s:302:6:302:Infinity":69,"s:305:4:305:Infinity":70,"s:306:4:306:Infinity":71,"b:308:4:320:Infinity:undefined:undefined:undefined:undefined":25,"s:308:4:320:Infinity":72,"s:309:39:318:Infinity":73,"s:319:6:319:Infinity":74,"f:327:8:327:15":9,"s:328:19:328:Infinity":75,"b:329:4:331:Infinity:undefined:undefined:undefined:undefined":26,"s:329:4:331:Infinity":76,"s:330:6:330:Infinity":77,"b:334:4:337:Infinity:undefined:undefined:undefined:undefined":27,"s:334:4:337:Infinity":78,"s:335:6:335:Infinity":79,"s:336:6:336:Infinity":80,"s:339:17:339:Infinity":81,"s:340:4:340:Infinity":82,"b:342:4:352:Infinity:undefined:undefined:undefined:undefined":28,"s:342:4:352:Infinity":83,"s:343:39:350:Infinity":84,"s:351:6:351:Infinity":85,"f:358:8:358:37":10,"s:359:4:359:Infinity":86,"f:359:48:359:49":11,"s:359:60:359:71":87,"f:365:8:365:12":12,"s:366:19:366:Infinity":88,"s:367:4:367:Infinity":89,"b:367:20:367:34:367:34:367:Infinity":29,"f:373:8:373:18":13,"s:374:4:378:Infinity":90,"b:375:6:377:Infinity:undefined:undefined:undefined:undefined":30,"s:375:6:377:Infinity":91,"s:376:8:376:Infinity":92,"s:379:4:379:Infinity":93,"f:391:8:391:15":14,"s:392:19:392:Infinity":94,"b:393:4:395:Infinity:undefined:undefined:undefined:undefined":31,"s:393:4:395:Infinity":95,"s:394:6:394:Infinity":96,"b:397:4:401:Infinity:undefined:undefined:undefined:undefined":32,"s:397:4:401:Infinity":97,"s:398:6:400:Infinity":98,"b:403:4:405:Infinity:undefined:undefined:undefined:undefined":33,"s:403:4:405:Infinity":99,"s:404:6:404:Infinity":100,"s:408:4:408:Infinity":101,"s:409:4:409:Infinity":102,"s:410:4:410:Infinity":103,"b:413:4:425:Infinity:undefined:undefined:undefined:undefined":34,"s:413:4:425:Infinity":104,"s:414:39:423:Infinity":105,"s:424:6:424:Infinity":106,"s:431:6:431:Infinity":107,"b:431:42:431:74:431:74:431:Infinity":35,"s:432:46:437:Infinity":108,"b:434:13:434:38:434:38:434:Infinity":36,"s:439:4:439:Infinity":109,"f:447:8:447:18":15,"s:448:19:448:Infinity":110,"s:449:4:449:Infinity":111,"b:449:11:449:29:449:29:449:Infinity":37,"f:455:8:455:28":16,"s:456:19:456:Infinity":112,"s:457:4:457:Infinity":113,"b:457:11:457:39:457:39:457:Infinity":38,"f:464:8:464:16":17,"s:465:19:465:Infinity":114,"b:466:4:468:Infinity:undefined:undefined:undefined:undefined":39,"s:466:4:468:Infinity":115,"s:467:6:467:Infinity":116,"s:469:16:469:Infinity":117,"s:470:4:470:Infinity":118,"s:471:4:471:Infinity":119,"f:478:2:478:16":18,"s:479:4:483:Infinity":120,"b:480:6:482:Infinity:undefined:undefined:undefined:undefined":40,"s:480:6:482:Infinity":121,"s:481:8:481:Infinity":122,"s:484:4:484:Infinity":123,"s:485:4:485:Infinity":124}}} +,"/Users/lukasmay/development/projects/codewalk-district/src/agent/output-handler.ts": {"path":"/Users/lukasmay/development/projects/codewalk-district/src/agent/output-handler.ts","statementMap":{"0":{"start":{"line":45,"column":6},"end":{"line":45,"column":null}},"1":{"start":{"line":82,"column":26},"end":{"line":82,"column":null}},"2":{"start":{"line":83,"column":28},"end":{"line":83,"column":null}},"3":{"start":{"line":86,"column":12},"end":{"line":86,"column":null}},"4":{"start":{"line":87,"column":12},"end":{"line":87,"column":null}},"5":{"start":{"line":88,"column":12},"end":{"line":88,"column":null}},"6":{"start":{"line":89,"column":12},"end":{"line":89,"column":null}},"7":{"start":{"line":90,"column":12},"end":{"line":90,"column":null}},"8":{"start":{"line":91,"column":12},"end":{"line":91,"column":null}},"9":{"start":{"line":92,"column":12},"end":{"line":92,"column":null}},"10":{"start":{"line":99,"column":4},"end":{"line":113,"column":null}},"11":{"start":{"line":100,"column":22},"end":{"line":100,"column":null}},"12":{"start":{"line":101,"column":22},"end":{"line":101,"column":null}},"13":{"start":{"line":102,"column":6},"end":{"line":102,"column":null}},"14":{"start":{"line":102,"column":20},"end":{"line":102,"column":null}},"15":{"start":{"line":105,"column":28},"end":{"line":105,"column":null}},"16":{"start":{"line":106,"column":6},"end":{"line":106,"column":null}},"17":{"start":{"line":106,"column":26},"end":{"line":106,"column":null}},"18":{"start":{"line":109,"column":6},"end":{"line":109,"column":null}},"19":{"start":{"line":110,"column":6},"end":{"line":110,"column":null}},"20":{"start":{"line":112,"column":6},"end":{"line":112,"column":null}},"21":{"start":{"line":121,"column":4},"end":{"line":150,"column":null}},"22":{"start":{"line":122,"column":22},"end":{"line":122,"column":null}},"23":{"start":{"line":124,"column":6},"end":{"line":126,"column":null}},"24":{"start":{"line":125,"column":8},"end":{"line":125,"column":null}},"25":{"start":{"line":129,"column":25},"end":{"line":129,"column":null}},"26":{"start":{"line":132,"column":20},"end":{"line":132,"column":null}},"27":{"start":{"line":136,"column":33},"end":{"line":136,"column":null}},"28":{"start":{"line":137,"column":28},"end":{"line":137,"column":null}},"29":{"start":{"line":140,"column":35},"end":{"line":140,"column":null}},"30":{"start":{"line":141,"column":26},"end":{"line":141,"column":null}},"31":{"start":{"line":143,"column":6},"end":{"line":146,"column":null}},"32":{"start":{"line":148,"column":6},"end":{"line":148,"column":null}},"33":{"start":{"line":149,"column":6},"end":{"line":149,"column":null}},"34":{"start":{"line":161,"column":4},"end":{"line":197,"column":null}},"35":{"start":{"line":163,"column":8},"end":{"line":168,"column":null}},"36":{"start":{"line":164,"column":10},"end":{"line":164,"column":null}},"37":{"start":{"line":165,"column":10},"end":{"line":167,"column":null}},"38":{"start":{"line":166,"column":12},"end":{"line":166,"column":null}},"39":{"start":{"line":169,"column":8},"end":{"line":169,"column":null}},"40":{"start":{"line":173,"column":8},"end":{"line":173,"column":null}},"41":{"start":{"line":176,"column":8},"end":{"line":176,"column":null}},"42":{"start":{"line":177,"column":8},"end":{"line":177,"column":null}},"43":{"start":{"line":180,"column":8},"end":{"line":187,"column":null}},"44":{"start":{"line":181,"column":10},"end":{"line":181,"column":null}},"45":{"start":{"line":182,"column":10},"end":{"line":182,"column":null}},"46":{"start":{"line":183,"column":10},"end":{"line":183,"column":null}},"47":{"start":{"line":184,"column":10},"end":{"line":186,"column":null}},"48":{"start":{"line":185,"column":12},"end":{"line":185,"column":null}},"49":{"start":{"line":188,"column":8},"end":{"line":188,"column":null}},"50":{"start":{"line":191,"column":8},"end":{"line":191,"column":null}},"51":{"start":{"line":192,"column":8},"end":{"line":192,"column":null}},"52":{"start":{"line":195,"column":8},"end":{"line":195,"column":null}},"53":{"start":{"line":196,"column":8},"end":{"line":196,"column":null}},"54":{"start":{"line":215,"column":4},"end":{"line":218,"column":null}},"55":{"start":{"line":216,"column":6},"end":{"line":216,"column":null}},"56":{"start":{"line":217,"column":6},"end":{"line":217,"column":null}},"57":{"start":{"line":220,"column":4},"end":{"line":220,"column":null}},"58":{"start":{"line":222,"column":4},"end":{"line":335,"column":null}},"59":{"start":{"line":223,"column":20},"end":{"line":223,"column":null}},"60":{"start":{"line":224,"column":6},"end":{"line":224,"column":null}},"61":{"start":{"line":224,"column":18},"end":{"line":224,"column":null}},"62":{"start":{"line":226,"column":12},"end":{"line":226,"column":null}},"63":{"start":{"line":227,"column":6},"end":{"line":227,"column":null}},"64":{"start":{"line":227,"column":21},"end":{"line":227,"column":null}},"65":{"start":{"line":229,"column":6},"end":{"line":229,"column":null}},"66":{"start":{"line":234,"column":27},"end":{"line":234,"column":null}},"67":{"start":{"line":235,"column":12},"end":{"line":235,"column":null}},"68":{"start":{"line":236,"column":12},"end":{"line":236,"column":null}},"69":{"start":{"line":237,"column":12},"end":{"line":237,"column":null}},"70":{"start":{"line":239,"column":12},"end":{"line":239,"column":null}},"71":{"start":{"line":240,"column":12},"end":{"line":240,"column":null}},"72":{"start":{"line":241,"column":12},"end":{"line":241,"column":null}},"73":{"start":{"line":243,"column":6},"end":{"line":250,"column":null}},"74":{"start":{"line":252,"column":6},"end":{"line":257,"column":null}},"75":{"start":{"line":253,"column":8},"end":{"line":256,"column":null}},"76":{"start":{"line":259,"column":23},"end":{"line":259,"column":null}},"77":{"start":{"line":263,"column":6},"end":{"line":267,"column":null}},"78":{"start":{"line":264,"column":8},"end":{"line":264,"column":null}},"79":{"start":{"line":265,"column":8},"end":{"line":265,"column":null}},"80":{"start":{"line":266,"column":8},"end":{"line":266,"column":null}},"81":{"start":{"line":269,"column":6},"end":{"line":314,"column":null}},"82":{"start":{"line":270,"column":8},"end":{"line":309,"column":null}},"83":{"start":{"line":271,"column":33},"end":{"line":271,"column":null}},"84":{"start":{"line":272,"column":10},"end":{"line":308,"column":null}},"85":{"start":{"line":274,"column":12},"end":{"line":274,"column":null}},"86":{"start":{"line":276,"column":40},"end":{"line":276,"column":null}},"87":{"start":{"line":277,"column":12},"end":{"line":277,"column":null}},"88":{"start":{"line":279,"column":12},"end":{"line":287,"column":null}},"89":{"start":{"line":280,"column":20},"end":{"line":280,"column":null}},"90":{"start":{"line":281,"column":36},"end":{"line":281,"column":null}},"91":{"start":{"line":282,"column":14},"end":{"line":282,"column":null}},"92":{"start":{"line":283,"column":14},"end":{"line":283,"column":null}},"93":{"start":{"line":284,"column":14},"end":{"line":284,"column":null}},"94":{"start":{"line":286,"column":14},"end":{"line":286,"column":null}},"95":{"start":{"line":290,"column":33},"end":{"line":290,"column":null}},"96":{"start":{"line":291,"column":72},"end":{"line":291,"column":null}},"97":{"start":{"line":293,"column":12},"end":{"line":297,"column":null}},"98":{"start":{"line":294,"column":14},"end":{"line":294,"column":null}},"99":{"start":{"line":295,"column":14},"end":{"line":295,"column":null}},"100":{"start":{"line":296,"column":14},"end":{"line":296,"column":null}},"101":{"start":{"line":300,"column":12},"end":{"line":307,"column":null}},"102":{"start":{"line":301,"column":34},"end":{"line":301,"column":null}},"103":{"start":{"line":302,"column":14},"end":{"line":306,"column":null}},"104":{"start":{"line":304,"column":16},"end":{"line":304,"column":null}},"105":{"start":{"line":305,"column":16},"end":{"line":305,"column":null}},"106":{"start":{"line":311,"column":8},"end":{"line":311,"column":null}},"107":{"start":{"line":312,"column":8},"end":{"line":312,"column":null}},"108":{"start":{"line":313,"column":8},"end":{"line":313,"column":null}},"109":{"start":{"line":317,"column":6},"end":{"line":331,"column":null}},"110":{"start":{"line":318,"column":14},"end":{"line":318,"column":null}},"111":{"start":{"line":319,"column":30},"end":{"line":319,"column":null}},"112":{"start":{"line":320,"column":8},"end":{"line":320,"column":null}},"113":{"start":{"line":321,"column":8},"end":{"line":321,"column":null}},"114":{"start":{"line":323,"column":8},"end":{"line":323,"column":null}},"115":{"start":{"line":324,"column":8},"end":{"line":330,"column":null}},"116":{"start":{"line":333,"column":6},"end":{"line":333,"column":null}},"117":{"start":{"line":334,"column":6},"end":{"line":334,"column":null}},"118":{"start":{"line":349,"column":18},"end":{"line":349,"column":null}},"119":{"start":{"line":350,"column":4},"end":{"line":350,"column":null}},"120":{"start":{"line":350,"column":16},"end":{"line":350,"column":null}},"121":{"start":{"line":356,"column":4},"end":{"line":369,"column":null}},"122":{"start":{"line":357,"column":6},"end":{"line":357,"column":null}},"123":{"start":{"line":358,"column":6},"end":{"line":358,"column":null}},"124":{"start":{"line":360,"column":6},"end":{"line":365,"column":null}},"125":{"start":{"line":366,"column":6},"end":{"line":366,"column":null}},"126":{"start":{"line":367,"column":6},"end":{"line":367,"column":null}},"127":{"start":{"line":368,"column":6},"end":{"line":368,"column":null}},"128":{"start":{"line":372,"column":4},"end":{"line":386,"column":null}},"129":{"start":{"line":373,"column":6},"end":{"line":373,"column":null}},"130":{"start":{"line":374,"column":6},"end":{"line":374,"column":null}},"131":{"start":{"line":376,"column":6},"end":{"line":382,"column":null}},"132":{"start":{"line":383,"column":6},"end":{"line":383,"column":null}},"133":{"start":{"line":384,"column":6},"end":{"line":384,"column":null}},"134":{"start":{"line":385,"column":6},"end":{"line":385,"column":null}},"135":{"start":{"line":388,"column":4},"end":{"line":398,"column":null}},"136":{"start":{"line":390,"column":8},"end":{"line":390,"column":null}},"137":{"start":{"line":391,"column":8},"end":{"line":391,"column":null}},"138":{"start":{"line":393,"column":8},"end":{"line":393,"column":null}},"139":{"start":{"line":394,"column":8},"end":{"line":394,"column":null}},"140":{"start":{"line":396,"column":8},"end":{"line":396,"column":null}},"141":{"start":{"line":397,"column":8},"end":{"line":397,"column":null}},"142":{"start":{"line":411,"column":25},"end":{"line":411,"column":null}},"143":{"start":{"line":412,"column":10},"end":{"line":412,"column":null}},"144":{"start":{"line":413,"column":25},"end":{"line":413,"column":null}},"145":{"start":{"line":414,"column":31},"end":{"line":414,"column":null}},"146":{"start":{"line":416,"column":24},"end":{"line":416,"column":null}},"147":{"start":{"line":417,"column":4},"end":{"line":630,"column":null}},"148":{"start":{"line":419,"column":14},"end":{"line":419,"column":null}},"149":{"start":{"line":420,"column":8},"end":{"line":492,"column":null}},"150":{"start":{"line":421,"column":54},"end":{"line":421,"column":null}},"151":{"start":{"line":424,"column":10},"end":{"line":448,"column":null}},"152":{"start":{"line":425,"column":12},"end":{"line":447,"column":null}},"153":{"start":{"line":426,"column":36},"end":{"line":426,"column":null}},"154":{"start":{"line":427,"column":30},"end":{"line":432,"column":null}},"155":{"start":{"line":433,"column":14},"end":{"line":439,"column":null}},"156":{"start":{"line":440,"column":14},"end":{"line":444,"column":null}},"157":{"start":{"line":446,"column":14},"end":{"line":446,"column":null}},"158":{"start":{"line":451,"column":29},"end":{"line":451,"column":null}},"159":{"start":{"line":452,"column":10},"end":{"line":469,"column":null}},"160":{"start":{"line":453,"column":28},"end":{"line":453,"column":null}},"161":{"start":{"line":454,"column":12},"end":{"line":454,"column":null}},"162":{"start":{"line":454,"column":60},"end":{"line":454,"column":null}},"163":{"start":{"line":455,"column":12},"end":{"line":468,"column":null}},"164":{"start":{"line":456,"column":14},"end":{"line":467,"column":null}},"165":{"start":{"line":457,"column":16},"end":{"line":457,"column":null}},"166":{"start":{"line":458,"column":16},"end":{"line":464,"column":null}},"167":{"start":{"line":466,"column":16},"end":{"line":466,"column":null}},"168":{"start":{"line":471,"column":10},"end":{"line":488,"column":null}},"169":{"start":{"line":472,"column":12},"end":{"line":487,"column":null}},"170":{"start":{"line":473,"column":25},"end":{"line":479,"column":null}},"171":{"start":{"line":480,"column":14},"end":{"line":484,"column":null}},"172":{"start":{"line":486,"column":14},"end":{"line":486,"column":null}},"173":{"start":{"line":489,"column":10},"end":{"line":489,"column":null}},"174":{"start":{"line":491,"column":10},"end":{"line":491,"column":null}},"175":{"start":{"line":493,"column":8},"end":{"line":493,"column":null}},"176":{"start":{"line":496,"column":14},"end":{"line":496,"column":null}},"177":{"start":{"line":497,"column":8},"end":{"line":560,"column":null}},"178":{"start":{"line":498,"column":16},"end":{"line":498,"column":null}},"179":{"start":{"line":499,"column":27},"end":{"line":499,"column":null}},"180":{"start":{"line":500,"column":54},"end":{"line":500,"column":null}},"181":{"start":{"line":503,"column":32},"end":{"line":503,"column":null}},"182":{"start":{"line":504,"column":32},"end":{"line":504,"column":null}},"183":{"start":{"line":504,"column":63},"end":{"line":504,"column":69}},"184":{"start":{"line":506,"column":10},"end":{"line":537,"column":null}},"185":{"start":{"line":507,"column":12},"end":{"line":510,"column":null}},"186":{"start":{"line":508,"column":14},"end":{"line":508,"column":null}},"187":{"start":{"line":509,"column":14},"end":{"line":509,"column":null}},"188":{"start":{"line":511,"column":12},"end":{"line":536,"column":null}},"189":{"start":{"line":512,"column":30},"end":{"line":520,"column":null}},"190":{"start":{"line":521,"column":14},"end":{"line":521,"column":null}},"191":{"start":{"line":522,"column":14},"end":{"line":528,"column":null}},"192":{"start":{"line":529,"column":14},"end":{"line":533,"column":null}},"193":{"start":{"line":535,"column":14},"end":{"line":535,"column":null}},"194":{"start":{"line":539,"column":10},"end":{"line":556,"column":null}},"195":{"start":{"line":540,"column":12},"end":{"line":555,"column":null}},"196":{"start":{"line":541,"column":25},"end":{"line":547,"column":null}},"197":{"start":{"line":548,"column":14},"end":{"line":552,"column":null}},"198":{"start":{"line":554,"column":14},"end":{"line":554,"column":null}},"199":{"start":{"line":557,"column":10},"end":{"line":557,"column":null}},"200":{"start":{"line":559,"column":10},"end":{"line":559,"column":null}},"201":{"start":{"line":561,"column":8},"end":{"line":561,"column":null}},"202":{"start":{"line":564,"column":14},"end":{"line":564,"column":null}},"203":{"start":{"line":565,"column":8},"end":{"line":565,"column":null}},"204":{"start":{"line":566,"column":8},"end":{"line":566,"column":null}},"205":{"start":{"line":569,"column":14},"end":{"line":569,"column":null}},"206":{"start":{"line":570,"column":8},"end":{"line":627,"column":null}},"207":{"start":{"line":571,"column":54},"end":{"line":571,"column":null}},"208":{"start":{"line":573,"column":10},"end":{"line":604,"column":null}},"209":{"start":{"line":574,"column":12},"end":{"line":603,"column":null}},"210":{"start":{"line":575,"column":14},"end":{"line":575,"column":null}},"211":{"start":{"line":575,"column":29},"end":{"line":575,"column":null}},"212":{"start":{"line":576,"column":31},"end":{"line":576,"column":null}},"213":{"start":{"line":577,"column":14},"end":{"line":580,"column":null}},"214":{"start":{"line":578,"column":16},"end":{"line":578,"column":null}},"215":{"start":{"line":579,"column":16},"end":{"line":579,"column":null}},"216":{"start":{"line":581,"column":36},"end":{"line":581,"column":null}},"217":{"start":{"line":582,"column":20},"end":{"line":582,"column":null}},"218":{"start":{"line":583,"column":14},"end":{"line":586,"column":null}},"219":{"start":{"line":587,"column":30},"end":{"line":587,"column":null}},"220":{"start":{"line":588,"column":14},"end":{"line":595,"column":null}},"221":{"start":{"line":596,"column":14},"end":{"line":600,"column":null}},"222":{"start":{"line":602,"column":14},"end":{"line":602,"column":null}},"223":{"start":{"line":606,"column":10},"end":{"line":623,"column":null}},"224":{"start":{"line":607,"column":12},"end":{"line":622,"column":null}},"225":{"start":{"line":608,"column":25},"end":{"line":614,"column":null}},"226":{"start":{"line":615,"column":14},"end":{"line":619,"column":null}},"227":{"start":{"line":621,"column":14},"end":{"line":621,"column":null}},"228":{"start":{"line":624,"column":10},"end":{"line":624,"column":null}},"229":{"start":{"line":626,"column":10},"end":{"line":626,"column":null}},"230":{"start":{"line":628,"column":8},"end":{"line":628,"column":null}},"231":{"start":{"line":632,"column":39},"end":{"line":636,"column":null}},"232":{"start":{"line":637,"column":4},"end":{"line":637,"column":null}},"233":{"start":{"line":639,"column":19},"end":{"line":639,"column":null}},"234":{"start":{"line":640,"column":4},"end":{"line":652,"column":null}},"235":{"start":{"line":641,"column":39},"end":{"line":650,"column":null}},"236":{"start":{"line":651,"column":6},"end":{"line":651,"column":null}},"237":{"start":{"line":654,"column":4},"end":{"line":654,"column":null}},"238":{"start":{"line":666,"column":47},"end":{"line":666,"column":null}},"239":{"start":{"line":668,"column":4},"end":{"line":668,"column":null}},"240":{"start":{"line":670,"column":4},"end":{"line":683,"column":null}},"241":{"start":{"line":671,"column":39},"end":{"line":681,"column":null}},"242":{"start":{"line":682,"column":6},"end":{"line":682,"column":null}},"243":{"start":{"line":694,"column":37},"end":{"line":694,"column":null}},"244":{"start":{"line":696,"column":4},"end":{"line":699,"column":null}},"245":{"start":{"line":701,"column":4},"end":{"line":701,"column":null}},"246":{"start":{"line":708,"column":4},"end":{"line":714,"column":null}},"247":{"start":{"line":709,"column":22},"end":{"line":709,"column":null}},"248":{"start":{"line":710,"column":19},"end":{"line":710,"column":null}},"249":{"start":{"line":711,"column":21},"end":{"line":711,"column":null}},"250":{"start":{"line":712,"column":21},"end":{"line":712,"column":null}},"251":{"start":{"line":713,"column":15},"end":{"line":713,"column":null}},"252":{"start":{"line":726,"column":18},"end":{"line":726,"column":null}},"253":{"start":{"line":727,"column":4},"end":{"line":727,"column":null}},"254":{"start":{"line":727,"column":16},"end":{"line":727,"column":null}},"255":{"start":{"line":730,"column":35},"end":{"line":730,"column":null}},"256":{"start":{"line":731,"column":4},"end":{"line":754,"column":null}},"257":{"start":{"line":732,"column":26},"end":{"line":732,"column":null}},"258":{"start":{"line":733,"column":6},"end":{"line":753,"column":null}},"259":{"start":{"line":735,"column":8},"end":{"line":743,"column":null}},"260":{"start":{"line":736,"column":10},"end":{"line":742,"column":null}},"261":{"start":{"line":737,"column":27},"end":{"line":737,"column":null}},"262":{"start":{"line":738,"column":12},"end":{"line":741,"column":null}},"263":{"start":{"line":739,"column":14},"end":{"line":739,"column":null}},"264":{"start":{"line":740,"column":14},"end":{"line":740,"column":null}},"265":{"start":{"line":740,"column":29},"end":{"line":740,"column":null}},"266":{"start":{"line":744,"column":6},"end":{"line":753,"column":null}},"267":{"start":{"line":745,"column":8},"end":{"line":752,"column":null}},"268":{"start":{"line":746,"column":10},"end":{"line":751,"column":null}},"269":{"start":{"line":747,"column":26},"end":{"line":747,"column":null}},"270":{"start":{"line":748,"column":12},"end":{"line":750,"column":null}},"271":{"start":{"line":749,"column":14},"end":{"line":749,"column":null}},"272":{"start":{"line":756,"column":4},"end":{"line":758,"column":null}},"273":{"start":{"line":757,"column":6},"end":{"line":757,"column":null}},"274":{"start":{"line":759,"column":4},"end":{"line":759,"column":null}},"275":{"start":{"line":761,"column":4},"end":{"line":800,"column":null}},"276":{"start":{"line":763,"column":46},"end":{"line":763,"column":null}},"277":{"start":{"line":764,"column":20},"end":{"line":764,"column":null}},"278":{"start":{"line":765,"column":6},"end":{"line":772,"column":null}},"279":{"start":{"line":766,"column":8},"end":{"line":771,"column":null}},"280":{"start":{"line":767,"column":25},"end":{"line":767,"column":null}},"281":{"start":{"line":768,"column":10},"end":{"line":770,"column":null}},"282":{"start":{"line":769,"column":12},"end":{"line":769,"column":null}},"283":{"start":{"line":774,"column":6},"end":{"line":778,"column":null}},"284":{"start":{"line":775,"column":8},"end":{"line":775,"column":null}},"285":{"start":{"line":776,"column":8},"end":{"line":776,"column":null}},"286":{"start":{"line":777,"column":8},"end":{"line":777,"column":null}},"287":{"start":{"line":781,"column":6},"end":{"line":785,"column":null}},"288":{"start":{"line":782,"column":8},"end":{"line":782,"column":null}},"289":{"start":{"line":783,"column":8},"end":{"line":783,"column":null}},"290":{"start":{"line":784,"column":8},"end":{"line":784,"column":null}},"291":{"start":{"line":788,"column":6},"end":{"line":795,"column":null}},"292":{"start":{"line":789,"column":23},"end":{"line":789,"column":null}},"293":{"start":{"line":790,"column":8},"end":{"line":790,"column":null}},"294":{"start":{"line":792,"column":8},"end":{"line":792,"column":null}},"295":{"start":{"line":793,"column":8},"end":{"line":793,"column":null}},"296":{"start":{"line":794,"column":8},"end":{"line":794,"column":null}},"297":{"start":{"line":797,"column":6},"end":{"line":797,"column":null}},"298":{"start":{"line":799,"column":6},"end":{"line":799,"column":null}},"299":{"start":{"line":813,"column":25},"end":{"line":813,"column":null}},"300":{"start":{"line":814,"column":18},"end":{"line":814,"column":null}},"301":{"start":{"line":815,"column":4},"end":{"line":815,"column":null}},"302":{"start":{"line":815,"column":16},"end":{"line":815,"column":null}},"303":{"start":{"line":817,"column":4},"end":{"line":817,"column":null}},"304":{"start":{"line":819,"column":37},"end":{"line":822,"column":null}},"305":{"start":{"line":824,"column":4},"end":{"line":827,"column":null}},"306":{"start":{"line":829,"column":4},"end":{"line":841,"column":null}},"307":{"start":{"line":830,"column":39},"end":{"line":839,"column":null}},"308":{"start":{"line":840,"column":6},"end":{"line":840,"column":null}},"309":{"start":{"line":849,"column":24},"end":{"line":849,"column":null}},"310":{"start":{"line":850,"column":24},"end":{"line":850,"column":null}},"311":{"start":{"line":851,"column":4},"end":{"line":851,"column":null}},"312":{"start":{"line":853,"column":18},"end":{"line":855,"column":null}},"313":{"start":{"line":854,"column":32},"end":{"line":854,"column":null}},"314":{"start":{"line":856,"column":23},"end":{"line":856,"column":null}},"315":{"start":{"line":858,"column":4},"end":{"line":858,"column":null}},"316":{"start":{"line":865,"column":4},"end":{"line":865,"column":null}},"317":{"start":{"line":865,"column":24},"end":{"line":865,"column":null}},"318":{"start":{"line":866,"column":18},"end":{"line":866,"column":null}},"319":{"start":{"line":867,"column":4},"end":{"line":867,"column":null}},"320":{"start":{"line":874,"column":4},"end":{"line":874,"column":null}},"321":{"start":{"line":874,"column":34},"end":{"line":874,"column":null}},"322":{"start":{"line":875,"column":18},"end":{"line":875,"column":null}},"323":{"start":{"line":876,"column":4},"end":{"line":876,"column":null}},"324":{"start":{"line":890,"column":4},"end":{"line":893,"column":null}},"325":{"start":{"line":891,"column":21},"end":{"line":891,"column":null}},"326":{"start":{"line":892,"column":6},"end":{"line":892,"column":null}},"327":{"start":{"line":896,"column":4},"end":{"line":910,"column":null}},"328":{"start":{"line":897,"column":12},"end":{"line":897,"column":null}},"329":{"start":{"line":898,"column":6},"end":{"line":898,"column":null}},"330":{"start":{"line":898,"column":35},"end":{"line":898,"column":null}},"331":{"start":{"line":900,"column":28},"end":{"line":900,"column":null}},"332":{"start":{"line":901,"column":21},"end":{"line":901,"column":null}},"333":{"start":{"line":903,"column":6},"end":{"line":905,"column":null}},"334":{"start":{"line":904,"column":8},"end":{"line":904,"column":null}},"335":{"start":{"line":906,"column":6},"end":{"line":906,"column":null}},"336":{"start":{"line":908,"column":6},"end":{"line":908,"column":null}},"337":{"start":{"line":909,"column":6},"end":{"line":909,"column":null}},"338":{"start":{"line":914,"column":4},"end":{"line":926,"column":null}},"339":{"start":{"line":915,"column":39},"end":{"line":924,"column":null}},"340":{"start":{"line":925,"column":6},"end":{"line":925,"column":null}}},"fnMap":{"0":{"name":"(anonymous_0)","decl":{"start":{"line":85,"column":2},"end":{"line":85,"column":null}},"loc":{"start":{"line":93,"column":4},"end":{"line":93,"column":null}},"line":93},"1":{"name":"(anonymous_1)","decl":{"start":{"line":98,"column":16},"end":{"line":98,"column":35}},"loc":{"start":{"line":98,"column":71},"end":{"line":114,"column":null}},"line":98},"2":{"name":"(anonymous_2)","decl":{"start":{"line":120,"column":16},"end":{"line":120,"column":34}},"loc":{"start":{"line":120,"column":130},"end":{"line":151,"column":null}},"line":120},"3":{"name":"(anonymous_3)","decl":{"start":{"line":156,"column":2},"end":{"line":156,"column":null}},"loc":{"start":{"line":160,"column":10},"end":{"line":198,"column":null}},"line":160},"4":{"name":"(anonymous_4)","decl":{"start":{"line":165,"column":80},"end":{"line":165,"column":81}},"loc":{"start":{"line":165,"column":89},"end":{"line":167,"column":11}},"line":165},"5":{"name":"(anonymous_5)","decl":{"start":{"line":209,"column":8},"end":{"line":209,"column":null}},"loc":{"start":{"line":213,"column":19},"end":{"line":336,"column":null}},"line":213},"6":{"name":"(anonymous_6)","decl":{"start":{"line":342,"column":8},"end":{"line":342,"column":null}},"loc":{"start":{"line":348,"column":19},"end":{"line":399,"column":null}},"line":348},"7":{"name":"(anonymous_7)","decl":{"start":{"line":405,"column":16},"end":{"line":405,"column":null}},"loc":{"start":{"line":410,"column":19},"end":{"line":655,"column":null}},"line":410},"8":{"name":"(anonymous_8)","decl":{"start":{"line":504,"column":58},"end":{"line":504,"column":63}},"loc":{"start":{"line":504,"column":63},"end":{"line":504,"column":69}},"line":504},"9":{"name":"(anonymous_9)","decl":{"start":{"line":660,"column":8},"end":{"line":660,"column":null}},"loc":{"start":{"line":665,"column":19},"end":{"line":684,"column":null}},"line":665},"10":{"name":"(anonymous_10)","decl":{"start":{"line":689,"column":8},"end":{"line":689,"column":null}},"loc":{"start":{"line":693,"column":19},"end":{"line":702,"column":null}},"line":693},"11":{"name":"(anonymous_11)","decl":{"start":{"line":707,"column":2},"end":{"line":707,"column":19}},"loc":{"start":{"line":707,"column":76},"end":{"line":715,"column":null}},"line":707},"12":{"name":"(anonymous_12)","decl":{"start":{"line":720,"column":8},"end":{"line":720,"column":null}},"loc":{"start":{"line":725,"column":19},"end":{"line":801,"column":null}},"line":725},"13":{"name":"(anonymous_13)","decl":{"start":{"line":807,"column":8},"end":{"line":807,"column":null}},"loc":{"start":{"line":812,"column":19},"end":{"line":842,"column":null}},"line":812},"14":{"name":"(anonymous_14)","decl":{"start":{"line":848,"column":2},"end":{"line":848,"column":24}},"loc":{"start":{"line":848,"column":65},"end":{"line":859,"column":null}},"line":848},"15":{"name":"(anonymous_15)","decl":{"start":{"line":854,"column":6},"end":{"line":854,"column":7}},"loc":{"start":{"line":854,"column":32},"end":{"line":854,"column":null}},"line":854},"16":{"name":"(anonymous_16)","decl":{"start":{"line":864,"column":8},"end":{"line":864,"column":18}},"loc":{"start":{"line":864,"column":86},"end":{"line":868,"column":null}},"line":864},"17":{"name":"(anonymous_17)","decl":{"start":{"line":873,"column":8},"end":{"line":873,"column":28}},"loc":{"start":{"line":873,"column":101},"end":{"line":877,"column":null}},"line":873},"18":{"name":"(anonymous_18)","decl":{"start":{"line":888,"column":16},"end":{"line":888,"column":37}},"loc":{"start":{"line":888,"column":83},"end":{"line":911,"column":null}},"line":888},"19":{"name":"(anonymous_19)","decl":{"start":{"line":913,"column":10},"end":{"line":913,"column":22}},"loc":{"start":{"line":913,"column":103},"end":{"line":927,"column":null}},"line":913}},"branchMap":{"0":{"loc":{"start":{"line":102,"column":6},"end":{"line":102,"column":null}},"type":"if","locations":[{"start":{"line":102,"column":6},"end":{"line":102,"column":null}},{"start":{},"end":{}}],"line":102},"1":{"loc":{"start":{"line":105,"column":28},"end":{"line":105,"column":null}},"type":"binary-expr","locations":[{"start":{"line":105,"column":28},"end":{"line":105,"column":53}},{"start":{"line":105,"column":53},"end":{"line":105,"column":null}}],"line":105},"2":{"loc":{"start":{"line":106,"column":6},"end":{"line":106,"column":null}},"type":"if","locations":[{"start":{"line":106,"column":6},"end":{"line":106,"column":null}},{"start":{},"end":{}}],"line":106},"3":{"loc":{"start":{"line":120,"column":52},"end":{"line":120,"column":130}},"type":"default-arg","locations":[{"start":{"line":120,"column":75},"end":{"line":120,"column":130}}],"line":120},"4":{"loc":{"start":{"line":124,"column":6},"end":{"line":126,"column":null}},"type":"if","locations":[{"start":{"line":124,"column":6},"end":{"line":126,"column":null}},{"start":{},"end":{}}],"line":124},"5":{"loc":{"start":{"line":137,"column":28},"end":{"line":137,"column":null}},"type":"cond-expr","locations":[{"start":{"line":137,"column":49},"end":{"line":137,"column":57}},{"start":{"line":137,"column":57},"end":{"line":137,"column":null}}],"line":137},"6":{"loc":{"start":{"line":140,"column":63},"end":{"line":140,"column":null}},"type":"cond-expr","locations":[{"start":{"line":140,"column":112},"end":{"line":140,"column":119}},{"start":{"line":140,"column":119},"end":{"line":140,"column":null}}],"line":140},"7":{"loc":{"start":{"line":140,"column":63},"end":{"line":140,"column":112}},"type":"binary-expr","locations":[{"start":{"line":140,"column":63},"end":{"line":140,"column":91}},{"start":{"line":140,"column":91},"end":{"line":140,"column":112}}],"line":140},"8":{"loc":{"start":{"line":148,"column":33},"end":{"line":148,"column":82}},"type":"cond-expr","locations":[{"start":{"line":148,"column":56},"end":{"line":148,"column":70}},{"start":{"line":148,"column":70},"end":{"line":148,"column":82}}],"line":148},"9":{"loc":{"start":{"line":161,"column":4},"end":{"line":197,"column":null}},"type":"switch","locations":[{"start":{"line":162,"column":6},"end":{"line":169,"column":null}},{"start":{"line":171,"column":6},"end":{"line":173,"column":null}},{"start":{"line":175,"column":6},"end":{"line":177,"column":null}},{"start":{"line":179,"column":6},"end":{"line":188,"column":null}},{"start":{"line":190,"column":6},"end":{"line":192,"column":null}},{"start":{"line":194,"column":6},"end":{"line":196,"column":null}}],"line":161},"10":{"loc":{"start":{"line":163,"column":8},"end":{"line":168,"column":null}},"type":"if","locations":[{"start":{"line":163,"column":8},"end":{"line":168,"column":null}},{"start":{},"end":{}}],"line":163},"11":{"loc":{"start":{"line":163,"column":12},"end":{"line":163,"column":39}},"type":"binary-expr","locations":[{"start":{"line":163,"column":12},"end":{"line":163,"column":22}},{"start":{"line":163,"column":22},"end":{"line":163,"column":39}}],"line":163},"12":{"loc":{"start":{"line":166,"column":37},"end":{"line":166,"column":86}},"type":"cond-expr","locations":[{"start":{"line":166,"column":60},"end":{"line":166,"column":74}},{"start":{"line":166,"column":74},"end":{"line":166,"column":86}}],"line":166},"13":{"loc":{"start":{"line":180,"column":8},"end":{"line":187,"column":null}},"type":"if","locations":[{"start":{"line":180,"column":8},"end":{"line":187,"column":null}},{"start":{},"end":{}}],"line":180},"14":{"loc":{"start":{"line":184,"column":10},"end":{"line":186,"column":null}},"type":"if","locations":[{"start":{"line":184,"column":10},"end":{"line":186,"column":null}},{"start":{},"end":{}}],"line":184},"15":{"loc":{"start":{"line":184,"column":14},"end":{"line":184,"column":58}},"type":"binary-expr","locations":[{"start":{"line":184,"column":14},"end":{"line":184,"column":41}},{"start":{"line":184,"column":41},"end":{"line":184,"column":58}}],"line":184},"16":{"loc":{"start":{"line":215,"column":4},"end":{"line":218,"column":null}},"type":"if","locations":[{"start":{"line":215,"column":4},"end":{"line":218,"column":null}},{"start":{},"end":{}}],"line":215},"17":{"loc":{"start":{"line":224,"column":6},"end":{"line":224,"column":null}},"type":"if","locations":[{"start":{"line":224,"column":6},"end":{"line":224,"column":null}},{"start":{},"end":{}}],"line":224},"18":{"loc":{"start":{"line":227,"column":6},"end":{"line":227,"column":null}},"type":"if","locations":[{"start":{"line":227,"column":6},"end":{"line":227,"column":null}},{"start":{},"end":{}}],"line":227},"19":{"loc":{"start":{"line":234,"column":27},"end":{"line":234,"column":null}},"type":"binary-expr","locations":[{"start":{"line":234,"column":27},"end":{"line":234,"column":47}},{"start":{"line":234,"column":47},"end":{"line":234,"column":null}}],"line":234},"20":{"loc":{"start":{"line":249,"column":22},"end":{"line":249,"column":null}},"type":"cond-expr","locations":[{"start":{"line":249,"column":40},"end":{"line":249,"column":49}},{"start":{"line":249,"column":49},"end":{"line":249,"column":null}}],"line":249},"21":{"loc":{"start":{"line":252,"column":6},"end":{"line":257,"column":null}},"type":"if","locations":[{"start":{"line":252,"column":6},"end":{"line":257,"column":null}},{"start":{},"end":{}}],"line":252},"22":{"loc":{"start":{"line":263,"column":6},"end":{"line":267,"column":null}},"type":"if","locations":[{"start":{"line":263,"column":6},"end":{"line":267,"column":null}},{"start":{},"end":{}}],"line":263},"23":{"loc":{"start":{"line":263,"column":10},"end":{"line":263,"column":47}},"type":"binary-expr","locations":[{"start":{"line":263,"column":10},"end":{"line":263,"column":24}},{"start":{"line":263,"column":24},"end":{"line":263,"column":47}}],"line":263},"24":{"loc":{"start":{"line":269,"column":6},"end":{"line":314,"column":null}},"type":"if","locations":[{"start":{"line":269,"column":6},"end":{"line":314,"column":null}},{"start":{},"end":{}}],"line":269},"25":{"loc":{"start":{"line":271,"column":33},"end":{"line":271,"column":null}},"type":"binary-expr","locations":[{"start":{"line":271,"column":33},"end":{"line":271,"column":59}},{"start":{"line":271,"column":59},"end":{"line":271,"column":null}}],"line":271},"26":{"loc":{"start":{"line":272,"column":10},"end":{"line":308,"column":null}},"type":"if","locations":[{"start":{"line":272,"column":10},"end":{"line":308,"column":null}},{"start":{},"end":{}}],"line":272},"27":{"loc":{"start":{"line":279,"column":12},"end":{"line":287,"column":null}},"type":"if","locations":[{"start":{"line":279,"column":12},"end":{"line":287,"column":null}},{"start":{"line":285,"column":19},"end":{"line":287,"column":null}}],"line":279},"28":{"loc":{"start":{"line":290,"column":33},"end":{"line":290,"column":null}},"type":"binary-expr","locations":[{"start":{"line":290,"column":33},"end":{"line":290,"column":68}},{"start":{"line":290,"column":68},"end":{"line":290,"column":null}}],"line":290},"29":{"loc":{"start":{"line":293,"column":12},"end":{"line":297,"column":null}},"type":"if","locations":[{"start":{"line":293,"column":12},"end":{"line":297,"column":null}},{"start":{},"end":{}}],"line":293},"30":{"loc":{"start":{"line":300,"column":12},"end":{"line":307,"column":null}},"type":"if","locations":[{"start":{"line":300,"column":12},"end":{"line":307,"column":null}},{"start":{},"end":{}}],"line":300},"31":{"loc":{"start":{"line":302,"column":14},"end":{"line":306,"column":null}},"type":"if","locations":[{"start":{"line":302,"column":14},"end":{"line":306,"column":null}},{"start":{},"end":{}}],"line":302},"32":{"loc":{"start":{"line":302,"column":18},"end":{"line":302,"column":74}},"type":"binary-expr","locations":[{"start":{"line":302,"column":18},"end":{"line":302,"column":40}},{"start":{"line":302,"column":40},"end":{"line":302,"column":74}}],"line":302},"33":{"loc":{"start":{"line":317,"column":6},"end":{"line":331,"column":null}},"type":"if","locations":[{"start":{"line":317,"column":6},"end":{"line":331,"column":null}},{"start":{"line":322,"column":13},"end":{"line":331,"column":null}}],"line":317},"34":{"loc":{"start":{"line":350,"column":4},"end":{"line":350,"column":null}},"type":"if","locations":[{"start":{"line":350,"column":4},"end":{"line":350,"column":null}},{"start":{},"end":{}}],"line":350},"35":{"loc":{"start":{"line":363,"column":15},"end":{"line":363,"column":null}},"type":"cond-expr","locations":[{"start":{"line":363,"column":44},"end":{"line":363,"column":64}},{"start":{"line":363,"column":64},"end":{"line":363,"column":null}}],"line":363},"36":{"loc":{"start":{"line":364,"column":15},"end":{"line":364,"column":null}},"type":"cond-expr","locations":[{"start":{"line":364,"column":44},"end":{"line":364,"column":62}},{"start":{"line":364,"column":62},"end":{"line":364,"column":null}}],"line":364},"37":{"loc":{"start":{"line":380,"column":15},"end":{"line":380,"column":null}},"type":"cond-expr","locations":[{"start":{"line":380,"column":46},"end":{"line":380,"column":68}},{"start":{"line":380,"column":68},"end":{"line":380,"column":null}}],"line":380},"38":{"loc":{"start":{"line":381,"column":15},"end":{"line":381,"column":null}},"type":"cond-expr","locations":[{"start":{"line":381,"column":46},"end":{"line":381,"column":66}},{"start":{"line":381,"column":66},"end":{"line":381,"column":null}}],"line":381},"39":{"loc":{"start":{"line":388,"column":4},"end":{"line":398,"column":null}},"type":"switch","locations":[{"start":{"line":389,"column":6},"end":{"line":391,"column":null}},{"start":{"line":392,"column":6},"end":{"line":394,"column":null}},{"start":{"line":395,"column":6},"end":{"line":397,"column":null}}],"line":388},"40":{"loc":{"start":{"line":414,"column":31},"end":{"line":414,"column":null}},"type":"binary-expr","locations":[{"start":{"line":414,"column":31},"end":{"line":414,"column":59}},{"start":{"line":414,"column":59},"end":{"line":414,"column":null}}],"line":414},"41":{"loc":{"start":{"line":416,"column":24},"end":{"line":416,"column":null}},"type":"binary-expr","locations":[{"start":{"line":416,"column":24},"end":{"line":416,"column":41}},{"start":{"line":416,"column":41},"end":{"line":416,"column":null}}],"line":416},"42":{"loc":{"start":{"line":417,"column":4},"end":{"line":630,"column":null}},"type":"switch","locations":[{"start":{"line":418,"column":6},"end":{"line":494,"column":null}},{"start":{"line":495,"column":6},"end":{"line":562,"column":null}},{"start":{"line":563,"column":6},"end":{"line":567,"column":null}},{"start":{"line":568,"column":6},"end":{"line":629,"column":null}}],"line":417},"43":{"loc":{"start":{"line":420,"column":8},"end":{"line":492,"column":null}},"type":"if","locations":[{"start":{"line":420,"column":8},"end":{"line":492,"column":null}},{"start":{"line":490,"column":15},"end":{"line":492,"column":null}}],"line":420},"44":{"loc":{"start":{"line":420,"column":12},"end":{"line":420,"column":77}},"type":"binary-expr","locations":[{"start":{"line":420,"column":12},"end":{"line":420,"column":34}},{"start":{"line":420,"column":34},"end":{"line":420,"column":58}},{"start":{"line":420,"column":58},"end":{"line":420,"column":77}}],"line":420},"45":{"loc":{"start":{"line":426,"column":36},"end":{"line":426,"column":null}},"type":"cond-expr","locations":[{"start":{"line":426,"column":45},"end":{"line":426,"column":92}},{"start":{"line":426,"column":92},"end":{"line":426,"column":null}}],"line":426},"46":{"loc":{"start":{"line":428,"column":20},"end":{"line":428,"column":null}},"type":"binary-expr","locations":[{"start":{"line":428,"column":20},"end":{"line":428,"column":28}},{"start":{"line":428,"column":28},"end":{"line":428,"column":null}}],"line":428},"47":{"loc":{"start":{"line":446,"column":55},"end":{"line":446,"column":104}},"type":"cond-expr","locations":[{"start":{"line":446,"column":78},"end":{"line":446,"column":92}},{"start":{"line":446,"column":92},"end":{"line":446,"column":104}}],"line":446},"48":{"loc":{"start":{"line":454,"column":12},"end":{"line":454,"column":null}},"type":"if","locations":[{"start":{"line":454,"column":12},"end":{"line":454,"column":null}},{"start":{},"end":{}}],"line":454},"49":{"loc":{"start":{"line":454,"column":16},"end":{"line":454,"column":60}},"type":"binary-expr","locations":[{"start":{"line":454,"column":16},"end":{"line":454,"column":28}},{"start":{"line":454,"column":28},"end":{"line":454,"column":60}}],"line":454},"50":{"loc":{"start":{"line":466,"column":61},"end":{"line":466,"column":110}},"type":"cond-expr","locations":[{"start":{"line":466,"column":84},"end":{"line":466,"column":98}},{"start":{"line":466,"column":98},"end":{"line":466,"column":110}}],"line":466},"51":{"loc":{"start":{"line":471,"column":10},"end":{"line":488,"column":null}},"type":"if","locations":[{"start":{"line":471,"column":10},"end":{"line":488,"column":null}},{"start":{},"end":{}}],"line":471},"52":{"loc":{"start":{"line":478,"column":25},"end":{"line":478,"column":null}},"type":"binary-expr","locations":[{"start":{"line":478,"column":25},"end":{"line":478,"column":42}},{"start":{"line":478,"column":42},"end":{"line":478,"column":null}}],"line":478},"53":{"loc":{"start":{"line":486,"column":39},"end":{"line":486,"column":88}},"type":"cond-expr","locations":[{"start":{"line":486,"column":62},"end":{"line":486,"column":76}},{"start":{"line":486,"column":76},"end":{"line":486,"column":88}}],"line":486},"54":{"loc":{"start":{"line":489,"column":26},"end":{"line":489,"column":null}},"type":"binary-expr","locations":[{"start":{"line":489,"column":26},"end":{"line":489,"column":43}},{"start":{"line":489,"column":43},"end":{"line":489,"column":null}}],"line":489},"55":{"loc":{"start":{"line":497,"column":8},"end":{"line":560,"column":null}},"type":"if","locations":[{"start":{"line":497,"column":8},"end":{"line":560,"column":null}},{"start":{"line":558,"column":15},"end":{"line":560,"column":null}}],"line":497},"56":{"loc":{"start":{"line":497,"column":12},"end":{"line":497,"column":75}},"type":"binary-expr","locations":[{"start":{"line":497,"column":12},"end":{"line":497,"column":34}},{"start":{"line":497,"column":34},"end":{"line":497,"column":57}},{"start":{"line":497,"column":57},"end":{"line":497,"column":75}}],"line":497},"57":{"loc":{"start":{"line":499,"column":27},"end":{"line":499,"column":null}},"type":"binary-expr","locations":[{"start":{"line":499,"column":27},"end":{"line":499,"column":62}},{"start":{"line":499,"column":62},"end":{"line":499,"column":null}}],"line":499},"58":{"loc":{"start":{"line":503,"column":32},"end":{"line":503,"column":null}},"type":"cond-expr","locations":[{"start":{"line":503,"column":42},"end":{"line":503,"column":93}},{"start":{"line":503,"column":93},"end":{"line":503,"column":null}}],"line":503},"59":{"loc":{"start":{"line":507,"column":12},"end":{"line":510,"column":null}},"type":"if","locations":[{"start":{"line":507,"column":12},"end":{"line":510,"column":null}},{"start":{},"end":{}}],"line":507},"60":{"loc":{"start":{"line":515,"column":30},"end":{"line":515,"column":null}},"type":"binary-expr","locations":[{"start":{"line":515,"column":30},"end":{"line":515,"column":46}},{"start":{"line":515,"column":46},"end":{"line":515,"column":null}}],"line":515},"61":{"loc":{"start":{"line":517,"column":29},"end":{"line":517,"column":null}},"type":"binary-expr","locations":[{"start":{"line":517,"column":29},"end":{"line":517,"column":39}},{"start":{"line":517,"column":39},"end":{"line":517,"column":null}}],"line":517},"62":{"loc":{"start":{"line":518,"column":27},"end":{"line":518,"column":null}},"type":"binary-expr","locations":[{"start":{"line":518,"column":27},"end":{"line":518,"column":49}},{"start":{"line":518,"column":49},"end":{"line":518,"column":null}}],"line":518},"63":{"loc":{"start":{"line":519,"column":23},"end":{"line":519,"column":null}},"type":"binary-expr","locations":[{"start":{"line":519,"column":23},"end":{"line":519,"column":41}},{"start":{"line":519,"column":41},"end":{"line":519,"column":null}}],"line":519},"64":{"loc":{"start":{"line":535,"column":54},"end":{"line":535,"column":103}},"type":"cond-expr","locations":[{"start":{"line":535,"column":77},"end":{"line":535,"column":91}},{"start":{"line":535,"column":91},"end":{"line":535,"column":103}}],"line":535},"65":{"loc":{"start":{"line":539,"column":10},"end":{"line":556,"column":null}},"type":"if","locations":[{"start":{"line":539,"column":10},"end":{"line":556,"column":null}},{"start":{},"end":{}}],"line":539},"66":{"loc":{"start":{"line":546,"column":25},"end":{"line":546,"column":null}},"type":"binary-expr","locations":[{"start":{"line":546,"column":25},"end":{"line":546,"column":42}},{"start":{"line":546,"column":42},"end":{"line":546,"column":null}}],"line":546},"67":{"loc":{"start":{"line":554,"column":39},"end":{"line":554,"column":88}},"type":"cond-expr","locations":[{"start":{"line":554,"column":62},"end":{"line":554,"column":76}},{"start":{"line":554,"column":76},"end":{"line":554,"column":88}}],"line":554},"68":{"loc":{"start":{"line":557,"column":26},"end":{"line":557,"column":null}},"type":"binary-expr","locations":[{"start":{"line":557,"column":26},"end":{"line":557,"column":43}},{"start":{"line":557,"column":43},"end":{"line":557,"column":null}}],"line":557},"69":{"loc":{"start":{"line":570,"column":8},"end":{"line":627,"column":null}},"type":"if","locations":[{"start":{"line":570,"column":8},"end":{"line":627,"column":null}},{"start":{"line":625,"column":15},"end":{"line":627,"column":null}}],"line":570},"70":{"loc":{"start":{"line":570,"column":12},"end":{"line":570,"column":75}},"type":"binary-expr","locations":[{"start":{"line":570,"column":12},"end":{"line":570,"column":34}},{"start":{"line":570,"column":34},"end":{"line":570,"column":57}},{"start":{"line":570,"column":57},"end":{"line":570,"column":75}}],"line":570},"71":{"loc":{"start":{"line":575,"column":14},"end":{"line":575,"column":null}},"type":"if","locations":[{"start":{"line":575,"column":14},"end":{"line":575,"column":null}},{"start":{},"end":{}}],"line":575},"72":{"loc":{"start":{"line":577,"column":14},"end":{"line":580,"column":null}},"type":"if","locations":[{"start":{"line":577,"column":14},"end":{"line":580,"column":null}},{"start":{},"end":{}}],"line":577},"73":{"loc":{"start":{"line":582,"column":54},"end":{"line":582,"column":66}},"type":"binary-expr","locations":[{"start":{"line":582,"column":54},"end":{"line":582,"column":64}},{"start":{"line":582,"column":64},"end":{"line":582,"column":66}}],"line":582},"74":{"loc":{"start":{"line":602,"column":57},"end":{"line":602,"column":106}},"type":"cond-expr","locations":[{"start":{"line":602,"column":80},"end":{"line":602,"column":94}},{"start":{"line":602,"column":94},"end":{"line":602,"column":106}}],"line":602},"75":{"loc":{"start":{"line":606,"column":10},"end":{"line":623,"column":null}},"type":"if","locations":[{"start":{"line":606,"column":10},"end":{"line":623,"column":null}},{"start":{},"end":{}}],"line":606},"76":{"loc":{"start":{"line":613,"column":25},"end":{"line":613,"column":null}},"type":"binary-expr","locations":[{"start":{"line":613,"column":25},"end":{"line":613,"column":42}},{"start":{"line":613,"column":42},"end":{"line":613,"column":null}}],"line":613},"77":{"loc":{"start":{"line":621,"column":39},"end":{"line":621,"column":88}},"type":"cond-expr","locations":[{"start":{"line":621,"column":62},"end":{"line":621,"column":76}},{"start":{"line":621,"column":76},"end":{"line":621,"column":88}}],"line":621},"78":{"loc":{"start":{"line":624,"column":26},"end":{"line":624,"column":null}},"type":"binary-expr","locations":[{"start":{"line":624,"column":26},"end":{"line":624,"column":43}},{"start":{"line":624,"column":43},"end":{"line":624,"column":null}}],"line":624},"79":{"loc":{"start":{"line":640,"column":4},"end":{"line":652,"column":null}},"type":"if","locations":[{"start":{"line":640,"column":4},"end":{"line":652,"column":null}},{"start":{},"end":{}}],"line":640},"80":{"loc":{"start":{"line":647,"column":18},"end":{"line":647,"column":null}},"type":"binary-expr","locations":[{"start":{"line":647,"column":18},"end":{"line":647,"column":34}},{"start":{"line":647,"column":34},"end":{"line":647,"column":null}}],"line":647},"81":{"loc":{"start":{"line":670,"column":4},"end":{"line":683,"column":null}},"type":"if","locations":[{"start":{"line":670,"column":4},"end":{"line":683,"column":null}},{"start":{},"end":{}}],"line":670},"82":{"loc":{"start":{"line":677,"column":18},"end":{"line":677,"column":null}},"type":"binary-expr","locations":[{"start":{"line":677,"column":18},"end":{"line":677,"column":34}},{"start":{"line":677,"column":34},"end":{"line":677,"column":null}}],"line":677},"83":{"loc":{"start":{"line":678,"column":21},"end":{"line":678,"column":null}},"type":"binary-expr","locations":[{"start":{"line":678,"column":21},"end":{"line":678,"column":34}},{"start":{"line":678,"column":34},"end":{"line":678,"column":53}},{"start":{"line":678,"column":53},"end":{"line":678,"column":null}}],"line":678},"84":{"loc":{"start":{"line":708,"column":4},"end":{"line":714,"column":null}},"type":"switch","locations":[{"start":{"line":709,"column":6},"end":{"line":709,"column":null}},{"start":{"line":710,"column":6},"end":{"line":710,"column":null}},{"start":{"line":711,"column":6},"end":{"line":711,"column":null}},{"start":{"line":712,"column":6},"end":{"line":712,"column":null}},{"start":{"line":713,"column":6},"end":{"line":713,"column":null}}],"line":708},"85":{"loc":{"start":{"line":727,"column":4},"end":{"line":727,"column":null}},"type":"if","locations":[{"start":{"line":727,"column":4},"end":{"line":727,"column":null}},{"start":{},"end":{}}],"line":727},"86":{"loc":{"start":{"line":731,"column":4},"end":{"line":754,"column":null}},"type":"if","locations":[{"start":{"line":731,"column":4},"end":{"line":754,"column":null}},{"start":{},"end":{}}],"line":731},"87":{"loc":{"start":{"line":733,"column":6},"end":{"line":753,"column":null}},"type":"if","locations":[{"start":{"line":733,"column":6},"end":{"line":753,"column":null}},{"start":{"line":744,"column":6},"end":{"line":753,"column":null}}],"line":733},"88":{"loc":{"start":{"line":738,"column":12},"end":{"line":741,"column":null}},"type":"if","locations":[{"start":{"line":738,"column":12},"end":{"line":741,"column":null}},{"start":{},"end":{}}],"line":738},"89":{"loc":{"start":{"line":738,"column":16},"end":{"line":738,"column":78}},"type":"binary-expr","locations":[{"start":{"line":738,"column":16},"end":{"line":738,"column":44}},{"start":{"line":738,"column":44},"end":{"line":738,"column":78}}],"line":738},"90":{"loc":{"start":{"line":739,"column":26},"end":{"line":739,"column":null}},"type":"binary-expr","locations":[{"start":{"line":739,"column":26},"end":{"line":739,"column":62}},{"start":{"line":739,"column":62},"end":{"line":739,"column":null}}],"line":739},"91":{"loc":{"start":{"line":740,"column":14},"end":{"line":740,"column":null}},"type":"if","locations":[{"start":{"line":740,"column":14},"end":{"line":740,"column":null}},{"start":{},"end":{}}],"line":740},"92":{"loc":{"start":{"line":744,"column":6},"end":{"line":753,"column":null}},"type":"if","locations":[{"start":{"line":744,"column":6},"end":{"line":753,"column":null}},{"start":{},"end":{}}],"line":744},"93":{"loc":{"start":{"line":748,"column":12},"end":{"line":750,"column":null}},"type":"if","locations":[{"start":{"line":748,"column":12},"end":{"line":750,"column":null}},{"start":{},"end":{}}],"line":748},"94":{"loc":{"start":{"line":749,"column":26},"end":{"line":749,"column":null}},"type":"binary-expr","locations":[{"start":{"line":749,"column":26},"end":{"line":749,"column":61}},{"start":{"line":749,"column":61},"end":{"line":749,"column":null}}],"line":749},"95":{"loc":{"start":{"line":756,"column":4},"end":{"line":758,"column":null}},"type":"if","locations":[{"start":{"line":756,"column":4},"end":{"line":758,"column":null}},{"start":{},"end":{}}],"line":756},"96":{"loc":{"start":{"line":761,"column":4},"end":{"line":800,"column":null}},"type":"if","locations":[{"start":{"line":761,"column":4},"end":{"line":800,"column":null}},{"start":{"line":798,"column":11},"end":{"line":800,"column":null}}],"line":761},"97":{"loc":{"start":{"line":768,"column":10},"end":{"line":770,"column":null}},"type":"if","locations":[{"start":{"line":768,"column":10},"end":{"line":770,"column":null}},{"start":{},"end":{}}],"line":768},"98":{"loc":{"start":{"line":774,"column":6},"end":{"line":778,"column":null}},"type":"if","locations":[{"start":{"line":774,"column":6},"end":{"line":778,"column":null}},{"start":{},"end":{}}],"line":774},"99":{"loc":{"start":{"line":781,"column":6},"end":{"line":785,"column":null}},"type":"if","locations":[{"start":{"line":781,"column":6},"end":{"line":785,"column":null}},{"start":{},"end":{}}],"line":781},"100":{"loc":{"start":{"line":789,"column":23},"end":{"line":789,"column":null}},"type":"binary-expr","locations":[{"start":{"line":789,"column":23},"end":{"line":789,"column":54}},{"start":{"line":789,"column":54},"end":{"line":789,"column":null}}],"line":789},"101":{"loc":{"start":{"line":792,"column":34},"end":{"line":792,"column":98}},"type":"cond-expr","locations":[{"start":{"line":792,"column":62},"end":{"line":792,"column":81}},{"start":{"line":792,"column":81},"end":{"line":792,"column":98}}],"line":792},"102":{"loc":{"start":{"line":797,"column":102},"end":{"line":797,"column":124}},"type":"binary-expr","locations":[{"start":{"line":797,"column":102},"end":{"line":797,"column":115}},{"start":{"line":797,"column":115},"end":{"line":797,"column":124}}],"line":797},"103":{"loc":{"start":{"line":799,"column":101},"end":{"line":799,"column":123}},"type":"binary-expr","locations":[{"start":{"line":799,"column":101},"end":{"line":799,"column":114}},{"start":{"line":799,"column":114},"end":{"line":799,"column":123}}],"line":799},"104":{"loc":{"start":{"line":813,"column":25},"end":{"line":813,"column":null}},"type":"cond-expr","locations":[{"start":{"line":813,"column":50},"end":{"line":813,"column":66}},{"start":{"line":813,"column":66},"end":{"line":813,"column":null}}],"line":813},"105":{"loc":{"start":{"line":815,"column":4},"end":{"line":815,"column":null}},"type":"if","locations":[{"start":{"line":815,"column":4},"end":{"line":815,"column":null}},{"start":{},"end":{}}],"line":815},"106":{"loc":{"start":{"line":829,"column":4},"end":{"line":841,"column":null}},"type":"if","locations":[{"start":{"line":829,"column":4},"end":{"line":841,"column":null}},{"start":{},"end":{}}],"line":829},"107":{"loc":{"start":{"line":836,"column":18},"end":{"line":836,"column":null}},"type":"binary-expr","locations":[{"start":{"line":836,"column":18},"end":{"line":836,"column":34}},{"start":{"line":836,"column":34},"end":{"line":836,"column":null}}],"line":836},"108":{"loc":{"start":{"line":858,"column":11},"end":{"line":858,"column":null}},"type":"cond-expr","locations":[{"start":{"line":858,"column":25},"end":{"line":858,"column":68}},{"start":{"line":858,"column":68},"end":{"line":858,"column":null}}],"line":858},"109":{"loc":{"start":{"line":865,"column":4},"end":{"line":865,"column":null}},"type":"if","locations":[{"start":{"line":865,"column":4},"end":{"line":865,"column":null}},{"start":{},"end":{}}],"line":865},"110":{"loc":{"start":{"line":867,"column":11},"end":{"line":867,"column":null}},"type":"cond-expr","locations":[{"start":{"line":867,"column":27},"end":{"line":867,"column":54}},{"start":{"line":867,"column":54},"end":{"line":867,"column":null}}],"line":867},"111":{"loc":{"start":{"line":874,"column":4},"end":{"line":874,"column":null}},"type":"if","locations":[{"start":{"line":874,"column":4},"end":{"line":874,"column":null}},{"start":{},"end":{}}],"line":874},"112":{"loc":{"start":{"line":876,"column":11},"end":{"line":876,"column":null}},"type":"cond-expr","locations":[{"start":{"line":876,"column":37},"end":{"line":876,"column":74}},{"start":{"line":876,"column":74},"end":{"line":876,"column":null}}],"line":876},"113":{"loc":{"start":{"line":890,"column":4},"end":{"line":893,"column":null}},"type":"if","locations":[{"start":{"line":890,"column":4},"end":{"line":893,"column":null}},{"start":{},"end":{}}],"line":890},"114":{"loc":{"start":{"line":892,"column":13},"end":{"line":892,"column":null}},"type":"cond-expr","locations":[{"start":{"line":892,"column":22},"end":{"line":892,"column":47}},{"start":{"line":892,"column":47},"end":{"line":892,"column":null}}],"line":892},"115":{"loc":{"start":{"line":898,"column":6},"end":{"line":898,"column":null}},"type":"if","locations":[{"start":{"line":898,"column":6},"end":{"line":898,"column":null}},{"start":{},"end":{}}],"line":898},"116":{"loc":{"start":{"line":903,"column":6},"end":{"line":905,"column":null}},"type":"if","locations":[{"start":{"line":903,"column":6},"end":{"line":905,"column":null}},{"start":{},"end":{}}],"line":903},"117":{"loc":{"start":{"line":903,"column":10},"end":{"line":903,"column":98}},"type":"binary-expr","locations":[{"start":{"line":903,"column":10},"end":{"line":903,"column":38}},{"start":{"line":903,"column":38},"end":{"line":903,"column":71}},{"start":{"line":903,"column":71},"end":{"line":903,"column":98}}],"line":903},"118":{"loc":{"start":{"line":908,"column":37},"end":{"line":908,"column":86}},"type":"cond-expr","locations":[{"start":{"line":908,"column":60},"end":{"line":908,"column":74}},{"start":{"line":908,"column":74},"end":{"line":908,"column":86}}],"line":908},"119":{"loc":{"start":{"line":914,"column":4},"end":{"line":926,"column":null}},"type":"if","locations":[{"start":{"line":914,"column":4},"end":{"line":926,"column":null}},{"start":{},"end":{}}],"line":914},"120":{"loc":{"start":{"line":921,"column":18},"end":{"line":921,"column":null}},"type":"binary-expr","locations":[{"start":{"line":921,"column":18},"end":{"line":921,"column":34}},{"start":{"line":921,"column":34},"end":{"line":921,"column":null}}],"line":921}},"s":{"0":20,"1":51,"2":51,"3":51,"4":51,"5":51,"6":51,"7":51,"8":51,"9":51,"10":2,"11":2,"12":2,"13":2,"14":2,"15":0,"16":2,"17":0,"18":0,"19":0,"20":0,"21":2,"22":2,"23":2,"24":2,"25":0,"26":0,"27":0,"28":0,"29":2,"30":2,"31":2,"32":0,"33":0,"34":0,"35":0,"36":0,"37":0,"38":0,"39":0,"40":0,"41":0,"42":0,"43":0,"44":0,"45":0,"46":0,"47":0,"48":0,"49":0,"50":0,"51":0,"52":0,"53":0,"54":18,"55":2,"56":2,"57":16,"58":16,"59":16,"60":14,"61":6,"62":8,"63":8,"64":0,"65":8,"66":8,"67":18,"68":18,"69":18,"70":18,"71":18,"72":18,"73":18,"74":18,"75":0,"76":8,"77":18,"78":0,"79":0,"80":0,"81":8,"82":8,"83":8,"84":8,"85":8,"86":8,"87":8,"88":8,"89":6,"90":6,"91":6,"92":6,"93":6,"94":2,"95":2,"96":8,"97":2,"98":0,"99":0,"100":0,"101":2,"102":0,"103":0,"104":0,"105":0,"106":2,"107":2,"108":2,"109":0,"110":0,"111":0,"112":0,"113":0,"114":0,"115":0,"116":16,"117":16,"118":8,"119":8,"120":0,"121":8,"122":8,"123":8,"124":0,"125":0,"126":0,"127":0,"128":8,"129":8,"130":8,"131":0,"132":0,"133":0,"134":0,"135":8,"136":3,"137":3,"138":5,"139":5,"140":0,"141":0,"142":3,"143":3,"144":3,"145":3,"146":3,"147":3,"148":0,"149":0,"150":0,"151":0,"152":0,"153":0,"154":0,"155":0,"156":0,"157":0,"158":0,"159":0,"160":0,"161":0,"162":0,"163":0,"164":0,"165":0,"166":0,"167":0,"168":0,"169":0,"170":0,"171":0,"172":0,"173":0,"174":0,"175":0,"176":0,"177":0,"178":0,"179":0,"180":0,"181":0,"182":0,"183":0,"184":0,"185":0,"186":0,"187":0,"188":0,"189":0,"190":0,"191":0,"192":0,"193":0,"194":0,"195":0,"196":0,"197":0,"198":0,"199":0,"200":0,"201":0,"202":0,"203":0,"204":0,"205":3,"206":3,"207":0,"208":0,"209":0,"210":0,"211":0,"212":0,"213":0,"214":0,"215":0,"216":0,"217":0,"218":0,"219":0,"220":0,"221":0,"222":0,"223":0,"224":0,"225":0,"226":0,"227":0,"228":0,"229":3,"230":3,"231":3,"232":3,"233":3,"234":3,"235":1,"236":1,"237":3,"238":5,"239":5,"240":5,"241":1,"242":1,"243":0,"244":0,"245":0,"246":3,"247":0,"248":0,"249":0,"250":3,"251":0,"252":3,"253":3,"254":0,"255":3,"256":3,"257":3,"258":3,"259":0,"260":0,"261":0,"262":0,"263":0,"264":0,"265":0,"266":3,"267":3,"268":3,"269":3,"270":3,"271":0,"272":3,"273":0,"274":3,"275":3,"276":3,"277":3,"278":3,"279":3,"280":3,"281":3,"282":3,"283":3,"284":0,"285":0,"286":0,"287":3,"288":0,"289":0,"290":0,"291":3,"292":3,"293":3,"294":1,"295":1,"296":1,"297":2,"298":0,"299":3,"300":3,"301":3,"302":0,"303":3,"304":3,"305":3,"306":3,"307":1,"308":1,"309":7,"310":7,"311":7,"312":7,"313":7,"314":7,"315":7,"316":1,"317":0,"318":1,"319":1,"320":2,"321":0,"322":2,"323":2,"324":14,"325":0,"326":0,"327":14,"328":14,"329":14,"330":3,"331":11,"332":11,"333":11,"334":9,"335":1,"336":1,"337":1,"338":0,"339":0,"340":0},"f":{"0":51,"1":2,"2":2,"3":0,"4":0,"5":18,"6":8,"7":3,"8":0,"9":5,"10":0,"11":3,"12":3,"13":3,"14":7,"15":7,"16":1,"17":2,"18":14,"19":0},"b":{"0":[2,0],"1":[0,0],"2":[0,2],"3":[2],"4":[2,0],"5":[0,0],"6":[0,0],"7":[2,0],"8":[0,0],"9":[0,0,0,0,0,0],"10":[0,0],"11":[0,0],"12":[0,0],"13":[0,0],"14":[0,0],"15":[0,0],"16":[2,16],"17":[6,8],"18":[0,8],"19":[8,8],"20":[8,0],"21":[0,18],"22":[0,18],"23":[18,0],"24":[8,0],"25":[8,0],"26":[8,0],"27":[6,2],"28":[2,2],"29":[0,2],"30":[0,2],"31":[0,0],"32":[0,0],"33":[0,0],"34":[0,8],"35":[0,0],"36":[0,0],"37":[0,0],"38":[0,0],"39":[3,5,0],"40":[3,0],"41":[3,3],"42":[0,0,0,3],"43":[0,0],"44":[0,0,0],"45":[0,0],"46":[0,0],"47":[0,0],"48":[0,0],"49":[0,0],"50":[0,0],"51":[0,0],"52":[0,0],"53":[0,0],"54":[0,0],"55":[0,0],"56":[0,0,0],"57":[0,0],"58":[0,0],"59":[0,0],"60":[0,0],"61":[0,0],"62":[0,0],"63":[0,0],"64":[0,0],"65":[0,0],"66":[0,0],"67":[0,0],"68":[0,0],"69":[0,3],"70":[3,0,0],"71":[0,0],"72":[0,0],"73":[0,0],"74":[0,0],"75":[0,0],"76":[0,0],"77":[0,0],"78":[0,0],"79":[1,2],"80":[1,0],"81":[1,4],"82":[1,0],"83":[1,1,0],"84":[0,0,0,3,0],"85":[0,3],"86":[3,0],"87":[0,3],"88":[0,0],"89":[0,0],"90":[0,0],"91":[0,0],"92":[3,0],"93":[0,3],"94":[0,0],"95":[0,3],"96":[3,0],"97":[3,0],"98":[0,3],"99":[0,3],"100":[3,3],"101":[1,0],"102":[2,2],"103":[0,0],"104":[3,0],"105":[0,3],"106":[1,2],"107":[1,0],"108":[3,4],"109":[0,1],"110":[0,1],"111":[0,2],"112":[1,1],"113":[0,14],"114":[0,0],"115":[3,11],"116":[9,2],"117":[11,7,2],"118":[1,0],"119":[0,0],"120":[0,0]},"meta":{"lastBranch":121,"lastFunction":20,"lastStatement":341,"seen":{"s:45:6:45:Infinity":0,"s:82:26:82:Infinity":1,"s:83:28:83:Infinity":2,"f:85:2:85:Infinity":0,"s:86:12:86:Infinity":3,"s:87:12:87:Infinity":4,"s:88:12:88:Infinity":5,"s:89:12:89:Infinity":6,"s:90:12:90:Infinity":7,"s:91:12:91:Infinity":8,"s:92:12:92:Infinity":9,"f:98:16:98:35":1,"s:99:4:113:Infinity":10,"s:100:22:100:Infinity":11,"s:101:22:101:Infinity":12,"b:102:6:102:Infinity:undefined:undefined:undefined:undefined":0,"s:102:6:102:Infinity":13,"s:102:20:102:Infinity":14,"s:105:28:105:Infinity":15,"b:105:28:105:53:105:53:105:Infinity":1,"b:106:6:106:Infinity:undefined:undefined:undefined:undefined":2,"s:106:6:106:Infinity":16,"s:106:26:106:Infinity":17,"s:109:6:109:Infinity":18,"s:110:6:110:Infinity":19,"s:112:6:112:Infinity":20,"f:120:16:120:34":2,"b:120:75:120:130":3,"s:121:4:150:Infinity":21,"s:122:22:122:Infinity":22,"b:124:6:126:Infinity:undefined:undefined:undefined:undefined":4,"s:124:6:126:Infinity":23,"s:125:8:125:Infinity":24,"s:129:25:129:Infinity":25,"s:132:20:132:Infinity":26,"s:136:33:136:Infinity":27,"s:137:28:137:Infinity":28,"b:137:49:137:57:137:57:137:Infinity":5,"s:140:35:140:Infinity":29,"b:140:112:140:119:140:119:140:Infinity":6,"b:140:63:140:91:140:91:140:112":7,"s:141:26:141:Infinity":30,"s:143:6:146:Infinity":31,"s:148:6:148:Infinity":32,"b:148:56:148:70:148:70:148:82":8,"s:149:6:149:Infinity":33,"f:156:2:156:Infinity":3,"b:162:6:169:Infinity:171:6:173:Infinity:175:6:177:Infinity:179:6:188:Infinity:190:6:192:Infinity:194:6:196:Infinity":9,"s:161:4:197:Infinity":34,"b:163:8:168:Infinity:undefined:undefined:undefined:undefined":10,"s:163:8:168:Infinity":35,"b:163:12:163:22:163:22:163:39":11,"s:164:10:164:Infinity":36,"s:165:10:167:Infinity":37,"f:165:80:165:81":4,"s:166:12:166:Infinity":38,"b:166:60:166:74:166:74:166:86":12,"s:169:8:169:Infinity":39,"s:173:8:173:Infinity":40,"s:176:8:176:Infinity":41,"s:177:8:177:Infinity":42,"b:180:8:187:Infinity:undefined:undefined:undefined:undefined":13,"s:180:8:187:Infinity":43,"s:181:10:181:Infinity":44,"s:182:10:182:Infinity":45,"s:183:10:183:Infinity":46,"b:184:10:186:Infinity:undefined:undefined:undefined:undefined":14,"s:184:10:186:Infinity":47,"b:184:14:184:41:184:41:184:58":15,"s:185:12:185:Infinity":48,"s:188:8:188:Infinity":49,"s:191:8:191:Infinity":50,"s:192:8:192:Infinity":51,"s:195:8:195:Infinity":52,"s:196:8:196:Infinity":53,"f:209:8:209:Infinity":5,"b:215:4:218:Infinity:undefined:undefined:undefined:undefined":16,"s:215:4:218:Infinity":54,"s:216:6:216:Infinity":55,"s:217:6:217:Infinity":56,"s:220:4:220:Infinity":57,"s:222:4:335:Infinity":58,"s:223:20:223:Infinity":59,"b:224:6:224:Infinity:undefined:undefined:undefined:undefined":17,"s:224:6:224:Infinity":60,"s:224:18:224:Infinity":61,"s:226:12:226:Infinity":62,"b:227:6:227:Infinity:undefined:undefined:undefined:undefined":18,"s:227:6:227:Infinity":63,"s:227:21:227:Infinity":64,"s:229:6:229:Infinity":65,"s:234:27:234:Infinity":66,"b:234:27:234:47:234:47:234:Infinity":19,"s:235:12:235:Infinity":67,"s:236:12:236:Infinity":68,"s:237:12:237:Infinity":69,"s:239:12:239:Infinity":70,"s:240:12:240:Infinity":71,"s:241:12:241:Infinity":72,"s:243:6:250:Infinity":73,"b:249:40:249:49:249:49:249:Infinity":20,"b:252:6:257:Infinity:undefined:undefined:undefined:undefined":21,"s:252:6:257:Infinity":74,"s:253:8:256:Infinity":75,"s:259:23:259:Infinity":76,"b:263:6:267:Infinity:undefined:undefined:undefined:undefined":22,"s:263:6:267:Infinity":77,"b:263:10:263:24:263:24:263:47":23,"s:264:8:264:Infinity":78,"s:265:8:265:Infinity":79,"s:266:8:266:Infinity":80,"b:269:6:314:Infinity:undefined:undefined:undefined:undefined":24,"s:269:6:314:Infinity":81,"s:270:8:309:Infinity":82,"s:271:33:271:Infinity":83,"b:271:33:271:59:271:59:271:Infinity":25,"b:272:10:308:Infinity:undefined:undefined:undefined:undefined":26,"s:272:10:308:Infinity":84,"s:274:12:274:Infinity":85,"s:276:40:276:Infinity":86,"s:277:12:277:Infinity":87,"b:279:12:287:Infinity:285:19:287:Infinity":27,"s:279:12:287:Infinity":88,"s:280:20:280:Infinity":89,"s:281:36:281:Infinity":90,"s:282:14:282:Infinity":91,"s:283:14:283:Infinity":92,"s:284:14:284:Infinity":93,"s:286:14:286:Infinity":94,"s:290:33:290:Infinity":95,"b:290:33:290:68:290:68:290:Infinity":28,"s:291:72:291:Infinity":96,"b:293:12:297:Infinity:undefined:undefined:undefined:undefined":29,"s:293:12:297:Infinity":97,"s:294:14:294:Infinity":98,"s:295:14:295:Infinity":99,"s:296:14:296:Infinity":100,"b:300:12:307:Infinity:undefined:undefined:undefined:undefined":30,"s:300:12:307:Infinity":101,"s:301:34:301:Infinity":102,"b:302:14:306:Infinity:undefined:undefined:undefined:undefined":31,"s:302:14:306:Infinity":103,"b:302:18:302:40:302:40:302:74":32,"s:304:16:304:Infinity":104,"s:305:16:305:Infinity":105,"s:311:8:311:Infinity":106,"s:312:8:312:Infinity":107,"s:313:8:313:Infinity":108,"b:317:6:331:Infinity:322:13:331:Infinity":33,"s:317:6:331:Infinity":109,"s:318:14:318:Infinity":110,"s:319:30:319:Infinity":111,"s:320:8:320:Infinity":112,"s:321:8:321:Infinity":113,"s:323:8:323:Infinity":114,"s:324:8:330:Infinity":115,"s:333:6:333:Infinity":116,"s:334:6:334:Infinity":117,"f:342:8:342:Infinity":6,"s:349:18:349:Infinity":118,"b:350:4:350:Infinity:undefined:undefined:undefined:undefined":34,"s:350:4:350:Infinity":119,"s:350:16:350:Infinity":120,"s:356:4:369:Infinity":121,"s:357:6:357:Infinity":122,"s:358:6:358:Infinity":123,"s:360:6:365:Infinity":124,"b:363:44:363:64:363:64:363:Infinity":35,"b:364:44:364:62:364:62:364:Infinity":36,"s:366:6:366:Infinity":125,"s:367:6:367:Infinity":126,"s:368:6:368:Infinity":127,"s:372:4:386:Infinity":128,"s:373:6:373:Infinity":129,"s:374:6:374:Infinity":130,"s:376:6:382:Infinity":131,"b:380:46:380:68:380:68:380:Infinity":37,"b:381:46:381:66:381:66:381:Infinity":38,"s:383:6:383:Infinity":132,"s:384:6:384:Infinity":133,"s:385:6:385:Infinity":134,"b:389:6:391:Infinity:392:6:394:Infinity:395:6:397:Infinity":39,"s:388:4:398:Infinity":135,"s:390:8:390:Infinity":136,"s:391:8:391:Infinity":137,"s:393:8:393:Infinity":138,"s:394:8:394:Infinity":139,"s:396:8:396:Infinity":140,"s:397:8:397:Infinity":141,"f:405:16:405:Infinity":7,"s:411:25:411:Infinity":142,"s:412:10:412:Infinity":143,"s:413:25:413:Infinity":144,"s:414:31:414:Infinity":145,"b:414:31:414:59:414:59:414:Infinity":40,"s:416:24:416:Infinity":146,"b:416:24:416:41:416:41:416:Infinity":41,"b:418:6:494:Infinity:495:6:562:Infinity:563:6:567:Infinity:568:6:629:Infinity":42,"s:417:4:630:Infinity":147,"s:419:14:419:Infinity":148,"b:420:8:492:Infinity:490:15:492:Infinity":43,"s:420:8:492:Infinity":149,"b:420:12:420:34:420:34:420:58:420:58:420:77":44,"s:421:54:421:Infinity":150,"s:424:10:448:Infinity":151,"s:425:12:447:Infinity":152,"s:426:36:426:Infinity":153,"b:426:45:426:92:426:92:426:Infinity":45,"s:427:30:432:Infinity":154,"b:428:20:428:28:428:28:428:Infinity":46,"s:433:14:439:Infinity":155,"s:440:14:444:Infinity":156,"s:446:14:446:Infinity":157,"b:446:78:446:92:446:92:446:104":47,"s:451:29:451:Infinity":158,"s:452:10:469:Infinity":159,"s:453:28:453:Infinity":160,"b:454:12:454:Infinity:undefined:undefined:undefined:undefined":48,"s:454:12:454:Infinity":161,"b:454:16:454:28:454:28:454:60":49,"s:454:60:454:Infinity":162,"s:455:12:468:Infinity":163,"s:456:14:467:Infinity":164,"s:457:16:457:Infinity":165,"s:458:16:464:Infinity":166,"s:466:16:466:Infinity":167,"b:466:84:466:98:466:98:466:110":50,"b:471:10:488:Infinity:undefined:undefined:undefined:undefined":51,"s:471:10:488:Infinity":168,"s:472:12:487:Infinity":169,"s:473:25:479:Infinity":170,"b:478:25:478:42:478:42:478:Infinity":52,"s:480:14:484:Infinity":171,"s:486:14:486:Infinity":172,"b:486:62:486:76:486:76:486:88":53,"s:489:10:489:Infinity":173,"b:489:26:489:43:489:43:489:Infinity":54,"s:491:10:491:Infinity":174,"s:493:8:493:Infinity":175,"s:496:14:496:Infinity":176,"b:497:8:560:Infinity:558:15:560:Infinity":55,"s:497:8:560:Infinity":177,"b:497:12:497:34:497:34:497:57:497:57:497:75":56,"s:498:16:498:Infinity":178,"s:499:27:499:Infinity":179,"b:499:27:499:62:499:62:499:Infinity":57,"s:500:54:500:Infinity":180,"s:503:32:503:Infinity":181,"b:503:42:503:93:503:93:503:Infinity":58,"s:504:32:504:Infinity":182,"f:504:58:504:63":8,"s:504:63:504:69":183,"s:506:10:537:Infinity":184,"b:507:12:510:Infinity:undefined:undefined:undefined:undefined":59,"s:507:12:510:Infinity":185,"s:508:14:508:Infinity":186,"s:509:14:509:Infinity":187,"s:511:12:536:Infinity":188,"s:512:30:520:Infinity":189,"b:515:30:515:46:515:46:515:Infinity":60,"b:517:29:517:39:517:39:517:Infinity":61,"b:518:27:518:49:518:49:518:Infinity":62,"b:519:23:519:41:519:41:519:Infinity":63,"s:521:14:521:Infinity":190,"s:522:14:528:Infinity":191,"s:529:14:533:Infinity":192,"s:535:14:535:Infinity":193,"b:535:77:535:91:535:91:535:103":64,"b:539:10:556:Infinity:undefined:undefined:undefined:undefined":65,"s:539:10:556:Infinity":194,"s:540:12:555:Infinity":195,"s:541:25:547:Infinity":196,"b:546:25:546:42:546:42:546:Infinity":66,"s:548:14:552:Infinity":197,"s:554:14:554:Infinity":198,"b:554:62:554:76:554:76:554:88":67,"s:557:10:557:Infinity":199,"b:557:26:557:43:557:43:557:Infinity":68,"s:559:10:559:Infinity":200,"s:561:8:561:Infinity":201,"s:564:14:564:Infinity":202,"s:565:8:565:Infinity":203,"s:566:8:566:Infinity":204,"s:569:14:569:Infinity":205,"b:570:8:627:Infinity:625:15:627:Infinity":69,"s:570:8:627:Infinity":206,"b:570:12:570:34:570:34:570:57:570:57:570:75":70,"s:571:54:571:Infinity":207,"s:573:10:604:Infinity":208,"s:574:12:603:Infinity":209,"b:575:14:575:Infinity:undefined:undefined:undefined:undefined":71,"s:575:14:575:Infinity":210,"s:575:29:575:Infinity":211,"s:576:31:576:Infinity":212,"b:577:14:580:Infinity:undefined:undefined:undefined:undefined":72,"s:577:14:580:Infinity":213,"s:578:16:578:Infinity":214,"s:579:16:579:Infinity":215,"s:581:36:581:Infinity":216,"s:582:20:582:Infinity":217,"b:582:54:582:64:582:64:582:66":73,"s:583:14:586:Infinity":218,"s:587:30:587:Infinity":219,"s:588:14:595:Infinity":220,"s:596:14:600:Infinity":221,"s:602:14:602:Infinity":222,"b:602:80:602:94:602:94:602:106":74,"b:606:10:623:Infinity:undefined:undefined:undefined:undefined":75,"s:606:10:623:Infinity":223,"s:607:12:622:Infinity":224,"s:608:25:614:Infinity":225,"b:613:25:613:42:613:42:613:Infinity":76,"s:615:14:619:Infinity":226,"s:621:14:621:Infinity":227,"b:621:62:621:76:621:76:621:88":77,"s:624:10:624:Infinity":228,"b:624:26:624:43:624:43:624:Infinity":78,"s:626:10:626:Infinity":229,"s:628:8:628:Infinity":230,"s:632:39:636:Infinity":231,"s:637:4:637:Infinity":232,"s:639:19:639:Infinity":233,"b:640:4:652:Infinity:undefined:undefined:undefined:undefined":79,"s:640:4:652:Infinity":234,"s:641:39:650:Infinity":235,"b:647:18:647:34:647:34:647:Infinity":80,"s:651:6:651:Infinity":236,"s:654:4:654:Infinity":237,"f:660:8:660:Infinity":9,"s:666:47:666:Infinity":238,"s:668:4:668:Infinity":239,"b:670:4:683:Infinity:undefined:undefined:undefined:undefined":81,"s:670:4:683:Infinity":240,"s:671:39:681:Infinity":241,"b:677:18:677:34:677:34:677:Infinity":82,"b:678:21:678:34:678:34:678:53:678:53:678:Infinity":83,"s:682:6:682:Infinity":242,"f:689:8:689:Infinity":10,"s:694:37:694:Infinity":243,"s:696:4:699:Infinity":244,"s:701:4:701:Infinity":245,"f:707:2:707:19":11,"b:709:6:709:Infinity:710:6:710:Infinity:711:6:711:Infinity:712:6:712:Infinity:713:6:713:Infinity":84,"s:708:4:714:Infinity":246,"s:709:22:709:Infinity":247,"s:710:19:710:Infinity":248,"s:711:21:711:Infinity":249,"s:712:21:712:Infinity":250,"s:713:15:713:Infinity":251,"f:720:8:720:Infinity":12,"s:726:18:726:Infinity":252,"b:727:4:727:Infinity:undefined:undefined:undefined:undefined":85,"s:727:4:727:Infinity":253,"s:727:16:727:Infinity":254,"s:730:35:730:Infinity":255,"b:731:4:754:Infinity:undefined:undefined:undefined:undefined":86,"s:731:4:754:Infinity":256,"s:732:26:732:Infinity":257,"b:733:6:753:Infinity:744:6:753:Infinity":87,"s:733:6:753:Infinity":258,"s:735:8:743:Infinity":259,"s:736:10:742:Infinity":260,"s:737:27:737:Infinity":261,"b:738:12:741:Infinity:undefined:undefined:undefined:undefined":88,"s:738:12:741:Infinity":262,"b:738:16:738:44:738:44:738:78":89,"s:739:14:739:Infinity":263,"b:739:26:739:62:739:62:739:Infinity":90,"b:740:14:740:Infinity:undefined:undefined:undefined:undefined":91,"s:740:14:740:Infinity":264,"s:740:29:740:Infinity":265,"b:744:6:753:Infinity:undefined:undefined:undefined:undefined":92,"s:744:6:753:Infinity":266,"s:745:8:752:Infinity":267,"s:746:10:751:Infinity":268,"s:747:26:747:Infinity":269,"b:748:12:750:Infinity:undefined:undefined:undefined:undefined":93,"s:748:12:750:Infinity":270,"s:749:14:749:Infinity":271,"b:749:26:749:61:749:61:749:Infinity":94,"b:756:4:758:Infinity:undefined:undefined:undefined:undefined":95,"s:756:4:758:Infinity":272,"s:757:6:757:Infinity":273,"s:759:4:759:Infinity":274,"b:761:4:800:Infinity:798:11:800:Infinity":96,"s:761:4:800:Infinity":275,"s:763:46:763:Infinity":276,"s:764:20:764:Infinity":277,"s:765:6:772:Infinity":278,"s:766:8:771:Infinity":279,"s:767:25:767:Infinity":280,"b:768:10:770:Infinity:undefined:undefined:undefined:undefined":97,"s:768:10:770:Infinity":281,"s:769:12:769:Infinity":282,"b:774:6:778:Infinity:undefined:undefined:undefined:undefined":98,"s:774:6:778:Infinity":283,"s:775:8:775:Infinity":284,"s:776:8:776:Infinity":285,"s:777:8:777:Infinity":286,"b:781:6:785:Infinity:undefined:undefined:undefined:undefined":99,"s:781:6:785:Infinity":287,"s:782:8:782:Infinity":288,"s:783:8:783:Infinity":289,"s:784:8:784:Infinity":290,"s:788:6:795:Infinity":291,"s:789:23:789:Infinity":292,"b:789:23:789:54:789:54:789:Infinity":100,"s:790:8:790:Infinity":293,"s:792:8:792:Infinity":294,"b:792:62:792:81:792:81:792:98":101,"s:793:8:793:Infinity":295,"s:794:8:794:Infinity":296,"s:797:6:797:Infinity":297,"b:797:102:797:115:797:115:797:124":102,"s:799:6:799:Infinity":298,"b:799:101:799:114:799:114:799:123":103,"f:807:8:807:Infinity":13,"s:813:25:813:Infinity":299,"b:813:50:813:66:813:66:813:Infinity":104,"s:814:18:814:Infinity":300,"b:815:4:815:Infinity:undefined:undefined:undefined:undefined":105,"s:815:4:815:Infinity":301,"s:815:16:815:Infinity":302,"s:817:4:817:Infinity":303,"s:819:37:822:Infinity":304,"s:824:4:827:Infinity":305,"b:829:4:841:Infinity:undefined:undefined:undefined:undefined":106,"s:829:4:841:Infinity":306,"s:830:39:839:Infinity":307,"b:836:18:836:34:836:34:836:Infinity":107,"s:840:6:840:Infinity":308,"f:848:2:848:24":14,"s:849:24:849:Infinity":309,"s:850:24:850:Infinity":310,"s:851:4:851:Infinity":311,"s:853:18:855:Infinity":312,"f:854:6:854:7":15,"s:854:32:854:Infinity":313,"s:856:23:856:Infinity":314,"s:858:4:858:Infinity":315,"b:858:25:858:68:858:68:858:Infinity":108,"f:864:8:864:18":16,"b:865:4:865:Infinity:undefined:undefined:undefined:undefined":109,"s:865:4:865:Infinity":316,"s:865:24:865:Infinity":317,"s:866:18:866:Infinity":318,"s:867:4:867:Infinity":319,"b:867:27:867:54:867:54:867:Infinity":110,"f:873:8:873:28":17,"b:874:4:874:Infinity:undefined:undefined:undefined:undefined":111,"s:874:4:874:Infinity":320,"s:874:34:874:Infinity":321,"s:875:18:875:Infinity":322,"s:876:4:876:Infinity":323,"b:876:37:876:74:876:74:876:Infinity":112,"f:888:16:888:37":18,"b:890:4:893:Infinity:undefined:undefined:undefined:undefined":113,"s:890:4:893:Infinity":324,"s:891:21:891:Infinity":325,"s:892:6:892:Infinity":326,"b:892:22:892:47:892:47:892:Infinity":114,"s:896:4:910:Infinity":327,"s:897:12:897:Infinity":328,"b:898:6:898:Infinity:undefined:undefined:undefined:undefined":115,"s:898:6:898:Infinity":329,"s:898:35:898:Infinity":330,"s:900:28:900:Infinity":331,"s:901:21:901:Infinity":332,"b:903:6:905:Infinity:undefined:undefined:undefined:undefined":116,"s:903:6:905:Infinity":333,"b:903:10:903:38:903:38:903:71:903:71:903:98":117,"s:904:8:904:Infinity":334,"s:906:6:906:Infinity":335,"s:908:6:908:Infinity":336,"b:908:60:908:74:908:74:908:86":118,"s:909:6:909:Infinity":337,"f:913:10:913:22":19,"b:914:4:926:Infinity:undefined:undefined:undefined:undefined":119,"s:914:4:926:Infinity":338,"s:915:39:924:Infinity":339,"b:921:18:921:34:921:34:921:Infinity":120,"s:925:6:925:Infinity":340}}} +,"/Users/lukasmay/development/projects/codewalk-district/src/agent/process-manager.ts": {"path":"/Users/lukasmay/development/projects/codewalk-district/src/agent/process-manager.ts","statementMap":{"0":{"start":{"line":21,"column":6},"end":{"line":21,"column":null}},"1":{"start":{"line":27,"column":2},"end":{"line":32,"column":null}},"2":{"start":{"line":28,"column":4},"end":{"line":28,"column":null}},"3":{"start":{"line":29,"column":4},"end":{"line":29,"column":null}},"4":{"start":{"line":31,"column":4},"end":{"line":31,"column":null}},"5":{"start":{"line":37,"column":12},"end":{"line":37,"column":null}},"6":{"start":{"line":38,"column":12},"end":{"line":38,"column":null}},"7":{"start":{"line":45,"column":4},"end":{"line":45,"column":null}},"8":{"start":{"line":58,"column":21},"end":{"line":58,"column":null}},"9":{"start":{"line":59,"column":25},"end":{"line":59,"column":null}},"10":{"start":{"line":61,"column":4},"end":{"line":67,"column":null}},"11":{"start":{"line":71,"column":4},"end":{"line":74,"column":null}},"12":{"start":{"line":72,"column":6},"end":{"line":72,"column":null}},"13":{"start":{"line":73,"column":6},"end":{"line":73,"column":null}},"14":{"start":{"line":76,"column":4},"end":{"line":96,"column":null}},"15":{"start":{"line":77,"column":24},"end":{"line":77,"column":null}},"16":{"start":{"line":78,"column":30},"end":{"line":78,"column":null}},"17":{"start":{"line":79,"column":34},"end":{"line":79,"column":null}},"18":{"start":{"line":80,"column":23},"end":{"line":80,"column":null}},"19":{"start":{"line":81,"column":27},"end":{"line":81,"column":null}},"20":{"start":{"line":82,"column":12},"end":{"line":82,"column":null}},"21":{"start":{"line":84,"column":6},"end":{"line":90,"column":null}},"22":{"start":{"line":92,"column":6},"end":{"line":95,"column":null}},"23":{"start":{"line":93,"column":8},"end":{"line":93,"column":null}},"24":{"start":{"line":94,"column":8},"end":{"line":94,"column":null}},"25":{"start":{"line":98,"column":4},"end":{"line":98,"column":null}},"26":{"start":{"line":105,"column":25},"end":{"line":105,"column":null}},"27":{"start":{"line":106,"column":28},"end":{"line":106,"column":null}},"28":{"start":{"line":108,"column":4},"end":{"line":108,"column":null}},"29":{"start":{"line":110,"column":21},"end":{"line":110,"column":null}},"30":{"start":{"line":111,"column":25},"end":{"line":111,"column":null}},"31":{"start":{"line":112,"column":10},"end":{"line":112,"column":null}},"32":{"start":{"line":114,"column":4},"end":{"line":119,"column":null}},"33":{"start":{"line":121,"column":4},"end":{"line":124,"column":null}},"34":{"start":{"line":122,"column":6},"end":{"line":122,"column":null}},"35":{"start":{"line":123,"column":6},"end":{"line":123,"column":null}},"36":{"start":{"line":126,"column":4},"end":{"line":126,"column":null}},"37":{"start":{"line":136,"column":17},"end":{"line":136,"column":null}},"38":{"start":{"line":137,"column":40},"end":{"line":137,"column":null}},"39":{"start":{"line":139,"column":4},"end":{"line":141,"column":null}},"40":{"start":{"line":140,"column":6},"end":{"line":140,"column":null}},"41":{"start":{"line":143,"column":4},"end":{"line":147,"column":null}},"42":{"start":{"line":144,"column":6},"end":{"line":144,"column":null}},"43":{"start":{"line":145,"column":4},"end":{"line":147,"column":null}},"44":{"start":{"line":146,"column":6},"end":{"line":146,"column":null}},"45":{"start":{"line":149,"column":4},"end":{"line":151,"column":null}},"46":{"start":{"line":150,"column":6},"end":{"line":150,"column":null}},"47":{"start":{"line":153,"column":4},"end":{"line":153,"column":null}},"48":{"start":{"line":164,"column":17},"end":{"line":164,"column":null}},"49":{"start":{"line":165,"column":40},"end":{"line":165,"column":null}},"50":{"start":{"line":167,"column":4},"end":{"line":179,"column":null}},"51":{"start":{"line":169,"column":8},"end":{"line":169,"column":null}},"52":{"start":{"line":170,"column":8},"end":{"line":170,"column":null}},"53":{"start":{"line":172,"column":8},"end":{"line":174,"column":null}},"54":{"start":{"line":173,"column":10},"end":{"line":173,"column":null}},"55":{"start":{"line":175,"column":8},"end":{"line":175,"column":null}},"56":{"start":{"line":176,"column":8},"end":{"line":176,"column":null}},"57":{"start":{"line":178,"column":8},"end":{"line":178,"column":null}},"58":{"start":{"line":181,"column":4},"end":{"line":185,"column":null}},"59":{"start":{"line":182,"column":6},"end":{"line":182,"column":null}},"60":{"start":{"line":183,"column":4},"end":{"line":185,"column":null}},"61":{"start":{"line":184,"column":6},"end":{"line":184,"column":null}},"62":{"start":{"line":187,"column":4},"end":{"line":189,"column":null}},"63":{"start":{"line":188,"column":6},"end":{"line":188,"column":null}},"64":{"start":{"line":191,"column":4},"end":{"line":191,"column":null}},"65":{"start":{"line":201,"column":4},"end":{"line":201,"column":null}},"66":{"start":{"line":201,"column":29},"end":{"line":201,"column":null}},"67":{"start":{"line":203,"column":4},"end":{"line":224,"column":null}},"68":{"start":{"line":204,"column":6},"end":{"line":207,"column":null}},"69":{"start":{"line":205,"column":23},"end":{"line":205,"column":null}},"70":{"start":{"line":206,"column":8},"end":{"line":206,"column":null}},"71":{"start":{"line":209,"column":6},"end":{"line":221,"column":null}},"72":{"start":{"line":210,"column":22},"end":{"line":210,"column":null}},"73":{"start":{"line":211,"column":8},"end":{"line":220,"column":null}},"74":{"start":{"line":212,"column":10},"end":{"line":219,"column":null}},"75":{"start":{"line":213,"column":26},"end":{"line":213,"column":null}},"76":{"start":{"line":214,"column":12},"end":{"line":216,"column":null}},"77":{"start":{"line":215,"column":14},"end":{"line":215,"column":null}},"78":{"start":{"line":226,"column":4},"end":{"line":226,"column":null}},"79":{"start":{"line":249,"column":10},"end":{"line":249,"column":null}},"80":{"start":{"line":250,"column":28},"end":{"line":250,"column":null}},"81":{"start":{"line":253,"column":28},"end":{"line":258,"column":null}},"82":{"start":{"line":260,"column":4},"end":{"line":267,"column":null}},"83":{"start":{"line":269,"column":4},"end":{"line":272,"column":null}},"84":{"start":{"line":270,"column":6},"end":{"line":270,"column":null}},"85":{"start":{"line":271,"column":6},"end":{"line":271,"column":null}},"86":{"start":{"line":274,"column":10},"end":{"line":274,"column":null}},"87":{"start":{"line":275,"column":4},"end":{"line":275,"column":null}},"88":{"start":{"line":276,"column":10},"end":{"line":276,"column":null}},"89":{"start":{"line":277,"column":10},"end":{"line":277,"column":null}},"90":{"start":{"line":279,"column":4},"end":{"line":281,"column":null}},"91":{"start":{"line":280,"column":6},"end":{"line":280,"column":null}},"92":{"start":{"line":283,"column":10},"end":{"line":283,"column":null}},"93":{"start":{"line":284,"column":10},"end":{"line":284,"column":null}},"94":{"start":{"line":286,"column":10},"end":{"line":291,"column":null}},"95":{"start":{"line":293,"column":4},"end":{"line":293,"column":null}},"96":{"start":{"line":294,"column":4},"end":{"line":294,"column":null}},"97":{"start":{"line":296,"column":4},"end":{"line":296,"column":null}},"98":{"start":{"line":298,"column":16},"end":{"line":298,"column":null}},"99":{"start":{"line":299,"column":4},"end":{"line":306,"column":null}},"100":{"start":{"line":308,"column":10},"end":{"line":308,"column":null}},"101":{"start":{"line":309,"column":19},"end":{"line":316,"column":null}},"102":{"start":{"line":318,"column":4},"end":{"line":320,"column":null}},"103":{"start":{"line":319,"column":6},"end":{"line":319,"column":null}},"104":{"start":{"line":322,"column":4},"end":{"line":322,"column":null}},"105":{"start":{"line":339,"column":20},"end":{"line":339,"column":null}},"106":{"start":{"line":340,"column":18},"end":{"line":352,"column":null}},"107":{"start":{"line":341,"column":6},"end":{"line":341,"column":null}},"108":{"start":{"line":341,"column":21},"end":{"line":341,"column":null}},"109":{"start":{"line":342,"column":6},"end":{"line":350,"column":null}},"110":{"start":{"line":343,"column":23},"end":{"line":343,"column":null}},"111":{"start":{"line":344,"column":8},"end":{"line":347,"column":null}},"112":{"start":{"line":345,"column":10},"end":{"line":345,"column":null}},"113":{"start":{"line":345,"column":41},"end":{"line":345,"column":65}},"114":{"start":{"line":346,"column":10},"end":{"line":346,"column":null}},"115":{"start":{"line":348,"column":8},"end":{"line":348,"column":null}},"116":{"start":{"line":348,"column":24},"end":{"line":348,"column":null}},"117":{"start":{"line":349,"column":8},"end":{"line":349,"column":null}},"118":{"start":{"line":351,"column":6},"end":{"line":351,"column":null}},"119":{"start":{"line":351,"column":22},"end":{"line":351,"column":null}},"120":{"start":{"line":353,"column":4},"end":{"line":353,"column":null}},"121":{"start":{"line":354,"column":4},"end":{"line":354,"column":null}},"122":{"start":{"line":354,"column":29},"end":{"line":354,"column":47}},"123":{"start":{"line":362,"column":4},"end":{"line":382,"column":null}},"124":{"start":{"line":363,"column":24},"end":{"line":363,"column":null}},"125":{"start":{"line":365,"column":20},"end":{"line":379,"column":null}},"126":{"start":{"line":366,"column":8},"end":{"line":371,"column":null}},"127":{"start":{"line":369,"column":10},"end":{"line":369,"column":null}},"128":{"start":{"line":370,"column":10},"end":{"line":370,"column":null}},"129":{"start":{"line":373,"column":8},"end":{"line":376,"column":null}},"130":{"start":{"line":374,"column":10},"end":{"line":374,"column":null}},"131":{"start":{"line":375,"column":10},"end":{"line":375,"column":null}},"132":{"start":{"line":378,"column":8},"end":{"line":378,"column":null}},"133":{"start":{"line":381,"column":6},"end":{"line":381,"column":null}},"134":{"start":{"line":392,"column":4},"end":{"line":392,"column":null}}},"fnMap":{"0":{"name":"isPidAlive","decl":{"start":{"line":26,"column":16},"end":{"line":26,"column":27}},"loc":{"start":{"line":26,"column":49},"end":{"line":33,"column":null}},"line":26},"1":{"name":"(anonymous_1)","decl":{"start":{"line":36,"column":2},"end":{"line":36,"column":null}},"loc":{"start":{"line":39,"column":4},"end":{"line":39,"column":null}},"line":39},"2":{"name":"(anonymous_2)","decl":{"start":{"line":44,"column":2},"end":{"line":44,"column":18}},"loc":{"start":{"line":44,"column":41},"end":{"line":46,"column":null}},"line":44},"3":{"name":"(anonymous_3)","decl":{"start":{"line":52,"column":8},"end":{"line":52,"column":null}},"loc":{"start":{"line":57,"column":21},"end":{"line":99,"column":null}},"line":57},"4":{"name":"(anonymous_4)","decl":{"start":{"line":104,"column":8},"end":{"line":104,"column":33}},"loc":{"start":{"line":104,"column":65},"end":{"line":127,"column":null}},"line":104},"5":{"name":"(anonymous_5)","decl":{"start":{"line":132,"column":2},"end":{"line":132,"column":null}},"loc":{"start":{"line":135,"column":70},"end":{"line":154,"column":null}},"line":135},"6":{"name":"(anonymous_6)","decl":{"start":{"line":159,"column":2},"end":{"line":159,"column":null}},"loc":{"start":{"line":163,"column":70},"end":{"line":192,"column":null}},"line":163},"7":{"name":"(anonymous_7)","decl":{"start":{"line":197,"column":2},"end":{"line":197,"column":null}},"loc":{"start":{"line":200,"column":19},"end":{"line":227,"column":null}},"line":200},"8":{"name":"(anonymous_8)","decl":{"start":{"line":236,"column":2},"end":{"line":236,"column":null}},"loc":{"start":{"line":247,"column":65},"end":{"line":323,"column":null}},"line":247},"9":{"name":"(anonymous_9)","decl":{"start":{"line":313,"column":27},"end":{"line":313,"column":33}},"loc":{"start":{"line":313,"column":33},"end":{"line":313,"column":null}},"line":313},"10":{"name":"(anonymous_10)","decl":{"start":{"line":318,"column":25},"end":{"line":318,"column":26}},"loc":{"start":{"line":318,"column":34},"end":{"line":320,"column":5}},"line":318},"11":{"name":"(anonymous_11)","decl":{"start":{"line":333,"column":2},"end":{"line":333,"column":null}},"loc":{"start":{"line":338,"column":28},"end":{"line":355,"column":null}},"line":338},"12":{"name":"(anonymous_12)","decl":{"start":{"line":340,"column":18},"end":{"line":340,"column":30}},"loc":{"start":{"line":340,"column":30},"end":{"line":352,"column":null}},"line":340},"13":{"name":"(anonymous_13)","decl":{"start":{"line":345,"column":28},"end":{"line":345,"column":29}},"loc":{"start":{"line":345,"column":41},"end":{"line":345,"column":65}},"line":345},"14":{"name":"(anonymous_14)","decl":{"start":{"line":354,"column":21},"end":{"line":354,"column":27}},"loc":{"start":{"line":354,"column":27},"end":{"line":354,"column":49}},"line":354},"15":{"name":"(anonymous_15)","decl":{"start":{"line":361,"column":8},"end":{"line":361,"column":33}},"loc":{"start":{"line":361,"column":112},"end":{"line":383,"column":null}},"line":361},"16":{"name":"(anonymous_16)","decl":{"start":{"line":362,"column":23},"end":{"line":362,"column":24}},"loc":{"start":{"line":362,"column":44},"end":{"line":382,"column":5}},"line":362},"17":{"name":"(anonymous_17)","decl":{"start":{"line":365,"column":20},"end":{"line":365,"column":26}},"loc":{"start":{"line":365,"column":26},"end":{"line":379,"column":null}},"line":365},"18":{"name":"(anonymous_18)","decl":{"start":{"line":389,"column":8},"end":{"line":389,"column":20}},"loc":{"start":{"line":389,"column":57},"end":{"line":393,"column":null}},"line":389}},"branchMap":{"0":{"loc":{"start":{"line":71,"column":4},"end":{"line":74,"column":null}},"type":"if","locations":[{"start":{"line":71,"column":4},"end":{"line":74,"column":null}},{"start":{},"end":{}}],"line":71},"1":{"loc":{"start":{"line":79,"column":34},"end":{"line":79,"column":null}},"type":"binary-expr","locations":[{"start":{"line":79,"column":34},"end":{"line":79,"column":48}},{"start":{"line":79,"column":48},"end":{"line":79,"column":null}}],"line":79},"2":{"loc":{"start":{"line":80,"column":66},"end":{"line":80,"column":98}},"type":"binary-expr","locations":[{"start":{"line":80,"column":66},"end":{"line":80,"column":80}},{"start":{"line":80,"column":80},"end":{"line":80,"column":98}}],"line":80},"3":{"loc":{"start":{"line":92,"column":6},"end":{"line":95,"column":null}},"type":"if","locations":[{"start":{"line":92,"column":6},"end":{"line":95,"column":null}},{"start":{},"end":{}}],"line":92},"4":{"loc":{"start":{"line":121,"column":4},"end":{"line":124,"column":null}},"type":"if","locations":[{"start":{"line":121,"column":4},"end":{"line":124,"column":null}},{"start":{},"end":{}}],"line":121},"5":{"loc":{"start":{"line":139,"column":4},"end":{"line":141,"column":null}},"type":"if","locations":[{"start":{"line":139,"column":4},"end":{"line":141,"column":null}},{"start":{},"end":{}}],"line":139},"6":{"loc":{"start":{"line":143,"column":4},"end":{"line":147,"column":null}},"type":"if","locations":[{"start":{"line":143,"column":4},"end":{"line":147,"column":null}},{"start":{"line":145,"column":4},"end":{"line":147,"column":null}}],"line":143},"7":{"loc":{"start":{"line":145,"column":4},"end":{"line":147,"column":null}},"type":"if","locations":[{"start":{"line":145,"column":4},"end":{"line":147,"column":null}},{"start":{},"end":{}}],"line":145},"8":{"loc":{"start":{"line":145,"column":15},"end":{"line":145,"column":86}},"type":"binary-expr","locations":[{"start":{"line":145,"column":15},"end":{"line":145,"column":49}},{"start":{"line":145,"column":49},"end":{"line":145,"column":86}}],"line":145},"9":{"loc":{"start":{"line":149,"column":4},"end":{"line":151,"column":null}},"type":"if","locations":[{"start":{"line":149,"column":4},"end":{"line":151,"column":null}},{"start":{},"end":{}}],"line":149},"10":{"loc":{"start":{"line":167,"column":4},"end":{"line":179,"column":null}},"type":"switch","locations":[{"start":{"line":168,"column":6},"end":{"line":170,"column":null}},{"start":{"line":171,"column":6},"end":{"line":176,"column":null}},{"start":{"line":177,"column":6},"end":{"line":178,"column":null}}],"line":167},"11":{"loc":{"start":{"line":172,"column":8},"end":{"line":174,"column":null}},"type":"if","locations":[{"start":{"line":172,"column":8},"end":{"line":174,"column":null}},{"start":{},"end":{}}],"line":172},"12":{"loc":{"start":{"line":181,"column":4},"end":{"line":185,"column":null}},"type":"if","locations":[{"start":{"line":181,"column":4},"end":{"line":185,"column":null}},{"start":{"line":183,"column":4},"end":{"line":185,"column":null}}],"line":181},"13":{"loc":{"start":{"line":183,"column":4},"end":{"line":185,"column":null}},"type":"if","locations":[{"start":{"line":183,"column":4},"end":{"line":185,"column":null}},{"start":{},"end":{}}],"line":183},"14":{"loc":{"start":{"line":183,"column":15},"end":{"line":183,"column":86}},"type":"binary-expr","locations":[{"start":{"line":183,"column":15},"end":{"line":183,"column":49}},{"start":{"line":183,"column":49},"end":{"line":183,"column":86}}],"line":183},"15":{"loc":{"start":{"line":187,"column":4},"end":{"line":189,"column":null}},"type":"if","locations":[{"start":{"line":187,"column":4},"end":{"line":189,"column":null}},{"start":{},"end":{}}],"line":187},"16":{"loc":{"start":{"line":201,"column":4},"end":{"line":201,"column":null}},"type":"if","locations":[{"start":{"line":201,"column":4},"end":{"line":201,"column":null}},{"start":{},"end":{}}],"line":201},"17":{"loc":{"start":{"line":204,"column":6},"end":{"line":207,"column":null}},"type":"if","locations":[{"start":{"line":204,"column":6},"end":{"line":207,"column":null}},{"start":{},"end":{}}],"line":204},"18":{"loc":{"start":{"line":206,"column":15},"end":{"line":206,"column":null}},"type":"binary-expr","locations":[{"start":{"line":206,"column":15},"end":{"line":206,"column":51}},{"start":{"line":206,"column":51},"end":{"line":206,"column":null}}],"line":206},"19":{"loc":{"start":{"line":209,"column":6},"end":{"line":221,"column":null}},"type":"if","locations":[{"start":{"line":209,"column":6},"end":{"line":221,"column":null}},{"start":{},"end":{}}],"line":209},"20":{"loc":{"start":{"line":214,"column":12},"end":{"line":216,"column":null}},"type":"if","locations":[{"start":{"line":214,"column":12},"end":{"line":216,"column":null}},{"start":{},"end":{}}],"line":214},"21":{"loc":{"start":{"line":215,"column":21},"end":{"line":215,"column":null}},"type":"binary-expr","locations":[{"start":{"line":215,"column":21},"end":{"line":215,"column":56}},{"start":{"line":215,"column":56},"end":{"line":215,"column":null}}],"line":215},"22":{"loc":{"start":{"line":269,"column":4},"end":{"line":272,"column":null}},"type":"if","locations":[{"start":{"line":269,"column":4},"end":{"line":272,"column":null}},{"start":{},"end":{}}],"line":269},"23":{"loc":{"start":{"line":279,"column":4},"end":{"line":281,"column":null}},"type":"if","locations":[{"start":{"line":279,"column":4},"end":{"line":281,"column":null}},{"start":{},"end":{}}],"line":279},"24":{"loc":{"start":{"line":313,"column":15},"end":{"line":313,"column":null}},"type":"binary-expr","locations":[{"start":{"line":313,"column":15},"end":{"line":313,"column":27}},{"start":{"line":313,"column":27},"end":{"line":313,"column":null}}],"line":313},"25":{"loc":{"start":{"line":319,"column":31},"end":{"line":319,"column":80}},"type":"cond-expr","locations":[{"start":{"line":319,"column":54},"end":{"line":319,"column":68}},{"start":{"line":319,"column":68},"end":{"line":319,"column":80}}],"line":319},"26":{"loc":{"start":{"line":341,"column":6},"end":{"line":341,"column":null}},"type":"if","locations":[{"start":{"line":341,"column":6},"end":{"line":341,"column":null}},{"start":{},"end":{}}],"line":341},"27":{"loc":{"start":{"line":342,"column":6},"end":{"line":350,"column":null}},"type":"if","locations":[{"start":{"line":342,"column":6},"end":{"line":350,"column":null}},{"start":{},"end":{}}],"line":342},"28":{"loc":{"start":{"line":344,"column":8},"end":{"line":347,"column":null}},"type":"if","locations":[{"start":{"line":344,"column":8},"end":{"line":347,"column":null}},{"start":{},"end":{}}],"line":344},"29":{"loc":{"start":{"line":348,"column":8},"end":{"line":348,"column":null}},"type":"if","locations":[{"start":{"line":348,"column":8},"end":{"line":348,"column":null}},{"start":{},"end":{}}],"line":348},"30":{"loc":{"start":{"line":351,"column":6},"end":{"line":351,"column":null}},"type":"if","locations":[{"start":{"line":351,"column":6},"end":{"line":351,"column":null}},{"start":{},"end":{}}],"line":351},"31":{"loc":{"start":{"line":361,"column":46},"end":{"line":361,"column":112}},"type":"default-arg","locations":[{"start":{"line":361,"column":66},"end":{"line":361,"column":112}}],"line":361},"32":{"loc":{"start":{"line":366,"column":8},"end":{"line":371,"column":null}},"type":"if","locations":[{"start":{"line":366,"column":8},"end":{"line":371,"column":null}},{"start":{},"end":{}}],"line":366},"33":{"loc":{"start":{"line":373,"column":8},"end":{"line":376,"column":null}},"type":"if","locations":[{"start":{"line":373,"column":8},"end":{"line":376,"column":null}},{"start":{},"end":{}}],"line":373}},"s":{"0":16,"1":10,"2":10,"3":10,"4":10,"5":38,"6":38,"7":16,"8":3,"9":3,"10":3,"11":3,"12":0,"13":0,"14":3,"15":3,"16":3,"17":3,"18":3,"19":3,"20":3,"21":3,"22":3,"23":1,"24":1,"25":2,"26":10,"27":10,"28":10,"29":10,"30":10,"31":10,"32":10,"33":10,"34":1,"35":1,"36":9,"37":10,"38":10,"39":10,"40":2,"41":10,"42":9,"43":1,"44":1,"45":10,"46":10,"47":10,"48":4,"49":4,"50":4,"51":3,"52":3,"53":0,"54":0,"55":0,"56":0,"57":1,"58":3,"59":3,"60":0,"61":0,"62":3,"63":3,"64":3,"65":0,"66":0,"67":0,"68":0,"69":0,"70":0,"71":0,"72":0,"73":0,"74":0,"75":0,"76":0,"77":0,"78":0,"79":15,"80":15,"81":15,"82":15,"83":15,"84":1,"85":1,"86":14,"87":14,"88":14,"89":14,"90":14,"91":11,"92":14,"93":14,"94":14,"95":14,"96":14,"97":14,"98":14,"99":14,"100":14,"101":14,"102":15,"103":0,"104":15,"105":10,"106":10,"107":10,"108":0,"109":10,"110":10,"111":10,"112":10,"113":10,"114":0,"115":0,"116":0,"117":0,"118":0,"119":0,"120":10,"121":10,"122":4,"123":0,"124":0,"125":0,"126":0,"127":0,"128":0,"129":0,"130":0,"131":0,"132":0,"133":0,"134":0},"f":{"0":10,"1":38,"2":16,"3":3,"4":10,"5":10,"6":4,"7":0,"8":15,"9":0,"10":0,"11":10,"12":10,"13":10,"14":4,"15":0,"16":0,"17":0,"18":0},"b":{"0":[0,3],"1":[3,3],"2":[3,3],"3":[1,2],"4":[1,9],"5":[2,8],"6":[9,1],"7":[1,0],"8":[1,1],"9":[10,0],"10":[3,0,1],"11":[0,0],"12":[3,0],"13":[0,0],"14":[0,0],"15":[3,0],"16":[0,0],"17":[0,0],"18":[0,0],"19":[0,0],"20":[0,0],"21":[0,0],"22":[1,14],"23":[11,3],"24":[14,0],"25":[0,0],"26":[0,10],"27":[10,0],"28":[10,0],"29":[0,0],"30":[0,0],"31":[0],"32":[0,0],"33":[0,0]},"meta":{"lastBranch":34,"lastFunction":19,"lastStatement":135,"seen":{"s:21:6:21:Infinity":0,"f:26:16:26:27":0,"s:27:2:32:Infinity":1,"s:28:4:28:Infinity":2,"s:29:4:29:Infinity":3,"s:31:4:31:Infinity":4,"f:36:2:36:Infinity":1,"s:37:12:37:Infinity":5,"s:38:12:38:Infinity":6,"f:44:2:44:18":2,"s:45:4:45:Infinity":7,"f:52:8:52:Infinity":3,"s:58:21:58:Infinity":8,"s:59:25:59:Infinity":9,"s:61:4:67:Infinity":10,"b:71:4:74:Infinity:undefined:undefined:undefined:undefined":0,"s:71:4:74:Infinity":11,"s:72:6:72:Infinity":12,"s:73:6:73:Infinity":13,"s:76:4:96:Infinity":14,"s:77:24:77:Infinity":15,"s:78:30:78:Infinity":16,"s:79:34:79:Infinity":17,"b:79:34:79:48:79:48:79:Infinity":1,"s:80:23:80:Infinity":18,"b:80:66:80:80:80:80:80:98":2,"s:81:27:81:Infinity":19,"s:82:12:82:Infinity":20,"s:84:6:90:Infinity":21,"b:92:6:95:Infinity:undefined:undefined:undefined:undefined":3,"s:92:6:95:Infinity":22,"s:93:8:93:Infinity":23,"s:94:8:94:Infinity":24,"s:98:4:98:Infinity":25,"f:104:8:104:33":4,"s:105:25:105:Infinity":26,"s:106:28:106:Infinity":27,"s:108:4:108:Infinity":28,"s:110:21:110:Infinity":29,"s:111:25:111:Infinity":30,"s:112:10:112:Infinity":31,"s:114:4:119:Infinity":32,"b:121:4:124:Infinity:undefined:undefined:undefined:undefined":4,"s:121:4:124:Infinity":33,"s:122:6:122:Infinity":34,"s:123:6:123:Infinity":35,"s:126:4:126:Infinity":36,"f:132:2:132:Infinity":5,"s:136:17:136:Infinity":37,"s:137:40:137:Infinity":38,"b:139:4:141:Infinity:undefined:undefined:undefined:undefined":5,"s:139:4:141:Infinity":39,"s:140:6:140:Infinity":40,"b:143:4:147:Infinity:145:4:147:Infinity":6,"s:143:4:147:Infinity":41,"s:144:6:144:Infinity":42,"b:145:4:147:Infinity:undefined:undefined:undefined:undefined":7,"s:145:4:147:Infinity":43,"b:145:15:145:49:145:49:145:86":8,"s:146:6:146:Infinity":44,"b:149:4:151:Infinity:undefined:undefined:undefined:undefined":9,"s:149:4:151:Infinity":45,"s:150:6:150:Infinity":46,"s:153:4:153:Infinity":47,"f:159:2:159:Infinity":6,"s:164:17:164:Infinity":48,"s:165:40:165:Infinity":49,"b:168:6:170:Infinity:171:6:176:Infinity:177:6:178:Infinity":10,"s:167:4:179:Infinity":50,"s:169:8:169:Infinity":51,"s:170:8:170:Infinity":52,"b:172:8:174:Infinity:undefined:undefined:undefined:undefined":11,"s:172:8:174:Infinity":53,"s:173:10:173:Infinity":54,"s:175:8:175:Infinity":55,"s:176:8:176:Infinity":56,"s:178:8:178:Infinity":57,"b:181:4:185:Infinity:183:4:185:Infinity":12,"s:181:4:185:Infinity":58,"s:182:6:182:Infinity":59,"b:183:4:185:Infinity:undefined:undefined:undefined:undefined":13,"s:183:4:185:Infinity":60,"b:183:15:183:49:183:49:183:86":14,"s:184:6:184:Infinity":61,"b:187:4:189:Infinity:undefined:undefined:undefined:undefined":15,"s:187:4:189:Infinity":62,"s:188:6:188:Infinity":63,"s:191:4:191:Infinity":64,"f:197:2:197:Infinity":7,"b:201:4:201:Infinity:undefined:undefined:undefined:undefined":16,"s:201:4:201:Infinity":65,"s:201:29:201:Infinity":66,"s:203:4:224:Infinity":67,"b:204:6:207:Infinity:undefined:undefined:undefined:undefined":17,"s:204:6:207:Infinity":68,"s:205:23:205:Infinity":69,"s:206:8:206:Infinity":70,"b:206:15:206:51:206:51:206:Infinity":18,"b:209:6:221:Infinity:undefined:undefined:undefined:undefined":19,"s:209:6:221:Infinity":71,"s:210:22:210:Infinity":72,"s:211:8:220:Infinity":73,"s:212:10:219:Infinity":74,"s:213:26:213:Infinity":75,"b:214:12:216:Infinity:undefined:undefined:undefined:undefined":20,"s:214:12:216:Infinity":76,"s:215:14:215:Infinity":77,"b:215:21:215:56:215:56:215:Infinity":21,"s:226:4:226:Infinity":78,"f:236:2:236:Infinity":8,"s:249:10:249:Infinity":79,"s:250:28:250:Infinity":80,"s:253:28:258:Infinity":81,"s:260:4:267:Infinity":82,"b:269:4:272:Infinity:undefined:undefined:undefined:undefined":22,"s:269:4:272:Infinity":83,"s:270:6:270:Infinity":84,"s:271:6:271:Infinity":85,"s:274:10:274:Infinity":86,"s:275:4:275:Infinity":87,"s:276:10:276:Infinity":88,"s:277:10:277:Infinity":89,"b:279:4:281:Infinity:undefined:undefined:undefined:undefined":23,"s:279:4:281:Infinity":90,"s:280:6:280:Infinity":91,"s:283:10:283:Infinity":92,"s:284:10:284:Infinity":93,"s:286:10:291:Infinity":94,"s:293:4:293:Infinity":95,"s:294:4:294:Infinity":96,"s:296:4:296:Infinity":97,"s:298:16:298:Infinity":98,"s:299:4:306:Infinity":99,"s:308:10:308:Infinity":100,"s:309:19:316:Infinity":101,"b:313:15:313:27:313:27:313:Infinity":24,"f:313:27:313:33":9,"s:318:4:320:Infinity":102,"f:318:25:318:26":10,"s:319:6:319:Infinity":103,"b:319:54:319:68:319:68:319:80":25,"s:322:4:322:Infinity":104,"f:333:2:333:Infinity":11,"s:339:20:339:Infinity":105,"s:340:18:352:Infinity":106,"f:340:18:340:30":12,"b:341:6:341:Infinity:undefined:undefined:undefined:undefined":26,"s:341:6:341:Infinity":107,"s:341:21:341:Infinity":108,"b:342:6:350:Infinity:undefined:undefined:undefined:undefined":27,"s:342:6:350:Infinity":109,"s:343:23:343:Infinity":110,"b:344:8:347:Infinity:undefined:undefined:undefined:undefined":28,"s:344:8:347:Infinity":111,"s:345:10:345:Infinity":112,"f:345:28:345:29":13,"s:345:41:345:65":113,"s:346:10:346:Infinity":114,"b:348:8:348:Infinity:undefined:undefined:undefined:undefined":29,"s:348:8:348:Infinity":115,"s:348:24:348:Infinity":116,"s:349:8:349:Infinity":117,"b:351:6:351:Infinity:undefined:undefined:undefined:undefined":30,"s:351:6:351:Infinity":118,"s:351:22:351:Infinity":119,"s:353:4:353:Infinity":120,"s:354:4:354:Infinity":121,"f:354:21:354:27":14,"s:354:29:354:47":122,"f:361:8:361:33":15,"b:361:66:361:112":31,"s:362:4:382:Infinity":123,"f:362:23:362:24":16,"s:363:24:363:Infinity":124,"s:365:20:379:Infinity":125,"f:365:20:365:26":17,"b:366:8:371:Infinity:undefined:undefined:undefined:undefined":32,"s:366:8:371:Infinity":126,"s:369:10:369:Infinity":127,"s:370:10:370:Infinity":128,"b:373:8:376:Infinity:undefined:undefined:undefined:undefined":33,"s:373:8:376:Infinity":129,"s:374:10:374:Infinity":130,"s:375:10:375:Infinity":131,"s:378:8:378:Infinity":132,"s:381:6:381:Infinity":133,"f:389:8:389:20":18,"s:392:4:392:Infinity":134}}} +,"/Users/lukasmay/development/projects/codewalk-district/src/agent/schema.ts": {"path":"/Users/lukasmay/development/projects/codewalk-district/src/agent/schema.ts","statementMap":{"0":{"start":{"line":14,"column":21},"end":{"line":17,"column":null}},"1":{"start":{"line":19,"column":34},"end":{"line":24,"column":null}},"2":{"start":{"line":32,"column":33},"end":{"line":36,"column":null}},"3":{"start":{"line":40,"column":37},"end":{"line":86,"column":null}},"4":{"start":{"line":93,"column":33},"end":{"line":93,"column":null}},"5":{"start":{"line":97,"column":37},"end":{"line":97,"column":null}}},"fnMap":{},"branchMap":{},"s":{"0":21,"1":21,"2":21,"3":21,"4":21,"5":21},"f":{},"b":{},"meta":{"lastBranch":0,"lastFunction":0,"lastStatement":6,"seen":{"s:14:21:17:Infinity":0,"s:19:34:24:Infinity":1,"s:32:33:36:Infinity":2,"s:40:37:86:Infinity":3,"s:93:33:93:Infinity":4,"s:97:37:97:Infinity":5}}} +,"/Users/lukasmay/development/projects/codewalk-district/src/agent/accounts/paths.ts": {"path":"/Users/lukasmay/development/projects/codewalk-district/src/agent/accounts/paths.ts","statementMap":{"0":{"start":{"line":4,"column":2},"end":{"line":4,"column":null}}},"fnMap":{"0":{"name":"getAccountConfigDir","decl":{"start":{"line":3,"column":16},"end":{"line":3,"column":36}},"loc":{"start":{"line":3,"column":86},"end":{"line":5,"column":null}},"line":3}},"branchMap":{},"s":{"0":0},"f":{"0":0},"b":{},"meta":{"lastBranch":0,"lastFunction":1,"lastStatement":1,"seen":{"f:3:16:3:36":0,"s:4:2:4:Infinity":0}}} +,"/Users/lukasmay/development/projects/codewalk-district/src/agent/accounts/setup.ts": {"path":"/Users/lukasmay/development/projects/codewalk-district/src/agent/accounts/setup.ts","statementMap":{"0":{"start":{"line":8,"column":2},"end":{"line":8,"column":null}},"1":{"start":{"line":11,"column":2},"end":{"line":11,"column":null}},"2":{"start":{"line":14,"column":2},"end":{"line":14,"column":null}}},"fnMap":{"0":{"name":"setupAccountConfigDir","decl":{"start":{"line":4,"column":16},"end":{"line":4,"column":null}},"loc":{"start":{"line":7,"column":8},"end":{"line":15,"column":null}},"line":7}},"branchMap":{},"s":{"0":0,"1":0,"2":0},"f":{"0":0},"b":{},"meta":{"lastBranch":0,"lastFunction":1,"lastStatement":3,"seen":{"f:4:16:4:Infinity":0,"s:8:2:8:Infinity":0,"s:11:2:11:Infinity":1,"s:14:2:14:Infinity":2}}} +,"/Users/lukasmay/development/projects/codewalk-district/src/agent/accounts/usage.ts": {"path":"/Users/lukasmay/development/projects/codewalk-district/src/agent/accounts/usage.ts","statementMap":{"0":{"start":{"line":10,"column":6},"end":{"line":10,"column":null}},"1":{"start":{"line":12,"column":22},"end":{"line":12,"column":null}},"2":{"start":{"line":13,"column":26},"end":{"line":13,"column":null}},"3":{"start":{"line":14,"column":24},"end":{"line":14,"column":null}},"4":{"start":{"line":15,"column":32},"end":{"line":15,"column":null}},"5":{"start":{"line":61,"column":2},"end":{"line":77,"column":null}},"6":{"start":{"line":62,"column":10},"end":{"line":62,"column":null}},"7":{"start":{"line":63,"column":4},"end":{"line":63,"column":null}},"8":{"start":{"line":63,"column":31},"end":{"line":63,"column":null}},"9":{"start":{"line":64,"column":10},"end":{"line":64,"column":null}},"10":{"start":{"line":65,"column":19},"end":{"line":65,"column":null}},"11":{"start":{"line":66,"column":18},"end":{"line":66,"column":null}},"12":{"start":{"line":67,"column":4},"end":{"line":67,"column":null}},"13":{"start":{"line":67,"column":38},"end":{"line":67,"column":null}},"14":{"start":{"line":68,"column":4},"end":{"line":74,"column":null}},"15":{"start":{"line":76,"column":4},"end":{"line":76,"column":null}},"16":{"start":{"line":81,"column":2},"end":{"line":81,"column":null}},"17":{"start":{"line":81,"column":30},"end":{"line":81,"column":null}},"18":{"start":{"line":82,"column":2},"end":{"line":82,"column":null}},"19":{"start":{"line":95,"column":8},"end":{"line":95,"column":null}},"20":{"start":{"line":98,"column":42},"end":{"line":98,"column":null}},"21":{"start":{"line":99,"column":2},"end":{"line":105,"column":null}},"22":{"start":{"line":100,"column":4},"end":{"line":102,"column":null}},"23":{"start":{"line":101,"column":6},"end":{"line":101,"column":null}},"24":{"start":{"line":108,"column":16},"end":{"line":108,"column":null}},"25":{"start":{"line":109,"column":20},"end":{"line":109,"column":null}},"26":{"start":{"line":112,"column":25},"end":{"line":112,"column":null}},"27":{"start":{"line":113,"column":2},"end":{"line":113,"column":null}},"28":{"start":{"line":114,"column":2},"end":{"line":114,"column":null}},"29":{"start":{"line":115,"column":2},"end":{"line":115,"column":null}},"30":{"start":{"line":116,"column":2},"end":{"line":116,"column":null}},"31":{"start":{"line":119,"column":2},"end":{"line":119,"column":null}},"32":{"start":{"line":122,"column":2},"end":{"line":122,"column":null}},"33":{"start":{"line":123,"column":2},"end":{"line":123,"column":null}},"34":{"start":{"line":129,"column":2},"end":{"line":149,"column":null}},"35":{"start":{"line":130,"column":21},"end":{"line":139,"column":null}},"36":{"start":{"line":140,"column":4},"end":{"line":140,"column":null}},"37":{"start":{"line":140,"column":22},"end":{"line":140,"column":null}},"38":{"start":{"line":141,"column":17},"end":{"line":141,"column":null}},"39":{"start":{"line":142,"column":4},"end":{"line":146,"column":null}},"40":{"start":{"line":148,"column":4},"end":{"line":148,"column":null}},"41":{"start":{"line":158,"column":2},"end":{"line":183,"column":null}},"42":{"start":{"line":159,"column":21},"end":{"line":166,"column":null}},"43":{"start":{"line":167,"column":4},"end":{"line":169,"column":null}},"44":{"start":{"line":168,"column":6},"end":{"line":168,"column":null}},"45":{"start":{"line":170,"column":17},"end":{"line":170,"column":null}},"46":{"start":{"line":171,"column":4},"end":{"line":180,"column":null}},"47":{"start":{"line":182,"column":4},"end":{"line":182,"column":null}},"48":{"start":{"line":192,"column":20},"end":{"line":192,"column":null}},"49":{"start":{"line":194,"column":24},"end":{"line":194,"column":null}},"50":{"start":{"line":194,"column":45},"end":{"line":194,"column":71}},"51":{"start":{"line":195,"column":23},"end":{"line":197,"column":null}},"52":{"start":{"line":196,"column":11},"end":{"line":196,"column":null}},"53":{"start":{"line":199,"column":36},"end":{"line":214,"column":null}},"54":{"start":{"line":216,"column":2},"end":{"line":218,"column":null}},"55":{"start":{"line":217,"column":4},"end":{"line":217,"column":null}},"56":{"start":{"line":221,"column":2},"end":{"line":230,"column":null}},"57":{"start":{"line":222,"column":4},"end":{"line":229,"column":null}},"58":{"start":{"line":223,"column":6},"end":{"line":226,"column":null}},"59":{"start":{"line":228,"column":6},"end":{"line":228,"column":null}},"60":{"start":{"line":232,"column":2},"end":{"line":333,"column":null}},"61":{"start":{"line":236,"column":42},"end":{"line":236,"column":null}},"62":{"start":{"line":238,"column":4},"end":{"line":291,"column":null}},"63":{"start":{"line":239,"column":21},"end":{"line":239,"column":null}},"64":{"start":{"line":240,"column":6},"end":{"line":246,"column":null}},"65":{"start":{"line":241,"column":8},"end":{"line":245,"column":null}},"66":{"start":{"line":247,"column":6},"end":{"line":247,"column":null}},"67":{"start":{"line":248,"column":6},"end":{"line":248,"column":null}},"68":{"start":{"line":249,"column":6},"end":{"line":249,"column":null}},"69":{"start":{"line":252,"column":26},"end":{"line":252,"column":null}},"70":{"start":{"line":253,"column":6},"end":{"line":258,"column":null}},"71":{"start":{"line":254,"column":8},"end":{"line":257,"column":null}},"72":{"start":{"line":260,"column":6},"end":{"line":260,"column":null}},"73":{"start":{"line":261,"column":6},"end":{"line":261,"column":null}},"74":{"start":{"line":262,"column":6},"end":{"line":262,"column":null}},"75":{"start":{"line":264,"column":6},"end":{"line":290,"column":null}},"76":{"start":{"line":265,"column":8},"end":{"line":272,"column":null}},"77":{"start":{"line":266,"column":10},"end":{"line":266,"column":null}},"78":{"start":{"line":267,"column":10},"end":{"line":271,"column":null}},"79":{"start":{"line":273,"column":8},"end":{"line":273,"column":null}},"80":{"start":{"line":274,"column":26},"end":{"line":274,"column":null}},"81":{"start":{"line":275,"column":8},"end":{"line":282,"column":null}},"82":{"start":{"line":276,"column":10},"end":{"line":276,"column":null}},"83":{"start":{"line":277,"column":10},"end":{"line":281,"column":null}},"84":{"start":{"line":283,"column":8},"end":{"line":283,"column":null}},"85":{"start":{"line":286,"column":32},"end":{"line":286,"column":null}},"86":{"start":{"line":287,"column":8},"end":{"line":287,"column":null}},"87":{"start":{"line":288,"column":8},"end":{"line":288,"column":null}},"88":{"start":{"line":289,"column":8},"end":{"line":289,"column":null}},"89":{"start":{"line":293,"column":25},"end":{"line":293,"column":null}},"90":{"start":{"line":294,"column":24},"end":{"line":294,"column":null}},"91":{"start":{"line":296,"column":4},"end":{"line":318,"column":null}},"92":{"start":{"line":297,"column":27},"end":{"line":299,"column":null}},"93":{"start":{"line":301,"column":6},"end":{"line":311,"column":null}},"94":{"start":{"line":303,"column":8},"end":{"line":310,"column":null}},"95":{"start":{"line":313,"column":6},"end":{"line":317,"column":null}},"96":{"start":{"line":320,"column":4},"end":{"line":327,"column":null}},"97":{"start":{"line":329,"column":4},"end":{"line":332,"column":null}},"98":{"start":{"line":347,"column":22},"end":{"line":347,"column":null}},"99":{"start":{"line":348,"column":2},"end":{"line":351,"column":null}},"100":{"start":{"line":349,"column":4},"end":{"line":349,"column":null}},"101":{"start":{"line":350,"column":4},"end":{"line":350,"column":null}},"102":{"start":{"line":353,"column":2},"end":{"line":356,"column":null}},"103":{"start":{"line":354,"column":4},"end":{"line":354,"column":null}},"104":{"start":{"line":355,"column":4},"end":{"line":355,"column":null}},"105":{"start":{"line":358,"column":2},"end":{"line":361,"column":null}},"106":{"start":{"line":359,"column":4},"end":{"line":359,"column":null}},"107":{"start":{"line":360,"column":4},"end":{"line":360,"column":null}},"108":{"start":{"line":363,"column":2},"end":{"line":363,"column":null}},"109":{"start":{"line":364,"column":20},"end":{"line":364,"column":null}},"110":{"start":{"line":365,"column":2},"end":{"line":368,"column":null}},"111":{"start":{"line":366,"column":4},"end":{"line":366,"column":null}},"112":{"start":{"line":367,"column":4},"end":{"line":367,"column":null}},"113":{"start":{"line":370,"column":26},"end":{"line":370,"column":null}},"114":{"start":{"line":371,"column":2},"end":{"line":371,"column":null}},"115":{"start":{"line":372,"column":2},"end":{"line":372,"column":null}},"116":{"start":{"line":373,"column":2},"end":{"line":373,"column":null}}},"fnMap":{"0":{"name":"readCredentials","decl":{"start":{"line":60,"column":9},"end":{"line":60,"column":25}},"loc":{"start":{"line":60,"column":69},"end":{"line":78,"column":null}},"line":60},"1":{"name":"isTokenExpired","decl":{"start":{"line":80,"column":9},"end":{"line":80,"column":24}},"loc":{"start":{"line":80,"column":64},"end":{"line":83,"column":null}},"line":80},"2":{"name":"writeCredentials","decl":{"start":{"line":89,"column":9},"end":{"line":89,"column":null}},"loc":{"start":{"line":94,"column":8},"end":{"line":124,"column":null}},"line":94},"3":{"name":"refreshToken","decl":{"start":{"line":126,"column":15},"end":{"line":126,"column":null}},"loc":{"start":{"line":128,"column":84},"end":{"line":150,"column":null}},"line":128},"4":{"name":"fetchUsage","decl":{"start":{"line":157,"column":15},"end":{"line":157,"column":26}},"loc":{"start":{"line":157,"column":74},"end":{"line":184,"column":null}},"line":157},"5":{"name":"checkAccountHealth","decl":{"start":{"line":186,"column":22},"end":{"line":186,"column":null}},"loc":{"start":{"line":191,"column":32},"end":{"line":334,"column":null}},"line":191},"6":{"name":"(anonymous_6)","decl":{"start":{"line":194,"column":38},"end":{"line":194,"column":39}},"loc":{"start":{"line":194,"column":45},"end":{"line":194,"column":71}},"line":194},"7":{"name":"(anonymous_7)","decl":{"start":{"line":196,"column":4},"end":{"line":196,"column":5}},"loc":{"start":{"line":196,"column":11},"end":{"line":196,"column":null}},"line":196},"8":{"name":"ensureAccountCredentials","decl":{"start":{"line":346,"column":22},"end":{"line":346,"column":47}},"loc":{"start":{"line":346,"column":84},"end":{"line":374,"column":null}},"line":346}},"branchMap":{"0":{"loc":{"start":{"line":63,"column":4},"end":{"line":63,"column":null}},"type":"if","locations":[{"start":{"line":63,"column":4},"end":{"line":63,"column":null}},{"start":{},"end":{}}],"line":63},"1":{"loc":{"start":{"line":67,"column":4},"end":{"line":67,"column":null}},"type":"if","locations":[{"start":{"line":67,"column":4},"end":{"line":67,"column":null}},{"start":{},"end":{}}],"line":67},"2":{"loc":{"start":{"line":67,"column":8},"end":{"line":67,"column":38}},"type":"binary-expr","locations":[{"start":{"line":67,"column":8},"end":{"line":67,"column":18}},{"start":{"line":67,"column":18},"end":{"line":67,"column":38}}],"line":67},"3":{"loc":{"start":{"line":70,"column":20},"end":{"line":70,"column":null}},"type":"binary-expr","locations":[{"start":{"line":70,"column":20},"end":{"line":70,"column":42}},{"start":{"line":70,"column":42},"end":{"line":70,"column":null}}],"line":70},"4":{"loc":{"start":{"line":71,"column":17},"end":{"line":71,"column":null}},"type":"binary-expr","locations":[{"start":{"line":71,"column":17},"end":{"line":71,"column":36}},{"start":{"line":71,"column":36},"end":{"line":71,"column":null}}],"line":71},"5":{"loc":{"start":{"line":72,"column":24},"end":{"line":72,"column":null}},"type":"binary-expr","locations":[{"start":{"line":72,"column":24},"end":{"line":72,"column":50}},{"start":{"line":72,"column":50},"end":{"line":72,"column":null}}],"line":72},"6":{"loc":{"start":{"line":73,"column":21},"end":{"line":73,"column":null}},"type":"binary-expr","locations":[{"start":{"line":73,"column":21},"end":{"line":73,"column":44}},{"start":{"line":73,"column":44},"end":{"line":73,"column":null}}],"line":73},"7":{"loc":{"start":{"line":81,"column":2},"end":{"line":81,"column":null}},"type":"if","locations":[{"start":{"line":81,"column":2},"end":{"line":81,"column":null}},{"start":{},"end":{}}],"line":81},"8":{"loc":{"start":{"line":100,"column":4},"end":{"line":102,"column":null}},"type":"if","locations":[{"start":{"line":100,"column":4},"end":{"line":102,"column":null}},{"start":{},"end":{}}],"line":100},"9":{"loc":{"start":{"line":112,"column":25},"end":{"line":112,"column":null}},"type":"binary-expr","locations":[{"start":{"line":112,"column":25},"end":{"line":112,"column":79}},{"start":{"line":112,"column":79},"end":{"line":112,"column":null}}],"line":112},"10":{"loc":{"start":{"line":140,"column":4},"end":{"line":140,"column":null}},"type":"if","locations":[{"start":{"line":140,"column":4},"end":{"line":140,"column":null}},{"start":{},"end":{}}],"line":140},"11":{"loc":{"start":{"line":167,"column":4},"end":{"line":169,"column":null}},"type":"if","locations":[{"start":{"line":167,"column":4},"end":{"line":169,"column":null}},{"start":{},"end":{}}],"line":167},"12":{"loc":{"start":{"line":174,"column":19},"end":{"line":174,"column":null}},"type":"binary-expr","locations":[{"start":{"line":174,"column":19},"end":{"line":174,"column":37}},{"start":{"line":174,"column":37},"end":{"line":174,"column":null}}],"line":174},"13":{"loc":{"start":{"line":175,"column":19},"end":{"line":175,"column":null}},"type":"binary-expr","locations":[{"start":{"line":175,"column":19},"end":{"line":175,"column":37}},{"start":{"line":175,"column":37},"end":{"line":175,"column":null}}],"line":175},"14":{"loc":{"start":{"line":176,"column":26},"end":{"line":176,"column":null}},"type":"binary-expr","locations":[{"start":{"line":176,"column":26},"end":{"line":176,"column":51}},{"start":{"line":176,"column":51},"end":{"line":176,"column":null}}],"line":176},"15":{"loc":{"start":{"line":177,"column":24},"end":{"line":177,"column":null}},"type":"binary-expr","locations":[{"start":{"line":177,"column":24},"end":{"line":177,"column":47}},{"start":{"line":177,"column":47},"end":{"line":177,"column":null}}],"line":177},"16":{"loc":{"start":{"line":178,"column":21},"end":{"line":178,"column":null}},"type":"binary-expr","locations":[{"start":{"line":178,"column":21},"end":{"line":178,"column":41}},{"start":{"line":178,"column":41},"end":{"line":178,"column":null}}],"line":178},"17":{"loc":{"start":{"line":182,"column":47},"end":{"line":182,"column":100}},"type":"cond-expr","locations":[{"start":{"line":182,"column":70},"end":{"line":182,"column":84}},{"start":{"line":182,"column":84},"end":{"line":182,"column":100}}],"line":182},"18":{"loc":{"start":{"line":192,"column":20},"end":{"line":192,"column":null}},"type":"cond-expr","locations":[{"start":{"line":192,"column":20},"end":{"line":192,"column":85}},{"start":{"line":192,"column":85},"end":{"line":192,"column":null}}],"line":192},"19":{"loc":{"start":{"line":196,"column":11},"end":{"line":196,"column":null}},"type":"binary-expr","locations":[{"start":{"line":196,"column":11},"end":{"line":196,"column":37}},{"start":{"line":196,"column":37},"end":{"line":196,"column":null}}],"line":196},"20":{"loc":{"start":{"line":210,"column":20},"end":{"line":210,"column":null}},"type":"binary-expr","locations":[{"start":{"line":210,"column":20},"end":{"line":210,"column":61}},{"start":{"line":210,"column":61},"end":{"line":210,"column":null}}],"line":210},"21":{"loc":{"start":{"line":211,"column":16},"end":{"line":211,"column":null}},"type":"binary-expr","locations":[{"start":{"line":211,"column":16},"end":{"line":211,"column":53}},{"start":{"line":211,"column":53},"end":{"line":211,"column":null}}],"line":211},"22":{"loc":{"start":{"line":216,"column":2},"end":{"line":218,"column":null}},"type":"if","locations":[{"start":{"line":216,"column":2},"end":{"line":218,"column":null}},{"start":{},"end":{}}],"line":216},"23":{"loc":{"start":{"line":221,"column":2},"end":{"line":230,"column":null}},"type":"if","locations":[{"start":{"line":221,"column":2},"end":{"line":230,"column":null}},{"start":{},"end":{}}],"line":221},"24":{"loc":{"start":{"line":221,"column":6},"end":{"line":221,"column":49}},"type":"binary-expr","locations":[{"start":{"line":221,"column":6},"end":{"line":221,"column":28}},{"start":{"line":221,"column":28},"end":{"line":221,"column":49}}],"line":221},"25":{"loc":{"start":{"line":228,"column":45},"end":{"line":228,"column":94}},"type":"cond-expr","locations":[{"start":{"line":228,"column":68},"end":{"line":228,"column":82}},{"start":{"line":228,"column":82},"end":{"line":228,"column":94}}],"line":228},"26":{"loc":{"start":{"line":238,"column":4},"end":{"line":291,"column":null}},"type":"if","locations":[{"start":{"line":238,"column":4},"end":{"line":291,"column":null}},{"start":{"line":250,"column":11},"end":{"line":291,"column":null}}],"line":238},"27":{"loc":{"start":{"line":240,"column":6},"end":{"line":246,"column":null}},"type":"if","locations":[{"start":{"line":240,"column":6},"end":{"line":246,"column":null}},{"start":{},"end":{}}],"line":240},"28":{"loc":{"start":{"line":240,"column":10},"end":{"line":240,"column":48}},"type":"binary-expr","locations":[{"start":{"line":240,"column":10},"end":{"line":240,"column":27}},{"start":{"line":240,"column":27},"end":{"line":240,"column":48}}],"line":240},"29":{"loc":{"start":{"line":244,"column":17},"end":{"line":244,"column":null}},"type":"binary-expr","locations":[{"start":{"line":244,"column":17},"end":{"line":244,"column":33}},{"start":{"line":244,"column":33},"end":{"line":244,"column":null}}],"line":244},"30":{"loc":{"start":{"line":253,"column":6},"end":{"line":258,"column":null}},"type":"if","locations":[{"start":{"line":253,"column":6},"end":{"line":258,"column":null}},{"start":{},"end":{}}],"line":253},"31":{"loc":{"start":{"line":264,"column":6},"end":{"line":290,"column":null}},"type":"if","locations":[{"start":{"line":264,"column":6},"end":{"line":290,"column":null}},{"start":{},"end":{}}],"line":264},"32":{"loc":{"start":{"line":265,"column":8},"end":{"line":272,"column":null}},"type":"if","locations":[{"start":{"line":265,"column":8},"end":{"line":272,"column":null}},{"start":{},"end":{}}],"line":265},"33":{"loc":{"start":{"line":275,"column":8},"end":{"line":282,"column":null}},"type":"if","locations":[{"start":{"line":275,"column":8},"end":{"line":282,"column":null}},{"start":{},"end":{}}],"line":275},"34":{"loc":{"start":{"line":286,"column":32},"end":{"line":286,"column":null}},"type":"binary-expr","locations":[{"start":{"line":286,"column":32},"end":{"line":286,"column":58}},{"start":{"line":286,"column":58},"end":{"line":286,"column":null}}],"line":286},"35":{"loc":{"start":{"line":296,"column":4},"end":{"line":318,"column":null}},"type":"if","locations":[{"start":{"line":296,"column":4},"end":{"line":318,"column":null}},{"start":{},"end":{}}],"line":296},"36":{"loc":{"start":{"line":297,"column":27},"end":{"line":299,"column":null}},"type":"cond-expr","locations":[{"start":{"line":298,"column":10},"end":{"line":298,"column":null}},{"start":{"line":299,"column":10},"end":{"line":299,"column":null}}],"line":297},"37":{"loc":{"start":{"line":301,"column":6},"end":{"line":311,"column":null}},"type":"if","locations":[{"start":{"line":301,"column":6},"end":{"line":311,"column":null}},{"start":{},"end":{}}],"line":301},"38":{"loc":{"start":{"line":324,"column":22},"end":{"line":324,"column":null}},"type":"cond-expr","locations":[{"start":{"line":324,"column":41},"end":{"line":324,"column":84}},{"start":{"line":324,"column":84},"end":{"line":324,"column":null}}],"line":324},"39":{"loc":{"start":{"line":331,"column":13},"end":{"line":331,"column":null}},"type":"cond-expr","locations":[{"start":{"line":331,"column":36},"end":{"line":331,"column":50}},{"start":{"line":331,"column":50},"end":{"line":331,"column":null}}],"line":331},"40":{"loc":{"start":{"line":348,"column":2},"end":{"line":351,"column":null}},"type":"if","locations":[{"start":{"line":348,"column":2},"end":{"line":351,"column":null}},{"start":{},"end":{}}],"line":348},"41":{"loc":{"start":{"line":353,"column":2},"end":{"line":356,"column":null}},"type":"if","locations":[{"start":{"line":353,"column":2},"end":{"line":356,"column":null}},{"start":{},"end":{}}],"line":353},"42":{"loc":{"start":{"line":358,"column":2},"end":{"line":361,"column":null}},"type":"if","locations":[{"start":{"line":358,"column":2},"end":{"line":361,"column":null}},{"start":{},"end":{}}],"line":358},"43":{"loc":{"start":{"line":365,"column":2},"end":{"line":368,"column":null}},"type":"if","locations":[{"start":{"line":365,"column":2},"end":{"line":368,"column":null}},{"start":{},"end":{}}],"line":365},"44":{"loc":{"start":{"line":370,"column":26},"end":{"line":370,"column":null}},"type":"binary-expr","locations":[{"start":{"line":370,"column":26},"end":{"line":370,"column":52}},{"start":{"line":370,"column":52},"end":{"line":370,"column":null}}],"line":370}},"s":{"0":18,"1":18,"2":18,"3":18,"4":18,"5":0,"6":0,"7":0,"8":0,"9":0,"10":0,"11":0,"12":0,"13":0,"14":0,"15":0,"16":0,"17":0,"18":0,"19":0,"20":0,"21":0,"22":0,"23":0,"24":0,"25":0,"26":0,"27":0,"28":0,"29":0,"30":0,"31":0,"32":0,"33":0,"34":0,"35":0,"36":0,"37":0,"38":0,"39":0,"40":0,"41":0,"42":0,"43":0,"44":0,"45":0,"46":0,"47":0,"48":0,"49":0,"50":0,"51":0,"52":0,"53":0,"54":0,"55":0,"56":0,"57":0,"58":0,"59":0,"60":0,"61":0,"62":0,"63":0,"64":0,"65":0,"66":0,"67":0,"68":0,"69":0,"70":0,"71":0,"72":0,"73":0,"74":0,"75":0,"76":0,"77":0,"78":0,"79":0,"80":0,"81":0,"82":0,"83":0,"84":0,"85":0,"86":0,"87":0,"88":0,"89":0,"90":0,"91":0,"92":0,"93":0,"94":0,"95":0,"96":0,"97":0,"98":0,"99":0,"100":0,"101":0,"102":0,"103":0,"104":0,"105":0,"106":0,"107":0,"108":0,"109":0,"110":0,"111":0,"112":0,"113":0,"114":0,"115":0,"116":0},"f":{"0":0,"1":0,"2":0,"3":0,"4":0,"5":0,"6":0,"7":0,"8":0},"b":{"0":[0,0],"1":[0,0],"2":[0,0],"3":[0,0],"4":[0,0],"5":[0,0],"6":[0,0],"7":[0,0],"8":[0,0],"9":[0,0],"10":[0,0],"11":[0,0],"12":[0,0],"13":[0,0],"14":[0,0],"15":[0,0],"16":[0,0],"17":[0,0],"18":[0,0],"19":[0,0],"20":[0,0],"21":[0,0],"22":[0,0],"23":[0,0],"24":[0,0],"25":[0,0],"26":[0,0],"27":[0,0],"28":[0,0],"29":[0,0],"30":[0,0],"31":[0,0],"32":[0,0],"33":[0,0],"34":[0,0],"35":[0,0],"36":[0,0],"37":[0,0],"38":[0,0],"39":[0,0],"40":[0,0],"41":[0,0],"42":[0,0],"43":[0,0],"44":[0,0]},"meta":{"lastBranch":45,"lastFunction":9,"lastStatement":117,"seen":{"s:10:6:10:Infinity":0,"s:12:22:12:Infinity":1,"s:13:26:13:Infinity":2,"s:14:24:14:Infinity":3,"s:15:32:15:Infinity":4,"f:60:9:60:25":0,"s:61:2:77:Infinity":5,"s:62:10:62:Infinity":6,"b:63:4:63:Infinity:undefined:undefined:undefined:undefined":0,"s:63:4:63:Infinity":7,"s:63:31:63:Infinity":8,"s:64:10:64:Infinity":9,"s:65:19:65:Infinity":10,"s:66:18:66:Infinity":11,"b:67:4:67:Infinity:undefined:undefined:undefined:undefined":1,"s:67:4:67:Infinity":12,"b:67:8:67:18:67:18:67:38":2,"s:67:38:67:Infinity":13,"s:68:4:74:Infinity":14,"b:70:20:70:42:70:42:70:Infinity":3,"b:71:17:71:36:71:36:71:Infinity":4,"b:72:24:72:50:72:50:72:Infinity":5,"b:73:21:73:44:73:44:73:Infinity":6,"s:76:4:76:Infinity":15,"f:80:9:80:24":1,"b:81:2:81:Infinity:undefined:undefined:undefined:undefined":7,"s:81:2:81:Infinity":16,"s:81:30:81:Infinity":17,"s:82:2:82:Infinity":18,"f:89:9:89:Infinity":2,"s:95:8:95:Infinity":19,"s:98:42:98:Infinity":20,"s:99:2:105:Infinity":21,"b:100:4:102:Infinity:undefined:undefined:undefined:undefined":8,"s:100:4:102:Infinity":22,"s:101:6:101:Infinity":23,"s:108:16:108:Infinity":24,"s:109:20:109:Infinity":25,"s:112:25:112:Infinity":26,"b:112:25:112:79:112:79:112:Infinity":9,"s:113:2:113:Infinity":27,"s:114:2:114:Infinity":28,"s:115:2:115:Infinity":29,"s:116:2:116:Infinity":30,"s:119:2:119:Infinity":31,"s:122:2:122:Infinity":32,"s:123:2:123:Infinity":33,"f:126:15:126:Infinity":3,"s:129:2:149:Infinity":34,"s:130:21:139:Infinity":35,"b:140:4:140:Infinity:undefined:undefined:undefined:undefined":10,"s:140:4:140:Infinity":36,"s:140:22:140:Infinity":37,"s:141:17:141:Infinity":38,"s:142:4:146:Infinity":39,"s:148:4:148:Infinity":40,"f:157:15:157:26":4,"s:158:2:183:Infinity":41,"s:159:21:166:Infinity":42,"b:167:4:169:Infinity:undefined:undefined:undefined:undefined":11,"s:167:4:169:Infinity":43,"s:168:6:168:Infinity":44,"s:170:17:170:Infinity":45,"s:171:4:180:Infinity":46,"b:174:19:174:37:174:37:174:Infinity":12,"b:175:19:175:37:175:37:175:Infinity":13,"b:176:26:176:51:176:51:176:Infinity":14,"b:177:24:177:47:177:47:177:Infinity":15,"b:178:21:178:41:178:41:178:Infinity":16,"s:182:4:182:Infinity":47,"b:182:70:182:84:182:84:182:100":17,"f:186:22:186:Infinity":5,"s:192:20:192:Infinity":48,"b:192:20:192:85:192:85:192:Infinity":18,"s:194:24:194:Infinity":49,"f:194:38:194:39":6,"s:194:45:194:71":50,"s:195:23:197:Infinity":51,"f:196:4:196:5":7,"s:196:11:196:Infinity":52,"b:196:11:196:37:196:37:196:Infinity":19,"s:199:36:214:Infinity":53,"b:210:20:210:61:210:61:210:Infinity":20,"b:211:16:211:53:211:53:211:Infinity":21,"b:216:2:218:Infinity:undefined:undefined:undefined:undefined":22,"s:216:2:218:Infinity":54,"s:217:4:217:Infinity":55,"b:221:2:230:Infinity:undefined:undefined:undefined:undefined":23,"s:221:2:230:Infinity":56,"b:221:6:221:28:221:28:221:49":24,"s:222:4:229:Infinity":57,"s:223:6:226:Infinity":58,"s:228:6:228:Infinity":59,"b:228:68:228:82:228:82:228:94":25,"s:232:2:333:Infinity":60,"s:236:42:236:Infinity":61,"b:238:4:291:Infinity:250:11:291:Infinity":26,"s:238:4:291:Infinity":62,"s:239:21:239:Infinity":63,"b:240:6:246:Infinity:undefined:undefined:undefined:undefined":27,"s:240:6:246:Infinity":64,"b:240:10:240:27:240:27:240:48":28,"s:241:8:245:Infinity":65,"b:244:17:244:33:244:33:244:Infinity":29,"s:247:6:247:Infinity":66,"s:248:6:248:Infinity":67,"s:249:6:249:Infinity":68,"s:252:26:252:Infinity":69,"b:253:6:258:Infinity:undefined:undefined:undefined:undefined":30,"s:253:6:258:Infinity":70,"s:254:8:257:Infinity":71,"s:260:6:260:Infinity":72,"s:261:6:261:Infinity":73,"s:262:6:262:Infinity":74,"b:264:6:290:Infinity:undefined:undefined:undefined:undefined":31,"s:264:6:290:Infinity":75,"b:265:8:272:Infinity:undefined:undefined:undefined:undefined":32,"s:265:8:272:Infinity":76,"s:266:10:266:Infinity":77,"s:267:10:271:Infinity":78,"s:273:8:273:Infinity":79,"s:274:26:274:Infinity":80,"b:275:8:282:Infinity:undefined:undefined:undefined:undefined":33,"s:275:8:282:Infinity":81,"s:276:10:276:Infinity":82,"s:277:10:281:Infinity":83,"s:283:8:283:Infinity":84,"s:286:32:286:Infinity":85,"b:286:32:286:58:286:58:286:Infinity":34,"s:287:8:287:Infinity":86,"s:288:8:288:Infinity":87,"s:289:8:289:Infinity":88,"s:293:25:293:Infinity":89,"s:294:24:294:Infinity":90,"b:296:4:318:Infinity:undefined:undefined:undefined:undefined":35,"s:296:4:318:Infinity":91,"s:297:27:299:Infinity":92,"b:298:10:298:Infinity:299:10:299:Infinity":36,"b:301:6:311:Infinity:undefined:undefined:undefined:undefined":37,"s:301:6:311:Infinity":93,"s:303:8:310:Infinity":94,"s:313:6:317:Infinity":95,"s:320:4:327:Infinity":96,"b:324:41:324:84:324:84:324:Infinity":38,"s:329:4:332:Infinity":97,"b:331:36:331:50:331:50:331:Infinity":39,"f:346:22:346:47":8,"s:347:22:347:Infinity":98,"b:348:2:351:Infinity:undefined:undefined:undefined:undefined":40,"s:348:2:351:Infinity":99,"s:349:4:349:Infinity":100,"s:350:4:350:Infinity":101,"b:353:2:356:Infinity:undefined:undefined:undefined:undefined":41,"s:353:2:356:Infinity":102,"s:354:4:354:Infinity":103,"s:355:4:355:Infinity":104,"b:358:2:361:Infinity:undefined:undefined:undefined:undefined":42,"s:358:2:361:Infinity":105,"s:359:4:359:Infinity":106,"s:360:4:360:Infinity":107,"s:363:2:363:Infinity":108,"s:364:20:364:Infinity":109,"b:365:2:368:Infinity:undefined:undefined:undefined:undefined":43,"s:365:2:368:Infinity":110,"s:366:4:366:Infinity":111,"s:367:4:367:Infinity":112,"s:370:26:370:Infinity":113,"b:370:26:370:52:370:52:370:Infinity":44,"s:371:2:371:Infinity":114,"s:372:2:372:Infinity":115,"s:373:2:373:Infinity":116}}} +,"/Users/lukasmay/development/projects/codewalk-district/src/agent/credentials/default-credential-manager.ts": {"path":"/Users/lukasmay/development/projects/codewalk-district/src/agent/credentials/default-credential-manager.ts","statementMap":{"0":{"start":{"line":25,"column":6},"end":{"line":25,"column":null}},"1":{"start":{"line":28,"column":26},"end":{"line":28,"column":null}},"2":{"start":{"line":31,"column":24},"end":{"line":31,"column":null}},"3":{"start":{"line":34,"column":32},"end":{"line":34,"column":null}},"4":{"start":{"line":43,"column":22},"end":{"line":43,"column":43}},"5":{"start":{"line":49,"column":4},"end":{"line":68,"column":null}},"6":{"start":{"line":50,"column":12},"end":{"line":50,"column":null}},"7":{"start":{"line":51,"column":6},"end":{"line":51,"column":null}},"8":{"start":{"line":51,"column":33},"end":{"line":51,"column":null}},"9":{"start":{"line":53,"column":12},"end":{"line":53,"column":null}},"10":{"start":{"line":54,"column":21},"end":{"line":54,"column":null}},"11":{"start":{"line":55,"column":20},"end":{"line":55,"column":null}},"12":{"start":{"line":57,"column":6},"end":{"line":57,"column":null}},"13":{"start":{"line":57,"column":40},"end":{"line":57,"column":null}},"14":{"start":{"line":59,"column":6},"end":{"line":65,"column":null}},"15":{"start":{"line":67,"column":6},"end":{"line":67,"column":null}},"16":{"start":{"line":75,"column":4},"end":{"line":75,"column":null}},"17":{"start":{"line":75,"column":32},"end":{"line":75,"column":null}},"18":{"start":{"line":76,"column":4},"end":{"line":76,"column":null}},"19":{"start":{"line":83,"column":4},"end":{"line":109,"column":null}},"20":{"start":{"line":84,"column":23},"end":{"line":93,"column":null}},"21":{"start":{"line":95,"column":6},"end":{"line":98,"column":null}},"22":{"start":{"line":96,"column":8},"end":{"line":96,"column":null}},"23":{"start":{"line":97,"column":8},"end":{"line":97,"column":null}},"24":{"start":{"line":100,"column":19},"end":{"line":100,"column":null}},"25":{"start":{"line":101,"column":6},"end":{"line":105,"column":null}},"26":{"start":{"line":107,"column":6},"end":{"line":107,"column":null}},"27":{"start":{"line":108,"column":6},"end":{"line":108,"column":null}},"28":{"start":{"line":121,"column":10},"end":{"line":121,"column":null}},"29":{"start":{"line":124,"column":44},"end":{"line":124,"column":null}},"30":{"start":{"line":125,"column":4},"end":{"line":131,"column":null}},"31":{"start":{"line":126,"column":6},"end":{"line":128,"column":null}},"32":{"start":{"line":127,"column":8},"end":{"line":127,"column":null}},"33":{"start":{"line":134,"column":18},"end":{"line":134,"column":null}},"34":{"start":{"line":135,"column":22},"end":{"line":135,"column":null}},"35":{"start":{"line":138,"column":27},"end":{"line":138,"column":null}},"36":{"start":{"line":139,"column":4},"end":{"line":139,"column":null}},"37":{"start":{"line":140,"column":4},"end":{"line":140,"column":null}},"38":{"start":{"line":141,"column":4},"end":{"line":141,"column":null}},"39":{"start":{"line":142,"column":4},"end":{"line":142,"column":null}},"40":{"start":{"line":145,"column":4},"end":{"line":145,"column":null}},"41":{"start":{"line":148,"column":4},"end":{"line":148,"column":null}},"42":{"start":{"line":149,"column":4},"end":{"line":149,"column":null}},"43":{"start":{"line":156,"column":24},"end":{"line":156,"column":null}},"44":{"start":{"line":158,"column":4},"end":{"line":167,"column":null}},"45":{"start":{"line":159,"column":6},"end":{"line":159,"column":null}},"46":{"start":{"line":160,"column":6},"end":{"line":160,"column":null}},"47":{"start":{"line":161,"column":6},"end":{"line":166,"column":null}},"48":{"start":{"line":169,"column":4},"end":{"line":178,"column":null}},"49":{"start":{"line":170,"column":6},"end":{"line":170,"column":null}},"50":{"start":{"line":171,"column":6},"end":{"line":171,"column":null}},"51":{"start":{"line":172,"column":6},"end":{"line":177,"column":null}},"52":{"start":{"line":181,"column":4},"end":{"line":190,"column":null}},"53":{"start":{"line":182,"column":6},"end":{"line":182,"column":null}},"54":{"start":{"line":183,"column":6},"end":{"line":183,"column":null}},"55":{"start":{"line":184,"column":6},"end":{"line":189,"column":null}},"56":{"start":{"line":192,"column":4},"end":{"line":192,"column":null}},"57":{"start":{"line":193,"column":30},"end":{"line":193,"column":null}},"58":{"start":{"line":194,"column":22},"end":{"line":194,"column":null}},"59":{"start":{"line":196,"column":4},"end":{"line":205,"column":null}},"60":{"start":{"line":197,"column":6},"end":{"line":197,"column":null}},"61":{"start":{"line":198,"column":6},"end":{"line":198,"column":null}},"62":{"start":{"line":199,"column":6},"end":{"line":204,"column":null}},"63":{"start":{"line":208,"column":28},"end":{"line":208,"column":null}},"64":{"start":{"line":209,"column":4},"end":{"line":209,"column":null}},"65":{"start":{"line":211,"column":25},"end":{"line":211,"column":null}},"66":{"start":{"line":212,"column":4},"end":{"line":212,"column":null}},"67":{"start":{"line":214,"column":4},"end":{"line":214,"column":null}},"68":{"start":{"line":215,"column":4},"end":{"line":215,"column":null}},"69":{"start":{"line":218,"column":31},"end":{"line":218,"column":null}},"70":{"start":{"line":219,"column":4},"end":{"line":224,"column":null}},"71":{"start":{"line":231,"column":24},"end":{"line":231,"column":null}},"72":{"start":{"line":233,"column":4},"end":{"line":241,"column":null}},"73":{"start":{"line":234,"column":6},"end":{"line":234,"column":null}},"74":{"start":{"line":235,"column":6},"end":{"line":240,"column":null}},"75":{"start":{"line":243,"column":20},"end":{"line":243,"column":null}},"76":{"start":{"line":244,"column":4},"end":{"line":244,"column":null}},"77":{"start":{"line":246,"column":4},"end":{"line":253,"column":null}},"78":{"start":{"line":247,"column":6},"end":{"line":252,"column":null}},"79":{"start":{"line":255,"column":4},"end":{"line":260,"column":null}},"80":{"start":{"line":271,"column":4},"end":{"line":271,"column":null}},"81":{"start":{"line":271,"column":24},"end":{"line":271,"column":null}},"82":{"start":{"line":273,"column":52},"end":{"line":281,"column":null}},"83":{"start":{"line":282,"column":4},"end":{"line":282,"column":null}},"84":{"start":{"line":293,"column":4},"end":{"line":293,"column":null}},"85":{"start":{"line":293,"column":24},"end":{"line":293,"column":null}},"86":{"start":{"line":295,"column":50},"end":{"line":303,"column":null}},"87":{"start":{"line":304,"column":4},"end":{"line":304,"column":null}},"88":{"start":{"line":316,"column":4},"end":{"line":316,"column":null}},"89":{"start":{"line":316,"column":24},"end":{"line":316,"column":null}},"90":{"start":{"line":318,"column":52},"end":{"line":327,"column":null}},"91":{"start":{"line":328,"column":4},"end":{"line":328,"column":null}}},"fnMap":{"0":{"name":"(anonymous_0)","decl":{"start":{"line":43,"column":2},"end":{"line":43,"column":22}},"loc":{"start":{"line":43,"column":43},"end":{"line":43,"column":null}},"line":43},"1":{"name":"(anonymous_1)","decl":{"start":{"line":48,"column":2},"end":{"line":48,"column":7}},"loc":{"start":{"line":48,"column":51},"end":{"line":69,"column":null}},"line":48},"2":{"name":"(anonymous_2)","decl":{"start":{"line":74,"column":2},"end":{"line":74,"column":12}},"loc":{"start":{"line":74,"column":52},"end":{"line":77,"column":null}},"line":74},"3":{"name":"(anonymous_3)","decl":{"start":{"line":82,"column":8},"end":{"line":82,"column":16}},"loc":{"start":{"line":82,"column":88},"end":{"line":110,"column":null}},"line":82},"4":{"name":"(anonymous_4)","decl":{"start":{"line":115,"column":2},"end":{"line":115,"column":null}},"loc":{"start":{"line":120,"column":10},"end":{"line":150,"column":null}},"line":120},"5":{"name":"(anonymous_5)","decl":{"start":{"line":155,"column":8},"end":{"line":155,"column":20}},"loc":{"start":{"line":155,"column":96},"end":{"line":225,"column":null}},"line":155},"6":{"name":"(anonymous_6)","decl":{"start":{"line":230,"column":8},"end":{"line":230,"column":17}},"loc":{"start":{"line":230,"column":93},"end":{"line":261,"column":null}},"line":230},"7":{"name":"(anonymous_7)","decl":{"start":{"line":266,"column":10},"end":{"line":266,"column":null}},"loc":{"start":{"line":270,"column":10},"end":{"line":283,"column":null}},"line":270},"8":{"name":"(anonymous_8)","decl":{"start":{"line":288,"column":10},"end":{"line":288,"column":null}},"loc":{"start":{"line":292,"column":10},"end":{"line":305,"column":null}},"line":292},"9":{"name":"(anonymous_9)","decl":{"start":{"line":310,"column":10},"end":{"line":310,"column":null}},"loc":{"start":{"line":315,"column":10},"end":{"line":329,"column":null}},"line":315}},"branchMap":{"0":{"loc":{"start":{"line":51,"column":6},"end":{"line":51,"column":null}},"type":"if","locations":[{"start":{"line":51,"column":6},"end":{"line":51,"column":null}},{"start":{},"end":{}}],"line":51},"1":{"loc":{"start":{"line":57,"column":6},"end":{"line":57,"column":null}},"type":"if","locations":[{"start":{"line":57,"column":6},"end":{"line":57,"column":null}},{"start":{},"end":{}}],"line":57},"2":{"loc":{"start":{"line":57,"column":10},"end":{"line":57,"column":40}},"type":"binary-expr","locations":[{"start":{"line":57,"column":10},"end":{"line":57,"column":20}},{"start":{"line":57,"column":20},"end":{"line":57,"column":40}}],"line":57},"3":{"loc":{"start":{"line":61,"column":22},"end":{"line":61,"column":null}},"type":"binary-expr","locations":[{"start":{"line":61,"column":22},"end":{"line":61,"column":44}},{"start":{"line":61,"column":44},"end":{"line":61,"column":null}}],"line":61},"4":{"loc":{"start":{"line":62,"column":19},"end":{"line":62,"column":null}},"type":"binary-expr","locations":[{"start":{"line":62,"column":19},"end":{"line":62,"column":38}},{"start":{"line":62,"column":38},"end":{"line":62,"column":null}}],"line":62},"5":{"loc":{"start":{"line":63,"column":26},"end":{"line":63,"column":null}},"type":"binary-expr","locations":[{"start":{"line":63,"column":26},"end":{"line":63,"column":52}},{"start":{"line":63,"column":52},"end":{"line":63,"column":null}}],"line":63},"6":{"loc":{"start":{"line":64,"column":23},"end":{"line":64,"column":null}},"type":"binary-expr","locations":[{"start":{"line":64,"column":23},"end":{"line":64,"column":46}},{"start":{"line":64,"column":46},"end":{"line":64,"column":null}}],"line":64},"7":{"loc":{"start":{"line":75,"column":4},"end":{"line":75,"column":null}},"type":"if","locations":[{"start":{"line":75,"column":4},"end":{"line":75,"column":null}},{"start":{},"end":{}}],"line":75},"8":{"loc":{"start":{"line":95,"column":6},"end":{"line":98,"column":null}},"type":"if","locations":[{"start":{"line":95,"column":6},"end":{"line":98,"column":null}},{"start":{},"end":{}}],"line":95},"9":{"loc":{"start":{"line":107,"column":34},"end":{"line":107,"column":83}},"type":"cond-expr","locations":[{"start":{"line":107,"column":57},"end":{"line":107,"column":71}},{"start":{"line":107,"column":71},"end":{"line":107,"column":83}}],"line":107},"10":{"loc":{"start":{"line":126,"column":6},"end":{"line":128,"column":null}},"type":"if","locations":[{"start":{"line":126,"column":6},"end":{"line":128,"column":null}},{"start":{},"end":{}}],"line":126},"11":{"loc":{"start":{"line":138,"column":27},"end":{"line":138,"column":null}},"type":"binary-expr","locations":[{"start":{"line":138,"column":27},"end":{"line":138,"column":81}},{"start":{"line":138,"column":81},"end":{"line":138,"column":null}}],"line":138},"12":{"loc":{"start":{"line":158,"column":4},"end":{"line":167,"column":null}},"type":"if","locations":[{"start":{"line":158,"column":4},"end":{"line":167,"column":null}},{"start":{},"end":{}}],"line":158},"13":{"loc":{"start":{"line":169,"column":4},"end":{"line":178,"column":null}},"type":"if","locations":[{"start":{"line":169,"column":4},"end":{"line":178,"column":null}},{"start":{},"end":{}}],"line":169},"14":{"loc":{"start":{"line":181,"column":4},"end":{"line":190,"column":null}},"type":"if","locations":[{"start":{"line":181,"column":4},"end":{"line":190,"column":null}},{"start":{},"end":{}}],"line":181},"15":{"loc":{"start":{"line":196,"column":4},"end":{"line":205,"column":null}},"type":"if","locations":[{"start":{"line":196,"column":4},"end":{"line":205,"column":null}},{"start":{},"end":{}}],"line":196},"16":{"loc":{"start":{"line":208,"column":28},"end":{"line":208,"column":null}},"type":"binary-expr","locations":[{"start":{"line":208,"column":28},"end":{"line":208,"column":54}},{"start":{"line":208,"column":54},"end":{"line":208,"column":null}}],"line":208},"17":{"loc":{"start":{"line":233,"column":4},"end":{"line":241,"column":null}},"type":"if","locations":[{"start":{"line":233,"column":4},"end":{"line":241,"column":null}},{"start":{},"end":{}}],"line":233},"18":{"loc":{"start":{"line":246,"column":4},"end":{"line":253,"column":null}},"type":"if","locations":[{"start":{"line":246,"column":4},"end":{"line":253,"column":null}},{"start":{},"end":{}}],"line":246},"19":{"loc":{"start":{"line":271,"column":4},"end":{"line":271,"column":null}},"type":"if","locations":[{"start":{"line":271,"column":4},"end":{"line":271,"column":null}},{"start":{},"end":{}}],"line":271},"20":{"loc":{"start":{"line":277,"column":19},"end":{"line":277,"column":null}},"type":"binary-expr","locations":[{"start":{"line":277,"column":19},"end":{"line":277,"column":32}},{"start":{"line":277,"column":32},"end":{"line":277,"column":null}}],"line":277},"21":{"loc":{"start":{"line":293,"column":4},"end":{"line":293,"column":null}},"type":"if","locations":[{"start":{"line":293,"column":4},"end":{"line":293,"column":null}},{"start":{},"end":{}}],"line":293},"22":{"loc":{"start":{"line":299,"column":19},"end":{"line":299,"column":null}},"type":"binary-expr","locations":[{"start":{"line":299,"column":19},"end":{"line":299,"column":32}},{"start":{"line":299,"column":32},"end":{"line":299,"column":null}}],"line":299},"23":{"loc":{"start":{"line":316,"column":4},"end":{"line":316,"column":null}},"type":"if","locations":[{"start":{"line":316,"column":4},"end":{"line":316,"column":null}},{"start":{},"end":{}}],"line":316},"24":{"loc":{"start":{"line":322,"column":19},"end":{"line":322,"column":null}},"type":"binary-expr","locations":[{"start":{"line":322,"column":19},"end":{"line":322,"column":32}},{"start":{"line":322,"column":32},"end":{"line":322,"column":null}}],"line":322}},"s":{"0":8,"1":8,"2":8,"3":8,"4":0,"5":0,"6":0,"7":0,"8":0,"9":0,"10":0,"11":0,"12":0,"13":0,"14":0,"15":0,"16":0,"17":0,"18":0,"19":0,"20":0,"21":0,"22":0,"23":0,"24":0,"25":0,"26":0,"27":0,"28":0,"29":0,"30":0,"31":0,"32":0,"33":0,"34":0,"35":0,"36":0,"37":0,"38":0,"39":0,"40":0,"41":0,"42":0,"43":0,"44":0,"45":0,"46":0,"47":0,"48":0,"49":0,"50":0,"51":0,"52":0,"53":0,"54":0,"55":0,"56":0,"57":0,"58":0,"59":0,"60":0,"61":0,"62":0,"63":0,"64":0,"65":0,"66":0,"67":0,"68":0,"69":0,"70":0,"71":0,"72":0,"73":0,"74":0,"75":0,"76":0,"77":0,"78":0,"79":0,"80":0,"81":0,"82":0,"83":0,"84":0,"85":0,"86":0,"87":0,"88":0,"89":0,"90":0,"91":0},"f":{"0":0,"1":0,"2":0,"3":0,"4":0,"5":0,"6":0,"7":0,"8":0,"9":0},"b":{"0":[0,0],"1":[0,0],"2":[0,0],"3":[0,0],"4":[0,0],"5":[0,0],"6":[0,0],"7":[0,0],"8":[0,0],"9":[0,0],"10":[0,0],"11":[0,0],"12":[0,0],"13":[0,0],"14":[0,0],"15":[0,0],"16":[0,0],"17":[0,0],"18":[0,0],"19":[0,0],"20":[0,0],"21":[0,0],"22":[0,0],"23":[0,0],"24":[0,0]},"meta":{"lastBranch":25,"lastFunction":10,"lastStatement":92,"seen":{"s:25:6:25:Infinity":0,"s:28:26:28:Infinity":1,"s:31:24:31:Infinity":2,"s:34:32:34:Infinity":3,"f:43:2:43:22":0,"s:43:22:43:43":4,"f:48:2:48:7":1,"s:49:4:68:Infinity":5,"s:50:12:50:Infinity":6,"b:51:6:51:Infinity:undefined:undefined:undefined:undefined":0,"s:51:6:51:Infinity":7,"s:51:33:51:Infinity":8,"s:53:12:53:Infinity":9,"s:54:21:54:Infinity":10,"s:55:20:55:Infinity":11,"b:57:6:57:Infinity:undefined:undefined:undefined:undefined":1,"s:57:6:57:Infinity":12,"b:57:10:57:20:57:20:57:40":2,"s:57:40:57:Infinity":13,"s:59:6:65:Infinity":14,"b:61:22:61:44:61:44:61:Infinity":3,"b:62:19:62:38:62:38:62:Infinity":4,"b:63:26:63:52:63:52:63:Infinity":5,"b:64:23:64:46:64:46:64:Infinity":6,"s:67:6:67:Infinity":15,"f:74:2:74:12":2,"b:75:4:75:Infinity:undefined:undefined:undefined:undefined":7,"s:75:4:75:Infinity":16,"s:75:32:75:Infinity":17,"s:76:4:76:Infinity":18,"f:82:8:82:16":3,"s:83:4:109:Infinity":19,"s:84:23:93:Infinity":20,"b:95:6:98:Infinity:undefined:undefined:undefined:undefined":8,"s:95:6:98:Infinity":21,"s:96:8:96:Infinity":22,"s:97:8:97:Infinity":23,"s:100:19:100:Infinity":24,"s:101:6:105:Infinity":25,"s:107:6:107:Infinity":26,"b:107:57:107:71:107:71:107:83":9,"s:108:6:108:Infinity":27,"f:115:2:115:Infinity":4,"s:121:10:121:Infinity":28,"s:124:44:124:Infinity":29,"s:125:4:131:Infinity":30,"b:126:6:128:Infinity:undefined:undefined:undefined:undefined":10,"s:126:6:128:Infinity":31,"s:127:8:127:Infinity":32,"s:134:18:134:Infinity":33,"s:135:22:135:Infinity":34,"s:138:27:138:Infinity":35,"b:138:27:138:81:138:81:138:Infinity":11,"s:139:4:139:Infinity":36,"s:140:4:140:Infinity":37,"s:141:4:141:Infinity":38,"s:142:4:142:Infinity":39,"s:145:4:145:Infinity":40,"s:148:4:148:Infinity":41,"s:149:4:149:Infinity":42,"f:155:8:155:20":5,"s:156:24:156:Infinity":43,"b:158:4:167:Infinity:undefined:undefined:undefined:undefined":12,"s:158:4:167:Infinity":44,"s:159:6:159:Infinity":45,"s:160:6:160:Infinity":46,"s:161:6:166:Infinity":47,"b:169:4:178:Infinity:undefined:undefined:undefined:undefined":13,"s:169:4:178:Infinity":48,"s:170:6:170:Infinity":49,"s:171:6:171:Infinity":50,"s:172:6:177:Infinity":51,"b:181:4:190:Infinity:undefined:undefined:undefined:undefined":14,"s:181:4:190:Infinity":52,"s:182:6:182:Infinity":53,"s:183:6:183:Infinity":54,"s:184:6:189:Infinity":55,"s:192:4:192:Infinity":56,"s:193:30:193:Infinity":57,"s:194:22:194:Infinity":58,"b:196:4:205:Infinity:undefined:undefined:undefined:undefined":15,"s:196:4:205:Infinity":59,"s:197:6:197:Infinity":60,"s:198:6:198:Infinity":61,"s:199:6:204:Infinity":62,"s:208:28:208:Infinity":63,"b:208:28:208:54:208:54:208:Infinity":16,"s:209:4:209:Infinity":64,"s:211:25:211:Infinity":65,"s:212:4:212:Infinity":66,"s:214:4:214:Infinity":67,"s:215:4:215:Infinity":68,"s:218:31:218:Infinity":69,"s:219:4:224:Infinity":70,"f:230:8:230:17":6,"s:231:24:231:Infinity":71,"b:233:4:241:Infinity:undefined:undefined:undefined:undefined":17,"s:233:4:241:Infinity":72,"s:234:6:234:Infinity":73,"s:235:6:240:Infinity":74,"s:243:20:243:Infinity":75,"s:244:4:244:Infinity":76,"b:246:4:253:Infinity:undefined:undefined:undefined:undefined":18,"s:246:4:253:Infinity":77,"s:247:6:252:Infinity":78,"s:255:4:260:Infinity":79,"f:266:10:266:Infinity":7,"b:271:4:271:Infinity:undefined:undefined:undefined:undefined":19,"s:271:4:271:Infinity":80,"s:271:24:271:Infinity":81,"s:273:52:281:Infinity":82,"b:277:19:277:32:277:32:277:Infinity":20,"s:282:4:282:Infinity":83,"f:288:10:288:Infinity":8,"b:293:4:293:Infinity:undefined:undefined:undefined:undefined":21,"s:293:4:293:Infinity":84,"s:293:24:293:Infinity":85,"s:295:50:303:Infinity":86,"b:299:19:299:32:299:32:299:Infinity":22,"s:304:4:304:Infinity":87,"f:310:10:310:Infinity":9,"b:316:4:316:Infinity:undefined:undefined:undefined:undefined":23,"s:316:4:316:Infinity":88,"s:316:24:316:Infinity":89,"s:318:52:327:Infinity":90,"b:322:19:322:32:322:32:322:Infinity":24,"s:328:4:328:Infinity":91}}} +,"/Users/lukasmay/development/projects/codewalk-district/src/agent/credentials/index.ts": {"path":"/Users/lukasmay/development/projects/codewalk-district/src/agent/credentials/index.ts","statementMap":{},"fnMap":{},"branchMap":{},"s":{},"f":{},"b":{},"meta":{"lastBranch":0,"lastFunction":0,"lastStatement":0,"seen":{}}} +,"/Users/lukasmay/development/projects/codewalk-district/src/agent/lifecycle/cleanup-strategy.ts": {"path":"/Users/lukasmay/development/projects/codewalk-district/src/agent/lifecycle/cleanup-strategy.ts","statementMap":{"0":{"start":{"line":11,"column":6},"end":{"line":11,"column":null}},"1":{"start":{"line":29,"column":22},"end":{"line":29,"column":54}},"2":{"start":{"line":36,"column":4},"end":{"line":41,"column":null}},"3":{"start":{"line":44,"column":4},"end":{"line":47,"column":null}},"4":{"start":{"line":45,"column":6},"end":{"line":45,"column":null}},"5":{"start":{"line":46,"column":6},"end":{"line":46,"column":null}},"6":{"start":{"line":50,"column":4},"end":{"line":53,"column":null}},"7":{"start":{"line":51,"column":6},"end":{"line":51,"column":null}},"8":{"start":{"line":52,"column":6},"end":{"line":52,"column":null}},"9":{"start":{"line":56,"column":4},"end":{"line":64,"column":null}},"10":{"start":{"line":57,"column":6},"end":{"line":63,"column":null}},"11":{"start":{"line":58,"column":8},"end":{"line":58,"column":null}},"12":{"start":{"line":59,"column":8},"end":{"line":59,"column":null}},"13":{"start":{"line":61,"column":8},"end":{"line":61,"column":null}},"14":{"start":{"line":62,"column":8},"end":{"line":62,"column":null}},"15":{"start":{"line":67,"column":4},"end":{"line":70,"column":null}},"16":{"start":{"line":68,"column":6},"end":{"line":68,"column":null}},"17":{"start":{"line":69,"column":6},"end":{"line":69,"column":null}},"18":{"start":{"line":73,"column":4},"end":{"line":73,"column":null}},"19":{"start":{"line":74,"column":4},"end":{"line":74,"column":null}},"20":{"start":{"line":81,"column":4},"end":{"line":85,"column":null}},"21":{"start":{"line":87,"column":4},"end":{"line":106,"column":null}},"22":{"start":{"line":89,"column":8},"end":{"line":89,"column":null}},"23":{"start":{"line":90,"column":8},"end":{"line":90,"column":null}},"24":{"start":{"line":91,"column":8},"end":{"line":91,"column":null}},"25":{"start":{"line":92,"column":8},"end":{"line":92,"column":null}},"26":{"start":{"line":93,"column":8},"end":{"line":93,"column":null}},"27":{"start":{"line":96,"column":8},"end":{"line":96,"column":null}},"28":{"start":{"line":97,"column":8},"end":{"line":97,"column":null}},"29":{"start":{"line":98,"column":8},"end":{"line":98,"column":null}},"30":{"start":{"line":101,"column":8},"end":{"line":101,"column":null}},"31":{"start":{"line":102,"column":8},"end":{"line":102,"column":null}},"32":{"start":{"line":105,"column":8},"end":{"line":105,"column":null}}},"fnMap":{"0":{"name":"(anonymous_0)","decl":{"start":{"line":29,"column":2},"end":{"line":29,"column":22}},"loc":{"start":{"line":29,"column":54},"end":{"line":29,"column":null}},"line":29},"1":{"name":"(anonymous_1)","decl":{"start":{"line":35,"column":8},"end":{"line":35,"column":22}},"loc":{"start":{"line":35,"column":86},"end":{"line":75,"column":null}},"line":35},"2":{"name":"(anonymous_2)","decl":{"start":{"line":80,"column":8},"end":{"line":80,"column":23}},"loc":{"start":{"line":80,"column":79},"end":{"line":107,"column":null}},"line":80}},"branchMap":{"0":{"loc":{"start":{"line":44,"column":4},"end":{"line":47,"column":null}},"type":"if","locations":[{"start":{"line":44,"column":4},"end":{"line":47,"column":null}},{"start":{},"end":{}}],"line":44},"1":{"loc":{"start":{"line":50,"column":4},"end":{"line":53,"column":null}},"type":"if","locations":[{"start":{"line":50,"column":4},"end":{"line":53,"column":null}},{"start":{},"end":{}}],"line":50},"2":{"loc":{"start":{"line":56,"column":4},"end":{"line":64,"column":null}},"type":"if","locations":[{"start":{"line":56,"column":4},"end":{"line":64,"column":null}},{"start":{},"end":{}}],"line":56},"3":{"loc":{"start":{"line":56,"column":8},"end":{"line":56,"column":95}},"type":"binary-expr","locations":[{"start":{"line":56,"column":8},"end":{"line":56,"column":35}},{"start":{"line":56,"column":35},"end":{"line":56,"column":67}},{"start":{"line":56,"column":67},"end":{"line":56,"column":95}}],"line":56},"4":{"loc":{"start":{"line":57,"column":6},"end":{"line":63,"column":null}},"type":"if","locations":[{"start":{"line":57,"column":6},"end":{"line":63,"column":null}},{"start":{"line":60,"column":13},"end":{"line":63,"column":null}}],"line":57},"5":{"loc":{"start":{"line":67,"column":4},"end":{"line":70,"column":null}},"type":"if","locations":[{"start":{"line":67,"column":4},"end":{"line":70,"column":null}},{"start":{},"end":{}}],"line":67},"6":{"loc":{"start":{"line":87,"column":4},"end":{"line":106,"column":null}},"type":"switch","locations":[{"start":{"line":88,"column":6},"end":{"line":93,"column":null}},{"start":{"line":95,"column":6},"end":{"line":98,"column":null}},{"start":{"line":100,"column":6},"end":{"line":102,"column":null}},{"start":{"line":104,"column":6},"end":{"line":105,"column":null}}],"line":87},"7":{"loc":{"start":{"line":89,"column":67},"end":{"line":89,"column":93}},"type":"binary-expr","locations":[{"start":{"line":89,"column":67},"end":{"line":89,"column":89}},{"start":{"line":89,"column":89},"end":{"line":89,"column":93}}],"line":89},"8":{"loc":{"start":{"line":90,"column":66},"end":{"line":90,"column":92}},"type":"binary-expr","locations":[{"start":{"line":90,"column":66},"end":{"line":90,"column":88}},{"start":{"line":90,"column":88},"end":{"line":90,"column":92}}],"line":90}},"s":{"0":15,"1":23,"2":0,"3":0,"4":0,"5":0,"6":0,"7":0,"8":0,"9":0,"10":0,"11":0,"12":0,"13":0,"14":0,"15":0,"16":0,"17":0,"18":0,"19":0,"20":0,"21":0,"22":0,"23":0,"24":0,"25":0,"26":0,"27":0,"28":0,"29":0,"30":0,"31":0,"32":0},"f":{"0":23,"1":0,"2":0},"b":{"0":[0,0],"1":[0,0],"2":[0,0],"3":[0,0,0],"4":[0,0],"5":[0,0],"6":[0,0,0,0],"7":[0,0],"8":[0,0]},"meta":{"lastBranch":9,"lastFunction":3,"lastStatement":33,"seen":{"s:11:6:11:Infinity":0,"f:29:2:29:22":0,"s:29:22:29:54":1,"f:35:8:35:22":1,"s:36:4:41:Infinity":2,"b:44:4:47:Infinity:undefined:undefined:undefined:undefined":0,"s:44:4:47:Infinity":3,"s:45:6:45:Infinity":4,"s:46:6:46:Infinity":5,"b:50:4:53:Infinity:undefined:undefined:undefined:undefined":1,"s:50:4:53:Infinity":6,"s:51:6:51:Infinity":7,"s:52:6:52:Infinity":8,"b:56:4:64:Infinity:undefined:undefined:undefined:undefined":2,"s:56:4:64:Infinity":9,"b:56:8:56:35:56:35:56:67:56:67:56:95":3,"b:57:6:63:Infinity:60:13:63:Infinity":4,"s:57:6:63:Infinity":10,"s:58:8:58:Infinity":11,"s:59:8:59:Infinity":12,"s:61:8:61:Infinity":13,"s:62:8:62:Infinity":14,"b:67:4:70:Infinity:undefined:undefined:undefined:undefined":5,"s:67:4:70:Infinity":15,"s:68:6:68:Infinity":16,"s:69:6:69:Infinity":17,"s:73:4:73:Infinity":18,"s:74:4:74:Infinity":19,"f:80:8:80:23":2,"s:81:4:85:Infinity":20,"b:88:6:93:Infinity:95:6:98:Infinity:100:6:102:Infinity:104:6:105:Infinity":6,"s:87:4:106:Infinity":21,"s:89:8:89:Infinity":22,"b:89:67:89:89:89:89:89:93":7,"s:90:8:90:Infinity":23,"b:90:66:90:88:90:88:90:92":8,"s:91:8:91:Infinity":24,"s:92:8:92:Infinity":25,"s:93:8:93:Infinity":26,"s:96:8:96:Infinity":27,"s:97:8:97:Infinity":28,"s:98:8:98:Infinity":29,"s:101:8:101:Infinity":30,"s:102:8:102:Infinity":31,"s:105:8:105:Infinity":32}}} +,"/Users/lukasmay/development/projects/codewalk-district/src/agent/lifecycle/controller.ts": {"path":"/Users/lukasmay/development/projects/codewalk-district/src/agent/lifecycle/controller.ts","statementMap":{"0":{"start":{"line":25,"column":6},"end":{"line":25,"column":null}},"1":{"start":{"line":42,"column":12},"end":{"line":42,"column":null}},"2":{"start":{"line":43,"column":12},"end":{"line":43,"column":null}},"3":{"start":{"line":44,"column":12},"end":{"line":44,"column":null}},"4":{"start":{"line":45,"column":12},"end":{"line":45,"column":null}},"5":{"start":{"line":46,"column":12},"end":{"line":46,"column":null}},"6":{"start":{"line":47,"column":12},"end":{"line":47,"column":null}},"7":{"start":{"line":48,"column":12},"end":{"line":48,"column":null}},"8":{"start":{"line":49,"column":12},"end":{"line":49,"column":null}},"9":{"start":{"line":50,"column":12},"end":{"line":50,"column":29}},"10":{"start":{"line":61,"column":4},"end":{"line":66,"column":null}},"11":{"start":{"line":68,"column":4},"end":{"line":68,"column":null}},"12":{"start":{"line":79,"column":4},"end":{"line":82,"column":null}},"13":{"start":{"line":84,"column":4},"end":{"line":89,"column":null}},"14":{"start":{"line":85,"column":6},"end":{"line":85,"column":null}},"15":{"start":{"line":86,"column":20},"end":{"line":86,"column":null}},"16":{"start":{"line":87,"column":6},"end":{"line":87,"column":null}},"17":{"start":{"line":87,"column":18},"end":{"line":87,"column":null}},"18":{"start":{"line":88,"column":6},"end":{"line":88,"column":null}},"19":{"start":{"line":101,"column":4},"end":{"line":199,"column":null}},"20":{"start":{"line":101,"column":23},"end":{"line":101,"column":26}},"21":{"start":{"line":102,"column":6},"end":{"line":198,"column":null}},"22":{"start":{"line":103,"column":8},"end":{"line":103,"column":null}},"23":{"start":{"line":106,"column":22},"end":{"line":106,"column":null}},"24":{"start":{"line":107,"column":29},"end":{"line":107,"column":null}},"25":{"start":{"line":110,"column":8},"end":{"line":110,"column":null}},"26":{"start":{"line":111,"column":8},"end":{"line":111,"column":null}},"27":{"start":{"line":114,"column":23},"end":{"line":114,"column":null}},"28":{"start":{"line":116,"column":8},"end":{"line":126,"column":null}},"29":{"start":{"line":118,"column":10},"end":{"line":118,"column":null}},"30":{"start":{"line":119,"column":10},"end":{"line":124,"column":null}},"31":{"start":{"line":125,"column":10},"end":{"line":125,"column":null}},"32":{"start":{"line":129,"column":27},"end":{"line":134,"column":null}},"33":{"start":{"line":137,"column":8},"end":{"line":139,"column":null}},"34":{"start":{"line":138,"column":10},"end":{"line":138,"column":null}},"35":{"start":{"line":142,"column":8},"end":{"line":145,"column":null}},"36":{"start":{"line":143,"column":10},"end":{"line":143,"column":null}},"37":{"start":{"line":144,"column":10},"end":{"line":144,"column":null}},"38":{"start":{"line":148,"column":8},"end":{"line":156,"column":null}},"39":{"start":{"line":149,"column":10},"end":{"line":154,"column":null}},"40":{"start":{"line":155,"column":10},"end":{"line":155,"column":null}},"41":{"start":{"line":159,"column":8},"end":{"line":166,"column":null}},"42":{"start":{"line":162,"column":10},"end":{"line":165,"column":null}},"43":{"start":{"line":169,"column":22},"end":{"line":169,"column":null}},"44":{"start":{"line":170,"column":8},"end":{"line":176,"column":null}},"45":{"start":{"line":177,"column":8},"end":{"line":177,"column":null}},"46":{"start":{"line":180,"column":8},"end":{"line":182,"column":null}},"47":{"start":{"line":181,"column":10},"end":{"line":181,"column":null}},"48":{"start":{"line":184,"column":8},"end":{"line":191,"column":null}},"49":{"start":{"line":185,"column":10},"end":{"line":189,"column":null}},"50":{"start":{"line":190,"column":10},"end":{"line":190,"column":null}},"51":{"start":{"line":193,"column":8},"end":{"line":197,"column":null}},"52":{"start":{"line":201,"column":4},"end":{"line":201,"column":null}},"53":{"start":{"line":209,"column":25},"end":{"line":209,"column":null}},"54":{"start":{"line":211,"column":4},"end":{"line":215,"column":null}},"55":{"start":{"line":222,"column":19},"end":{"line":222,"column":null}},"56":{"start":{"line":224,"column":4},"end":{"line":230,"column":null}},"57":{"start":{"line":225,"column":6},"end":{"line":228,"column":null}},"58":{"start":{"line":229,"column":6},"end":{"line":229,"column":null}},"59":{"start":{"line":233,"column":4},"end":{"line":236,"column":null}},"60":{"start":{"line":238,"column":4},"end":{"line":242,"column":null}},"61":{"start":{"line":250,"column":4},"end":{"line":253,"column":null}},"62":{"start":{"line":251,"column":6},"end":{"line":251,"column":null}},"63":{"start":{"line":252,"column":6},"end":{"line":252,"column":null}},"64":{"start":{"line":255,"column":4},"end":{"line":269,"column":null}},"65":{"start":{"line":256,"column":28},"end":{"line":256,"column":null}},"66":{"start":{"line":257,"column":6},"end":{"line":257,"column":null}},"67":{"start":{"line":259,"column":6},"end":{"line":263,"column":null}},"68":{"start":{"line":265,"column":6},"end":{"line":268,"column":null}},"69":{"start":{"line":276,"column":4},"end":{"line":303,"column":null}},"70":{"start":{"line":277,"column":24},"end":{"line":284,"column":null}},"71":{"start":{"line":288,"column":6},"end":{"line":291,"column":null}},"72":{"start":{"line":293,"column":6},"end":{"line":297,"column":null}},"73":{"start":{"line":299,"column":6},"end":{"line":302,"column":null}},"74":{"start":{"line":310,"column":4},"end":{"line":313,"column":null}},"75":{"start":{"line":311,"column":6},"end":{"line":311,"column":null}},"76":{"start":{"line":312,"column":6},"end":{"line":312,"column":null}},"77":{"start":{"line":315,"column":4},"end":{"line":336,"column":null}},"78":{"start":{"line":316,"column":20},"end":{"line":316,"column":null}},"79":{"start":{"line":317,"column":6},"end":{"line":320,"column":null}},"80":{"start":{"line":318,"column":8},"end":{"line":318,"column":null}},"81":{"start":{"line":319,"column":8},"end":{"line":319,"column":null}},"82":{"start":{"line":323,"column":29},"end":{"line":323,"column":null}},"83":{"start":{"line":324,"column":6},"end":{"line":324,"column":null}},"84":{"start":{"line":326,"column":6},"end":{"line":330,"column":null}},"85":{"start":{"line":332,"column":6},"end":{"line":335,"column":null}},"86":{"start":{"line":343,"column":4},"end":{"line":343,"column":null}},"87":{"start":{"line":343,"column":34},"end":{"line":343,"column":57}},"88":{"start":{"line":350,"column":4},"end":{"line":356,"column":null}}},"fnMap":{"0":{"name":"(anonymous_0)","decl":{"start":{"line":41,"column":2},"end":{"line":41,"column":null}},"loc":{"start":{"line":51,"column":4},"end":{"line":51,"column":null}},"line":51},"1":{"name":"(anonymous_1)","decl":{"start":{"line":57,"column":8},"end":{"line":57,"column":null}},"loc":{"start":{"line":60,"column":24},"end":{"line":69,"column":null}},"line":60},"2":{"name":"(anonymous_2)","decl":{"start":{"line":75,"column":8},"end":{"line":75,"column":null}},"loc":{"start":{"line":78,"column":19},"end":{"line":90,"column":null}},"line":78},"3":{"name":"(anonymous_3)","decl":{"start":{"line":84,"column":42},"end":{"line":84,"column":54}},"loc":{"start":{"line":84,"column":54},"end":{"line":89,"column":7}},"line":84},"4":{"name":"(anonymous_4)","decl":{"start":{"line":95,"column":16},"end":{"line":95,"column":null}},"loc":{"start":{"line":99,"column":24},"end":{"line":202,"column":null}},"line":99},"5":{"name":"(anonymous_5)","decl":{"start":{"line":208,"column":16},"end":{"line":208,"column":34}},"loc":{"start":{"line":208,"column":79},"end":{"line":243,"column":null}},"line":208},"6":{"name":"(anonymous_6)","decl":{"start":{"line":248,"column":16},"end":{"line":248,"column":37}},"loc":{"start":{"line":248,"column":70},"end":{"line":270,"column":null}},"line":248},"7":{"name":"(anonymous_7)","decl":{"start":{"line":275,"column":16},"end":{"line":275,"column":29}},"loc":{"start":{"line":275,"column":80},"end":{"line":304,"column":null}},"line":275},"8":{"name":"(anonymous_8)","decl":{"start":{"line":309,"column":16},"end":{"line":309,"column":40}},"loc":{"start":{"line":309,"column":72},"end":{"line":337,"column":null}},"line":309},"9":{"name":"(anonymous_9)","decl":{"start":{"line":342,"column":10},"end":{"line":342,"column":16}},"loc":{"start":{"line":342,"column":43},"end":{"line":344,"column":null}},"line":342},"10":{"name":"(anonymous_10)","decl":{"start":{"line":343,"column":23},"end":{"line":343,"column":34}},"loc":{"start":{"line":343,"column":34},"end":{"line":343,"column":57}},"line":343},"11":{"name":"(anonymous_11)","decl":{"start":{"line":349,"column":10},"end":{"line":349,"column":22}},"loc":{"start":{"line":349,"column":45},"end":{"line":357,"column":null}},"line":349}},"branchMap":{"0":{"loc":{"start":{"line":50,"column":12},"end":{"line":50,"column":null}},"type":"default-arg","locations":[{"start":{"line":50,"column":29},"end":{"line":50,"column":null}}],"line":50},"1":{"loc":{"start":{"line":87,"column":6},"end":{"line":87,"column":null}},"type":"if","locations":[{"start":{"line":87,"column":6},"end":{"line":87,"column":null}},{"start":{},"end":{}}],"line":87},"2":{"loc":{"start":{"line":116,"column":8},"end":{"line":126,"column":null}},"type":"if","locations":[{"start":{"line":116,"column":8},"end":{"line":126,"column":null}},{"start":{},"end":{}}],"line":116},"3":{"loc":{"start":{"line":130,"column":10},"end":{"line":130,"column":null}},"type":"binary-expr","locations":[{"start":{"line":130,"column":10},"end":{"line":130,"column":26}},{"start":{"line":130,"column":26},"end":{"line":130,"column":null}}],"line":130},"4":{"loc":{"start":{"line":137,"column":8},"end":{"line":139,"column":null}},"type":"if","locations":[{"start":{"line":137,"column":8},"end":{"line":139,"column":null}},{"start":{},"end":{}}],"line":137},"5":{"loc":{"start":{"line":142,"column":8},"end":{"line":145,"column":null}},"type":"if","locations":[{"start":{"line":142,"column":8},"end":{"line":145,"column":null}},{"start":{},"end":{}}],"line":142},"6":{"loc":{"start":{"line":148,"column":8},"end":{"line":156,"column":null}},"type":"if","locations":[{"start":{"line":148,"column":8},"end":{"line":156,"column":null}},{"start":{},"end":{}}],"line":148},"7":{"loc":{"start":{"line":159,"column":8},"end":{"line":166,"column":null}},"type":"if","locations":[{"start":{"line":159,"column":8},"end":{"line":166,"column":null}},{"start":{},"end":{}}],"line":159},"8":{"loc":{"start":{"line":180,"column":8},"end":{"line":182,"column":null}},"type":"if","locations":[{"start":{"line":180,"column":8},"end":{"line":182,"column":null}},{"start":{},"end":{}}],"line":180},"9":{"loc":{"start":{"line":180,"column":12},"end":{"line":180,"column":88}},"type":"binary-expr","locations":[{"start":{"line":180,"column":12},"end":{"line":180,"column":52}},{"start":{"line":180,"column":52},"end":{"line":180,"column":88}}],"line":180},"10":{"loc":{"start":{"line":184,"column":8},"end":{"line":191,"column":null}},"type":"if","locations":[{"start":{"line":184,"column":8},"end":{"line":191,"column":null}},{"start":{},"end":{}}],"line":184},"11":{"loc":{"start":{"line":188,"column":19},"end":{"line":188,"column":null}},"type":"cond-expr","locations":[{"start":{"line":188,"column":44},"end":{"line":188,"column":60}},{"start":{"line":188,"column":60},"end":{"line":188,"column":null}}],"line":188},"12":{"loc":{"start":{"line":196,"column":17},"end":{"line":196,"column":null}},"type":"cond-expr","locations":[{"start":{"line":196,"column":42},"end":{"line":196,"column":58}},{"start":{"line":196,"column":58},"end":{"line":196,"column":null}}],"line":196},"13":{"loc":{"start":{"line":224,"column":4},"end":{"line":230,"column":null}},"type":"if","locations":[{"start":{"line":224,"column":4},"end":{"line":230,"column":null}},{"start":{},"end":{}}],"line":224},"14":{"loc":{"start":{"line":250,"column":4},"end":{"line":253,"column":null}},"type":"if","locations":[{"start":{"line":250,"column":4},"end":{"line":253,"column":null}},{"start":{},"end":{}}],"line":250},"15":{"loc":{"start":{"line":267,"column":15},"end":{"line":267,"column":null}},"type":"cond-expr","locations":[{"start":{"line":267,"column":40},"end":{"line":267,"column":56}},{"start":{"line":267,"column":56},"end":{"line":267,"column":null}}],"line":267},"16":{"loc":{"start":{"line":301,"column":15},"end":{"line":301,"column":null}},"type":"cond-expr","locations":[{"start":{"line":301,"column":42},"end":{"line":301,"column":60}},{"start":{"line":301,"column":60},"end":{"line":301,"column":null}}],"line":301},"17":{"loc":{"start":{"line":310,"column":4},"end":{"line":313,"column":null}},"type":"if","locations":[{"start":{"line":310,"column":4},"end":{"line":313,"column":null}},{"start":{},"end":{}}],"line":310},"18":{"loc":{"start":{"line":317,"column":6},"end":{"line":320,"column":null}},"type":"if","locations":[{"start":{"line":317,"column":6},"end":{"line":320,"column":null}},{"start":{},"end":{}}],"line":317},"19":{"loc":{"start":{"line":334,"column":15},"end":{"line":334,"column":null}},"type":"cond-expr","locations":[{"start":{"line":334,"column":40},"end":{"line":334,"column":56}},{"start":{"line":334,"column":56},"end":{"line":334,"column":null}}],"line":334}},"s":{"0":15,"1":23,"2":23,"3":23,"4":23,"5":23,"6":23,"7":23,"8":23,"9":23,"10":0,"11":0,"12":0,"13":0,"14":0,"15":0,"16":0,"17":0,"18":0,"19":0,"20":0,"21":0,"22":0,"23":0,"24":0,"25":0,"26":0,"27":0,"28":0,"29":0,"30":0,"31":0,"32":0,"33":0,"34":0,"35":0,"36":0,"37":0,"38":0,"39":0,"40":0,"41":0,"42":0,"43":0,"44":0,"45":0,"46":0,"47":0,"48":0,"49":0,"50":0,"51":0,"52":0,"53":0,"54":0,"55":0,"56":0,"57":0,"58":0,"59":0,"60":0,"61":0,"62":0,"63":0,"64":0,"65":0,"66":0,"67":0,"68":0,"69":0,"70":0,"71":0,"72":0,"73":0,"74":0,"75":0,"76":0,"77":0,"78":0,"79":0,"80":0,"81":0,"82":0,"83":0,"84":0,"85":0,"86":0,"87":0,"88":0},"f":{"0":23,"1":0,"2":0,"3":0,"4":0,"5":0,"6":0,"7":0,"8":0,"9":0,"10":0,"11":0},"b":{"0":[23],"1":[0,0],"2":[0,0],"3":[0,0],"4":[0,0],"5":[0,0],"6":[0,0],"7":[0,0],"8":[0,0],"9":[0,0],"10":[0,0],"11":[0,0],"12":[0,0],"13":[0,0],"14":[0,0],"15":[0,0],"16":[0,0],"17":[0,0],"18":[0,0],"19":[0,0]},"meta":{"lastBranch":20,"lastFunction":12,"lastStatement":89,"seen":{"s:25:6:25:Infinity":0,"f:41:2:41:Infinity":0,"b:50:29:50:Infinity":0,"s:42:12:42:Infinity":1,"s:43:12:43:Infinity":2,"s:44:12:44:Infinity":3,"s:45:12:45:Infinity":4,"s:46:12:46:Infinity":5,"s:47:12:47:Infinity":6,"s:48:12:48:Infinity":7,"s:49:12:49:Infinity":8,"s:50:12:50:29":9,"f:57:8:57:Infinity":1,"s:61:4:66:Infinity":10,"s:68:4:68:Infinity":11,"f:75:8:75:Infinity":2,"s:79:4:82:Infinity":12,"s:84:4:89:Infinity":13,"f:84:42:84:54":3,"s:85:6:85:Infinity":14,"s:86:20:86:Infinity":15,"b:87:6:87:Infinity:undefined:undefined:undefined:undefined":1,"s:87:6:87:Infinity":16,"s:87:18:87:Infinity":17,"s:88:6:88:Infinity":18,"f:95:16:95:Infinity":4,"s:101:4:199:Infinity":19,"s:101:23:101:26":20,"s:102:6:198:Infinity":21,"s:103:8:103:Infinity":22,"s:106:22:106:Infinity":23,"s:107:29:107:Infinity":24,"s:110:8:110:Infinity":25,"s:111:8:111:Infinity":26,"s:114:23:114:Infinity":27,"b:116:8:126:Infinity:undefined:undefined:undefined:undefined":2,"s:116:8:126:Infinity":28,"s:118:10:118:Infinity":29,"s:119:10:124:Infinity":30,"s:125:10:125:Infinity":31,"s:129:27:134:Infinity":32,"b:130:10:130:26:130:26:130:Infinity":3,"b:137:8:139:Infinity:undefined:undefined:undefined:undefined":4,"s:137:8:139:Infinity":33,"s:138:10:138:Infinity":34,"b:142:8:145:Infinity:undefined:undefined:undefined:undefined":5,"s:142:8:145:Infinity":35,"s:143:10:143:Infinity":36,"s:144:10:144:Infinity":37,"b:148:8:156:Infinity:undefined:undefined:undefined:undefined":6,"s:148:8:156:Infinity":38,"s:149:10:154:Infinity":39,"s:155:10:155:Infinity":40,"b:159:8:166:Infinity:undefined:undefined:undefined:undefined":7,"s:159:8:166:Infinity":41,"s:162:10:165:Infinity":42,"s:169:22:169:Infinity":43,"s:170:8:176:Infinity":44,"s:177:8:177:Infinity":45,"b:180:8:182:Infinity:undefined:undefined:undefined:undefined":8,"s:180:8:182:Infinity":46,"b:180:12:180:52:180:52:180:88":9,"s:181:10:181:Infinity":47,"b:184:8:191:Infinity:undefined:undefined:undefined:undefined":10,"s:184:8:191:Infinity":48,"s:185:10:189:Infinity":49,"b:188:44:188:60:188:60:188:Infinity":11,"s:190:10:190:Infinity":50,"s:193:8:197:Infinity":51,"b:196:42:196:58:196:58:196:Infinity":12,"s:201:4:201:Infinity":52,"f:208:16:208:34":5,"s:209:25:209:Infinity":53,"s:211:4:215:Infinity":54,"s:222:19:222:Infinity":55,"b:224:4:230:Infinity:undefined:undefined:undefined:undefined":13,"s:224:4:230:Infinity":56,"s:225:6:228:Infinity":57,"s:229:6:229:Infinity":58,"s:233:4:236:Infinity":59,"s:238:4:242:Infinity":60,"f:248:16:248:37":6,"b:250:4:253:Infinity:undefined:undefined:undefined:undefined":14,"s:250:4:253:Infinity":61,"s:251:6:251:Infinity":62,"s:252:6:252:Infinity":63,"s:255:4:269:Infinity":64,"s:256:28:256:Infinity":65,"s:257:6:257:Infinity":66,"s:259:6:263:Infinity":67,"s:265:6:268:Infinity":68,"b:267:40:267:56:267:56:267:Infinity":15,"f:275:16:275:29":7,"s:276:4:303:Infinity":69,"s:277:24:284:Infinity":70,"s:288:6:291:Infinity":71,"s:293:6:297:Infinity":72,"s:299:6:302:Infinity":73,"b:301:42:301:60:301:60:301:Infinity":16,"f:309:16:309:40":8,"b:310:4:313:Infinity:undefined:undefined:undefined:undefined":17,"s:310:4:313:Infinity":74,"s:311:6:311:Infinity":75,"s:312:6:312:Infinity":76,"s:315:4:336:Infinity":77,"s:316:20:316:Infinity":78,"b:317:6:320:Infinity:undefined:undefined:undefined:undefined":18,"s:317:6:320:Infinity":79,"s:318:8:318:Infinity":80,"s:319:8:319:Infinity":81,"s:323:29:323:Infinity":82,"s:324:6:324:Infinity":83,"s:326:6:330:Infinity":84,"s:332:6:335:Infinity":85,"b:334:40:334:56:334:56:334:Infinity":19,"f:342:10:342:16":9,"s:343:4:343:Infinity":86,"f:343:23:343:34":10,"s:343:34:343:57":87,"f:349:10:349:22":11,"s:350:4:356:Infinity":88}}} +,"/Users/lukasmay/development/projects/codewalk-district/src/agent/lifecycle/error-analyzer.ts": {"path":"/Users/lukasmay/development/projects/codewalk-district/src/agent/lifecycle/error-analyzer.ts","statementMap":{"0":{"start":{"line":13,"column":6},"end":{"line":13,"column":null}},"1":{"start":{"line":16,"column":23},"end":{"line":50,"column":null}},"2":{"start":{"line":53,"column":22},"end":{"line":53,"column":52}},"3":{"start":{"line":65,"column":25},"end":{"line":65,"column":null}},"4":{"start":{"line":66,"column":24},"end":{"line":66,"column":null}},"5":{"start":{"line":68,"column":4},"end":{"line":73,"column":null}},"6":{"start":{"line":76,"column":4},"end":{"line":86,"column":null}},"7":{"start":{"line":77,"column":6},"end":{"line":85,"column":null}},"8":{"start":{"line":89,"column":4},"end":{"line":99,"column":null}},"9":{"start":{"line":90,"column":6},"end":{"line":98,"column":null}},"10":{"start":{"line":102,"column":4},"end":{"line":112,"column":null}},"11":{"start":{"line":103,"column":6},"end":{"line":111,"column":null}},"12":{"start":{"line":115,"column":4},"end":{"line":129,"column":null}},"13":{"start":{"line":116,"column":24},"end":{"line":116,"column":null}},"14":{"start":{"line":117,"column":6},"end":{"line":128,"column":null}},"15":{"start":{"line":118,"column":8},"end":{"line":118,"column":null}},"16":{"start":{"line":119,"column":8},"end":{"line":127,"column":null}},"17":{"start":{"line":132,"column":4},"end":{"line":147,"column":null}},"18":{"start":{"line":136,"column":26},"end":{"line":136,"column":null}},"19":{"start":{"line":138,"column":6},"end":{"line":146,"column":null}},"20":{"start":{"line":150,"column":4},"end":{"line":154,"column":null}},"21":{"start":{"line":156,"column":4},"end":{"line":164,"column":null}},"22":{"start":{"line":175,"column":4},"end":{"line":175,"column":null}},"23":{"start":{"line":176,"column":4},"end":{"line":176,"column":null}},"24":{"start":{"line":183,"column":4},"end":{"line":183,"column":null}},"25":{"start":{"line":183,"column":15},"end":{"line":183,"column":null}},"26":{"start":{"line":184,"column":4},"end":{"line":184,"column":null}},"27":{"start":{"line":184,"column":36},"end":{"line":184,"column":54}},"28":{"start":{"line":193,"column":31},"end":{"line":198,"column":null}},"29":{"start":{"line":200,"column":4},"end":{"line":211,"column":null}},"30":{"start":{"line":201,"column":6},"end":{"line":204,"column":null}},"31":{"start":{"line":202,"column":8},"end":{"line":202,"column":null}},"32":{"start":{"line":203,"column":8},"end":{"line":203,"column":null}},"33":{"start":{"line":207,"column":6},"end":{"line":210,"column":null}},"34":{"start":{"line":208,"column":8},"end":{"line":208,"column":null}},"35":{"start":{"line":209,"column":8},"end":{"line":209,"column":null}},"36":{"start":{"line":214,"column":4},"end":{"line":228,"column":null}},"37":{"start":{"line":215,"column":32},"end":{"line":222,"column":null}},"38":{"start":{"line":224,"column":6},"end":{"line":227,"column":null}},"39":{"start":{"line":224,"column":44},"end":{"line":224,"column":64}},"40":{"start":{"line":225,"column":8},"end":{"line":225,"column":null}},"41":{"start":{"line":226,"column":8},"end":{"line":226,"column":null}},"42":{"start":{"line":230,"column":4},"end":{"line":230,"column":null}},"43":{"start":{"line":231,"column":4},"end":{"line":231,"column":null}}},"fnMap":{"0":{"name":"(anonymous_0)","decl":{"start":{"line":53,"column":2},"end":{"line":53,"column":22}},"loc":{"start":{"line":53,"column":52},"end":{"line":53,"column":null}},"line":53},"1":{"name":"(anonymous_1)","decl":{"start":{"line":59,"column":8},"end":{"line":59,"column":null}},"loc":{"start":{"line":64,"column":25},"end":{"line":165,"column":null}},"line":64},"2":{"name":"(anonymous_2)","decl":{"start":{"line":171,"column":8},"end":{"line":171,"column":40}},"loc":{"start":{"line":171,"column":77},"end":{"line":177,"column":null}},"line":171},"3":{"name":"(anonymous_3)","decl":{"start":{"line":182,"column":10},"end":{"line":182,"column":25}},"loc":{"start":{"line":182,"column":68},"end":{"line":185,"column":null}},"line":182},"4":{"name":"(anonymous_4)","decl":{"start":{"line":184,"column":25},"end":{"line":184,"column":36}},"loc":{"start":{"line":184,"column":36},"end":{"line":184,"column":54}},"line":184},"5":{"name":"(anonymous_5)","decl":{"start":{"line":191,"column":10},"end":{"line":191,"column":27}},"loc":{"start":{"line":191,"column":79},"end":{"line":232,"column":null}},"line":191},"6":{"name":"(anonymous_6)","decl":{"start":{"line":224,"column":33},"end":{"line":224,"column":44}},"loc":{"start":{"line":224,"column":44},"end":{"line":224,"column":64}},"line":224}},"branchMap":{"0":{"loc":{"start":{"line":65,"column":25},"end":{"line":65,"column":null}},"type":"cond-expr","locations":[{"start":{"line":65,"column":50},"end":{"line":65,"column":66}},{"start":{"line":65,"column":66},"end":{"line":65,"column":null}}],"line":65},"1":{"loc":{"start":{"line":76,"column":4},"end":{"line":86,"column":null}},"type":"if","locations":[{"start":{"line":76,"column":4},"end":{"line":86,"column":null}},{"start":{},"end":{}}],"line":76},"2":{"loc":{"start":{"line":84,"column":23},"end":{"line":84,"column":null}},"type":"cond-expr","locations":[{"start":{"line":84,"column":48},"end":{"line":84,"column":56}},{"start":{"line":84,"column":56},"end":{"line":84,"column":null}}],"line":84},"3":{"loc":{"start":{"line":89,"column":4},"end":{"line":99,"column":null}},"type":"if","locations":[{"start":{"line":89,"column":4},"end":{"line":99,"column":null}},{"start":{},"end":{}}],"line":89},"4":{"loc":{"start":{"line":97,"column":23},"end":{"line":97,"column":null}},"type":"cond-expr","locations":[{"start":{"line":97,"column":48},"end":{"line":97,"column":56}},{"start":{"line":97,"column":56},"end":{"line":97,"column":null}}],"line":97},"5":{"loc":{"start":{"line":102,"column":4},"end":{"line":112,"column":null}},"type":"if","locations":[{"start":{"line":102,"column":4},"end":{"line":112,"column":null}},{"start":{},"end":{}}],"line":102},"6":{"loc":{"start":{"line":110,"column":23},"end":{"line":110,"column":null}},"type":"cond-expr","locations":[{"start":{"line":110,"column":48},"end":{"line":110,"column":56}},{"start":{"line":110,"column":56},"end":{"line":110,"column":null}}],"line":110},"7":{"loc":{"start":{"line":115,"column":4},"end":{"line":129,"column":null}},"type":"if","locations":[{"start":{"line":115,"column":4},"end":{"line":129,"column":null}},{"start":{},"end":{}}],"line":115},"8":{"loc":{"start":{"line":115,"column":8},"end":{"line":115,"column":40}},"type":"binary-expr","locations":[{"start":{"line":115,"column":8},"end":{"line":115,"column":24}},{"start":{"line":115,"column":24},"end":{"line":115,"column":40}}],"line":115},"9":{"loc":{"start":{"line":117,"column":6},"end":{"line":128,"column":null}},"type":"if","locations":[{"start":{"line":117,"column":6},"end":{"line":128,"column":null}},{"start":{},"end":{}}],"line":117},"10":{"loc":{"start":{"line":126,"column":25},"end":{"line":126,"column":null}},"type":"cond-expr","locations":[{"start":{"line":126,"column":50},"end":{"line":126,"column":58}},{"start":{"line":126,"column":58},"end":{"line":126,"column":null}}],"line":126},"11":{"loc":{"start":{"line":132,"column":4},"end":{"line":147,"column":null}},"type":"if","locations":[{"start":{"line":132,"column":4},"end":{"line":147,"column":null}},{"start":{},"end":{}}],"line":132},"12":{"loc":{"start":{"line":132,"column":8},"end":{"line":133,"column":73}},"type":"binary-expr","locations":[{"start":{"line":132,"column":8},"end":{"line":132,"column":null}},{"start":{"line":133,"column":9},"end":{"line":133,"column":30}},{"start":{"line":133,"column":30},"end":{"line":133,"column":48}},{"start":{"line":133,"column":48},"end":{"line":133,"column":73}}],"line":132},"13":{"loc":{"start":{"line":145,"column":23},"end":{"line":145,"column":null}},"type":"cond-expr","locations":[{"start":{"line":145,"column":48},"end":{"line":145,"column":56}},{"start":{"line":145,"column":56},"end":{"line":145,"column":null}}],"line":145},"14":{"loc":{"start":{"line":163,"column":21},"end":{"line":163,"column":null}},"type":"cond-expr","locations":[{"start":{"line":163,"column":46},"end":{"line":163,"column":54}},{"start":{"line":163,"column":54},"end":{"line":163,"column":null}}],"line":163},"15":{"loc":{"start":{"line":183,"column":4},"end":{"line":183,"column":null}},"type":"if","locations":[{"start":{"line":183,"column":4},"end":{"line":183,"column":null}},{"start":{},"end":{}}],"line":183},"16":{"loc":{"start":{"line":200,"column":4},"end":{"line":211,"column":null}},"type":"if","locations":[{"start":{"line":200,"column":4},"end":{"line":211,"column":null}},{"start":{},"end":{}}],"line":200},"17":{"loc":{"start":{"line":200,"column":8},"end":{"line":200,"column":53}},"type":"binary-expr","locations":[{"start":{"line":200,"column":8},"end":{"line":200,"column":29}},{"start":{"line":200,"column":29},"end":{"line":200,"column":53}}],"line":200},"18":{"loc":{"start":{"line":201,"column":6},"end":{"line":204,"column":null}},"type":"if","locations":[{"start":{"line":201,"column":6},"end":{"line":204,"column":null}},{"start":{},"end":{}}],"line":201},"19":{"loc":{"start":{"line":207,"column":6},"end":{"line":210,"column":null}},"type":"if","locations":[{"start":{"line":207,"column":6},"end":{"line":210,"column":null}},{"start":{},"end":{}}],"line":207},"20":{"loc":{"start":{"line":207,"column":10},"end":{"line":207,"column":44}},"type":"binary-expr","locations":[{"start":{"line":207,"column":10},"end":{"line":207,"column":28}},{"start":{"line":207,"column":28},"end":{"line":207,"column":44}}],"line":207},"21":{"loc":{"start":{"line":214,"column":4},"end":{"line":228,"column":null}},"type":"if","locations":[{"start":{"line":214,"column":4},"end":{"line":228,"column":null}},{"start":{},"end":{}}],"line":214},"22":{"loc":{"start":{"line":224,"column":6},"end":{"line":227,"column":null}},"type":"if","locations":[{"start":{"line":224,"column":6},"end":{"line":227,"column":null}},{"start":{},"end":{}}],"line":224}},"s":{"0":16,"1":16,"2":44,"3":21,"4":21,"5":21,"6":21,"7":4,"8":17,"9":4,"10":13,"11":2,"12":11,"13":2,"14":2,"15":1,"16":1,"17":10,"18":6,"19":6,"20":4,"21":21,"22":0,"23":0,"24":61,"25":0,"26":61,"27":347,"28":6,"29":6,"30":6,"31":4,"32":4,"33":2,"34":1,"35":1,"36":1,"37":1,"38":1,"39":6,"40":0,"41":0,"42":1,"43":1},"f":{"0":44,"1":21,"2":0,"3":61,"4":347,"5":6,"6":6},"b":{"0":[20,1],"1":[4,17],"2":[4,0],"3":[4,13],"4":[4,0],"5":[2,11],"6":[2,0],"7":[2,9],"8":[11,3],"9":[1,1],"10":[1,0],"11":[6,4],"12":[10,9,9,8],"13":[6,0],"14":[3,1],"15":[0,61],"16":[6,0],"17":[6,6],"18":[4,2],"19":[1,1],"20":[2,1],"21":[1,0],"22":[0,1]},"meta":{"lastBranch":23,"lastFunction":7,"lastStatement":44,"seen":{"s:13:6:13:Infinity":0,"s:16:23:50:Infinity":1,"f:53:2:53:22":0,"s:53:22:53:52":2,"f:59:8:59:Infinity":1,"s:65:25:65:Infinity":3,"b:65:50:65:66:65:66:65:Infinity":0,"s:66:24:66:Infinity":4,"s:68:4:73:Infinity":5,"b:76:4:86:Infinity:undefined:undefined:undefined:undefined":1,"s:76:4:86:Infinity":6,"s:77:6:85:Infinity":7,"b:84:48:84:56:84:56:84:Infinity":2,"b:89:4:99:Infinity:undefined:undefined:undefined:undefined":3,"s:89:4:99:Infinity":8,"s:90:6:98:Infinity":9,"b:97:48:97:56:97:56:97:Infinity":4,"b:102:4:112:Infinity:undefined:undefined:undefined:undefined":5,"s:102:4:112:Infinity":10,"s:103:6:111:Infinity":11,"b:110:48:110:56:110:56:110:Infinity":6,"b:115:4:129:Infinity:undefined:undefined:undefined:undefined":7,"s:115:4:129:Infinity":12,"b:115:8:115:24:115:24:115:40":8,"s:116:24:116:Infinity":13,"b:117:6:128:Infinity:undefined:undefined:undefined:undefined":9,"s:117:6:128:Infinity":14,"s:118:8:118:Infinity":15,"s:119:8:127:Infinity":16,"b:126:50:126:58:126:58:126:Infinity":10,"b:132:4:147:Infinity:undefined:undefined:undefined:undefined":11,"s:132:4:147:Infinity":17,"b:132:8:132:Infinity:133:9:133:30:133:30:133:48:133:48:133:73":12,"s:136:26:136:Infinity":18,"s:138:6:146:Infinity":19,"b:145:48:145:56:145:56:145:Infinity":13,"s:150:4:154:Infinity":20,"s:156:4:164:Infinity":21,"b:163:46:163:54:163:54:163:Infinity":14,"f:171:8:171:40":2,"s:175:4:175:Infinity":22,"s:176:4:176:Infinity":23,"f:182:10:182:25":3,"b:183:4:183:Infinity:undefined:undefined:undefined:undefined":15,"s:183:4:183:Infinity":24,"s:183:15:183:Infinity":25,"s:184:4:184:Infinity":26,"f:184:25:184:36":4,"s:184:36:184:54":27,"f:191:10:191:27":5,"s:193:31:198:Infinity":28,"b:200:4:211:Infinity:undefined:undefined:undefined:undefined":16,"s:200:4:211:Infinity":29,"b:200:8:200:29:200:29:200:53":17,"b:201:6:204:Infinity:undefined:undefined:undefined:undefined":18,"s:201:6:204:Infinity":30,"s:202:8:202:Infinity":31,"s:203:8:203:Infinity":32,"b:207:6:210:Infinity:undefined:undefined:undefined:undefined":19,"s:207:6:210:Infinity":33,"b:207:10:207:28:207:28:207:44":20,"s:208:8:208:Infinity":34,"s:209:8:209:Infinity":35,"b:214:4:228:Infinity:undefined:undefined:undefined:undefined":21,"s:214:4:228:Infinity":36,"s:215:32:222:Infinity":37,"b:224:6:227:Infinity:undefined:undefined:undefined:undefined":22,"s:224:6:227:Infinity":38,"f:224:33:224:44":6,"s:224:44:224:64":39,"s:225:8:225:Infinity":40,"s:226:8:226:Infinity":41,"s:230:4:230:Infinity":42,"s:231:4:231:Infinity":43}}} +,"/Users/lukasmay/development/projects/codewalk-district/src/agent/lifecycle/factory.ts": {"path":"/Users/lukasmay/development/projects/codewalk-district/src/agent/lifecycle/factory.ts","statementMap":{"0":{"start":{"line":36,"column":6},"end":{"line":36,"column":null}},"1":{"start":{"line":39,"column":24},"end":{"line":39,"column":null}},"2":{"start":{"line":40,"column":22},"end":{"line":40,"column":null}},"3":{"start":{"line":41,"column":24},"end":{"line":41,"column":null}},"4":{"start":{"line":42,"column":26},"end":{"line":42,"column":null}},"5":{"start":{"line":45,"column":30},"end":{"line":55,"column":null}},"6":{"start":{"line":57,"column":2},"end":{"line":57,"column":null}}},"fnMap":{"0":{"name":"createLifecycleController","decl":{"start":{"line":29,"column":16},"end":{"line":29,"column":42}},"loc":{"start":{"line":29,"column":102},"end":{"line":58,"column":null}},"line":29}},"branchMap":{"0":{"loc":{"start":{"line":35,"column":4},"end":{"line":35,"column":null}},"type":"default-arg","locations":[{"start":{"line":35,"column":12},"end":{"line":35,"column":null}}],"line":35}},"s":{"0":23,"1":23,"2":23,"3":23,"4":23,"5":23,"6":23},"f":{"0":23},"b":{"0":[23]},"meta":{"lastBranch":1,"lastFunction":1,"lastStatement":7,"seen":{"f:29:16:29:42":0,"s:36:6:36:Infinity":0,"b:35:12:35:Infinity":0,"s:39:24:39:Infinity":1,"s:40:22:40:Infinity":2,"s:41:24:41:Infinity":3,"s:42:26:42:Infinity":4,"s:45:30:55:Infinity":5,"s:57:2:57:Infinity":6}}} +,"/Users/lukasmay/development/projects/codewalk-district/src/agent/lifecycle/instructions.ts": {"path":"/Users/lukasmay/development/projects/codewalk-district/src/agent/lifecycle/instructions.ts","statementMap":{"0":{"start":{"line":5,"column":42},"end":{"line":5,"column":null}},"1":{"start":{"line":27,"column":2},"end":{"line":27,"column":null}}},"fnMap":{"0":{"name":"addInstructionToPrompt","decl":{"start":{"line":26,"column":16},"end":{"line":26,"column":39}},"loc":{"start":{"line":26,"column":92},"end":{"line":28,"column":null}},"line":26}},"branchMap":{},"s":{"0":1,"1":4},"f":{"0":4},"b":{},"meta":{"lastBranch":0,"lastFunction":1,"lastStatement":2,"seen":{"s:5:42:5:Infinity":0,"f:26:16:26:39":0,"s:27:2:27:Infinity":1}}} +,"/Users/lukasmay/development/projects/codewalk-district/src/agent/lifecycle/retry-policy.ts": {"path":"/Users/lukasmay/development/projects/codewalk-district/src/agent/lifecycle/retry-policy.ts","statementMap":{"0":{"start":{"line":10,"column":6},"end":{"line":10,"column":null}},"1":{"start":{"line":39,"column":25},"end":{"line":39,"column":null}},"2":{"start":{"line":40,"column":23},"end":{"line":40,"column":null}},"3":{"start":{"line":43,"column":4},"end":{"line":50,"column":null}},"4":{"start":{"line":44,"column":6},"end":{"line":48,"column":null}},"5":{"start":{"line":49,"column":6},"end":{"line":49,"column":null}},"6":{"start":{"line":52,"column":4},"end":{"line":89,"column":null}},"7":{"start":{"line":55,"column":8},"end":{"line":55,"column":null}},"8":{"start":{"line":56,"column":8},"end":{"line":56,"column":null}},"9":{"start":{"line":60,"column":8},"end":{"line":60,"column":null}},"10":{"start":{"line":61,"column":8},"end":{"line":61,"column":null}},"11":{"start":{"line":65,"column":8},"end":{"line":65,"column":null}},"12":{"start":{"line":66,"column":8},"end":{"line":66,"column":null}},"13":{"start":{"line":70,"column":37},"end":{"line":70,"column":null}},"14":{"start":{"line":71,"column":8},"end":{"line":76,"column":null}},"15":{"start":{"line":77,"column":8},"end":{"line":77,"column":null}},"16":{"start":{"line":81,"column":8},"end":{"line":81,"column":null}},"17":{"start":{"line":82,"column":8},"end":{"line":82,"column":null}},"18":{"start":{"line":87,"column":8},"end":{"line":87,"column":null}},"19":{"start":{"line":88,"column":8},"end":{"line":88,"column":null}},"20":{"start":{"line":93,"column":18},"end":{"line":93,"column":null}},"21":{"start":{"line":94,"column":18},"end":{"line":94,"column":null}},"22":{"start":{"line":96,"column":4},"end":{"line":96,"column":null}},"23":{"start":{"line":97,"column":4},"end":{"line":97,"column":null}},"24":{"start":{"line":107,"column":4},"end":{"line":107,"column":null}},"25":{"start":{"line":106,"column":47},"end":{"line":106,"column":75}},"26":{"start":{"line":108,"column":4},"end":{"line":108,"column":null}},"27":{"start":{"line":118,"column":4},"end":{"line":118,"column":null}},"28":{"start":{"line":117,"column":47},"end":{"line":117,"column":75}},"29":{"start":{"line":119,"column":4},"end":{"line":119,"column":null}}},"fnMap":{"0":{"name":"(anonymous_0)","decl":{"start":{"line":42,"column":2},"end":{"line":42,"column":14}},"loc":{"start":{"line":42,"column":59},"end":{"line":90,"column":null}},"line":42},"1":{"name":"(anonymous_1)","decl":{"start":{"line":92,"column":2},"end":{"line":92,"column":16}},"loc":{"start":{"line":92,"column":41},"end":{"line":98,"column":null}},"line":92},"2":{"name":"(anonymous_2)","decl":{"start":{"line":106,"column":2},"end":{"line":106,"column":14}},"loc":{"start":{"line":106,"column":75},"end":{"line":109,"column":null}},"line":106},"3":{"name":"(anonymous_3)","decl":{"start":{"line":117,"column":2},"end":{"line":117,"column":14}},"loc":{"start":{"line":117,"column":75},"end":{"line":120,"column":null}},"line":117}},"branchMap":{"0":{"loc":{"start":{"line":43,"column":4},"end":{"line":50,"column":null}},"type":"if","locations":[{"start":{"line":43,"column":4},"end":{"line":50,"column":null}},{"start":{},"end":{}}],"line":43},"1":{"loc":{"start":{"line":52,"column":4},"end":{"line":89,"column":null}},"type":"switch","locations":[{"start":{"line":53,"column":6},"end":{"line":56,"column":null}},{"start":{"line":58,"column":6},"end":{"line":61,"column":null}},{"start":{"line":63,"column":6},"end":{"line":66,"column":null}},{"start":{"line":68,"column":6},"end":{"line":77,"column":null}},{"start":{"line":79,"column":6},"end":{"line":82,"column":null}},{"start":{"line":84,"column":6},"end":{"line":84,"column":null}},{"start":{"line":85,"column":6},"end":{"line":88,"column":null}}],"line":52},"2":{"loc":{"start":{"line":94,"column":18},"end":{"line":94,"column":null}},"type":"binary-expr","locations":[{"start":{"line":94,"column":18},"end":{"line":94,"column":43}},{"start":{"line":94,"column":43},"end":{"line":94,"column":null}}],"line":94}},"s":{"0":16,"1":35,"2":35,"3":19,"4":5,"5":5,"6":14,"7":2,"8":2,"9":2,"10":2,"11":2,"12":2,"13":4,"14":4,"15":4,"16":2,"17":2,"18":2,"19":2,"20":5,"21":5,"22":5,"23":5,"24":0,"25":0,"26":0,"27":0,"28":0,"29":0},"f":{"0":19,"1":5,"2":0,"3":0},"b":{"0":[5,14],"1":[14,2,2,4,2,2,2],"2":[5,0]},"meta":{"lastBranch":3,"lastFunction":4,"lastStatement":30,"seen":{"s:10:6:10:Infinity":0,"s:39:25:39:Infinity":1,"s:40:23:40:Infinity":2,"f:42:2:42:14":0,"b:43:4:50:Infinity:undefined:undefined:undefined:undefined":0,"s:43:4:50:Infinity":3,"s:44:6:48:Infinity":4,"s:49:6:49:Infinity":5,"b:53:6:56:Infinity:58:6:61:Infinity:63:6:66:Infinity:68:6:77:Infinity:79:6:82:Infinity:84:6:84:Infinity:85:6:88:Infinity":1,"s:52:4:89:Infinity":6,"s:55:8:55:Infinity":7,"s:56:8:56:Infinity":8,"s:60:8:60:Infinity":9,"s:61:8:61:Infinity":10,"s:65:8:65:Infinity":11,"s:66:8:66:Infinity":12,"s:70:37:70:Infinity":13,"s:71:8:76:Infinity":14,"s:77:8:77:Infinity":15,"s:81:8:81:Infinity":16,"s:82:8:82:Infinity":17,"s:87:8:87:Infinity":18,"s:88:8:88:Infinity":19,"f:92:2:92:16":1,"s:93:18:93:Infinity":20,"s:94:18:94:Infinity":21,"b:94:18:94:43:94:43:94:Infinity":2,"s:96:4:96:Infinity":22,"s:97:4:97:Infinity":23,"f:106:2:106:14":2,"s:107:4:107:Infinity":24,"s:106:47:106:75":25,"s:108:4:108:Infinity":26,"f:117:2:117:14":3,"s:118:4:118:Infinity":27,"s:117:47:117:75":28,"s:119:4:119:Infinity":29}}} +,"/Users/lukasmay/development/projects/codewalk-district/src/agent/lifecycle/signal-manager.ts": {"path":"/Users/lukasmay/development/projects/codewalk-district/src/agent/lifecycle/signal-manager.ts","statementMap":{"0":{"start":{"line":13,"column":6},"end":{"line":13,"column":null}},"1":{"start":{"line":39,"column":10},"end":{"line":39,"column":null}},"2":{"start":{"line":40,"column":4},"end":{"line":50,"column":null}},"3":{"start":{"line":41,"column":6},"end":{"line":41,"column":null}},"4":{"start":{"line":42,"column":6},"end":{"line":42,"column":null}},"5":{"start":{"line":44,"column":6},"end":{"line":47,"column":null}},"6":{"start":{"line":45,"column":8},"end":{"line":45,"column":null}},"7":{"start":{"line":46,"column":8},"end":{"line":46,"column":null}},"8":{"start":{"line":49,"column":6},"end":{"line":49,"column":null}},"9":{"start":{"line":57,"column":10},"end":{"line":57,"column":null}},"10":{"start":{"line":58,"column":4},"end":{"line":58,"column":null}},"11":{"start":{"line":66,"column":10},"end":{"line":66,"column":null}},"12":{"start":{"line":68,"column":4},"end":{"line":99,"column":null}},"13":{"start":{"line":69,"column":6},"end":{"line":71,"column":null}},"14":{"start":{"line":70,"column":8},"end":{"line":70,"column":null}},"15":{"start":{"line":73,"column":22},"end":{"line":73,"column":null}},"16":{"start":{"line":74,"column":22},"end":{"line":74,"column":null}},"17":{"start":{"line":76,"column":6},"end":{"line":79,"column":null}},"18":{"start":{"line":77,"column":8},"end":{"line":77,"column":null}},"19":{"start":{"line":78,"column":8},"end":{"line":78,"column":null}},"20":{"start":{"line":81,"column":21},"end":{"line":81,"column":null}},"21":{"start":{"line":84,"column":6},"end":{"line":87,"column":null}},"22":{"start":{"line":85,"column":8},"end":{"line":85,"column":null}},"23":{"start":{"line":86,"column":8},"end":{"line":86,"column":null}},"24":{"start":{"line":89,"column":6},"end":{"line":89,"column":null}},"25":{"start":{"line":90,"column":6},"end":{"line":90,"column":null}},"26":{"start":{"line":93,"column":6},"end":{"line":97,"column":null}},"27":{"start":{"line":98,"column":6},"end":{"line":98,"column":null}},"28":{"start":{"line":107,"column":22},"end":{"line":107,"column":null}},"29":{"start":{"line":108,"column":10},"end":{"line":108,"column":null}},"30":{"start":{"line":109,"column":18},"end":{"line":109,"column":null}},"31":{"start":{"line":111,"column":4},"end":{"line":111,"column":null}},"32":{"start":{"line":113,"column":4},"end":{"line":129,"column":null}},"33":{"start":{"line":114,"column":21},"end":{"line":114,"column":null}},"34":{"start":{"line":115,"column":6},"end":{"line":123,"column":null}},"35":{"start":{"line":116,"column":8},"end":{"line":121,"column":null}},"36":{"start":{"line":122,"column":8},"end":{"line":122,"column":null}},"37":{"start":{"line":126,"column":20},"end":{"line":126,"column":null}},"38":{"start":{"line":127,"column":6},"end":{"line":127,"column":null}},"39":{"start":{"line":127,"column":35},"end":{"line":127,"column":61}},"40":{"start":{"line":128,"column":6},"end":{"line":128,"column":null}},"41":{"start":{"line":131,"column":4},"end":{"line":136,"column":null}},"42":{"start":{"line":137,"column":4},"end":{"line":137,"column":null}},"43":{"start":{"line":145,"column":4},"end":{"line":176,"column":null}},"44":{"start":{"line":146,"column":6},"end":{"line":148,"column":null}},"45":{"start":{"line":147,"column":8},"end":{"line":147,"column":null}},"46":{"start":{"line":151,"column":20},"end":{"line":151,"column":null}},"47":{"start":{"line":152,"column":6},"end":{"line":154,"column":null}},"48":{"start":{"line":153,"column":8},"end":{"line":153,"column":null}},"49":{"start":{"line":156,"column":22},"end":{"line":156,"column":null}},"50":{"start":{"line":157,"column":22},"end":{"line":157,"column":null}},"51":{"start":{"line":159,"column":6},"end":{"line":161,"column":null}},"52":{"start":{"line":160,"column":8},"end":{"line":160,"column":null}},"53":{"start":{"line":164,"column":28},"end":{"line":164,"column":null}},"54":{"start":{"line":165,"column":6},"end":{"line":167,"column":null}},"55":{"start":{"line":166,"column":8},"end":{"line":166,"column":null}},"56":{"start":{"line":170,"column":6},"end":{"line":170,"column":null}},"57":{"start":{"line":171,"column":6},"end":{"line":171,"column":null}},"58":{"start":{"line":174,"column":6},"end":{"line":174,"column":null}},"59":{"start":{"line":175,"column":6},"end":{"line":175,"column":null}}},"fnMap":{"0":{"name":"(anonymous_0)","decl":{"start":{"line":38,"column":8},"end":{"line":38,"column":20}},"loc":{"start":{"line":38,"column":57},"end":{"line":51,"column":null}},"line":38},"1":{"name":"(anonymous_1)","decl":{"start":{"line":56,"column":8},"end":{"line":56,"column":26}},"loc":{"start":{"line":56,"column":66},"end":{"line":59,"column":null}},"line":56},"2":{"name":"(anonymous_2)","decl":{"start":{"line":65,"column":8},"end":{"line":65,"column":19}},"loc":{"start":{"line":65,"column":69},"end":{"line":100,"column":null}},"line":65},"3":{"name":"(anonymous_3)","decl":{"start":{"line":106,"column":8},"end":{"line":106,"column":22}},"loc":{"start":{"line":106,"column":91},"end":{"line":138,"column":null}},"line":106},"4":{"name":"(anonymous_4)","decl":{"start":{"line":127,"column":24},"end":{"line":127,"column":35}},"loc":{"start":{"line":127,"column":35},"end":{"line":127,"column":61}},"line":127},"5":{"name":"(anonymous_5)","decl":{"start":{"line":144,"column":8},"end":{"line":144,"column":27}},"loc":{"start":{"line":144,"column":65},"end":{"line":177,"column":null}},"line":144}},"branchMap":{"0":{"loc":{"start":{"line":44,"column":6},"end":{"line":47,"column":null}},"type":"if","locations":[{"start":{"line":44,"column":6},"end":{"line":47,"column":null}},{"start":{},"end":{}}],"line":44},"1":{"loc":{"start":{"line":69,"column":6},"end":{"line":71,"column":null}},"type":"if","locations":[{"start":{"line":69,"column":6},"end":{"line":71,"column":null}},{"start":{},"end":{}}],"line":69},"2":{"loc":{"start":{"line":76,"column":6},"end":{"line":79,"column":null}},"type":"if","locations":[{"start":{"line":76,"column":6},"end":{"line":79,"column":null}},{"start":{},"end":{}}],"line":76},"3":{"loc":{"start":{"line":84,"column":6},"end":{"line":87,"column":null}},"type":"if","locations":[{"start":{"line":84,"column":6},"end":{"line":87,"column":null}},{"start":{},"end":{}}],"line":84},"4":{"loc":{"start":{"line":84,"column":10},"end":{"line":84,"column":85}},"type":"binary-expr","locations":[{"start":{"line":84,"column":10},"end":{"line":84,"column":28}},{"start":{"line":84,"column":28},"end":{"line":84,"column":85}}],"line":84},"5":{"loc":{"start":{"line":96,"column":15},"end":{"line":96,"column":null}},"type":"cond-expr","locations":[{"start":{"line":96,"column":40},"end":{"line":96,"column":56}},{"start":{"line":96,"column":56},"end":{"line":96,"column":null}}],"line":96},"6":{"loc":{"start":{"line":115,"column":6},"end":{"line":123,"column":null}},"type":"if","locations":[{"start":{"line":115,"column":6},"end":{"line":123,"column":null}},{"start":{},"end":{}}],"line":115},"7":{"loc":{"start":{"line":146,"column":6},"end":{"line":148,"column":null}},"type":"if","locations":[{"start":{"line":146,"column":6},"end":{"line":148,"column":null}},{"start":{},"end":{}}],"line":146},"8":{"loc":{"start":{"line":152,"column":6},"end":{"line":154,"column":null}},"type":"if","locations":[{"start":{"line":152,"column":6},"end":{"line":154,"column":null}},{"start":{},"end":{}}],"line":152},"9":{"loc":{"start":{"line":159,"column":6},"end":{"line":161,"column":null}},"type":"if","locations":[{"start":{"line":159,"column":6},"end":{"line":161,"column":null}},{"start":{},"end":{}}],"line":159},"10":{"loc":{"start":{"line":164,"column":28},"end":{"line":164,"column":null}},"type":"binary-expr","locations":[{"start":{"line":164,"column":28},"end":{"line":164,"column":53}},{"start":{"line":164,"column":53},"end":{"line":164,"column":null}}],"line":164},"11":{"loc":{"start":{"line":165,"column":6},"end":{"line":167,"column":null}},"type":"if","locations":[{"start":{"line":165,"column":6},"end":{"line":167,"column":null}},{"start":{},"end":{}}],"line":165},"12":{"loc":{"start":{"line":174,"column":37},"end":{"line":174,"column":92}},"type":"cond-expr","locations":[{"start":{"line":174,"column":62},"end":{"line":174,"column":78}},{"start":{"line":174,"column":78},"end":{"line":174,"column":92}}],"line":174}},"s":{"0":16,"1":2,"2":2,"3":2,"4":1,"5":1,"6":0,"7":0,"8":1,"9":3,"10":3,"11":12,"12":12,"13":12,"14":4,"15":8,"16":8,"17":8,"18":1,"19":1,"20":7,"21":7,"22":1,"23":1,"24":5,"25":5,"26":1,"27":1,"28":3,"29":3,"30":3,"31":3,"32":3,"33":5,"34":5,"35":2,"36":2,"37":3,"38":3,"39":3,"40":3,"41":1,"42":1,"43":4,"44":4,"45":1,"46":3,"47":3,"48":1,"49":2,"50":2,"51":2,"52":0,"53":2,"54":4,"55":1,"56":1,"57":1,"58":0,"59":0},"f":{"0":2,"1":3,"2":12,"3":3,"4":3,"5":4},"b":{"0":[0,1],"1":[4,8],"2":[1,7],"3":[1,6],"4":[7,6],"5":[1,0],"6":[2,3],"7":[1,3],"8":[1,2],"9":[0,2],"10":[2,1],"11":[1,3],"12":[0,0]},"meta":{"lastBranch":13,"lastFunction":6,"lastStatement":60,"seen":{"s:13:6:13:Infinity":0,"f:38:8:38:20":0,"s:39:10:39:Infinity":1,"s:40:4:50:Infinity":2,"s:41:6:41:Infinity":3,"s:42:6:42:Infinity":4,"b:44:6:47:Infinity:undefined:undefined:undefined:undefined":0,"s:44:6:47:Infinity":5,"s:45:8:45:Infinity":6,"s:46:8:46:Infinity":7,"s:49:6:49:Infinity":8,"f:56:8:56:26":1,"s:57:10:57:Infinity":9,"s:58:4:58:Infinity":10,"f:65:8:65:19":2,"s:66:10:66:Infinity":11,"s:68:4:99:Infinity":12,"b:69:6:71:Infinity:undefined:undefined:undefined:undefined":1,"s:69:6:71:Infinity":13,"s:70:8:70:Infinity":14,"s:73:22:73:Infinity":15,"s:74:22:74:Infinity":16,"b:76:6:79:Infinity:undefined:undefined:undefined:undefined":2,"s:76:6:79:Infinity":17,"s:77:8:77:Infinity":18,"s:78:8:78:Infinity":19,"s:81:21:81:Infinity":20,"b:84:6:87:Infinity:undefined:undefined:undefined:undefined":3,"s:84:6:87:Infinity":21,"b:84:10:84:28:84:28:84:85":4,"s:85:8:85:Infinity":22,"s:86:8:86:Infinity":23,"s:89:6:89:Infinity":24,"s:90:6:90:Infinity":25,"s:93:6:97:Infinity":26,"b:96:40:96:56:96:56:96:Infinity":5,"s:98:6:98:Infinity":27,"f:106:8:106:22":3,"s:107:22:107:Infinity":28,"s:108:10:108:Infinity":29,"s:109:18:109:Infinity":30,"s:111:4:111:Infinity":31,"s:113:4:129:Infinity":32,"s:114:21:114:Infinity":33,"b:115:6:123:Infinity:undefined:undefined:undefined:undefined":6,"s:115:6:123:Infinity":34,"s:116:8:121:Infinity":35,"s:122:8:122:Infinity":36,"s:126:20:126:Infinity":37,"s:127:6:127:Infinity":38,"f:127:24:127:35":4,"s:127:35:127:61":39,"s:128:6:128:Infinity":40,"s:131:4:136:Infinity":41,"s:137:4:137:Infinity":42,"f:144:8:144:27":5,"s:145:4:176:Infinity":43,"b:146:6:148:Infinity:undefined:undefined:undefined:undefined":7,"s:146:6:148:Infinity":44,"s:147:8:147:Infinity":45,"s:151:20:151:Infinity":46,"b:152:6:154:Infinity:undefined:undefined:undefined:undefined":8,"s:152:6:154:Infinity":47,"s:153:8:153:Infinity":48,"s:156:22:156:Infinity":49,"s:157:22:157:Infinity":50,"b:159:6:161:Infinity:undefined:undefined:undefined:undefined":9,"s:159:6:161:Infinity":51,"s:160:8:160:Infinity":52,"s:164:28:164:Infinity":53,"b:164:28:164:53:164:53:164:Infinity":10,"b:165:6:167:Infinity:undefined:undefined:undefined:undefined":11,"s:165:6:167:Infinity":54,"s:166:8:166:Infinity":55,"s:170:6:170:Infinity":56,"s:171:6:171:Infinity":57,"s:174:6:174:Infinity":58,"b:174:62:174:78:174:78:174:92":12,"s:175:6:175:Infinity":59}}} +,"/Users/lukasmay/development/projects/codewalk-district/src/agent/prompts/detail.ts": {"path":"/Users/lukasmay/development/projects/codewalk-district/src/agent/prompts/detail.ts","statementMap":{"0":{"start":{"line":8,"column":2},"end":{"line":83,"column":null}}},"fnMap":{"0":{"name":"buildDetailPrompt","decl":{"start":{"line":7,"column":16},"end":{"line":7,"column":44}},"loc":{"start":{"line":7,"column":44},"end":{"line":94,"column":null}},"line":7}},"branchMap":{},"s":{"0":9},"f":{"0":9},"b":{},"meta":{"lastBranch":0,"lastFunction":1,"lastStatement":1,"seen":{"f:7:16:7:44":0,"s:8:2:83:Infinity":0}}} +,"/Users/lukasmay/development/projects/codewalk-district/src/agent/prompts/discuss.ts": {"path":"/Users/lukasmay/development/projects/codewalk-district/src/agent/prompts/discuss.ts","statementMap":{"0":{"start":{"line":8,"column":2},"end":{"line":21,"column":null}}},"fnMap":{"0":{"name":"buildDiscussPrompt","decl":{"start":{"line":7,"column":16},"end":{"line":7,"column":45}},"loc":{"start":{"line":7,"column":45},"end":{"line":64,"column":null}},"line":7}},"branchMap":{},"s":{"0":3},"f":{"0":3},"b":{},"meta":{"lastBranch":0,"lastFunction":1,"lastStatement":1,"seen":{"f:7:16:7:45":0,"s:8:2:21:Infinity":0}}} +,"/Users/lukasmay/development/projects/codewalk-district/src/agent/prompts/execute.ts": {"path":"/Users/lukasmay/development/projects/codewalk-district/src/agent/prompts/execute.ts","statementMap":{"0":{"start":{"line":17,"column":22},"end":{"line":19,"column":null}},"1":{"start":{"line":21,"column":2},"end":{"line":62,"column":null}}},"fnMap":{"0":{"name":"buildExecutePrompt","decl":{"start":{"line":16,"column":16},"end":{"line":16,"column":35}},"loc":{"start":{"line":16,"column":69},"end":{"line":74,"column":null}},"line":16}},"branchMap":{"0":{"loc":{"start":{"line":17,"column":22},"end":{"line":19,"column":null}},"type":"cond-expr","locations":[{"start":{"line":18,"column":6},"end":{"line":18,"column":null}},{"start":{"line":19,"column":6},"end":{"line":19,"column":null}}],"line":17}},"s":{"0":35,"1":35},"f":{"0":35},"b":{"0":[35,0]},"meta":{"lastBranch":1,"lastFunction":1,"lastStatement":2,"seen":{"f:16:16:16:35":0,"s:17:22:19:Infinity":0,"b:18:6:18:Infinity:19:6:19:Infinity":0,"s:21:2:62:Infinity":1}}} +,"/Users/lukasmay/development/projects/codewalk-district/src/agent/prompts/index.ts": {"path":"/Users/lukasmay/development/projects/codewalk-district/src/agent/prompts/index.ts","statementMap":{},"fnMap":{},"branchMap":{},"s":{},"f":{},"b":{},"meta":{"lastBranch":0,"lastFunction":0,"lastStatement":0,"seen":{}}} +,"/Users/lukasmay/development/projects/codewalk-district/src/agent/prompts/plan.ts": {"path":"/Users/lukasmay/development/projects/codewalk-district/src/agent/prompts/plan.ts","statementMap":{"0":{"start":{"line":8,"column":2},"end":{"line":62,"column":null}}},"fnMap":{"0":{"name":"buildPlanPrompt","decl":{"start":{"line":7,"column":16},"end":{"line":7,"column":42}},"loc":{"start":{"line":7,"column":42},"end":{"line":70,"column":null}},"line":7}},"branchMap":{},"s":{"0":7},"f":{"0":7},"b":{},"meta":{"lastBranch":0,"lastFunction":1,"lastStatement":1,"seen":{"f:7:16:7:42":0,"s:8:2:62:Infinity":0}}} +,"/Users/lukasmay/development/projects/codewalk-district/src/agent/prompts/refine.ts": {"path":"/Users/lukasmay/development/projects/codewalk-district/src/agent/prompts/refine.ts","statementMap":{"0":{"start":{"line":8,"column":2},"end":{"line":10,"column":null}}},"fnMap":{"0":{"name":"buildRefinePrompt","decl":{"start":{"line":7,"column":16},"end":{"line":7,"column":44}},"loc":{"start":{"line":7,"column":44},"end":{"line":39,"column":null}},"line":7}},"branchMap":{},"s":{"0":0},"f":{"0":0},"b":{},"meta":{"lastBranch":0,"lastFunction":1,"lastStatement":1,"seen":{"f:7:16:7:44":0,"s:8:2:10:Infinity":0}}} +,"/Users/lukasmay/development/projects/codewalk-district/src/agent/prompts/shared.ts": {"path":"/Users/lukasmay/development/projects/codewalk-district/src/agent/prompts/shared.ts","statementMap":{"0":{"start":{"line":5,"column":29},"end":{"line":5,"column":null}},"1":{"start":{"line":13,"column":27},"end":{"line":13,"column":null}},"2":{"start":{"line":31,"column":29},"end":{"line":31,"column":null}},"3":{"start":{"line":40,"column":31},"end":{"line":40,"column":null}},"4":{"start":{"line":52,"column":28},"end":{"line":52,"column":null}},"5":{"start":{"line":61,"column":34},"end":{"line":61,"column":null}},"6":{"start":{"line":66,"column":30},"end":{"line":66,"column":null}},"7":{"start":{"line":75,"column":31},"end":{"line":75,"column":null}},"8":{"start":{"line":83,"column":33},"end":{"line":83,"column":null}},"9":{"start":{"line":102,"column":2},"end":{"line":110,"column":null}}},"fnMap":{"0":{"name":"buildInterAgentCommunication","decl":{"start":{"line":101,"column":16},"end":{"line":101,"column":45}},"loc":{"start":{"line":101,"column":70},"end":{"line":122,"column":null}},"line":101}},"branchMap":{},"s":{"0":19,"1":19,"2":19,"3":19,"4":19,"5":19,"6":19,"7":19,"8":19,"9":8},"f":{"0":8},"b":{},"meta":{"lastBranch":0,"lastFunction":1,"lastStatement":10,"seen":{"s:5:29:5:Infinity":0,"s:13:27:13:Infinity":1,"s:31:29:31:Infinity":2,"s:40:31:40:Infinity":3,"s:52:28:52:Infinity":4,"s:61:34:61:Infinity":5,"s:66:30:66:Infinity":6,"s:75:31:75:Infinity":7,"s:83:33:83:Infinity":8,"f:101:16:101:45":0,"s:102:2:110:Infinity":9}}} +,"/Users/lukasmay/development/projects/codewalk-district/src/agent/prompts/workspace.ts": {"path":"/Users/lukasmay/development/projects/codewalk-district/src/agent/prompts/workspace.ts","statementMap":{"0":{"start":{"line":10,"column":2},"end":{"line":16,"column":null}},"1":{"start":{"line":11,"column":4},"end":{"line":13,"column":null}},"2":{"start":{"line":12,"column":19},"end":{"line":12,"column":54}},"3":{"start":{"line":13,"column":16},"end":{"line":13,"column":22}},"4":{"start":{"line":15,"column":4},"end":{"line":15,"column":null}},"5":{"start":{"line":18,"column":2},"end":{"line":20,"column":null}},"6":{"start":{"line":19,"column":4},"end":{"line":19,"column":null}},"7":{"start":{"line":22,"column":16},"end":{"line":24,"column":null}},"8":{"start":{"line":23,"column":12},"end":{"line":23,"column":null}},"9":{"start":{"line":26,"column":2},"end":{"line":32,"column":null}}},"fnMap":{"0":{"name":"buildWorkspaceLayout","decl":{"start":{"line":8,"column":16},"end":{"line":8,"column":37}},"loc":{"start":{"line":8,"column":63},"end":{"line":33,"column":null}},"line":8},"1":{"name":"(anonymous_1)","decl":{"start":{"line":12,"column":14},"end":{"line":12,"column":19}},"loc":{"start":{"line":12,"column":19},"end":{"line":12,"column":54}},"line":12},"2":{"name":"(anonymous_2)","decl":{"start":{"line":13,"column":11},"end":{"line":13,"column":16}},"loc":{"start":{"line":13,"column":16},"end":{"line":13,"column":22}},"line":13},"3":{"name":"(anonymous_3)","decl":{"start":{"line":23,"column":4},"end":{"line":23,"column":12}},"loc":{"start":{"line":23,"column":12},"end":{"line":23,"column":null}},"line":23}},"branchMap":{"0":{"loc":{"start":{"line":12,"column":19},"end":{"line":12,"column":54}},"type":"binary-expr","locations":[{"start":{"line":12,"column":19},"end":{"line":12,"column":38}},{"start":{"line":12,"column":38},"end":{"line":12,"column":54}}],"line":12},"1":{"loc":{"start":{"line":18,"column":2},"end":{"line":20,"column":null}},"type":"if","locations":[{"start":{"line":18,"column":2},"end":{"line":20,"column":null}},{"start":{},"end":{}}],"line":18}},"s":{"0":8,"1":8,"2":0,"3":0,"4":8,"5":0,"6":0,"7":0,"8":0,"9":0},"f":{"0":8,"1":0,"2":0,"3":0},"b":{"0":[0,0],"1":[0,0]},"meta":{"lastBranch":2,"lastFunction":4,"lastStatement":10,"seen":{"f:8:16:8:37":0,"s:10:2:16:Infinity":0,"s:11:4:13:Infinity":1,"f:12:14:12:19":1,"s:12:19:12:54":2,"b:12:19:12:38:12:38:12:54":0,"f:13:11:13:16":2,"s:13:16:13:22":3,"s:15:4:15:Infinity":4,"b:18:2:20:Infinity:undefined:undefined:undefined:undefined":1,"s:18:2:20:Infinity":5,"s:19:4:19:Infinity":6,"s:22:16:24:Infinity":7,"f:23:4:23:12":3,"s:23:12:23:Infinity":8,"s:26:2:32:Infinity":9}}} +,"/Users/lukasmay/development/projects/codewalk-district/src/agent/providers/index.ts": {"path":"/Users/lukasmay/development/projects/codewalk-district/src/agent/providers/index.ts","statementMap":{},"fnMap":{},"branchMap":{},"s":{},"f":{},"b":{},"meta":{"lastBranch":0,"lastFunction":0,"lastStatement":0,"seen":{}}} +,"/Users/lukasmay/development/projects/codewalk-district/src/agent/providers/presets.ts": {"path":"/Users/lukasmay/development/projects/codewalk-district/src/agent/providers/presets.ts","statementMap":{"0":{"start":{"line":10,"column":69},"end":{"line":145,"column":null}}},"fnMap":{},"branchMap":{},"s":{"0":23},"f":{},"b":{},"meta":{"lastBranch":0,"lastFunction":0,"lastStatement":1,"seen":{"s:10:69:145:Infinity":0}}} +,"/Users/lukasmay/development/projects/codewalk-district/src/agent/providers/registry.ts": {"path":"/Users/lukasmay/development/projects/codewalk-district/src/agent/providers/registry.ts","statementMap":{"0":{"start":{"line":13,"column":18},"end":{"line":15,"column":null}},"1":{"start":{"line":22,"column":2},"end":{"line":22,"column":null}},"2":{"start":{"line":29,"column":2},"end":{"line":29,"column":null}},"3":{"start":{"line":36,"column":2},"end":{"line":36,"column":null}},"4":{"start":{"line":45,"column":8},"end":{"line":45,"column":null}},"5":{"start":{"line":46,"column":17},"end":{"line":46,"column":null}},"6":{"start":{"line":47,"column":2},"end":{"line":49,"column":null}},"7":{"start":{"line":48,"column":4},"end":{"line":48,"column":null}}},"fnMap":{"0":{"name":"getProvider","decl":{"start":{"line":21,"column":16},"end":{"line":21,"column":28}},"loc":{"start":{"line":21,"column":70},"end":{"line":23,"column":null}},"line":21},"1":{"name":"listProviders","decl":{"start":{"line":28,"column":16},"end":{"line":28,"column":42}},"loc":{"start":{"line":28,"column":42},"end":{"line":30,"column":null}},"line":28},"2":{"name":"registerProvider","decl":{"start":{"line":35,"column":16},"end":{"line":35,"column":33}},"loc":{"start":{"line":35,"column":68},"end":{"line":37,"column":null}},"line":35},"3":{"name":"loadProvidersFromFile","decl":{"start":{"line":44,"column":16},"end":{"line":44,"column":38}},"loc":{"start":{"line":44,"column":58},"end":{"line":50,"column":null}},"line":44}},"branchMap":{"0":{"loc":{"start":{"line":22,"column":9},"end":{"line":22,"column":null}},"type":"binary-expr","locations":[{"start":{"line":22,"column":9},"end":{"line":22,"column":32}},{"start":{"line":22,"column":32},"end":{"line":22,"column":null}}],"line":22}},"s":{"0":23,"1":22,"2":0,"3":0,"4":0,"5":0,"6":0,"7":0},"f":{"0":22,"1":0,"2":0,"3":0},"b":{"0":[22,0]},"meta":{"lastBranch":1,"lastFunction":4,"lastStatement":8,"seen":{"s:13:18:15:Infinity":0,"f:21:16:21:28":0,"s:22:2:22:Infinity":1,"b:22:9:22:32:22:32:22:Infinity":0,"f:28:16:28:42":1,"s:29:2:29:Infinity":2,"f:35:16:35:33":2,"s:36:2:36:Infinity":3,"f:44:16:44:38":3,"s:45:8:45:Infinity":4,"s:46:17:46:Infinity":5,"s:47:2:49:Infinity":6,"s:48:4:48:Infinity":7}}} +,"/Users/lukasmay/development/projects/codewalk-district/src/agent/providers/parsers/claude.ts": {"path":"/Users/lukasmay/development/projects/codewalk-district/src/agent/providers/parsers/claude.ts","statementMap":{"0":{"start":{"line":65,"column":22},"end":{"line":65,"column":null}},"1":{"start":{"line":68,"column":20},"end":{"line":68,"column":null}},"2":{"start":{"line":69,"column":4},"end":{"line":69,"column":null}},"3":{"start":{"line":69,"column":18},"end":{"line":69,"column":null}},"4":{"start":{"line":72,"column":4},"end":{"line":77,"column":null}},"5":{"start":{"line":73,"column":6},"end":{"line":73,"column":null}},"6":{"start":{"line":76,"column":6},"end":{"line":76,"column":null}},"7":{"start":{"line":81,"column":4},"end":{"line":83,"column":null}},"8":{"start":{"line":82,"column":6},"end":{"line":82,"column":null}},"9":{"start":{"line":85,"column":34},"end":{"line":85,"column":null}},"10":{"start":{"line":87,"column":4},"end":{"line":158,"column":null}},"11":{"start":{"line":89,"column":25},"end":{"line":89,"column":null}},"12":{"start":{"line":90,"column":8},"end":{"line":92,"column":null}},"13":{"start":{"line":91,"column":10},"end":{"line":91,"column":null}},"14":{"start":{"line":93,"column":8},"end":{"line":93,"column":null}},"15":{"start":{"line":97,"column":28},"end":{"line":97,"column":null}},"16":{"start":{"line":98,"column":22},"end":{"line":98,"column":null}},"17":{"start":{"line":99,"column":8},"end":{"line":99,"column":null}},"18":{"start":{"line":99,"column":20},"end":{"line":99,"column":null}},"19":{"start":{"line":101,"column":8},"end":{"line":124,"column":null}},"20":{"start":{"line":103,"column":12},"end":{"line":105,"column":null}},"21":{"start":{"line":104,"column":14},"end":{"line":104,"column":null}},"22":{"start":{"line":106,"column":12},"end":{"line":106,"column":null}},"23":{"start":{"line":110,"column":12},"end":{"line":114,"column":null}},"24":{"start":{"line":111,"column":27},"end":{"line":111,"column":null}},"25":{"start":{"line":112,"column":25},"end":{"line":112,"column":null}},"26":{"start":{"line":113,"column":14},"end":{"line":113,"column":null}},"27":{"start":{"line":115,"column":12},"end":{"line":115,"column":null}},"28":{"start":{"line":119,"column":12},"end":{"line":121,"column":null}},"29":{"start":{"line":120,"column":14},"end":{"line":120,"column":null}},"30":{"start":{"line":122,"column":12},"end":{"line":122,"column":null}},"31":{"start":{"line":125,"column":8},"end":{"line":125,"column":null}},"32":{"start":{"line":131,"column":31},"end":{"line":131,"column":null}},"33":{"start":{"line":132,"column":24},"end":{"line":132,"column":null}},"34":{"start":{"line":133,"column":8},"end":{"line":141,"column":null}},"35":{"start":{"line":134,"column":10},"end":{"line":140,"column":null}},"36":{"start":{"line":135,"column":12},"end":{"line":139,"column":null}},"37":{"start":{"line":136,"column":14},"end":{"line":136,"column":null}},"38":{"start":{"line":137,"column":12},"end":{"line":139,"column":null}},"39":{"start":{"line":138,"column":14},"end":{"line":138,"column":null}},"40":{"start":{"line":142,"column":8},"end":{"line":142,"column":null}},"41":{"start":{"line":146,"column":28},"end":{"line":146,"column":null}},"42":{"start":{"line":147,"column":8},"end":{"line":153,"column":null}},"43":{"start":{"line":154,"column":8},"end":{"line":154,"column":null}},"44":{"start":{"line":160,"column":4},"end":{"line":160,"column":null}},"45":{"start":{"line":165,"column":4},"end":{"line":165,"column":null}}},"fnMap":{"0":{"name":"(anonymous_0)","decl":{"start":{"line":67,"column":2},"end":{"line":67,"column":12}},"loc":{"start":{"line":67,"column":41},"end":{"line":161,"column":null}},"line":67},"1":{"name":"(anonymous_1)","decl":{"start":{"line":163,"column":2},"end":{"line":163,"column":23}},"loc":{"start":{"line":163,"column":23},"end":{"line":166,"column":null}},"line":163}},"branchMap":{"0":{"loc":{"start":{"line":69,"column":4},"end":{"line":69,"column":null}},"type":"if","locations":[{"start":{"line":69,"column":4},"end":{"line":69,"column":null}},{"start":{},"end":{}}],"line":69},"1":{"loc":{"start":{"line":81,"column":4},"end":{"line":83,"column":null}},"type":"if","locations":[{"start":{"line":81,"column":4},"end":{"line":83,"column":null}},{"start":{},"end":{}}],"line":81},"2":{"loc":{"start":{"line":81,"column":8},"end":{"line":81,"column":99}},"type":"binary-expr","locations":[{"start":{"line":81,"column":8},"end":{"line":81,"column":32}},{"start":{"line":81,"column":32},"end":{"line":81,"column":51}},{"start":{"line":81,"column":51},"end":{"line":81,"column":73}},{"start":{"line":81,"column":73},"end":{"line":81,"column":99}}],"line":81},"3":{"loc":{"start":{"line":87,"column":4},"end":{"line":158,"column":null}},"type":"switch","locations":[{"start":{"line":88,"column":6},"end":{"line":94,"column":null}},{"start":{"line":96,"column":6},"end":{"line":126,"column":null}},{"start":{"line":128,"column":6},"end":{"line":143,"column":null}},{"start":{"line":145,"column":6},"end":{"line":155,"column":null}}],"line":87},"4":{"loc":{"start":{"line":90,"column":8},"end":{"line":92,"column":null}},"type":"if","locations":[{"start":{"line":90,"column":8},"end":{"line":92,"column":null}},{"start":{},"end":{}}],"line":90},"5":{"loc":{"start":{"line":90,"column":12},"end":{"line":90,"column":64}},"type":"binary-expr","locations":[{"start":{"line":90,"column":12},"end":{"line":90,"column":43}},{"start":{"line":90,"column":43},"end":{"line":90,"column":64}}],"line":90},"6":{"loc":{"start":{"line":99,"column":8},"end":{"line":99,"column":null}},"type":"if","locations":[{"start":{"line":99,"column":8},"end":{"line":99,"column":null}},{"start":{},"end":{}}],"line":99},"7":{"loc":{"start":{"line":101,"column":8},"end":{"line":124,"column":null}},"type":"switch","locations":[{"start":{"line":102,"column":10},"end":{"line":107,"column":null}},{"start":{"line":109,"column":10},"end":{"line":116,"column":null}},{"start":{"line":118,"column":10},"end":{"line":123,"column":null}}],"line":101},"8":{"loc":{"start":{"line":103,"column":12},"end":{"line":105,"column":null}},"type":"if","locations":[{"start":{"line":103,"column":12},"end":{"line":105,"column":null}},{"start":{},"end":{}}],"line":103},"9":{"loc":{"start":{"line":103,"column":16},"end":{"line":103,"column":72}},"type":"binary-expr","locations":[{"start":{"line":103,"column":16},"end":{"line":103,"column":54}},{"start":{"line":103,"column":54},"end":{"line":103,"column":72}}],"line":103},"10":{"loc":{"start":{"line":110,"column":12},"end":{"line":114,"column":null}},"type":"if","locations":[{"start":{"line":110,"column":12},"end":{"line":114,"column":null}},{"start":{},"end":{}}],"line":110},"11":{"loc":{"start":{"line":111,"column":27},"end":{"line":111,"column":null}},"type":"binary-expr","locations":[{"start":{"line":111,"column":27},"end":{"line":111,"column":55}},{"start":{"line":111,"column":55},"end":{"line":111,"column":null}}],"line":111},"12":{"loc":{"start":{"line":112,"column":25},"end":{"line":112,"column":null}},"type":"binary-expr","locations":[{"start":{"line":112,"column":25},"end":{"line":112,"column":51}},{"start":{"line":112,"column":51},"end":{"line":112,"column":null}}],"line":112},"13":{"loc":{"start":{"line":119,"column":12},"end":{"line":121,"column":null}},"type":"if","locations":[{"start":{"line":119,"column":12},"end":{"line":121,"column":null}},{"start":{},"end":{}}],"line":119},"14":{"loc":{"start":{"line":133,"column":8},"end":{"line":141,"column":null}},"type":"if","locations":[{"start":{"line":133,"column":8},"end":{"line":141,"column":null}},{"start":{},"end":{}}],"line":133},"15":{"loc":{"start":{"line":135,"column":12},"end":{"line":139,"column":null}},"type":"if","locations":[{"start":{"line":135,"column":12},"end":{"line":139,"column":null}},{"start":{"line":137,"column":12},"end":{"line":139,"column":null}}],"line":135},"16":{"loc":{"start":{"line":135,"column":16},"end":{"line":135,"column":53}},"type":"binary-expr","locations":[{"start":{"line":135,"column":16},"end":{"line":135,"column":41}},{"start":{"line":135,"column":41},"end":{"line":135,"column":53}}],"line":135},"17":{"loc":{"start":{"line":137,"column":12},"end":{"line":139,"column":null}},"type":"if","locations":[{"start":{"line":137,"column":12},"end":{"line":139,"column":null}},{"start":{},"end":{}}],"line":137},"18":{"loc":{"start":{"line":137,"column":23},"end":{"line":137,"column":64}},"type":"binary-expr","locations":[{"start":{"line":137,"column":23},"end":{"line":137,"column":52}},{"start":{"line":137,"column":52},"end":{"line":137,"column":64}}],"line":137},"19":{"loc":{"start":{"line":138,"column":74},"end":{"line":138,"column":89}},"type":"binary-expr","locations":[{"start":{"line":138,"column":74},"end":{"line":138,"column":86}},{"start":{"line":138,"column":86},"end":{"line":138,"column":89}}],"line":138},"20":{"loc":{"start":{"line":149,"column":16},"end":{"line":149,"column":null}},"type":"binary-expr","locations":[{"start":{"line":149,"column":16},"end":{"line":149,"column":38}},{"start":{"line":149,"column":38},"end":{"line":149,"column":null}}],"line":149}},"s":{"0":10,"1":0,"2":0,"3":0,"4":0,"5":0,"6":0,"7":0,"8":0,"9":0,"10":0,"11":0,"12":0,"13":0,"14":0,"15":0,"16":0,"17":0,"18":0,"19":0,"20":0,"21":0,"22":0,"23":0,"24":0,"25":0,"26":0,"27":0,"28":0,"29":0,"30":0,"31":0,"32":0,"33":0,"34":0,"35":0,"36":0,"37":0,"38":0,"39":0,"40":0,"41":0,"42":0,"43":0,"44":0,"45":0},"f":{"0":0,"1":0},"b":{"0":[0,0],"1":[0,0],"2":[0,0,0,0],"3":[0,0,0,0],"4":[0,0],"5":[0,0],"6":[0,0],"7":[0,0,0],"8":[0,0],"9":[0,0],"10":[0,0],"11":[0,0],"12":[0,0],"13":[0,0],"14":[0,0],"15":[0,0],"16":[0,0],"17":[0,0],"18":[0,0],"19":[0,0],"20":[0,0]},"meta":{"lastBranch":21,"lastFunction":2,"lastStatement":46,"seen":{"s:65:22:65:Infinity":0,"f:67:2:67:12":0,"s:68:20:68:Infinity":1,"b:69:4:69:Infinity:undefined:undefined:undefined:undefined":0,"s:69:4:69:Infinity":2,"s:69:18:69:Infinity":3,"s:72:4:77:Infinity":4,"s:73:6:73:Infinity":5,"s:76:6:76:Infinity":6,"b:81:4:83:Infinity:undefined:undefined:undefined:undefined":1,"s:81:4:83:Infinity":7,"b:81:8:81:32:81:32:81:51:81:51:81:73:81:73:81:99":2,"s:82:6:82:Infinity":8,"s:85:34:85:Infinity":9,"b:88:6:94:Infinity:96:6:126:Infinity:128:6:143:Infinity:145:6:155:Infinity":3,"s:87:4:158:Infinity":10,"s:89:25:89:Infinity":11,"b:90:8:92:Infinity:undefined:undefined:undefined:undefined":4,"s:90:8:92:Infinity":12,"b:90:12:90:43:90:43:90:64":5,"s:91:10:91:Infinity":13,"s:93:8:93:Infinity":14,"s:97:28:97:Infinity":15,"s:98:22:98:Infinity":16,"b:99:8:99:Infinity:undefined:undefined:undefined:undefined":6,"s:99:8:99:Infinity":17,"s:99:20:99:Infinity":18,"b:102:10:107:Infinity:109:10:116:Infinity:118:10:123:Infinity":7,"s:101:8:124:Infinity":19,"b:103:12:105:Infinity:undefined:undefined:undefined:undefined":8,"s:103:12:105:Infinity":20,"b:103:16:103:54:103:54:103:72":9,"s:104:14:104:Infinity":21,"s:106:12:106:Infinity":22,"b:110:12:114:Infinity:undefined:undefined:undefined:undefined":10,"s:110:12:114:Infinity":23,"s:111:27:111:Infinity":24,"b:111:27:111:55:111:55:111:Infinity":11,"s:112:25:112:Infinity":25,"b:112:25:112:51:112:51:112:Infinity":12,"s:113:14:113:Infinity":26,"s:115:12:115:Infinity":27,"b:119:12:121:Infinity:undefined:undefined:undefined:undefined":13,"s:119:12:121:Infinity":28,"s:120:14:120:Infinity":29,"s:122:12:122:Infinity":30,"s:125:8:125:Infinity":31,"s:131:31:131:Infinity":32,"s:132:24:132:Infinity":33,"b:133:8:141:Infinity:undefined:undefined:undefined:undefined":14,"s:133:8:141:Infinity":34,"s:134:10:140:Infinity":35,"b:135:12:139:Infinity:137:12:139:Infinity":15,"s:135:12:139:Infinity":36,"b:135:16:135:41:135:41:135:53":16,"s:136:14:136:Infinity":37,"b:137:12:139:Infinity:undefined:undefined:undefined:undefined":17,"s:137:12:139:Infinity":38,"b:137:23:137:52:137:52:137:64":18,"s:138:14:138:Infinity":39,"b:138:74:138:86:138:86:138:89":19,"s:142:8:142:Infinity":40,"s:146:28:146:Infinity":41,"s:147:8:153:Infinity":42,"b:149:16:149:38:149:38:149:Infinity":20,"s:154:8:154:Infinity":43,"s:160:4:160:Infinity":44,"f:163:2:163:23":1,"s:165:4:165:Infinity":45}}} +,"/Users/lukasmay/development/projects/codewalk-district/src/agent/providers/parsers/generic.ts": {"path":"/Users/lukasmay/development/projects/codewalk-district/src/agent/providers/parsers/generic.ts","statementMap":{"0":{"start":{"line":11,"column":22},"end":{"line":11,"column":null}},"1":{"start":{"line":12,"column":34},"end":{"line":12,"column":null}},"2":{"start":{"line":15,"column":4},"end":{"line":15,"column":null}},"3":{"start":{"line":15,"column":15},"end":{"line":15,"column":null}},"4":{"start":{"line":17,"column":4},"end":{"line":17,"column":null}},"5":{"start":{"line":20,"column":4},"end":{"line":20,"column":null}},"6":{"start":{"line":25,"column":21},"end":{"line":25,"column":null}},"7":{"start":{"line":26,"column":4},"end":{"line":26,"column":null}},"8":{"start":{"line":28,"column":4},"end":{"line":28,"column":null}},"9":{"start":{"line":28,"column":19},"end":{"line":28,"column":null}},"10":{"start":{"line":30,"column":4},"end":{"line":30,"column":null}}},"fnMap":{"0":{"name":"(anonymous_0)","decl":{"start":{"line":14,"column":2},"end":{"line":14,"column":12}},"loc":{"start":{"line":14,"column":41},"end":{"line":21,"column":null}},"line":14},"1":{"name":"(anonymous_1)","decl":{"start":{"line":23,"column":2},"end":{"line":23,"column":23}},"loc":{"start":{"line":23,"column":23},"end":{"line":31,"column":null}},"line":23}},"branchMap":{"0":{"loc":{"start":{"line":15,"column":4},"end":{"line":15,"column":null}},"type":"if","locations":[{"start":{"line":15,"column":4},"end":{"line":15,"column":null}},{"start":{},"end":{}}],"line":15},"1":{"loc":{"start":{"line":28,"column":4},"end":{"line":28,"column":null}},"type":"if","locations":[{"start":{"line":28,"column":4},"end":{"line":28,"column":null}},{"start":{},"end":{}}],"line":28}},"s":{"0":0,"1":0,"2":0,"3":0,"4":0,"5":0,"6":0,"7":0,"8":0,"9":0,"10":0},"f":{"0":0,"1":0},"b":{"0":[0,0],"1":[0,0]},"meta":{"lastBranch":2,"lastFunction":2,"lastStatement":11,"seen":{"s:11:22:11:Infinity":0,"s:12:34:12:Infinity":1,"f:14:2:14:12":0,"b:15:4:15:Infinity:undefined:undefined:undefined:undefined":0,"s:15:4:15:Infinity":2,"s:15:15:15:Infinity":3,"s:17:4:17:Infinity":4,"s:20:4:20:Infinity":5,"f:23:2:23:23":1,"s:25:21:25:Infinity":6,"s:26:4:26:Infinity":7,"b:28:4:28:Infinity:undefined:undefined:undefined:undefined":1,"s:28:4:28:Infinity":8,"s:28:19:28:Infinity":9,"s:30:4:30:Infinity":10}}} +,"/Users/lukasmay/development/projects/codewalk-district/src/agent/providers/parsers/index.ts": {"path":"/Users/lukasmay/development/projects/codewalk-district/src/agent/providers/parsers/index.ts","statementMap":{"0":{"start":{"line":12,"column":63},"end":{"line":14,"column":null}},"1":{"start":{"line":21,"column":22},"end":{"line":21,"column":null}},"2":{"start":{"line":22,"column":2},"end":{"line":24,"column":null}},"3":{"start":{"line":23,"column":4},"end":{"line":23,"column":null}},"4":{"start":{"line":25,"column":2},"end":{"line":25,"column":null}}},"fnMap":{"0":{"name":"getStreamParser","decl":{"start":{"line":20,"column":16},"end":{"line":20,"column":32}},"loc":{"start":{"line":20,"column":68},"end":{"line":26,"column":null}},"line":20}},"branchMap":{"0":{"loc":{"start":{"line":22,"column":2},"end":{"line":24,"column":null}},"type":"if","locations":[{"start":{"line":22,"column":2},"end":{"line":24,"column":null}},{"start":{},"end":{}}],"line":22}},"s":{"0":15,"1":10,"2":10,"3":10,"4":0},"f":{"0":10},"b":{"0":[10,0]},"meta":{"lastBranch":1,"lastFunction":1,"lastStatement":5,"seen":{"s:12:63:14:Infinity":0,"f:20:16:20:32":0,"s:21:22:21:Infinity":1,"b:22:2:24:Infinity:undefined:undefined:undefined:undefined":0,"s:22:2:24:Infinity":2,"s:23:4:23:Infinity":3,"s:25:2:25:Infinity":4}}} +,"/Users/lukasmay/development/projects/codewalk-district/src/cli/trpc-client.ts": {"path":"/Users/lukasmay/development/projects/codewalk-district/src/cli/trpc-client.ts","statementMap":{"0":{"start":{"line":12,"column":21},"end":{"line":12,"column":null}},"1":{"start":{"line":15,"column":21},"end":{"line":15,"column":null}},"2":{"start":{"line":33,"column":14},"end":{"line":33,"column":null}},"3":{"start":{"line":34,"column":2},"end":{"line":42,"column":null}},"4":{"start":{"line":37,"column":27},"end":{"line":37,"column":null}},"5":{"start":{"line":54,"column":15},"end":{"line":54,"column":null}},"6":{"start":{"line":55,"column":15},"end":{"line":55,"column":null}},"7":{"start":{"line":56,"column":2},"end":{"line":56,"column":null}}},"fnMap":{"0":{"name":"createTrpcClient","decl":{"start":{"line":29,"column":16},"end":{"line":29,"column":null}},"loc":{"start":{"line":32,"column":14},"end":{"line":43,"column":null}},"line":32},"1":{"name":"(anonymous_1)","decl":{"start":{"line":37,"column":19},"end":{"line":37,"column":20}},"loc":{"start":{"line":37,"column":27},"end":{"line":37,"column":null}},"line":37},"2":{"name":"createDefaultTrpcClient","decl":{"start":{"line":53,"column":16},"end":{"line":53,"column":54}},"loc":{"start":{"line":53,"column":54},"end":{"line":57,"column":null}},"line":53}},"branchMap":{"0":{"loc":{"start":{"line":30,"column":2},"end":{"line":30,"column":null}},"type":"default-arg","locations":[{"start":{"line":30,"column":17},"end":{"line":30,"column":null}}],"line":30},"1":{"loc":{"start":{"line":31,"column":2},"end":{"line":31,"column":null}},"type":"default-arg","locations":[{"start":{"line":31,"column":17},"end":{"line":31,"column":null}}],"line":31},"2":{"loc":{"start":{"line":54,"column":15},"end":{"line":54,"column":null}},"type":"cond-expr","locations":[{"start":{"line":54,"column":37},"end":{"line":54,"column":73}},{"start":{"line":54,"column":73},"end":{"line":54,"column":null}}],"line":54},"3":{"loc":{"start":{"line":55,"column":15},"end":{"line":55,"column":null}},"type":"binary-expr","locations":[{"start":{"line":55,"column":15},"end":{"line":55,"column":38}},{"start":{"line":55,"column":38},"end":{"line":55,"column":null}}],"line":55}},"s":{"0":1,"1":1,"2":2,"3":2,"4":8,"5":0,"6":0,"7":0},"f":{"0":2,"1":8,"2":0},"b":{"0":[2],"1":[2],"2":[0,0],"3":[0,0]},"meta":{"lastBranch":4,"lastFunction":3,"lastStatement":8,"seen":{"s:12:21:12:Infinity":0,"s:15:21:15:Infinity":1,"f:29:16:29:Infinity":0,"b:30:17:30:Infinity":0,"b:31:17:31:Infinity":1,"s:33:14:33:Infinity":2,"s:34:2:42:Infinity":3,"f:37:19:37:20":1,"s:37:27:37:Infinity":4,"f:53:16:53:54":2,"s:54:15:54:Infinity":5,"b:54:37:54:73:54:73:54:Infinity":2,"s:55:15:55:Infinity":6,"b:55:15:55:38:55:38:55:Infinity":3,"s:56:2:56:Infinity":7}}} +,"/Users/lukasmay/development/projects/codewalk-district/src/config/cwrc.ts": {"path":"/Users/lukasmay/development/projects/codewalk-district/src/config/cwrc.ts","statementMap":{"0":{"start":{"line":13,"column":22},"end":{"line":13,"column":null}},"1":{"start":{"line":21,"column":12},"end":{"line":21,"column":null}},"2":{"start":{"line":23,"column":2},"end":{"line":35,"column":null}},"3":{"start":{"line":24,"column":10},"end":{"line":24,"column":null}},"4":{"start":{"line":25,"column":4},"end":{"line":27,"column":null}},"5":{"start":{"line":26,"column":6},"end":{"line":26,"column":null}},"6":{"start":{"line":29,"column":10},"end":{"line":29,"column":null}},"7":{"start":{"line":30,"column":4},"end":{"line":33,"column":null}},"8":{"start":{"line":32,"column":6},"end":{"line":32,"column":null}},"9":{"start":{"line":34,"column":4},"end":{"line":34,"column":null}},"10":{"start":{"line":44,"column":8},"end":{"line":44,"column":null}},"11":{"start":{"line":45,"column":2},"end":{"line":47,"column":null}},"12":{"start":{"line":46,"column":4},"end":{"line":46,"column":null}},"13":{"start":{"line":49,"column":8},"end":{"line":49,"column":null}},"14":{"start":{"line":50,"column":2},"end":{"line":50,"column":null}},"15":{"start":{"line":57,"column":8},"end":{"line":57,"column":null}},"16":{"start":{"line":58,"column":2},"end":{"line":58,"column":null}},"17":{"start":{"line":65,"column":2},"end":{"line":65,"column":null}}},"fnMap":{"0":{"name":"findWorkspaceRoot","decl":{"start":{"line":20,"column":16},"end":{"line":20,"column":34}},"loc":{"start":{"line":20,"column":83},"end":{"line":36,"column":null}},"line":20},"1":{"name":"readCwrc","decl":{"start":{"line":43,"column":16},"end":{"line":43,"column":25}},"loc":{"start":{"line":43,"column":55},"end":{"line":51,"column":null}},"line":43},"2":{"name":"writeCwrc","decl":{"start":{"line":56,"column":16},"end":{"line":56,"column":26}},"loc":{"start":{"line":56,"column":63},"end":{"line":59,"column":null}},"line":56},"3":{"name":"defaultCwConfig","decl":{"start":{"line":64,"column":16},"end":{"line":64,"column":44}},"loc":{"start":{"line":64,"column":44},"end":{"line":66,"column":null}},"line":64}},"branchMap":{"0":{"loc":{"start":{"line":20,"column":34},"end":{"line":20,"column":83}},"type":"default-arg","locations":[{"start":{"line":20,"column":53},"end":{"line":20,"column":83}}],"line":20},"1":{"loc":{"start":{"line":25,"column":4},"end":{"line":27,"column":null}},"type":"if","locations":[{"start":{"line":25,"column":4},"end":{"line":27,"column":null}},{"start":{},"end":{}}],"line":25},"2":{"loc":{"start":{"line":30,"column":4},"end":{"line":33,"column":null}},"type":"if","locations":[{"start":{"line":30,"column":4},"end":{"line":33,"column":null}},{"start":{},"end":{}}],"line":30},"3":{"loc":{"start":{"line":45,"column":2},"end":{"line":47,"column":null}},"type":"if","locations":[{"start":{"line":45,"column":2},"end":{"line":47,"column":null}},{"start":{},"end":{}}],"line":45}},"s":{"0":8,"1":0,"2":0,"3":0,"4":0,"5":0,"6":0,"7":0,"8":0,"9":0,"10":0,"11":0,"12":0,"13":0,"14":0,"15":0,"16":0,"17":0},"f":{"0":0,"1":0,"2":0,"3":0},"b":{"0":[0],"1":[0,0],"2":[0,0],"3":[0,0]},"meta":{"lastBranch":4,"lastFunction":4,"lastStatement":18,"seen":{"s:13:22:13:Infinity":0,"f:20:16:20:34":0,"b:20:53:20:83":0,"s:21:12:21:Infinity":1,"s:23:2:35:Infinity":2,"s:24:10:24:Infinity":3,"b:25:4:27:Infinity:undefined:undefined:undefined:undefined":1,"s:25:4:27:Infinity":4,"s:26:6:26:Infinity":5,"s:29:10:29:Infinity":6,"b:30:4:33:Infinity:undefined:undefined:undefined:undefined":2,"s:30:4:33:Infinity":7,"s:32:6:32:Infinity":8,"s:34:4:34:Infinity":9,"f:43:16:43:25":1,"s:44:8:44:Infinity":10,"b:45:2:47:Infinity:undefined:undefined:undefined:undefined":3,"s:45:2:47:Infinity":11,"s:46:4:46:Infinity":12,"s:49:8:49:Infinity":13,"s:50:2:50:Infinity":14,"f:56:16:56:26":2,"s:57:8:57:Infinity":15,"s:58:2:58:Infinity":16,"f:64:16:64:44":3,"s:65:2:65:Infinity":17}}} +,"/Users/lukasmay/development/projects/codewalk-district/src/config/index.ts": {"path":"/Users/lukasmay/development/projects/codewalk-district/src/config/index.ts","statementMap":{},"fnMap":{},"branchMap":{},"s":{},"f":{},"b":{},"meta":{"lastBranch":0,"lastFunction":0,"lastStatement":0,"seen":{}}} +,"/Users/lukasmay/development/projects/codewalk-district/src/coordination/conflict-resolution-service.ts": {"path":"/Users/lukasmay/development/projects/codewalk-district/src/coordination/conflict-resolution-service.ts","statementMap":{"0":{"start":{"line":57,"column":12},"end":{"line":57,"column":null}},"1":{"start":{"line":58,"column":12},"end":{"line":58,"column":null}},"2":{"start":{"line":59,"column":12},"end":{"line":59,"column":null}},"3":{"start":{"line":60,"column":12},"end":{"line":60,"column":null}},"4":{"start":{"line":69,"column":25},"end":{"line":69,"column":null}},"5":{"start":{"line":70,"column":4},"end":{"line":72,"column":null}},"6":{"start":{"line":71,"column":6},"end":{"line":71,"column":null}},"7":{"start":{"line":75,"column":18},"end":{"line":75,"column":null}},"8":{"start":{"line":76,"column":4},"end":{"line":78,"column":null}},"9":{"start":{"line":77,"column":6},"end":{"line":77,"column":null}},"10":{"start":{"line":81,"column":29},"end":{"line":88,"column":null}},"11":{"start":{"line":84,"column":30},"end":{"line":84,"column":38}},"12":{"start":{"line":90,"column":4},"end":{"line":100,"column":null}},"13":{"start":{"line":91,"column":6},"end":{"line":95,"column":null}},"14":{"start":{"line":97,"column":6},"end":{"line":99,"column":null}},"15":{"start":{"line":102,"column":32},"end":{"line":102,"column":null}},"16":{"start":{"line":105,"column":25},"end":{"line":116,"column":null}},"17":{"start":{"line":119,"column":4},"end":{"line":119,"column":null}},"18":{"start":{"line":122,"column":4},"end":{"line":143,"column":null}},"19":{"start":{"line":123,"column":29},"end":{"line":132,"column":null}},"20":{"start":{"line":127,"column":32},"end":{"line":127,"column":40}},"21":{"start":{"line":134,"column":6},"end":{"line":142,"column":null}},"22":{"start":{"line":146,"column":4},"end":{"line":157,"column":null}},"23":{"start":{"line":147,"column":37},"end":{"line":155,"column":null}},"24":{"start":{"line":156,"column":6},"end":{"line":156,"column":null}}},"fnMap":{"0":{"name":"(anonymous_0)","decl":{"start":{"line":56,"column":2},"end":{"line":56,"column":null}},"loc":{"start":{"line":61,"column":4},"end":{"line":61,"column":null}},"line":61},"1":{"name":"(anonymous_1)","decl":{"start":{"line":67,"column":8},"end":{"line":67,"column":23}},"loc":{"start":{"line":67,"column":104},"end":{"line":158,"column":null}},"line":67},"2":{"name":"(anonymous_2)","decl":{"start":{"line":84,"column":23},"end":{"line":84,"column":24}},"loc":{"start":{"line":84,"column":30},"end":{"line":84,"column":38}},"line":84},"3":{"name":"(anonymous_3)","decl":{"start":{"line":127,"column":25},"end":{"line":127,"column":26}},"loc":{"start":{"line":127,"column":32},"end":{"line":127,"column":40}},"line":127}},"branchMap":{"0":{"loc":{"start":{"line":70,"column":4},"end":{"line":72,"column":null}},"type":"if","locations":[{"start":{"line":70,"column":4},"end":{"line":72,"column":null}},{"start":{},"end":{}}],"line":70},"1":{"loc":{"start":{"line":76,"column":4},"end":{"line":78,"column":null}},"type":"if","locations":[{"start":{"line":76,"column":4},"end":{"line":78,"column":null}},{"start":{},"end":{}}],"line":76},"2":{"loc":{"start":{"line":90,"column":4},"end":{"line":100,"column":null}},"type":"if","locations":[{"start":{"line":90,"column":4},"end":{"line":100,"column":null}},{"start":{"line":96,"column":11},"end":{"line":100,"column":null}}],"line":90},"3":{"loc":{"start":{"line":111,"column":16},"end":{"line":111,"column":null}},"type":"cond-expr","locations":[{"start":{"line":111,"column":31},"end":{"line":111,"column":41}},{"start":{"line":111,"column":41},"end":{"line":111,"column":null}}],"line":111},"4":{"loc":{"start":{"line":122,"column":4},"end":{"line":143,"column":null}},"type":"if","locations":[{"start":{"line":122,"column":4},"end":{"line":143,"column":null}},{"start":{},"end":{}}],"line":122},"5":{"loc":{"start":{"line":146,"column":4},"end":{"line":157,"column":null}},"type":"if","locations":[{"start":{"line":146,"column":4},"end":{"line":157,"column":null}},{"start":{},"end":{}}],"line":146}},"s":{"0":115,"1":115,"2":115,"3":115,"4":24,"5":24,"6":2,"7":22,"8":22,"9":2,"10":20,"11":28,"12":20,"13":0,"14":20,"15":20,"16":20,"17":20,"18":20,"19":19,"20":27,"21":19,"22":20,"23":19,"24":19},"f":{"0":115,"1":24,"2":28,"3":27},"b":{"0":[2,22],"1":[2,20],"2":[0,20],"3":[0,20],"4":[19,1],"5":[19,1]},"meta":{"lastBranch":6,"lastFunction":4,"lastStatement":25,"seen":{"f:56:2:56:Infinity":0,"s:57:12:57:Infinity":0,"s:58:12:58:Infinity":1,"s:59:12:59:Infinity":2,"s:60:12:60:Infinity":3,"f:67:8:67:23":1,"s:69:25:69:Infinity":4,"b:70:4:72:Infinity:undefined:undefined:undefined:undefined":0,"s:70:4:72:Infinity":5,"s:71:6:71:Infinity":6,"s:75:18:75:Infinity":7,"b:76:4:78:Infinity:undefined:undefined:undefined:undefined":1,"s:76:4:78:Infinity":8,"s:77:6:77:Infinity":9,"s:81:29:88:Infinity":10,"f:84:23:84:24":2,"s:84:30:84:38":11,"b:90:4:100:Infinity:96:11:100:Infinity":2,"s:90:4:100:Infinity":12,"s:91:6:95:Infinity":13,"s:97:6:99:Infinity":14,"s:102:32:102:Infinity":15,"s:105:25:116:Infinity":16,"b:111:31:111:41:111:41:111:Infinity":3,"s:119:4:119:Infinity":17,"b:122:4:143:Infinity:undefined:undefined:undefined:undefined":4,"s:122:4:143:Infinity":18,"s:123:29:132:Infinity":19,"f:127:25:127:26":3,"s:127:32:127:40":20,"s:134:6:142:Infinity":21,"b:146:4:157:Infinity:undefined:undefined:undefined:undefined":5,"s:146:4:157:Infinity":22,"s:147:37:155:Infinity":23,"s:156:6:156:Infinity":24}}} +,"/Users/lukasmay/development/projects/codewalk-district/src/coordination/manager.ts": {"path":"/Users/lukasmay/development/projects/codewalk-district/src/coordination/manager.ts","statementMap":{"0":{"start":{"line":48,"column":60},"end":{"line":48,"column":null}},"1":{"start":{"line":51,"column":37},"end":{"line":51,"column":null}},"2":{"start":{"line":54,"column":51},"end":{"line":54,"column":null}},"3":{"start":{"line":60,"column":12},"end":{"line":60,"column":null}},"4":{"start":{"line":61,"column":12},"end":{"line":61,"column":null}},"5":{"start":{"line":62,"column":12},"end":{"line":62,"column":null}},"6":{"start":{"line":63,"column":12},"end":{"line":63,"column":null}},"7":{"start":{"line":64,"column":12},"end":{"line":64,"column":null}},"8":{"start":{"line":68,"column":4},"end":{"line":77,"column":null}},"9":{"start":{"line":69,"column":6},"end":{"line":69,"column":null}},"10":{"start":{"line":70,"column":4},"end":{"line":77,"column":null}},"11":{"start":{"line":71,"column":6},"end":{"line":76,"column":null}},"12":{"start":{"line":86,"column":4},"end":{"line":88,"column":null}},"13":{"start":{"line":87,"column":6},"end":{"line":87,"column":null}},"14":{"start":{"line":90,"column":17},"end":{"line":90,"column":null}},"15":{"start":{"line":91,"column":4},"end":{"line":93,"column":null}},"16":{"start":{"line":92,"column":6},"end":{"line":92,"column":null}},"17":{"start":{"line":96,"column":4},"end":{"line":98,"column":null}},"18":{"start":{"line":97,"column":6},"end":{"line":97,"column":null}},"19":{"start":{"line":100,"column":18},"end":{"line":100,"column":null}},"20":{"start":{"line":101,"column":4},"end":{"line":103,"column":null}},"21":{"start":{"line":102,"column":6},"end":{"line":102,"column":null}},"22":{"start":{"line":107,"column":32},"end":{"line":107,"column":null}},"23":{"start":{"line":109,"column":46},"end":{"line":117,"column":null}},"24":{"start":{"line":119,"column":4},"end":{"line":119,"column":null}},"25":{"start":{"line":122,"column":36},"end":{"line":131,"column":null}},"26":{"start":{"line":132,"column":4},"end":{"line":132,"column":null}},"27":{"start":{"line":140,"column":24},"end":{"line":142,"column":null}},"28":{"start":{"line":141,"column":16},"end":{"line":141,"column":null}},"29":{"start":{"line":144,"column":4},"end":{"line":146,"column":null}},"30":{"start":{"line":145,"column":6},"end":{"line":145,"column":null}},"31":{"start":{"line":149,"column":23},"end":{"line":151,"column":null}},"32":{"start":{"line":150,"column":6},"end":{"line":150,"column":null}},"33":{"start":{"line":150,"column":42},"end":{"line":150,"column":73}},"34":{"start":{"line":153,"column":4},"end":{"line":155,"column":null}},"35":{"start":{"line":154,"column":6},"end":{"line":154,"column":null}},"36":{"start":{"line":158,"column":50},"end":{"line":158,"column":null}},"37":{"start":{"line":160,"column":4},"end":{"line":166,"column":null}},"38":{"start":{"line":161,"column":27},"end":{"line":161,"column":null}},"39":{"start":{"line":162,"column":6},"end":{"line":164,"column":null}},"40":{"start":{"line":163,"column":8},"end":{"line":163,"column":null}},"41":{"start":{"line":165,"column":6},"end":{"line":165,"column":null}},"42":{"start":{"line":169,"column":17},"end":{"line":169,"column":null}},"43":{"start":{"line":170,"column":4},"end":{"line":177,"column":null}},"44":{"start":{"line":185,"column":4},"end":{"line":187,"column":null}},"45":{"start":{"line":186,"column":6},"end":{"line":186,"column":null}},"46":{"start":{"line":189,"column":35},"end":{"line":189,"column":null}},"47":{"start":{"line":192,"column":19},"end":{"line":192,"column":null}},"48":{"start":{"line":194,"column":4},"end":{"line":272,"column":null}},"49":{"start":{"line":195,"column":24},"end":{"line":195,"column":null}},"50":{"start":{"line":198,"column":6},"end":{"line":198,"column":null}},"51":{"start":{"line":201,"column":44},"end":{"line":210,"column":null}},"52":{"start":{"line":211,"column":6},"end":{"line":211,"column":null}},"53":{"start":{"line":214,"column":26},"end":{"line":214,"column":null}},"54":{"start":{"line":216,"column":6},"end":{"line":268,"column":null}},"55":{"start":{"line":218,"column":8},"end":{"line":218,"column":null}},"56":{"start":{"line":219,"column":8},"end":{"line":219,"column":null}},"57":{"start":{"line":222,"column":52},"end":{"line":231,"column":null}},"58":{"start":{"line":232,"column":8},"end":{"line":232,"column":null}},"59":{"start":{"line":234,"column":8},"end":{"line":238,"column":null}},"60":{"start":{"line":241,"column":26},"end":{"line":241,"column":null}},"61":{"start":{"line":242,"column":8},"end":{"line":242,"column":null}},"62":{"start":{"line":243,"column":8},"end":{"line":243,"column":null}},"63":{"start":{"line":246,"column":52},"end":{"line":256,"column":null}},"64":{"start":{"line":257,"column":8},"end":{"line":257,"column":null}},"65":{"start":{"line":260,"column":8},"end":{"line":260,"column":null}},"66":{"start":{"line":262,"column":8},"end":{"line":267,"column":null}},"67":{"start":{"line":271,"column":6},"end":{"line":271,"column":null}},"68":{"start":{"line":274,"column":4},"end":{"line":274,"column":null}},"69":{"start":{"line":282,"column":4},"end":{"line":284,"column":null}},"70":{"start":{"line":283,"column":6},"end":{"line":283,"column":null}},"71":{"start":{"line":286,"column":4},"end":{"line":286,"column":null}},"72":{"start":{"line":298,"column":21},"end":{"line":298,"column":null}},"73":{"start":{"line":301,"column":19},"end":{"line":310,"column":null}},"74":{"start":{"line":302,"column":24},"end":{"line":302,"column":48}},"75":{"start":{"line":303,"column":22},"end":{"line":310,"column":8}},"76":{"start":{"line":312,"column":23},"end":{"line":321,"column":null}},"77":{"start":{"line":313,"column":24},"end":{"line":313,"column":53}},"78":{"start":{"line":314,"column":22},"end":{"line":321,"column":8}},"79":{"start":{"line":323,"column":19},"end":{"line":323,"column":null}},"80":{"start":{"line":325,"column":23},"end":{"line":328,"column":null}},"81":{"start":{"line":325,"column":96},"end":{"line":328,"column":6}},"82":{"start":{"line":330,"column":4},"end":{"line":330,"column":null}}},"fnMap":{"0":{"name":"(anonymous_0)","decl":{"start":{"line":59,"column":2},"end":{"line":59,"column":null}},"loc":{"start":{"line":66,"column":4},"end":{"line":78,"column":null}},"line":66},"1":{"name":"(anonymous_1)","decl":{"start":{"line":84,"column":8},"end":{"line":84,"column":19}},"loc":{"start":{"line":84,"column":50},"end":{"line":133,"column":null}},"line":84},"2":{"name":"(anonymous_2)","decl":{"start":{"line":139,"column":8},"end":{"line":139,"column":59}},"loc":{"start":{"line":139,"column":59},"end":{"line":178,"column":null}},"line":139},"3":{"name":"(anonymous_3)","decl":{"start":{"line":141,"column":6},"end":{"line":141,"column":7}},"loc":{"start":{"line":141,"column":16},"end":{"line":141,"column":null}},"line":141},"4":{"name":"(anonymous_4)","decl":{"start":{"line":149,"column":42},"end":{"line":149,"column":43}},"loc":{"start":{"line":150,"column":6},"end":{"line":150,"column":null}},"line":150},"5":{"name":"(anonymous_5)","decl":{"start":{"line":150,"column":27},"end":{"line":150,"column":28}},"loc":{"start":{"line":150,"column":42},"end":{"line":150,"column":73}},"line":150},"6":{"name":"(anonymous_6)","decl":{"start":{"line":160,"column":20},"end":{"line":160,"column":21}},"loc":{"start":{"line":160,"column":30},"end":{"line":166,"column":5}},"line":160},"7":{"name":"(anonymous_7)","decl":{"start":{"line":184,"column":8},"end":{"line":184,"column":22}},"loc":{"start":{"line":184,"column":68},"end":{"line":275,"column":null}},"line":184},"8":{"name":"(anonymous_8)","decl":{"start":{"line":281,"column":8},"end":{"line":281,"column":23}},"loc":{"start":{"line":281,"column":75},"end":{"line":287,"column":null}},"line":281},"9":{"name":"(anonymous_9)","decl":{"start":{"line":292,"column":8},"end":{"line":292,"column":null}},"loc":{"start":{"line":297,"column":5},"end":{"line":331,"column":null}},"line":297},"10":{"name":"(anonymous_10)","decl":{"start":{"line":302,"column":14},"end":{"line":302,"column":15}},"loc":{"start":{"line":302,"column":24},"end":{"line":302,"column":48}},"line":302},"11":{"name":"(anonymous_11)","decl":{"start":{"line":303,"column":11},"end":{"line":303,"column":12}},"loc":{"start":{"line":303,"column":22},"end":{"line":310,"column":8}},"line":303},"12":{"name":"(anonymous_12)","decl":{"start":{"line":313,"column":14},"end":{"line":313,"column":15}},"loc":{"start":{"line":313,"column":24},"end":{"line":313,"column":53}},"line":313},"13":{"name":"(anonymous_13)","decl":{"start":{"line":314,"column":11},"end":{"line":314,"column":12}},"loc":{"start":{"line":314,"column":22},"end":{"line":321,"column":8}},"line":314},"14":{"name":"(anonymous_14)","decl":{"start":{"line":325,"column":70},"end":{"line":325,"column":71}},"loc":{"start":{"line":325,"column":96},"end":{"line":328,"column":6}},"line":325}},"branchMap":{"0":{"loc":{"start":{"line":68,"column":4},"end":{"line":77,"column":null}},"type":"if","locations":[{"start":{"line":68,"column":4},"end":{"line":77,"column":null}},{"start":{"line":70,"column":4},"end":{"line":77,"column":null}}],"line":68},"1":{"loc":{"start":{"line":70,"column":4},"end":{"line":77,"column":null}},"type":"if","locations":[{"start":{"line":70,"column":4},"end":{"line":77,"column":null}},{"start":{},"end":{}}],"line":70},"2":{"loc":{"start":{"line":70,"column":15},"end":{"line":70,"column":50}},"type":"binary-expr","locations":[{"start":{"line":70,"column":15},"end":{"line":70,"column":33}},{"start":{"line":70,"column":33},"end":{"line":70,"column":50}}],"line":70},"3":{"loc":{"start":{"line":86,"column":4},"end":{"line":88,"column":null}},"type":"if","locations":[{"start":{"line":86,"column":4},"end":{"line":88,"column":null}},{"start":{},"end":{}}],"line":86},"4":{"loc":{"start":{"line":91,"column":4},"end":{"line":93,"column":null}},"type":"if","locations":[{"start":{"line":91,"column":4},"end":{"line":93,"column":null}},{"start":{},"end":{}}],"line":91},"5":{"loc":{"start":{"line":96,"column":4},"end":{"line":98,"column":null}},"type":"if","locations":[{"start":{"line":96,"column":4},"end":{"line":98,"column":null}},{"start":{},"end":{}}],"line":96},"6":{"loc":{"start":{"line":101,"column":4},"end":{"line":103,"column":null}},"type":"if","locations":[{"start":{"line":101,"column":4},"end":{"line":103,"column":null}},{"start":{},"end":{}}],"line":101},"7":{"loc":{"start":{"line":144,"column":4},"end":{"line":146,"column":null}},"type":"if","locations":[{"start":{"line":144,"column":4},"end":{"line":146,"column":null}},{"start":{},"end":{}}],"line":144},"8":{"loc":{"start":{"line":153,"column":4},"end":{"line":155,"column":null}},"type":"if","locations":[{"start":{"line":153,"column":4},"end":{"line":155,"column":null}},{"start":{},"end":{}}],"line":153},"9":{"loc":{"start":{"line":162,"column":6},"end":{"line":164,"column":null}},"type":"if","locations":[{"start":{"line":162,"column":6},"end":{"line":164,"column":null}},{"start":{},"end":{}}],"line":162},"10":{"loc":{"start":{"line":185,"column":4},"end":{"line":187,"column":null}},"type":"if","locations":[{"start":{"line":185,"column":4},"end":{"line":187,"column":null}},{"start":{},"end":{}}],"line":185},"11":{"loc":{"start":{"line":216,"column":6},"end":{"line":268,"column":null}},"type":"if","locations":[{"start":{"line":216,"column":6},"end":{"line":268,"column":null}},{"start":{"line":239,"column":13},"end":{"line":268,"column":null}}],"line":216},"12":{"loc":{"start":{"line":241,"column":26},"end":{"line":241,"column":null}},"type":"binary-expr","locations":[{"start":{"line":241,"column":26},"end":{"line":241,"column":51}},{"start":{"line":241,"column":51},"end":{"line":241,"column":null}}],"line":241},"13":{"loc":{"start":{"line":282,"column":4},"end":{"line":284,"column":null}},"type":"if","locations":[{"start":{"line":282,"column":4},"end":{"line":284,"column":null}},{"start":{},"end":{}}],"line":282}},"s":{"0":105,"1":105,"2":105,"3":105,"4":105,"5":105,"6":105,"7":105,"8":105,"9":0,"10":105,"11":103,"12":40,"13":1,"14":39,"15":39,"16":1,"17":38,"18":1,"19":37,"20":37,"21":1,"22":36,"23":36,"24":36,"25":36,"26":36,"27":54,"28":37,"29":54,"30":24,"31":30,"32":37,"33":0,"34":30,"35":0,"36":30,"37":30,"38":9,"39":9,"40":7,"41":2,"42":30,"43":30,"44":24,"45":1,"46":23,"47":23,"48":23,"49":27,"50":27,"51":27,"52":27,"53":27,"54":27,"55":15,"56":15,"57":15,"58":15,"59":15,"60":12,"61":12,"62":12,"63":12,"64":12,"65":12,"66":12,"67":27,"68":23,"69":14,"70":0,"71":14,"72":11,"73":11,"74":3,"75":3,"76":11,"77":3,"78":0,"79":11,"80":11,"81":8,"82":11},"f":{"0":105,"1":40,"2":54,"3":37,"4":37,"5":0,"6":9,"7":24,"8":14,"9":11,"10":3,"11":3,"12":3,"13":0,"14":8},"b":{"0":[0,105],"1":[103,2],"2":[105,104],"3":[1,39],"4":[1,38],"5":[1,37],"6":[1,36],"7":[24,30],"8":[0,30],"9":[7,2],"10":[1,23],"11":[15,12],"12":[12,0],"13":[0,14]},"meta":{"lastBranch":14,"lastFunction":15,"lastStatement":83,"seen":{"s:48:60:48:Infinity":0,"s:51:37:51:Infinity":1,"s:54:51:54:Infinity":2,"f:59:2:59:Infinity":0,"s:60:12:60:Infinity":3,"s:61:12:61:Infinity":4,"s:62:12:62:Infinity":5,"s:63:12:63:Infinity":6,"s:64:12:64:Infinity":7,"b:68:4:77:Infinity:70:4:77:Infinity":0,"s:68:4:77:Infinity":8,"s:69:6:69:Infinity":9,"b:70:4:77:Infinity:undefined:undefined:undefined:undefined":1,"s:70:4:77:Infinity":10,"b:70:15:70:33:70:33:70:50":2,"s:71:6:76:Infinity":11,"f:84:8:84:19":1,"b:86:4:88:Infinity:undefined:undefined:undefined:undefined":3,"s:86:4:88:Infinity":12,"s:87:6:87:Infinity":13,"s:90:17:90:Infinity":14,"b:91:4:93:Infinity:undefined:undefined:undefined:undefined":4,"s:91:4:93:Infinity":15,"s:92:6:92:Infinity":16,"b:96:4:98:Infinity:undefined:undefined:undefined:undefined":5,"s:96:4:98:Infinity":17,"s:97:6:97:Infinity":18,"s:100:18:100:Infinity":19,"b:101:4:103:Infinity:undefined:undefined:undefined:undefined":6,"s:101:4:103:Infinity":20,"s:102:6:102:Infinity":21,"s:107:32:107:Infinity":22,"s:109:46:117:Infinity":23,"s:119:4:119:Infinity":24,"s:122:36:131:Infinity":25,"s:132:4:132:Infinity":26,"f:139:8:139:59":2,"s:140:24:142:Infinity":27,"f:141:6:141:7":3,"s:141:16:141:Infinity":28,"b:144:4:146:Infinity:undefined:undefined:undefined:undefined":7,"s:144:4:146:Infinity":29,"s:145:6:145:Infinity":30,"s:149:23:151:Infinity":31,"f:149:42:149:43":4,"s:150:6:150:Infinity":32,"f:150:27:150:28":5,"s:150:42:150:73":33,"b:153:4:155:Infinity:undefined:undefined:undefined:undefined":8,"s:153:4:155:Infinity":34,"s:154:6:154:Infinity":35,"s:158:50:158:Infinity":36,"s:160:4:166:Infinity":37,"f:160:20:160:21":6,"s:161:27:161:Infinity":38,"b:162:6:164:Infinity:undefined:undefined:undefined:undefined":9,"s:162:6:164:Infinity":39,"s:163:8:163:Infinity":40,"s:165:6:165:Infinity":41,"s:169:17:169:Infinity":42,"s:170:4:177:Infinity":43,"f:184:8:184:22":7,"b:185:4:187:Infinity:undefined:undefined:undefined:undefined":10,"s:185:4:187:Infinity":44,"s:186:6:186:Infinity":45,"s:189:35:189:Infinity":46,"s:192:19:192:Infinity":47,"s:194:4:272:Infinity":48,"s:195:24:195:Infinity":49,"s:198:6:198:Infinity":50,"s:201:44:210:Infinity":51,"s:211:6:211:Infinity":52,"s:214:26:214:Infinity":53,"b:216:6:268:Infinity:239:13:268:Infinity":11,"s:216:6:268:Infinity":54,"s:218:8:218:Infinity":55,"s:219:8:219:Infinity":56,"s:222:52:231:Infinity":57,"s:232:8:232:Infinity":58,"s:234:8:238:Infinity":59,"s:241:26:241:Infinity":60,"b:241:26:241:51:241:51:241:Infinity":12,"s:242:8:242:Infinity":61,"s:243:8:243:Infinity":62,"s:246:52:256:Infinity":63,"s:257:8:257:Infinity":64,"s:260:8:260:Infinity":65,"s:262:8:267:Infinity":66,"s:271:6:271:Infinity":67,"s:274:4:274:Infinity":68,"f:281:8:281:23":8,"b:282:4:284:Infinity:undefined:undefined:undefined:undefined":13,"s:282:4:284:Infinity":69,"s:283:6:283:Infinity":70,"s:286:4:286:Infinity":71,"f:292:8:292:Infinity":9,"s:298:21:298:Infinity":72,"s:301:19:310:Infinity":73,"f:302:14:302:15":10,"s:302:24:302:48":74,"f:303:11:303:12":11,"s:303:22:310:8":75,"s:312:23:321:Infinity":76,"f:313:14:313:15":12,"s:313:24:313:53":77,"f:314:11:314:12":13,"s:314:22:321:8":78,"s:323:19:323:Infinity":79,"s:325:23:328:Infinity":80,"f:325:70:325:71":14,"s:325:96:328:6":81,"s:330:4:330:Infinity":82}}} +,"/Users/lukasmay/development/projects/codewalk-district/src/db/config.ts": {"path":"/Users/lukasmay/development/projects/codewalk-district/src/db/config.ts","statementMap":{"0":{"start":{"line":14,"column":18},"end":{"line":14,"column":null}},"1":{"start":{"line":15,"column":2},"end":{"line":17,"column":null}},"2":{"start":{"line":16,"column":4},"end":{"line":16,"column":null}},"3":{"start":{"line":19,"column":8},"end":{"line":19,"column":null}},"4":{"start":{"line":20,"column":2},"end":{"line":24,"column":null}},"5":{"start":{"line":21,"column":4},"end":{"line":23,"column":null}},"6":{"start":{"line":25,"column":2},"end":{"line":25,"column":null}},"7":{"start":{"line":34,"column":2},"end":{"line":36,"column":null}},"8":{"start":{"line":35,"column":4},"end":{"line":35,"column":null}},"9":{"start":{"line":38,"column":8},"end":{"line":38,"column":null}},"10":{"start":{"line":39,"column":2},"end":{"line":39,"column":null}}},"fnMap":{"0":{"name":"getDbPath","decl":{"start":{"line":13,"column":16},"end":{"line":13,"column":36}},"loc":{"start":{"line":13,"column":36},"end":{"line":26,"column":null}},"line":13},"1":{"name":"ensureDbDirectory","decl":{"start":{"line":32,"column":16},"end":{"line":32,"column":34}},"loc":{"start":{"line":32,"column":56},"end":{"line":40,"column":null}},"line":32}},"branchMap":{"0":{"loc":{"start":{"line":15,"column":2},"end":{"line":17,"column":null}},"type":"if","locations":[{"start":{"line":15,"column":2},"end":{"line":17,"column":null}},{"start":{},"end":{}}],"line":15},"1":{"loc":{"start":{"line":20,"column":2},"end":{"line":24,"column":null}},"type":"if","locations":[{"start":{"line":20,"column":2},"end":{"line":24,"column":null}},{"start":{},"end":{}}],"line":20},"2":{"loc":{"start":{"line":34,"column":2},"end":{"line":36,"column":null}},"type":"if","locations":[{"start":{"line":34,"column":2},"end":{"line":36,"column":null}},{"start":{},"end":{}}],"line":34}},"s":{"0":0,"1":0,"2":0,"3":0,"4":0,"5":0,"6":0,"7":0,"8":0,"9":0,"10":0},"f":{"0":0,"1":0},"b":{"0":[0,0],"1":[0,0],"2":[0,0]},"meta":{"lastBranch":3,"lastFunction":2,"lastStatement":11,"seen":{"f:13:16:13:36":0,"s:14:18:14:Infinity":0,"b:15:2:17:Infinity:undefined:undefined:undefined:undefined":0,"s:15:2:17:Infinity":1,"s:16:4:16:Infinity":2,"s:19:8:19:Infinity":3,"b:20:2:24:Infinity:undefined:undefined:undefined:undefined":1,"s:20:2:24:Infinity":4,"s:21:4:23:Infinity":5,"s:25:2:25:Infinity":6,"f:32:16:32:34":1,"b:34:2:36:Infinity:undefined:undefined:undefined:undefined":2,"s:34:2:36:Infinity":7,"s:35:4:35:Infinity":8,"s:38:8:38:Infinity":9,"s:39:2:39:Infinity":10}}} +,"/Users/lukasmay/development/projects/codewalk-district/src/db/ensure-schema.ts": {"path":"/Users/lukasmay/development/projects/codewalk-district/src/db/ensure-schema.ts","statementMap":{"0":{"start":{"line":14,"column":6},"end":{"line":14,"column":null}},"1":{"start":{"line":21,"column":8},"end":{"line":21,"column":null}},"2":{"start":{"line":23,"column":2},"end":{"line":23,"column":null}},"3":{"start":{"line":35,"column":2},"end":{"line":35,"column":null}},"4":{"start":{"line":36,"column":2},"end":{"line":36,"column":null}},"5":{"start":{"line":37,"column":2},"end":{"line":37,"column":null}}},"fnMap":{"0":{"name":"getMigrationsPath","decl":{"start":{"line":20,"column":9},"end":{"line":20,"column":37}},"loc":{"start":{"line":20,"column":37},"end":{"line":24,"column":null}},"line":20},"1":{"name":"ensureSchema","decl":{"start":{"line":34,"column":16},"end":{"line":34,"column":29}},"loc":{"start":{"line":34,"column":56},"end":{"line":38,"column":null}},"line":34}},"branchMap":{},"s":{"0":24,"1":239,"2":239,"3":239,"4":239,"5":239},"f":{"0":239,"1":239},"b":{},"meta":{"lastBranch":0,"lastFunction":2,"lastStatement":6,"seen":{"s:14:6:14:Infinity":0,"f:20:9:20:37":0,"s:21:8:21:Infinity":1,"s:23:2:23:Infinity":2,"f:34:16:34:29":1,"s:35:2:35:Infinity":3,"s:36:2:36:Infinity":4,"s:37:2:37:Infinity":5}}} +,"/Users/lukasmay/development/projects/codewalk-district/src/db/index.ts": {"path":"/Users/lukasmay/development/projects/codewalk-district/src/db/index.ts","statementMap":{"0":{"start":{"line":21,"column":17},"end":{"line":21,"column":null}},"1":{"start":{"line":24,"column":2},"end":{"line":24,"column":null}},"2":{"start":{"line":27,"column":17},"end":{"line":27,"column":null}},"3":{"start":{"line":30,"column":2},"end":{"line":30,"column":null}},"4":{"start":{"line":33,"column":2},"end":{"line":33,"column":null}},"5":{"start":{"line":36,"column":2},"end":{"line":36,"column":null}}},"fnMap":{"0":{"name":"createDatabase","decl":{"start":{"line":20,"column":16},"end":{"line":20,"column":31}},"loc":{"start":{"line":20,"column":63},"end":{"line":37,"column":null}},"line":20}},"branchMap":{"0":{"loc":{"start":{"line":21,"column":17},"end":{"line":21,"column":null}},"type":"binary-expr","locations":[{"start":{"line":21,"column":17},"end":{"line":21,"column":25}},{"start":{"line":21,"column":17},"end":{"line":21,"column":null}}],"line":21}},"s":{"0":0,"1":0,"2":0,"3":0,"4":0,"5":0},"f":{"0":0},"b":{"0":[0,0]},"meta":{"lastBranch":1,"lastFunction":1,"lastStatement":6,"seen":{"f:20:16:20:31":0,"s:21:17:21:Infinity":0,"b:21:17:21:25:21:17:21:Infinity":0,"s:24:2:24:Infinity":1,"s:27:17:27:Infinity":2,"s:30:2:30:Infinity":3,"s:33:2:33:Infinity":4,"s:36:2:36:Infinity":5}}} +,"/Users/lukasmay/development/projects/codewalk-district/src/db/schema.ts": {"path":"/Users/lukasmay/development/projects/codewalk-district/src/db/schema.ts","statementMap":{"0":{"start":{"line":19,"column":13},"end":{"line":34,"column":null}},"1":{"start":{"line":36,"column":13},"end":{"line":42,"column":null}},"2":{"start":{"line":36,"column":74},"end":{"line":42,"column":2}},"3":{"start":{"line":51,"column":13},"end":{"line":63,"column":null}},"4":{"start":{"line":55,"column":22},"end":{"line":55,"column":38}},"5":{"start":{"line":65,"column":13},"end":{"line":75,"column":null}},"6":{"start":{"line":65,"column":69},"end":{"line":75,"column":2}},"7":{"start":{"line":84,"column":13},"end":{"line":93,"column":null}},"8":{"start":{"line":88,"column":22},"end":{"line":88,"column":33}},"9":{"start":{"line":91,"column":22},"end":{"line":91,"column":33}},"10":{"start":{"line":95,"column":13},"end":{"line":106,"column":null}},"11":{"start":{"line":95,"column":85},"end":{"line":106,"column":2}},"12":{"start":{"line":119,"column":31},"end":{"line":129,"column":null}},"13":{"start":{"line":133,"column":13},"end":{"line":164,"column":null}},"14":{"start":{"line":136,"column":45},"end":{"line":136,"column":56}},"15":{"start":{"line":137,"column":55},"end":{"line":137,"column":71}},"16":{"start":{"line":139,"column":81},"end":{"line":139,"column":91}},"17":{"start":{"line":166,"column":13},"end":{"line":187,"column":null}},"18":{"start":{"line":166,"column":67},"end":{"line":187,"column":2}},"19":{"start":{"line":196,"column":13},"end":{"line":205,"column":null}},"20":{"start":{"line":200,"column":22},"end":{"line":200,"column":32}},"21":{"start":{"line":203,"column":22},"end":{"line":203,"column":32}},"22":{"start":{"line":207,"column":13},"end":{"line":218,"column":null}},"23":{"start":{"line":207,"column":83},"end":{"line":218,"column":2}},"24":{"start":{"line":227,"column":13},"end":{"line":239,"column":null}},"25":{"start":{"line":241,"column":13},"end":{"line":243,"column":null}},"26":{"start":{"line":241,"column":68},"end":{"line":243,"column":2}},"27":{"start":{"line":252,"column":13},"end":{"line":277,"column":null}},"28":{"start":{"line":255,"column":43},"end":{"line":255,"column":53}},"29":{"start":{"line":256,"column":55},"end":{"line":256,"column":71}},"30":{"start":{"line":260,"column":49},"end":{"line":260,"column":62}},"31":{"start":{"line":279,"column":13},"end":{"line":293,"column":null}},"32":{"start":{"line":279,"column":69},"end":{"line":293,"column":2}},"33":{"start":{"line":302,"column":13},"end":{"line":319,"column":null}},"34":{"start":{"line":305,"column":22},"end":{"line":305,"column":33}},"35":{"start":{"line":309,"column":22},"end":{"line":309,"column":38}},"36":{"start":{"line":317,"column":14},"end":{"line":319,"column":1}},"37":{"start":{"line":321,"column":13},"end":{"line":331,"column":null}},"38":{"start":{"line":321,"column":77},"end":{"line":331,"column":2}},"39":{"start":{"line":336,"column":13},"end":{"line":350,"column":null}},"40":{"start":{"line":340,"column":22},"end":{"line":340,"column":37}},"41":{"start":{"line":348,"column":14},"end":{"line":350,"column":1}},"42":{"start":{"line":352,"column":13},"end":{"line":357,"column":null}},"43":{"start":{"line":352,"column":83},"end":{"line":357,"column":2}},"44":{"start":{"line":366,"column":13},"end":{"line":385,"column":null}},"45":{"start":{"line":369,"column":47},"end":{"line":369,"column":58}},"46":{"start":{"line":371,"column":53},"end":{"line":371,"column":64}},"47":{"start":{"line":382,"column":87},"end":{"line":382,"column":100}},"48":{"start":{"line":387,"column":13},"end":{"line":408,"column":null}},"49":{"start":{"line":387,"column":73},"end":{"line":408,"column":2}},"50":{"start":{"line":417,"column":13},"end":{"line":428,"column":null}},"51":{"start":{"line":421,"column":22},"end":{"line":421,"column":38}},"52":{"start":{"line":422,"column":81},"end":{"line":422,"column":91}},"53":{"start":{"line":430,"column":13},"end":{"line":441,"column":null}},"54":{"start":{"line":430,"column":67},"end":{"line":441,"column":2}},"55":{"start":{"line":450,"column":13},"end":{"line":457,"column":null}},"56":{"start":{"line":459,"column":13},"end":{"line":461,"column":null}},"57":{"start":{"line":459,"column":68},"end":{"line":461,"column":2}},"58":{"start":{"line":470,"column":13},"end":{"line":481,"column":null}},"59":{"start":{"line":474,"column":22},"end":{"line":474,"column":38}},"60":{"start":{"line":477,"column":22},"end":{"line":477,"column":35}},"61":{"start":{"line":479,"column":14},"end":{"line":481,"column":1}},"62":{"start":{"line":483,"column":13},"end":{"line":492,"column":null}},"63":{"start":{"line":483,"column":87},"end":{"line":492,"column":2}},"64":{"start":{"line":501,"column":13},"end":{"line":510,"column":null}},"65":{"start":{"line":508,"column":14},"end":{"line":510,"column":1}},"66":{"start":{"line":519,"column":13},"end":{"line":534,"column":null}},"67":{"start":{"line":521,"column":64},"end":{"line":521,"column":75}},"68":{"start":{"line":522,"column":60},"end":{"line":522,"column":71}},"69":{"start":{"line":523,"column":55},"end":{"line":523,"column":71}},"70":{"start":{"line":524,"column":45},"end":{"line":524,"column":56}},"71":{"start":{"line":525,"column":43},"end":{"line":525,"column":53}},"72":{"start":{"line":531,"column":14},"end":{"line":534,"column":1}}},"fnMap":{"0":{"name":"(anonymous_0)","decl":{"start":{"line":36,"column":59},"end":{"line":36,"column":60}},"loc":{"start":{"line":36,"column":74},"end":{"line":42,"column":2}},"line":36},"1":{"name":"(anonymous_1)","decl":{"start":{"line":55,"column":16},"end":{"line":55,"column":22}},"loc":{"start":{"line":55,"column":22},"end":{"line":55,"column":38}},"line":55},"2":{"name":"(anonymous_2)","decl":{"start":{"line":65,"column":49},"end":{"line":65,"column":50}},"loc":{"start":{"line":65,"column":69},"end":{"line":75,"column":2}},"line":65},"3":{"name":"(anonymous_3)","decl":{"start":{"line":88,"column":16},"end":{"line":88,"column":22}},"loc":{"start":{"line":88,"column":22},"end":{"line":88,"column":33}},"line":88},"4":{"name":"(anonymous_4)","decl":{"start":{"line":91,"column":16},"end":{"line":91,"column":22}},"loc":{"start":{"line":91,"column":22},"end":{"line":91,"column":33}},"line":91},"5":{"name":"(anonymous_5)","decl":{"start":{"line":95,"column":71},"end":{"line":95,"column":72}},"loc":{"start":{"line":95,"column":85},"end":{"line":106,"column":2}},"line":95},"6":{"name":"(anonymous_6)","decl":{"start":{"line":136,"column":39},"end":{"line":136,"column":45}},"loc":{"start":{"line":136,"column":45},"end":{"line":136,"column":56}},"line":136},"7":{"name":"(anonymous_7)","decl":{"start":{"line":137,"column":49},"end":{"line":137,"column":55}},"loc":{"start":{"line":137,"column":55},"end":{"line":137,"column":71}},"line":137},"8":{"name":"(anonymous_8)","decl":{"start":{"line":139,"column":50},"end":{"line":139,"column":81}},"loc":{"start":{"line":139,"column":81},"end":{"line":139,"column":91}},"line":139},"9":{"name":"(anonymous_9)","decl":{"start":{"line":166,"column":47},"end":{"line":166,"column":48}},"loc":{"start":{"line":166,"column":67},"end":{"line":187,"column":2}},"line":166},"10":{"name":"(anonymous_10)","decl":{"start":{"line":200,"column":16},"end":{"line":200,"column":22}},"loc":{"start":{"line":200,"column":22},"end":{"line":200,"column":32}},"line":200},"11":{"name":"(anonymous_11)","decl":{"start":{"line":203,"column":16},"end":{"line":203,"column":22}},"loc":{"start":{"line":203,"column":22},"end":{"line":203,"column":32}},"line":203},"12":{"name":"(anonymous_12)","decl":{"start":{"line":207,"column":69},"end":{"line":207,"column":70}},"loc":{"start":{"line":207,"column":83},"end":{"line":218,"column":2}},"line":207},"13":{"name":"(anonymous_13)","decl":{"start":{"line":241,"column":53},"end":{"line":241,"column":54}},"loc":{"start":{"line":241,"column":68},"end":{"line":243,"column":2}},"line":241},"14":{"name":"(anonymous_14)","decl":{"start":{"line":255,"column":37},"end":{"line":255,"column":43}},"loc":{"start":{"line":255,"column":43},"end":{"line":255,"column":53}},"line":255},"15":{"name":"(anonymous_15)","decl":{"start":{"line":256,"column":49},"end":{"line":256,"column":55}},"loc":{"start":{"line":256,"column":55},"end":{"line":256,"column":71}},"line":256},"16":{"name":"(anonymous_16)","decl":{"start":{"line":260,"column":43},"end":{"line":260,"column":49}},"loc":{"start":{"line":260,"column":49},"end":{"line":260,"column":62}},"line":260},"17":{"name":"(anonymous_17)","decl":{"start":{"line":279,"column":49},"end":{"line":279,"column":50}},"loc":{"start":{"line":279,"column":69},"end":{"line":293,"column":2}},"line":279},"18":{"name":"(anonymous_18)","decl":{"start":{"line":305,"column":16},"end":{"line":305,"column":22}},"loc":{"start":{"line":305,"column":22},"end":{"line":305,"column":33}},"line":305},"19":{"name":"(anonymous_19)","decl":{"start":{"line":309,"column":16},"end":{"line":309,"column":22}},"loc":{"start":{"line":309,"column":22},"end":{"line":309,"column":38}},"line":309},"20":{"name":"(anonymous_20)","decl":{"start":{"line":317,"column":3},"end":{"line":317,"column":4}},"loc":{"start":{"line":317,"column":14},"end":{"line":319,"column":1}},"line":317},"21":{"name":"(anonymous_21)","decl":{"start":{"line":321,"column":57},"end":{"line":321,"column":58}},"loc":{"start":{"line":321,"column":77},"end":{"line":331,"column":2}},"line":321},"22":{"name":"(anonymous_22)","decl":{"start":{"line":340,"column":16},"end":{"line":340,"column":22}},"loc":{"start":{"line":340,"column":22},"end":{"line":340,"column":37}},"line":340},"23":{"name":"(anonymous_23)","decl":{"start":{"line":348,"column":3},"end":{"line":348,"column":4}},"loc":{"start":{"line":348,"column":14},"end":{"line":350,"column":1}},"line":348},"24":{"name":"(anonymous_24)","decl":{"start":{"line":352,"column":69},"end":{"line":352,"column":70}},"loc":{"start":{"line":352,"column":83},"end":{"line":357,"column":2}},"line":352},"25":{"name":"(anonymous_25)","decl":{"start":{"line":369,"column":41},"end":{"line":369,"column":47}},"loc":{"start":{"line":369,"column":47},"end":{"line":369,"column":58}},"line":369},"26":{"name":"(anonymous_26)","decl":{"start":{"line":371,"column":47},"end":{"line":371,"column":53}},"loc":{"start":{"line":371,"column":53},"end":{"line":371,"column":64}},"line":371},"27":{"name":"(anonymous_27)","decl":{"start":{"line":382,"column":56},"end":{"line":382,"column":87}},"loc":{"start":{"line":382,"column":87},"end":{"line":382,"column":100}},"line":382},"28":{"name":"(anonymous_28)","decl":{"start":{"line":387,"column":53},"end":{"line":387,"column":54}},"loc":{"start":{"line":387,"column":73},"end":{"line":408,"column":2}},"line":387},"29":{"name":"(anonymous_29)","decl":{"start":{"line":421,"column":16},"end":{"line":421,"column":22}},"loc":{"start":{"line":421,"column":22},"end":{"line":421,"column":38}},"line":421},"30":{"name":"(anonymous_30)","decl":{"start":{"line":422,"column":50},"end":{"line":422,"column":81}},"loc":{"start":{"line":422,"column":81},"end":{"line":422,"column":91}},"line":422},"31":{"name":"(anonymous_31)","decl":{"start":{"line":430,"column":47},"end":{"line":430,"column":48}},"loc":{"start":{"line":430,"column":67},"end":{"line":441,"column":2}},"line":430},"32":{"name":"(anonymous_32)","decl":{"start":{"line":459,"column":53},"end":{"line":459,"column":54}},"loc":{"start":{"line":459,"column":68},"end":{"line":461,"column":2}},"line":459},"33":{"name":"(anonymous_33)","decl":{"start":{"line":474,"column":16},"end":{"line":474,"column":22}},"loc":{"start":{"line":474,"column":22},"end":{"line":474,"column":38}},"line":474},"34":{"name":"(anonymous_34)","decl":{"start":{"line":477,"column":16},"end":{"line":477,"column":22}},"loc":{"start":{"line":477,"column":22},"end":{"line":477,"column":35}},"line":477},"35":{"name":"(anonymous_35)","decl":{"start":{"line":479,"column":3},"end":{"line":479,"column":4}},"loc":{"start":{"line":479,"column":14},"end":{"line":481,"column":1}},"line":479},"36":{"name":"(anonymous_36)","decl":{"start":{"line":483,"column":73},"end":{"line":483,"column":74}},"loc":{"start":{"line":483,"column":87},"end":{"line":492,"column":2}},"line":483},"37":{"name":"(anonymous_37)","decl":{"start":{"line":508,"column":3},"end":{"line":508,"column":4}},"loc":{"start":{"line":508,"column":14},"end":{"line":510,"column":1}},"line":508},"38":{"name":"(anonymous_38)","decl":{"start":{"line":521,"column":58},"end":{"line":521,"column":64}},"loc":{"start":{"line":521,"column":64},"end":{"line":521,"column":75}},"line":521},"39":{"name":"(anonymous_39)","decl":{"start":{"line":522,"column":54},"end":{"line":522,"column":60}},"loc":{"start":{"line":522,"column":60},"end":{"line":522,"column":71}},"line":522},"40":{"name":"(anonymous_40)","decl":{"start":{"line":523,"column":49},"end":{"line":523,"column":55}},"loc":{"start":{"line":523,"column":55},"end":{"line":523,"column":71}},"line":523},"41":{"name":"(anonymous_41)","decl":{"start":{"line":524,"column":39},"end":{"line":524,"column":45}},"loc":{"start":{"line":524,"column":45},"end":{"line":524,"column":56}},"line":524},"42":{"name":"(anonymous_42)","decl":{"start":{"line":525,"column":37},"end":{"line":525,"column":43}},"loc":{"start":{"line":525,"column":43},"end":{"line":525,"column":53}},"line":525},"43":{"name":"(anonymous_43)","decl":{"start":{"line":531,"column":3},"end":{"line":531,"column":4}},"loc":{"start":{"line":531,"column":14},"end":{"line":534,"column":1}},"line":531}},"branchMap":{},"s":{"0":24,"1":24,"2":239,"3":24,"4":0,"5":24,"6":239,"7":24,"8":0,"9":0,"10":24,"11":239,"12":24,"13":24,"14":0,"15":0,"16":0,"17":24,"18":239,"19":24,"20":0,"21":0,"22":24,"23":239,"24":24,"25":24,"26":239,"27":24,"28":0,"29":0,"30":0,"31":24,"32":239,"33":24,"34":0,"35":0,"36":239,"37":24,"38":239,"39":24,"40":0,"41":239,"42":24,"43":239,"44":24,"45":0,"46":0,"47":0,"48":24,"49":239,"50":24,"51":0,"52":0,"53":24,"54":239,"55":24,"56":24,"57":239,"58":24,"59":0,"60":0,"61":239,"62":24,"63":239,"64":24,"65":239,"66":24,"67":0,"68":0,"69":0,"70":0,"71":0,"72":239},"f":{"0":239,"1":0,"2":239,"3":0,"4":0,"5":239,"6":0,"7":0,"8":0,"9":239,"10":0,"11":0,"12":239,"13":239,"14":0,"15":0,"16":0,"17":239,"18":0,"19":0,"20":239,"21":239,"22":0,"23":239,"24":239,"25":0,"26":0,"27":0,"28":239,"29":0,"30":0,"31":239,"32":239,"33":0,"34":0,"35":239,"36":239,"37":239,"38":0,"39":0,"40":0,"41":0,"42":0,"43":239},"b":{},"meta":{"lastBranch":0,"lastFunction":44,"lastStatement":73,"seen":{"s:19:13:34:Infinity":0,"s:36:13:42:Infinity":1,"f:36:59:36:60":0,"s:36:74:42:2":2,"s:51:13:63:Infinity":3,"f:55:16:55:22":1,"s:55:22:55:38":4,"s:65:13:75:Infinity":5,"f:65:49:65:50":2,"s:65:69:75:2":6,"s:84:13:93:Infinity":7,"f:88:16:88:22":3,"s:88:22:88:33":8,"f:91:16:91:22":4,"s:91:22:91:33":9,"s:95:13:106:Infinity":10,"f:95:71:95:72":5,"s:95:85:106:2":11,"s:119:31:129:Infinity":12,"s:133:13:164:Infinity":13,"f:136:39:136:45":6,"s:136:45:136:56":14,"f:137:49:137:55":7,"s:137:55:137:71":15,"f:139:50:139:81":8,"s:139:81:139:91":16,"s:166:13:187:Infinity":17,"f:166:47:166:48":9,"s:166:67:187:2":18,"s:196:13:205:Infinity":19,"f:200:16:200:22":10,"s:200:22:200:32":20,"f:203:16:203:22":11,"s:203:22:203:32":21,"s:207:13:218:Infinity":22,"f:207:69:207:70":12,"s:207:83:218:2":23,"s:227:13:239:Infinity":24,"s:241:13:243:Infinity":25,"f:241:53:241:54":13,"s:241:68:243:2":26,"s:252:13:277:Infinity":27,"f:255:37:255:43":14,"s:255:43:255:53":28,"f:256:49:256:55":15,"s:256:55:256:71":29,"f:260:43:260:49":16,"s:260:49:260:62":30,"s:279:13:293:Infinity":31,"f:279:49:279:50":17,"s:279:69:293:2":32,"s:302:13:319:Infinity":33,"f:305:16:305:22":18,"s:305:22:305:33":34,"f:309:16:309:22":19,"s:309:22:309:38":35,"f:317:3:317:4":20,"s:317:14:319:1":36,"s:321:13:331:Infinity":37,"f:321:57:321:58":21,"s:321:77:331:2":38,"s:336:13:350:Infinity":39,"f:340:16:340:22":22,"s:340:22:340:37":40,"f:348:3:348:4":23,"s:348:14:350:1":41,"s:352:13:357:Infinity":42,"f:352:69:352:70":24,"s:352:83:357:2":43,"s:366:13:385:Infinity":44,"f:369:41:369:47":25,"s:369:47:369:58":45,"f:371:47:371:53":26,"s:371:53:371:64":46,"f:382:56:382:87":27,"s:382:87:382:100":47,"s:387:13:408:Infinity":48,"f:387:53:387:54":28,"s:387:73:408:2":49,"s:417:13:428:Infinity":50,"f:421:16:421:22":29,"s:421:22:421:38":51,"f:422:50:422:81":30,"s:422:81:422:91":52,"s:430:13:441:Infinity":53,"f:430:47:430:48":31,"s:430:67:441:2":54,"s:450:13:457:Infinity":55,"s:459:13:461:Infinity":56,"f:459:53:459:54":32,"s:459:68:461:2":57,"s:470:13:481:Infinity":58,"f:474:16:474:22":33,"s:474:22:474:38":59,"f:477:16:477:22":34,"s:477:22:477:35":60,"f:479:3:479:4":35,"s:479:14:481:1":61,"s:483:13:492:Infinity":62,"f:483:73:483:74":36,"s:483:87:492:2":63,"s:501:13:510:Infinity":64,"f:508:3:508:4":37,"s:508:14:510:1":65,"s:519:13:534:Infinity":66,"f:521:58:521:64":38,"s:521:64:521:75":67,"f:522:54:522:60":39,"s:522:60:522:71":68,"f:523:49:523:55":40,"s:523:55:523:71":69,"f:524:39:524:45":41,"s:524:45:524:56":70,"f:525:37:525:43":42,"s:525:43:525:53":71,"f:531:3:531:4":43,"s:531:14:534:1":72}}} +,"/Users/lukasmay/development/projects/codewalk-district/src/db/repositories/index.ts": {"path":"/Users/lukasmay/development/projects/codewalk-district/src/db/repositories/index.ts","statementMap":{},"fnMap":{},"branchMap":{},"s":{},"f":{},"b":{},"meta":{"lastBranch":0,"lastFunction":0,"lastStatement":0,"seen":{}}} +,"/Users/lukasmay/development/projects/codewalk-district/src/db/repositories/drizzle/account.ts": {"path":"/Users/lukasmay/development/projects/codewalk-district/src/db/repositories/drizzle/account.ts","statementMap":{"0":{"start":{"line":16,"column":22},"end":{"line":16,"column":43}},"1":{"start":{"line":19,"column":10},"end":{"line":19,"column":null}},"2":{"start":{"line":20,"column":16},"end":{"line":20,"column":null}},"3":{"start":{"line":22,"column":22},"end":{"line":34,"column":null}},"4":{"start":{"line":36,"column":4},"end":{"line":36,"column":null}},"5":{"start":{"line":40,"column":19},"end":{"line":44,"column":null}},"6":{"start":{"line":45,"column":4},"end":{"line":45,"column":null}},"7":{"start":{"line":49,"column":19},"end":{"line":53,"column":null}},"8":{"start":{"line":54,"column":4},"end":{"line":54,"column":null}},"9":{"start":{"line":58,"column":4},"end":{"line":61,"column":null}},"10":{"start":{"line":65,"column":4},"end":{"line":65,"column":null}},"11":{"start":{"line":67,"column":19},"end":{"line":77,"column":null}},"12":{"start":{"line":79,"column":4},"end":{"line":79,"column":null}},"13":{"start":{"line":83,"column":16},"end":{"line":83,"column":null}},"14":{"start":{"line":84,"column":22},"end":{"line":92,"column":null}},"15":{"start":{"line":94,"column":4},"end":{"line":96,"column":null}},"16":{"start":{"line":95,"column":6},"end":{"line":95,"column":null}},"17":{"start":{"line":98,"column":4},"end":{"line":98,"column":null}},"18":{"start":{"line":102,"column":16},"end":{"line":102,"column":null}},"19":{"start":{"line":103,"column":22},"end":{"line":111,"column":null}},"20":{"start":{"line":113,"column":4},"end":{"line":115,"column":null}},"21":{"start":{"line":114,"column":6},"end":{"line":114,"column":null}},"22":{"start":{"line":117,"column":4},"end":{"line":117,"column":null}},"23":{"start":{"line":121,"column":16},"end":{"line":121,"column":null}},"24":{"start":{"line":122,"column":22},"end":{"line":126,"column":null}},"25":{"start":{"line":128,"column":4},"end":{"line":130,"column":null}},"26":{"start":{"line":129,"column":6},"end":{"line":129,"column":null}},"27":{"start":{"line":132,"column":4},"end":{"line":132,"column":null}},"28":{"start":{"line":136,"column":16},"end":{"line":136,"column":null}},"29":{"start":{"line":138,"column":20},"end":{"line":151,"column":null}},"30":{"start":{"line":153,"column":4},"end":{"line":153,"column":null}},"31":{"start":{"line":157,"column":4},"end":{"line":157,"column":null}},"32":{"start":{"line":161,"column":16},"end":{"line":161,"column":null}},"33":{"start":{"line":162,"column":22},"end":{"line":166,"column":null}},"34":{"start":{"line":168,"column":4},"end":{"line":170,"column":null}},"35":{"start":{"line":169,"column":6},"end":{"line":169,"column":null}},"36":{"start":{"line":172,"column":4},"end":{"line":172,"column":null}},"37":{"start":{"line":176,"column":16},"end":{"line":176,"column":null}},"38":{"start":{"line":177,"column":22},"end":{"line":181,"column":null}},"39":{"start":{"line":183,"column":4},"end":{"line":185,"column":null}},"40":{"start":{"line":184,"column":6},"end":{"line":184,"column":null}},"41":{"start":{"line":187,"column":4},"end":{"line":187,"column":null}},"42":{"start":{"line":192,"column":4},"end":{"line":195,"column":null}},"43":{"start":{"line":197,"column":22},"end":{"line":197,"column":null}},"44":{"start":{"line":199,"column":4},"end":{"line":201,"column":null}},"45":{"start":{"line":200,"column":6},"end":{"line":200,"column":null}}},"fnMap":{"0":{"name":"(anonymous_0)","decl":{"start":{"line":16,"column":2},"end":{"line":16,"column":22}},"loc":{"start":{"line":16,"column":43},"end":{"line":16,"column":null}},"line":16},"1":{"name":"(anonymous_1)","decl":{"start":{"line":18,"column":8},"end":{"line":18,"column":15}},"loc":{"start":{"line":18,"column":58},"end":{"line":37,"column":null}},"line":18},"2":{"name":"(anonymous_2)","decl":{"start":{"line":39,"column":8},"end":{"line":39,"column":17}},"loc":{"start":{"line":39,"column":54},"end":{"line":46,"column":null}},"line":39},"3":{"name":"(anonymous_3)","decl":{"start":{"line":48,"column":8},"end":{"line":48,"column":20}},"loc":{"start":{"line":48,"column":60},"end":{"line":55,"column":null}},"line":48},"4":{"name":"(anonymous_4)","decl":{"start":{"line":57,"column":8},"end":{"line":57,"column":23}},"loc":{"start":{"line":57,"column":61},"end":{"line":62,"column":null}},"line":57},"5":{"name":"(anonymous_5)","decl":{"start":{"line":64,"column":8},"end":{"line":64,"column":26}},"loc":{"start":{"line":64,"column":69},"end":{"line":80,"column":null}},"line":64},"6":{"name":"(anonymous_6)","decl":{"start":{"line":82,"column":8},"end":{"line":82,"column":22}},"loc":{"start":{"line":82,"column":65},"end":{"line":99,"column":null}},"line":82},"7":{"name":"(anonymous_7)","decl":{"start":{"line":101,"column":8},"end":{"line":101,"column":22}},"loc":{"start":{"line":101,"column":52},"end":{"line":118,"column":null}},"line":101},"8":{"name":"(anonymous_8)","decl":{"start":{"line":120,"column":8},"end":{"line":120,"column":23}},"loc":{"start":{"line":120,"column":53},"end":{"line":133,"column":null}},"line":120},"9":{"name":"(anonymous_9)","decl":{"start":{"line":135,"column":8},"end":{"line":135,"column":50}},"loc":{"start":{"line":135,"column":50},"end":{"line":154,"column":null}},"line":135},"10":{"name":"(anonymous_10)","decl":{"start":{"line":156,"column":8},"end":{"line":156,"column":38}},"loc":{"start":{"line":156,"column":38},"end":{"line":158,"column":null}},"line":156},"11":{"name":"(anonymous_11)","decl":{"start":{"line":160,"column":8},"end":{"line":160,"column":26}},"loc":{"start":{"line":160,"column":77},"end":{"line":173,"column":null}},"line":160},"12":{"name":"(anonymous_12)","decl":{"start":{"line":175,"column":8},"end":{"line":175,"column":26}},"loc":{"start":{"line":175,"column":97},"end":{"line":188,"column":null}},"line":175},"13":{"name":"(anonymous_13)","decl":{"start":{"line":190,"column":8},"end":{"line":190,"column":15}},"loc":{"start":{"line":190,"column":42},"end":{"line":202,"column":null}},"line":190}},"branchMap":{"0":{"loc":{"start":{"line":25,"column":16},"end":{"line":25,"column":null}},"type":"binary-expr","locations":[{"start":{"line":25,"column":16},"end":{"line":25,"column":33}},{"start":{"line":25,"column":33},"end":{"line":25,"column":null}}],"line":25},"1":{"loc":{"start":{"line":26,"column":18},"end":{"line":26,"column":null}},"type":"binary-expr","locations":[{"start":{"line":26,"column":18},"end":{"line":26,"column":37}},{"start":{"line":26,"column":37},"end":{"line":26,"column":null}}],"line":26},"2":{"loc":{"start":{"line":27,"column":19},"end":{"line":27,"column":null}},"type":"binary-expr","locations":[{"start":{"line":27,"column":19},"end":{"line":27,"column":39}},{"start":{"line":27,"column":39},"end":{"line":27,"column":null}}],"line":27},"3":{"loc":{"start":{"line":45,"column":11},"end":{"line":45,"column":null}},"type":"binary-expr","locations":[{"start":{"line":45,"column":11},"end":{"line":45,"column":24}},{"start":{"line":45,"column":24},"end":{"line":45,"column":null}}],"line":45},"4":{"loc":{"start":{"line":54,"column":11},"end":{"line":54,"column":null}},"type":"binary-expr","locations":[{"start":{"line":54,"column":11},"end":{"line":54,"column":24}},{"start":{"line":54,"column":24},"end":{"line":54,"column":null}}],"line":54},"5":{"loc":{"start":{"line":79,"column":11},"end":{"line":79,"column":null}},"type":"binary-expr","locations":[{"start":{"line":79,"column":11},"end":{"line":79,"column":24}},{"start":{"line":79,"column":24},"end":{"line":79,"column":null}}],"line":79},"6":{"loc":{"start":{"line":94,"column":4},"end":{"line":96,"column":null}},"type":"if","locations":[{"start":{"line":94,"column":4},"end":{"line":96,"column":null}},{"start":{},"end":{}}],"line":94},"7":{"loc":{"start":{"line":113,"column":4},"end":{"line":115,"column":null}},"type":"if","locations":[{"start":{"line":113,"column":4},"end":{"line":115,"column":null}},{"start":{},"end":{}}],"line":113},"8":{"loc":{"start":{"line":128,"column":4},"end":{"line":130,"column":null}},"type":"if","locations":[{"start":{"line":128,"column":4},"end":{"line":130,"column":null}},{"start":{},"end":{}}],"line":128},"9":{"loc":{"start":{"line":168,"column":4},"end":{"line":170,"column":null}},"type":"if","locations":[{"start":{"line":168,"column":4},"end":{"line":170,"column":null}},{"start":{},"end":{}}],"line":168},"10":{"loc":{"start":{"line":183,"column":4},"end":{"line":185,"column":null}},"type":"if","locations":[{"start":{"line":183,"column":4},"end":{"line":185,"column":null}},{"start":{},"end":{}}],"line":183},"11":{"loc":{"start":{"line":199,"column":4},"end":{"line":201,"column":null}},"type":"if","locations":[{"start":{"line":199,"column":4},"end":{"line":201,"column":null}},{"start":{},"end":{}}],"line":199}},"s":{"0":80,"1":0,"2":0,"3":0,"4":0,"5":0,"6":0,"7":0,"8":0,"9":0,"10":0,"11":0,"12":0,"13":0,"14":0,"15":0,"16":0,"17":0,"18":0,"19":0,"20":0,"21":0,"22":0,"23":0,"24":0,"25":0,"26":0,"27":0,"28":0,"29":0,"30":0,"31":0,"32":0,"33":0,"34":0,"35":0,"36":0,"37":0,"38":0,"39":0,"40":0,"41":0,"42":0,"43":0,"44":0,"45":0},"f":{"0":80,"1":0,"2":0,"3":0,"4":0,"5":0,"6":0,"7":0,"8":0,"9":0,"10":0,"11":0,"12":0,"13":0},"b":{"0":[0,0],"1":[0,0],"2":[0,0],"3":[0,0],"4":[0,0],"5":[0,0],"6":[0,0],"7":[0,0],"8":[0,0],"9":[0,0],"10":[0,0],"11":[0,0]},"meta":{"lastBranch":12,"lastFunction":14,"lastStatement":46,"seen":{"f:16:2:16:22":0,"s:16:22:16:43":0,"f:18:8:18:15":1,"s:19:10:19:Infinity":1,"s:20:16:20:Infinity":2,"s:22:22:34:Infinity":3,"b:25:16:25:33:25:33:25:Infinity":0,"b:26:18:26:37:26:37:26:Infinity":1,"b:27:19:27:39:27:39:27:Infinity":2,"s:36:4:36:Infinity":4,"f:39:8:39:17":2,"s:40:19:44:Infinity":5,"s:45:4:45:Infinity":6,"b:45:11:45:24:45:24:45:Infinity":3,"f:48:8:48:20":3,"s:49:19:53:Infinity":7,"s:54:4:54:Infinity":8,"b:54:11:54:24:54:24:54:Infinity":4,"f:57:8:57:23":4,"s:58:4:61:Infinity":9,"f:64:8:64:26":5,"s:65:4:65:Infinity":10,"s:67:19:77:Infinity":11,"s:79:4:79:Infinity":12,"b:79:11:79:24:79:24:79:Infinity":5,"f:82:8:82:22":6,"s:83:16:83:Infinity":13,"s:84:22:92:Infinity":14,"b:94:4:96:Infinity:undefined:undefined:undefined:undefined":6,"s:94:4:96:Infinity":15,"s:95:6:95:Infinity":16,"s:98:4:98:Infinity":17,"f:101:8:101:22":7,"s:102:16:102:Infinity":18,"s:103:22:111:Infinity":19,"b:113:4:115:Infinity:undefined:undefined:undefined:undefined":7,"s:113:4:115:Infinity":20,"s:114:6:114:Infinity":21,"s:117:4:117:Infinity":22,"f:120:8:120:23":8,"s:121:16:121:Infinity":23,"s:122:22:126:Infinity":24,"b:128:4:130:Infinity:undefined:undefined:undefined:undefined":8,"s:128:4:130:Infinity":25,"s:129:6:129:Infinity":26,"s:132:4:132:Infinity":27,"f:135:8:135:50":9,"s:136:16:136:Infinity":28,"s:138:20:151:Infinity":29,"s:153:4:153:Infinity":30,"f:156:8:156:38":10,"s:157:4:157:Infinity":31,"f:160:8:160:26":11,"s:161:16:161:Infinity":32,"s:162:22:166:Infinity":33,"b:168:4:170:Infinity:undefined:undefined:undefined:undefined":9,"s:168:4:170:Infinity":34,"s:169:6:169:Infinity":35,"s:172:4:172:Infinity":36,"f:175:8:175:26":12,"s:176:16:176:Infinity":37,"s:177:22:181:Infinity":38,"b:183:4:185:Infinity:undefined:undefined:undefined:undefined":10,"s:183:4:185:Infinity":39,"s:184:6:184:Infinity":40,"s:187:4:187:Infinity":41,"f:190:8:190:15":13,"s:192:4:195:Infinity":42,"s:197:22:197:Infinity":43,"b:199:4:201:Infinity:undefined:undefined:undefined:undefined":11,"s:199:4:201:Infinity":44,"s:200:6:200:Infinity":45}}} +,"/Users/lukasmay/development/projects/codewalk-district/src/db/repositories/drizzle/agent.ts": {"path":"/Users/lukasmay/development/projects/codewalk-district/src/db/repositories/drizzle/agent.ts","statementMap":{"0":{"start":{"line":25,"column":22},"end":{"line":25,"column":43}},"1":{"start":{"line":28,"column":10},"end":{"line":28,"column":null}},"2":{"start":{"line":29,"column":16},"end":{"line":29,"column":null}},"3":{"start":{"line":31,"column":22},"end":{"line":44,"column":null}},"4":{"start":{"line":46,"column":4},"end":{"line":46,"column":null}},"5":{"start":{"line":50,"column":19},"end":{"line":54,"column":null}},"6":{"start":{"line":56,"column":4},"end":{"line":56,"column":null}},"7":{"start":{"line":60,"column":19},"end":{"line":64,"column":null}},"8":{"start":{"line":66,"column":4},"end":{"line":66,"column":null}},"9":{"start":{"line":70,"column":19},"end":{"line":74,"column":null}},"10":{"start":{"line":76,"column":4},"end":{"line":76,"column":null}},"11":{"start":{"line":80,"column":19},"end":{"line":84,"column":null}},"12":{"start":{"line":86,"column":4},"end":{"line":86,"column":null}},"13":{"start":{"line":90,"column":4},"end":{"line":90,"column":null}},"14":{"start":{"line":94,"column":4},"end":{"line":94,"column":null}},"15":{"start":{"line":98,"column":16},"end":{"line":98,"column":null}},"16":{"start":{"line":99,"column":22},"end":{"line":103,"column":null}},"17":{"start":{"line":105,"column":4},"end":{"line":107,"column":null}},"18":{"start":{"line":106,"column":6},"end":{"line":106,"column":null}},"19":{"start":{"line":109,"column":4},"end":{"line":109,"column":null}},"20":{"start":{"line":113,"column":22},"end":{"line":113,"column":null}},"21":{"start":{"line":115,"column":4},"end":{"line":117,"column":null}},"22":{"start":{"line":116,"column":6},"end":{"line":116,"column":null}}},"fnMap":{"0":{"name":"(anonymous_0)","decl":{"start":{"line":25,"column":2},"end":{"line":25,"column":22}},"loc":{"start":{"line":25,"column":43},"end":{"line":25,"column":null}},"line":25},"1":{"name":"(anonymous_1)","decl":{"start":{"line":27,"column":8},"end":{"line":27,"column":15}},"loc":{"start":{"line":27,"column":54},"end":{"line":47,"column":null}},"line":27},"2":{"name":"(anonymous_2)","decl":{"start":{"line":49,"column":8},"end":{"line":49,"column":17}},"loc":{"start":{"line":49,"column":52},"end":{"line":57,"column":null}},"line":49},"3":{"name":"(anonymous_3)","decl":{"start":{"line":59,"column":8},"end":{"line":59,"column":19}},"loc":{"start":{"line":59,"column":56},"end":{"line":67,"column":null}},"line":59},"4":{"name":"(anonymous_4)","decl":{"start":{"line":69,"column":8},"end":{"line":69,"column":21}},"loc":{"start":{"line":69,"column":60},"end":{"line":77,"column":null}},"line":69},"5":{"name":"(anonymous_5)","decl":{"start":{"line":79,"column":8},"end":{"line":79,"column":24}},"loc":{"start":{"line":79,"column":66},"end":{"line":87,"column":null}},"line":79},"6":{"name":"(anonymous_6)","decl":{"start":{"line":89,"column":8},"end":{"line":89,"column":36}},"loc":{"start":{"line":89,"column":36},"end":{"line":91,"column":null}},"line":89},"7":{"name":"(anonymous_7)","decl":{"start":{"line":93,"column":8},"end":{"line":93,"column":21}},"loc":{"start":{"line":93,"column":60},"end":{"line":95,"column":null}},"line":93},"8":{"name":"(anonymous_8)","decl":{"start":{"line":97,"column":8},"end":{"line":97,"column":15}},"loc":{"start":{"line":97,"column":66},"end":{"line":110,"column":null}},"line":97},"9":{"name":"(anonymous_9)","decl":{"start":{"line":112,"column":8},"end":{"line":112,"column":15}},"loc":{"start":{"line":112,"column":42},"end":{"line":118,"column":null}},"line":112}},"branchMap":{"0":{"loc":{"start":{"line":34,"column":14},"end":{"line":34,"column":null}},"type":"binary-expr","locations":[{"start":{"line":34,"column":14},"end":{"line":34,"column":29}},{"start":{"line":34,"column":29},"end":{"line":34,"column":null}}],"line":34},"1":{"loc":{"start":{"line":35,"column":20},"end":{"line":35,"column":null}},"type":"binary-expr","locations":[{"start":{"line":35,"column":20},"end":{"line":35,"column":41}},{"start":{"line":35,"column":41},"end":{"line":35,"column":null}}],"line":35},"2":{"loc":{"start":{"line":36,"column":17},"end":{"line":36,"column":null}},"type":"binary-expr","locations":[{"start":{"line":36,"column":17},"end":{"line":36,"column":35}},{"start":{"line":36,"column":35},"end":{"line":36,"column":null}}],"line":36},"3":{"loc":{"start":{"line":38,"column":16},"end":{"line":38,"column":null}},"type":"binary-expr","locations":[{"start":{"line":38,"column":16},"end":{"line":38,"column":33}},{"start":{"line":38,"column":33},"end":{"line":38,"column":null}}],"line":38},"4":{"loc":{"start":{"line":39,"column":17},"end":{"line":39,"column":null}},"type":"binary-expr","locations":[{"start":{"line":39,"column":17},"end":{"line":39,"column":35}},{"start":{"line":39,"column":35},"end":{"line":39,"column":null}}],"line":39},"5":{"loc":{"start":{"line":40,"column":14},"end":{"line":40,"column":null}},"type":"binary-expr","locations":[{"start":{"line":40,"column":14},"end":{"line":40,"column":29}},{"start":{"line":40,"column":29},"end":{"line":40,"column":null}}],"line":40},"6":{"loc":{"start":{"line":41,"column":12},"end":{"line":41,"column":null}},"type":"binary-expr","locations":[{"start":{"line":41,"column":12},"end":{"line":41,"column":25}},{"start":{"line":41,"column":25},"end":{"line":41,"column":null}}],"line":41},"7":{"loc":{"start":{"line":56,"column":11},"end":{"line":56,"column":null}},"type":"binary-expr","locations":[{"start":{"line":56,"column":11},"end":{"line":56,"column":24}},{"start":{"line":56,"column":24},"end":{"line":56,"column":null}}],"line":56},"8":{"loc":{"start":{"line":66,"column":11},"end":{"line":66,"column":null}},"type":"binary-expr","locations":[{"start":{"line":66,"column":11},"end":{"line":66,"column":24}},{"start":{"line":66,"column":24},"end":{"line":66,"column":null}}],"line":66},"9":{"loc":{"start":{"line":76,"column":11},"end":{"line":76,"column":null}},"type":"binary-expr","locations":[{"start":{"line":76,"column":11},"end":{"line":76,"column":24}},{"start":{"line":76,"column":24},"end":{"line":76,"column":null}}],"line":76},"10":{"loc":{"start":{"line":86,"column":11},"end":{"line":86,"column":null}},"type":"binary-expr","locations":[{"start":{"line":86,"column":11},"end":{"line":86,"column":24}},{"start":{"line":86,"column":24},"end":{"line":86,"column":null}}],"line":86},"11":{"loc":{"start":{"line":105,"column":4},"end":{"line":107,"column":null}},"type":"if","locations":[{"start":{"line":105,"column":4},"end":{"line":107,"column":null}},{"start":{},"end":{}}],"line":105},"12":{"loc":{"start":{"line":115,"column":4},"end":{"line":117,"column":null}},"type":"if","locations":[{"start":{"line":115,"column":4},"end":{"line":117,"column":null}},{"start":{},"end":{}}],"line":115}},"s":{"0":156,"1":89,"2":89,"3":89,"4":88,"5":6,"6":6,"7":2,"8":2,"9":61,"10":61,"11":2,"12":2,"13":2,"14":4,"15":6,"16":6,"17":6,"18":1,"19":5,"20":2,"21":2,"22":1},"f":{"0":156,"1":89,"2":6,"3":2,"4":61,"5":2,"6":2,"7":4,"8":6,"9":2},"b":{"0":[89,23],"1":[89,81],"2":[89,89],"3":[89,89],"4":[89,89],"5":[89,72],"6":[89,89],"7":[6,2],"8":[2,1],"9":[61,4],"10":[2,1],"11":[1,5],"12":[1,1]},"meta":{"lastBranch":13,"lastFunction":10,"lastStatement":23,"seen":{"f:25:2:25:22":0,"s:25:22:25:43":0,"f:27:8:27:15":1,"s:28:10:28:Infinity":1,"s:29:16:29:Infinity":2,"s:31:22:44:Infinity":3,"b:34:14:34:29:34:29:34:Infinity":0,"b:35:20:35:41:35:41:35:Infinity":1,"b:36:17:36:35:36:35:36:Infinity":2,"b:38:16:38:33:38:33:38:Infinity":3,"b:39:17:39:35:39:35:39:Infinity":4,"b:40:14:40:29:40:29:40:Infinity":5,"b:41:12:41:25:41:25:41:Infinity":6,"s:46:4:46:Infinity":4,"f:49:8:49:17":2,"s:50:19:54:Infinity":5,"s:56:4:56:Infinity":6,"b:56:11:56:24:56:24:56:Infinity":7,"f:59:8:59:19":3,"s:60:19:64:Infinity":7,"s:66:4:66:Infinity":8,"b:66:11:66:24:66:24:66:Infinity":8,"f:69:8:69:21":4,"s:70:19:74:Infinity":9,"s:76:4:76:Infinity":10,"b:76:11:76:24:76:24:76:Infinity":9,"f:79:8:79:24":5,"s:80:19:84:Infinity":11,"s:86:4:86:Infinity":12,"b:86:11:86:24:86:24:86:Infinity":10,"f:89:8:89:36":6,"s:90:4:90:Infinity":13,"f:93:8:93:21":7,"s:94:4:94:Infinity":14,"f:97:8:97:15":8,"s:98:16:98:Infinity":15,"s:99:22:103:Infinity":16,"b:105:4:107:Infinity:undefined:undefined:undefined:undefined":11,"s:105:4:107:Infinity":17,"s:106:6:106:Infinity":18,"s:109:4:109:Infinity":19,"f:112:8:112:15":9,"s:113:22:113:Infinity":20,"b:115:4:117:Infinity:undefined:undefined:undefined:undefined":12,"s:115:4:117:Infinity":21,"s:116:6:116:Infinity":22}}} +,"/Users/lukasmay/development/projects/codewalk-district/src/db/repositories/drizzle/change-set.ts": {"path":"/Users/lukasmay/development/projects/codewalk-district/src/db/repositories/drizzle/change-set.ts","statementMap":{"0":{"start":{"line":19,"column":22},"end":{"line":19,"column":43}},"1":{"start":{"line":22,"column":10},"end":{"line":22,"column":null}},"2":{"start":{"line":23,"column":16},"end":{"line":23,"column":null}},"3":{"start":{"line":26,"column":4},"end":{"line":55,"column":null}},"4":{"start":{"line":27,"column":24},"end":{"line":36,"column":null}},"5":{"start":{"line":38,"column":6},"end":{"line":52,"column":null}},"6":{"start":{"line":39,"column":26},"end":{"line":49,"column":null}},"7":{"start":{"line":39,"column":49},"end":{"line":49,"column":10}},"8":{"start":{"line":51,"column":8},"end":{"line":51,"column":null}},"9":{"start":{"line":54,"column":6},"end":{"line":54,"column":null}},"10":{"start":{"line":59,"column":19},"end":{"line":63,"column":null}},"11":{"start":{"line":65,"column":4},"end":{"line":65,"column":null}},"12":{"start":{"line":69,"column":15},"end":{"line":69,"column":null}},"13":{"start":{"line":70,"column":4},"end":{"line":70,"column":null}},"14":{"start":{"line":70,"column":13},"end":{"line":70,"column":null}},"15":{"start":{"line":72,"column":20},"end":{"line":76,"column":null}},"16":{"start":{"line":78,"column":4},"end":{"line":78,"column":null}},"17":{"start":{"line":82,"column":4},"end":{"line":86,"column":null}},"18":{"start":{"line":90,"column":4},"end":{"line":94,"column":null}},"19":{"start":{"line":98,"column":22},"end":{"line":102,"column":null}},"20":{"start":{"line":104,"column":4},"end":{"line":106,"column":null}},"21":{"start":{"line":105,"column":6},"end":{"line":105,"column":null}},"22":{"start":{"line":108,"column":4},"end":{"line":108,"column":null}}},"fnMap":{"0":{"name":"(anonymous_0)","decl":{"start":{"line":19,"column":2},"end":{"line":19,"column":22}},"loc":{"start":{"line":19,"column":43},"end":{"line":19,"column":null}},"line":19},"1":{"name":"(anonymous_1)","decl":{"start":{"line":21,"column":8},"end":{"line":21,"column":26}},"loc":{"start":{"line":21,"column":110},"end":{"line":56,"column":null}},"line":21},"2":{"name":"(anonymous_2)","decl":{"start":{"line":26,"column":31},"end":{"line":26,"column":38}},"loc":{"start":{"line":26,"column":45},"end":{"line":55,"column":5}},"line":26},"3":{"name":"(anonymous_3)","decl":{"start":{"line":39,"column":38},"end":{"line":39,"column":39}},"loc":{"start":{"line":39,"column":49},"end":{"line":49,"column":10}},"line":39},"4":{"name":"(anonymous_4)","decl":{"start":{"line":58,"column":8},"end":{"line":58,"column":17}},"loc":{"start":{"line":58,"column":56},"end":{"line":66,"column":null}},"line":58},"5":{"name":"(anonymous_5)","decl":{"start":{"line":68,"column":8},"end":{"line":68,"column":28}},"loc":{"start":{"line":68,"column":78},"end":{"line":79,"column":null}},"line":68},"6":{"name":"(anonymous_6)","decl":{"start":{"line":81,"column":8},"end":{"line":81,"column":27}},"loc":{"start":{"line":81,"column":71},"end":{"line":87,"column":null}},"line":81},"7":{"name":"(anonymous_7)","decl":{"start":{"line":89,"column":8},"end":{"line":89,"column":22}},"loc":{"start":{"line":89,"column":61},"end":{"line":95,"column":null}},"line":89},"8":{"name":"(anonymous_8)","decl":{"start":{"line":97,"column":8},"end":{"line":97,"column":21}},"loc":{"start":{"line":97,"column":53},"end":{"line":109,"column":null}},"line":97}},"branchMap":{"0":{"loc":{"start":{"line":33,"column":17},"end":{"line":33,"column":null}},"type":"binary-expr","locations":[{"start":{"line":33,"column":17},"end":{"line":33,"column":33}},{"start":{"line":33,"column":33},"end":{"line":33,"column":null}}],"line":33},"1":{"loc":{"start":{"line":38,"column":6},"end":{"line":52,"column":null}},"type":"if","locations":[{"start":{"line":38,"column":6},"end":{"line":52,"column":null}},{"start":{},"end":{}}],"line":38},"2":{"loc":{"start":{"line":45,"column":25},"end":{"line":45,"column":null}},"type":"binary-expr","locations":[{"start":{"line":45,"column":25},"end":{"line":45,"column":44}},{"start":{"line":45,"column":44},"end":{"line":45,"column":null}}],"line":45},"3":{"loc":{"start":{"line":46,"column":20},"end":{"line":46,"column":null}},"type":"binary-expr","locations":[{"start":{"line":46,"column":20},"end":{"line":46,"column":34}},{"start":{"line":46,"column":34},"end":{"line":46,"column":null}}],"line":46},"4":{"loc":{"start":{"line":47,"column":21},"end":{"line":47,"column":null}},"type":"binary-expr","locations":[{"start":{"line":47,"column":21},"end":{"line":47,"column":36}},{"start":{"line":47,"column":36},"end":{"line":47,"column":null}}],"line":47},"5":{"loc":{"start":{"line":65,"column":11},"end":{"line":65,"column":null}},"type":"binary-expr","locations":[{"start":{"line":65,"column":11},"end":{"line":65,"column":24}},{"start":{"line":65,"column":24},"end":{"line":65,"column":null}}],"line":65},"6":{"loc":{"start":{"line":70,"column":4},"end":{"line":70,"column":null}},"type":"if","locations":[{"start":{"line":70,"column":4},"end":{"line":70,"column":null}},{"start":{},"end":{}}],"line":70},"7":{"loc":{"start":{"line":104,"column":4},"end":{"line":106,"column":null}},"type":"if","locations":[{"start":{"line":104,"column":4},"end":{"line":106,"column":null}},{"start":{},"end":{}}],"line":104}},"s":{"0":84,"1":0,"2":0,"3":0,"4":0,"5":0,"6":0,"7":0,"8":0,"9":0,"10":6,"11":6,"12":0,"13":0,"14":0,"15":0,"16":0,"17":0,"18":0,"19":0,"20":0,"21":0,"22":0},"f":{"0":84,"1":0,"2":0,"3":0,"4":6,"5":0,"6":0,"7":0,"8":0},"b":{"0":[0,0],"1":[0,0],"2":[0,0],"3":[0,0],"4":[0,0],"5":[6,1],"6":[0,0],"7":[0,0]},"meta":{"lastBranch":8,"lastFunction":9,"lastStatement":23,"seen":{"f:19:2:19:22":0,"s:19:22:19:43":0,"f:21:8:21:26":1,"s:22:10:22:Infinity":1,"s:23:16:23:Infinity":2,"s:26:4:55:Infinity":3,"f:26:31:26:38":2,"s:27:24:36:Infinity":4,"b:33:17:33:33:33:33:33:Infinity":0,"b:38:6:52:Infinity:undefined:undefined:undefined:undefined":1,"s:38:6:52:Infinity":5,"s:39:26:49:Infinity":6,"f:39:38:39:39":3,"s:39:49:49:10":7,"b:45:25:45:44:45:44:45:Infinity":2,"b:46:20:46:34:46:34:46:Infinity":3,"b:47:21:47:36:47:36:47:Infinity":4,"s:51:8:51:Infinity":8,"s:54:6:54:Infinity":9,"f:58:8:58:17":4,"s:59:19:63:Infinity":10,"s:65:4:65:Infinity":11,"b:65:11:65:24:65:24:65:Infinity":5,"f:68:8:68:28":5,"s:69:15:69:Infinity":12,"b:70:4:70:Infinity:undefined:undefined:undefined:undefined":6,"s:70:4:70:Infinity":13,"s:70:13:70:Infinity":14,"s:72:20:76:Infinity":15,"s:78:4:78:Infinity":16,"f:81:8:81:27":6,"s:82:4:86:Infinity":17,"f:89:8:89:22":7,"s:90:4:94:Infinity":18,"f:97:8:97:21":8,"s:98:22:102:Infinity":19,"b:104:4:106:Infinity:undefined:undefined:undefined:undefined":7,"s:104:4:106:Infinity":20,"s:105:6:105:Infinity":21,"s:108:4:108:Infinity":22}}} +,"/Users/lukasmay/development/projects/codewalk-district/src/db/repositories/drizzle/conversation.ts": {"path":"/Users/lukasmay/development/projects/codewalk-district/src/db/repositories/drizzle/conversation.ts","statementMap":{"0":{"start":{"line":14,"column":22},"end":{"line":14,"column":43}},"1":{"start":{"line":17,"column":16},"end":{"line":17,"column":null}},"2":{"start":{"line":18,"column":10},"end":{"line":18,"column":null}},"3":{"start":{"line":19,"column":4},"end":{"line":30,"column":null}},"4":{"start":{"line":31,"column":4},"end":{"line":31,"column":null}},"5":{"start":{"line":35,"column":17},"end":{"line":39,"column":null}},"6":{"start":{"line":40,"column":4},"end":{"line":40,"column":null}},"7":{"start":{"line":44,"column":4},"end":{"line":53,"column":null}},"8":{"start":{"line":57,"column":4},"end":{"line":64,"column":null}},"9":{"start":{"line":65,"column":4},"end":{"line":65,"column":null}}},"fnMap":{"0":{"name":"(anonymous_0)","decl":{"start":{"line":14,"column":2},"end":{"line":14,"column":22}},"loc":{"start":{"line":14,"column":43},"end":{"line":14,"column":null}},"line":14},"1":{"name":"(anonymous_1)","decl":{"start":{"line":16,"column":8},"end":{"line":16,"column":15}},"loc":{"start":{"line":16,"column":68},"end":{"line":32,"column":null}},"line":16},"2":{"name":"(anonymous_2)","decl":{"start":{"line":34,"column":8},"end":{"line":34,"column":17}},"loc":{"start":{"line":34,"column":59},"end":{"line":41,"column":null}},"line":34},"3":{"name":"(anonymous_3)","decl":{"start":{"line":43,"column":8},"end":{"line":43,"column":28}},"loc":{"start":{"line":43,"column":72},"end":{"line":54,"column":null}},"line":43},"4":{"name":"(anonymous_4)","decl":{"start":{"line":56,"column":8},"end":{"line":56,"column":15}},"loc":{"start":{"line":56,"column":73},"end":{"line":66,"column":null}},"line":56}},"branchMap":{"0":{"loc":{"start":{"line":23,"column":20},"end":{"line":23,"column":null}},"type":"binary-expr","locations":[{"start":{"line":23,"column":20},"end":{"line":23,"column":41}},{"start":{"line":23,"column":41},"end":{"line":23,"column":null}}],"line":23},"1":{"loc":{"start":{"line":24,"column":15},"end":{"line":24,"column":null}},"type":"binary-expr","locations":[{"start":{"line":24,"column":15},"end":{"line":24,"column":31}},{"start":{"line":24,"column":31},"end":{"line":24,"column":null}}],"line":24},"2":{"loc":{"start":{"line":25,"column":14},"end":{"line":25,"column":null}},"type":"binary-expr","locations":[{"start":{"line":25,"column":14},"end":{"line":25,"column":29}},{"start":{"line":25,"column":29},"end":{"line":25,"column":null}}],"line":25},"3":{"loc":{"start":{"line":40,"column":11},"end":{"line":40,"column":null}},"type":"binary-expr","locations":[{"start":{"line":40,"column":11},"end":{"line":40,"column":22}},{"start":{"line":40,"column":22},"end":{"line":40,"column":null}}],"line":40}},"s":{"0":84,"1":4,"2":4,"3":4,"4":4,"5":5,"6":5,"7":0,"8":0,"9":0},"f":{"0":84,"1":4,"2":5,"3":0,"4":0},"b":{"0":[4,0],"1":[4,4],"2":[4,4],"3":[5,0]},"meta":{"lastBranch":4,"lastFunction":5,"lastStatement":10,"seen":{"f:14:2:14:22":0,"s:14:22:14:43":0,"f:16:8:16:15":1,"s:17:16:17:Infinity":1,"s:18:10:18:Infinity":2,"s:19:4:30:Infinity":3,"b:23:20:23:41:23:41:23:Infinity":0,"b:24:15:24:31:24:31:24:Infinity":1,"b:25:14:25:29:25:29:25:Infinity":2,"s:31:4:31:Infinity":4,"f:34:8:34:17":2,"s:35:17:39:Infinity":5,"s:40:4:40:Infinity":6,"b:40:11:40:22:40:22:40:Infinity":3,"f:43:8:43:28":3,"s:44:4:53:Infinity":7,"f:56:8:56:15":4,"s:57:4:64:Infinity":8,"s:65:4:65:Infinity":9}}} +,"/Users/lukasmay/development/projects/codewalk-district/src/db/repositories/drizzle/index.ts": {"path":"/Users/lukasmay/development/projects/codewalk-district/src/db/repositories/drizzle/index.ts","statementMap":{},"fnMap":{},"branchMap":{},"s":{},"f":{},"b":{},"meta":{"lastBranch":0,"lastFunction":0,"lastStatement":0,"seen":{}}} +,"/Users/lukasmay/development/projects/codewalk-district/src/db/repositories/drizzle/initiative.ts": {"path":"/Users/lukasmay/development/projects/codewalk-district/src/db/repositories/drizzle/initiative.ts","statementMap":{"0":{"start":{"line":24,"column":22},"end":{"line":24,"column":43}},"1":{"start":{"line":27,"column":10},"end":{"line":27,"column":null}},"2":{"start":{"line":28,"column":16},"end":{"line":28,"column":null}},"3":{"start":{"line":30,"column":22},"end":{"line":36,"column":null}},"4":{"start":{"line":38,"column":4},"end":{"line":38,"column":null}},"5":{"start":{"line":42,"column":19},"end":{"line":46,"column":null}},"6":{"start":{"line":48,"column":4},"end":{"line":48,"column":null}},"7":{"start":{"line":52,"column":4},"end":{"line":52,"column":null}},"8":{"start":{"line":56,"column":4},"end":{"line":59,"column":null}},"9":{"start":{"line":63,"column":22},"end":{"line":67,"column":null}},"10":{"start":{"line":69,"column":4},"end":{"line":71,"column":null}},"11":{"start":{"line":70,"column":6},"end":{"line":70,"column":null}},"12":{"start":{"line":73,"column":4},"end":{"line":73,"column":null}},"13":{"start":{"line":79,"column":4},"end":{"line":79,"column":null}},"14":{"start":{"line":81,"column":22},"end":{"line":81,"column":null}},"15":{"start":{"line":83,"column":4},"end":{"line":85,"column":null}},"16":{"start":{"line":84,"column":6},"end":{"line":84,"column":null}}},"fnMap":{"0":{"name":"(anonymous_0)","decl":{"start":{"line":24,"column":2},"end":{"line":24,"column":22}},"loc":{"start":{"line":24,"column":43},"end":{"line":24,"column":null}},"line":24},"1":{"name":"(anonymous_1)","decl":{"start":{"line":26,"column":8},"end":{"line":26,"column":15}},"loc":{"start":{"line":26,"column":64},"end":{"line":39,"column":null}},"line":26},"2":{"name":"(anonymous_2)","decl":{"start":{"line":41,"column":8},"end":{"line":41,"column":17}},"loc":{"start":{"line":41,"column":57},"end":{"line":49,"column":null}},"line":41},"3":{"name":"(anonymous_3)","decl":{"start":{"line":51,"column":8},"end":{"line":51,"column":41}},"loc":{"start":{"line":51,"column":41},"end":{"line":53,"column":null}},"line":51},"4":{"name":"(anonymous_4)","decl":{"start":{"line":55,"column":8},"end":{"line":55,"column":21}},"loc":{"start":{"line":55,"column":89},"end":{"line":60,"column":null}},"line":55},"5":{"name":"(anonymous_5)","decl":{"start":{"line":62,"column":8},"end":{"line":62,"column":15}},"loc":{"start":{"line":62,"column":76},"end":{"line":74,"column":null}},"line":62},"6":{"name":"(anonymous_6)","decl":{"start":{"line":76,"column":8},"end":{"line":76,"column":15}},"loc":{"start":{"line":76,"column":42},"end":{"line":86,"column":null}},"line":76}},"branchMap":{"0":{"loc":{"start":{"line":33,"column":14},"end":{"line":33,"column":null}},"type":"binary-expr","locations":[{"start":{"line":33,"column":14},"end":{"line":33,"column":29}},{"start":{"line":33,"column":29},"end":{"line":33,"column":null}}],"line":33},"1":{"loc":{"start":{"line":48,"column":11},"end":{"line":48,"column":null}},"type":"binary-expr","locations":[{"start":{"line":48,"column":11},"end":{"line":48,"column":24}},{"start":{"line":48,"column":24},"end":{"line":48,"column":null}}],"line":48},"2":{"loc":{"start":{"line":69,"column":4},"end":{"line":71,"column":null}},"type":"if","locations":[{"start":{"line":69,"column":4},"end":{"line":71,"column":null}},{"start":{},"end":{}}],"line":69},"3":{"loc":{"start":{"line":83,"column":4},"end":{"line":85,"column":null}},"type":"if","locations":[{"start":{"line":83,"column":4},"end":{"line":85,"column":null}},{"start":{},"end":{}}],"line":83}},"s":{"0":287,"1":236,"2":236,"3":236,"4":236,"5":27,"6":27,"7":2,"8":4,"9":2,"10":2,"11":1,"12":1,"13":4,"14":4,"15":4,"16":1},"f":{"0":287,"1":236,"2":27,"3":2,"4":4,"5":2,"6":4},"b":{"0":[236,155],"1":[27,3],"2":[1,1],"3":[1,3]},"meta":{"lastBranch":4,"lastFunction":7,"lastStatement":17,"seen":{"f:24:2:24:22":0,"s:24:22:24:43":0,"f:26:8:26:15":1,"s:27:10:27:Infinity":1,"s:28:16:28:Infinity":2,"s:30:22:36:Infinity":3,"b:33:14:33:29:33:29:33:Infinity":0,"s:38:4:38:Infinity":4,"f:41:8:41:17":2,"s:42:19:46:Infinity":5,"s:48:4:48:Infinity":6,"b:48:11:48:24:48:24:48:Infinity":1,"f:51:8:51:41":3,"s:52:4:52:Infinity":7,"f:55:8:55:21":4,"s:56:4:59:Infinity":8,"f:62:8:62:15":5,"s:63:22:67:Infinity":9,"b:69:4:71:Infinity:undefined:undefined:undefined:undefined":2,"s:69:4:71:Infinity":10,"s:70:6:70:Infinity":11,"s:73:4:73:Infinity":12,"f:76:8:76:15":6,"s:79:4:79:Infinity":13,"s:81:22:81:Infinity":14,"b:83:4:85:Infinity:undefined:undefined:undefined:undefined":3,"s:83:4:85:Infinity":15,"s:84:6:84:Infinity":16}}} +,"/Users/lukasmay/development/projects/codewalk-district/src/db/repositories/drizzle/log-chunk.ts": {"path":"/Users/lukasmay/development/projects/codewalk-district/src/db/repositories/drizzle/log-chunk.ts","statementMap":{"0":{"start":{"line":14,"column":22},"end":{"line":14,"column":43}},"1":{"start":{"line":22,"column":4},"end":{"line":29,"column":null}},"2":{"start":{"line":33,"column":4},"end":{"line":41,"column":null}},"3":{"start":{"line":45,"column":4},"end":{"line":47,"column":null}},"4":{"start":{"line":51,"column":19},"end":{"line":54,"column":null}},"5":{"start":{"line":56,"column":4},"end":{"line":56,"column":null}}},"fnMap":{"0":{"name":"(anonymous_0)","decl":{"start":{"line":14,"column":2},"end":{"line":14,"column":22}},"loc":{"start":{"line":14,"column":43},"end":{"line":14,"column":null}},"line":14},"1":{"name":"(anonymous_1)","decl":{"start":{"line":16,"column":8},"end":{"line":16,"column":20}},"loc":{"start":{"line":21,"column":20},"end":{"line":30,"column":null}},"line":21},"2":{"name":"(anonymous_2)","decl":{"start":{"line":32,"column":8},"end":{"line":32,"column":22}},"loc":{"start":{"line":32,"column":111},"end":{"line":42,"column":null}},"line":32},"3":{"name":"(anonymous_3)","decl":{"start":{"line":44,"column":8},"end":{"line":44,"column":24}},"loc":{"start":{"line":44,"column":56},"end":{"line":48,"column":null}},"line":44},"4":{"name":"(anonymous_4)","decl":{"start":{"line":50,"column":8},"end":{"line":50,"column":24}},"loc":{"start":{"line":50,"column":58},"end":{"line":57,"column":null}},"line":50}},"branchMap":{"0":{"loc":{"start":{"line":56,"column":11},"end":{"line":56,"column":null}},"type":"binary-expr","locations":[{"start":{"line":56,"column":11},"end":{"line":56,"column":36}},{"start":{"line":56,"column":36},"end":{"line":56,"column":null}}],"line":56}},"s":{"0":80,"1":0,"2":0,"3":0,"4":0,"5":0},"f":{"0":80,"1":0,"2":0,"3":0,"4":0},"b":{"0":[0,0]},"meta":{"lastBranch":1,"lastFunction":5,"lastStatement":6,"seen":{"f:14:2:14:22":0,"s:14:22:14:43":0,"f:16:8:16:20":1,"s:22:4:29:Infinity":1,"f:32:8:32:22":2,"s:33:4:41:Infinity":2,"f:44:8:44:24":3,"s:45:4:47:Infinity":3,"f:50:8:50:24":4,"s:51:19:54:Infinity":4,"s:56:4:56:Infinity":5,"b:56:11:56:36:56:36:56:Infinity":0}}} +,"/Users/lukasmay/development/projects/codewalk-district/src/db/repositories/drizzle/message.ts": {"path":"/Users/lukasmay/development/projects/codewalk-district/src/db/repositories/drizzle/message.ts","statementMap":{"0":{"start":{"line":25,"column":22},"end":{"line":25,"column":43}},"1":{"start":{"line":28,"column":10},"end":{"line":28,"column":null}},"2":{"start":{"line":29,"column":16},"end":{"line":29,"column":null}},"3":{"start":{"line":31,"column":22},"end":{"line":44,"column":null}},"4":{"start":{"line":46,"column":4},"end":{"line":46,"column":null}},"5":{"start":{"line":50,"column":19},"end":{"line":54,"column":null}},"6":{"start":{"line":56,"column":4},"end":{"line":56,"column":null}},"7":{"start":{"line":60,"column":4},"end":{"line":66,"column":null}},"8":{"start":{"line":61,"column":6},"end":{"line":65,"column":null}},"9":{"start":{"line":69,"column":4},"end":{"line":73,"column":null}},"10":{"start":{"line":77,"column":4},"end":{"line":83,"column":null}},"11":{"start":{"line":78,"column":6},"end":{"line":82,"column":null}},"12":{"start":{"line":86,"column":4},"end":{"line":90,"column":null}},"13":{"start":{"line":94,"column":4},"end":{"line":98,"column":null}},"14":{"start":{"line":102,"column":4},"end":{"line":106,"column":null}},"15":{"start":{"line":110,"column":4},"end":{"line":114,"column":null}},"16":{"start":{"line":118,"column":22},"end":{"line":122,"column":null}},"17":{"start":{"line":124,"column":4},"end":{"line":126,"column":null}},"18":{"start":{"line":125,"column":6},"end":{"line":125,"column":null}},"19":{"start":{"line":128,"column":4},"end":{"line":128,"column":null}},"20":{"start":{"line":132,"column":22},"end":{"line":132,"column":null}},"21":{"start":{"line":134,"column":4},"end":{"line":136,"column":null}},"22":{"start":{"line":135,"column":6},"end":{"line":135,"column":null}}},"fnMap":{"0":{"name":"(anonymous_0)","decl":{"start":{"line":25,"column":2},"end":{"line":25,"column":22}},"loc":{"start":{"line":25,"column":43},"end":{"line":25,"column":null}},"line":25},"1":{"name":"(anonymous_1)","decl":{"start":{"line":27,"column":8},"end":{"line":27,"column":15}},"loc":{"start":{"line":27,"column":58},"end":{"line":47,"column":null}},"line":27},"2":{"name":"(anonymous_2)","decl":{"start":{"line":49,"column":8},"end":{"line":49,"column":17}},"loc":{"start":{"line":49,"column":54},"end":{"line":57,"column":null}},"line":49},"3":{"name":"(anonymous_3)","decl":{"start":{"line":59,"column":8},"end":{"line":59,"column":21}},"loc":{"start":{"line":59,"column":84},"end":{"line":74,"column":null}},"line":59},"4":{"name":"(anonymous_4)","decl":{"start":{"line":76,"column":8},"end":{"line":76,"column":24}},"loc":{"start":{"line":76,"column":87},"end":{"line":91,"column":null}},"line":76},"5":{"name":"(anonymous_5)","decl":{"start":{"line":93,"column":8},"end":{"line":93,"column":49}},"loc":{"start":{"line":93,"column":49},"end":{"line":99,"column":null}},"line":93},"6":{"name":"(anonymous_6)","decl":{"start":{"line":101,"column":8},"end":{"line":101,"column":52}},"loc":{"start":{"line":101,"column":52},"end":{"line":107,"column":null}},"line":101},"7":{"name":"(anonymous_7)","decl":{"start":{"line":109,"column":8},"end":{"line":109,"column":20}},"loc":{"start":{"line":109,"column":65},"end":{"line":115,"column":null}},"line":109},"8":{"name":"(anonymous_8)","decl":{"start":{"line":117,"column":8},"end":{"line":117,"column":15}},"loc":{"start":{"line":117,"column":70},"end":{"line":129,"column":null}},"line":117},"9":{"name":"(anonymous_9)","decl":{"start":{"line":131,"column":8},"end":{"line":131,"column":15}},"loc":{"start":{"line":131,"column":42},"end":{"line":137,"column":null}},"line":131}},"branchMap":{"0":{"loc":{"start":{"line":34,"column":16},"end":{"line":34,"column":null}},"type":"binary-expr","locations":[{"start":{"line":34,"column":16},"end":{"line":34,"column":33}},{"start":{"line":34,"column":33},"end":{"line":34,"column":null}}],"line":34},"1":{"loc":{"start":{"line":36,"column":19},"end":{"line":36,"column":null}},"type":"binary-expr","locations":[{"start":{"line":36,"column":19},"end":{"line":36,"column":39}},{"start":{"line":36,"column":39},"end":{"line":36,"column":null}}],"line":36},"2":{"loc":{"start":{"line":37,"column":12},"end":{"line":37,"column":null}},"type":"binary-expr","locations":[{"start":{"line":37,"column":12},"end":{"line":37,"column":25}},{"start":{"line":37,"column":25},"end":{"line":37,"column":null}}],"line":37},"3":{"loc":{"start":{"line":39,"column":24},"end":{"line":39,"column":null}},"type":"binary-expr","locations":[{"start":{"line":39,"column":24},"end":{"line":39,"column":49}},{"start":{"line":39,"column":49},"end":{"line":39,"column":null}}],"line":39},"4":{"loc":{"start":{"line":40,"column":14},"end":{"line":40,"column":null}},"type":"binary-expr","locations":[{"start":{"line":40,"column":14},"end":{"line":40,"column":29}},{"start":{"line":40,"column":29},"end":{"line":40,"column":null}}],"line":40},"5":{"loc":{"start":{"line":41,"column":23},"end":{"line":41,"column":null}},"type":"binary-expr","locations":[{"start":{"line":41,"column":23},"end":{"line":41,"column":47}},{"start":{"line":41,"column":47},"end":{"line":41,"column":null}}],"line":41},"6":{"loc":{"start":{"line":56,"column":11},"end":{"line":56,"column":null}},"type":"binary-expr","locations":[{"start":{"line":56,"column":11},"end":{"line":56,"column":24}},{"start":{"line":56,"column":24},"end":{"line":56,"column":null}}],"line":56},"7":{"loc":{"start":{"line":60,"column":4},"end":{"line":66,"column":null}},"type":"if","locations":[{"start":{"line":60,"column":4},"end":{"line":66,"column":null}},{"start":{},"end":{}}],"line":60},"8":{"loc":{"start":{"line":77,"column":4},"end":{"line":83,"column":null}},"type":"if","locations":[{"start":{"line":77,"column":4},"end":{"line":83,"column":null}},{"start":{},"end":{}}],"line":77},"9":{"loc":{"start":{"line":124,"column":4},"end":{"line":126,"column":null}},"type":"if","locations":[{"start":{"line":124,"column":4},"end":{"line":126,"column":null}},{"start":{},"end":{}}],"line":124},"10":{"loc":{"start":{"line":134,"column":4},"end":{"line":136,"column":null}},"type":"if","locations":[{"start":{"line":134,"column":4},"end":{"line":136,"column":null}},{"start":{},"end":{}}],"line":134}},"s":{"0":145,"1":46,"2":46,"3":46,"4":46,"5":3,"6":3,"7":3,"8":2,"9":1,"10":5,"11":4,"12":1,"13":2,"14":2,"15":2,"16":6,"17":6,"18":1,"19":5,"20":2,"21":2,"22":1},"f":{"0":145,"1":46,"2":3,"3":3,"4":5,"5":2,"6":2,"7":2,"8":6,"9":2},"b":{"0":[46,26],"1":[46,20],"2":[46,16],"3":[46,19],"4":[46,45],"5":[46,43],"6":[3,2],"7":[2,1],"8":[4,1],"9":[1,5],"10":[1,1]},"meta":{"lastBranch":11,"lastFunction":10,"lastStatement":23,"seen":{"f:25:2:25:22":0,"s:25:22:25:43":0,"f:27:8:27:15":1,"s:28:10:28:Infinity":1,"s:29:16:29:Infinity":2,"s:31:22:44:Infinity":3,"b:34:16:34:33:34:33:34:Infinity":0,"b:36:19:36:39:36:39:36:Infinity":1,"b:37:12:37:25:37:25:37:Infinity":2,"b:39:24:39:49:39:49:39:Infinity":3,"b:40:14:40:29:40:29:40:Infinity":4,"b:41:23:41:47:41:47:41:Infinity":5,"s:46:4:46:Infinity":4,"f:49:8:49:17":2,"s:50:19:54:Infinity":5,"s:56:4:56:Infinity":6,"b:56:11:56:24:56:24:56:Infinity":6,"f:59:8:59:21":3,"b:60:4:66:Infinity:undefined:undefined:undefined:undefined":7,"s:60:4:66:Infinity":7,"s:61:6:65:Infinity":8,"s:69:4:73:Infinity":9,"f:76:8:76:24":4,"b:77:4:83:Infinity:undefined:undefined:undefined:undefined":8,"s:77:4:83:Infinity":10,"s:78:6:82:Infinity":11,"s:86:4:90:Infinity":12,"f:93:8:93:49":5,"s:94:4:98:Infinity":13,"f:101:8:101:52":6,"s:102:4:106:Infinity":14,"f:109:8:109:20":7,"s:110:4:114:Infinity":15,"f:117:8:117:15":8,"s:118:22:122:Infinity":16,"b:124:4:126:Infinity:undefined:undefined:undefined:undefined":9,"s:124:4:126:Infinity":17,"s:125:6:125:Infinity":18,"s:128:4:128:Infinity":19,"f:131:8:131:15":9,"s:132:22:132:Infinity":20,"b:134:4:136:Infinity:undefined:undefined:undefined:undefined":10,"s:134:4:136:Infinity":21,"s:135:6:135:Infinity":22}}} +,"/Users/lukasmay/development/projects/codewalk-district/src/db/repositories/drizzle/page.ts": {"path":"/Users/lukasmay/development/projects/codewalk-district/src/db/repositories/drizzle/page.ts","statementMap":{"0":{"start":{"line":18,"column":22},"end":{"line":18,"column":43}},"1":{"start":{"line":21,"column":10},"end":{"line":21,"column":null}},"2":{"start":{"line":22,"column":16},"end":{"line":22,"column":null}},"3":{"start":{"line":24,"column":22},"end":{"line":29,"column":null}},"4":{"start":{"line":31,"column":4},"end":{"line":31,"column":null}},"5":{"start":{"line":35,"column":19},"end":{"line":39,"column":null}},"6":{"start":{"line":41,"column":4},"end":{"line":41,"column":null}},"7":{"start":{"line":45,"column":4},"end":{"line":45,"column":null}},"8":{"start":{"line":45,"column":26},"end":{"line":45,"column":null}},"9":{"start":{"line":46,"column":4},"end":{"line":49,"column":null}},"10":{"start":{"line":53,"column":4},"end":{"line":57,"column":null}},"11":{"start":{"line":61,"column":4},"end":{"line":65,"column":null}},"12":{"start":{"line":69,"column":19},"end":{"line":78,"column":null}},"13":{"start":{"line":80,"column":4},"end":{"line":80,"column":null}},"14":{"start":{"line":84,"column":21},"end":{"line":84,"column":null}},"15":{"start":{"line":85,"column":4},"end":{"line":85,"column":null}},"16":{"start":{"line":85,"column":18},"end":{"line":85,"column":null}},"17":{"start":{"line":87,"column":4},"end":{"line":93,"column":null}},"18":{"start":{"line":97,"column":22},"end":{"line":101,"column":null}},"19":{"start":{"line":103,"column":4},"end":{"line":105,"column":null}},"20":{"start":{"line":104,"column":6},"end":{"line":104,"column":null}},"21":{"start":{"line":107,"column":4},"end":{"line":107,"column":null}},"22":{"start":{"line":111,"column":22},"end":{"line":111,"column":null}},"23":{"start":{"line":113,"column":4},"end":{"line":115,"column":null}},"24":{"start":{"line":114,"column":6},"end":{"line":114,"column":null}}},"fnMap":{"0":{"name":"(anonymous_0)","decl":{"start":{"line":18,"column":2},"end":{"line":18,"column":22}},"loc":{"start":{"line":18,"column":43},"end":{"line":18,"column":null}},"line":18},"1":{"name":"(anonymous_1)","decl":{"start":{"line":20,"column":8},"end":{"line":20,"column":15}},"loc":{"start":{"line":20,"column":52},"end":{"line":32,"column":null}},"line":20},"2":{"name":"(anonymous_2)","decl":{"start":{"line":34,"column":8},"end":{"line":34,"column":17}},"loc":{"start":{"line":34,"column":51},"end":{"line":42,"column":null}},"line":34},"3":{"name":"(anonymous_3)","decl":{"start":{"line":44,"column":8},"end":{"line":44,"column":18}},"loc":{"start":{"line":44,"column":50},"end":{"line":50,"column":null}},"line":44},"4":{"name":"(anonymous_4)","decl":{"start":{"line":52,"column":8},"end":{"line":52,"column":27}},"loc":{"start":{"line":52,"column":66},"end":{"line":58,"column":null}},"line":52},"5":{"name":"(anonymous_5)","decl":{"start":{"line":60,"column":8},"end":{"line":60,"column":27}},"loc":{"start":{"line":60,"column":66},"end":{"line":66,"column":null}},"line":60},"6":{"name":"(anonymous_6)","decl":{"start":{"line":68,"column":8},"end":{"line":68,"column":21}},"loc":{"start":{"line":68,"column":65},"end":{"line":81,"column":null}},"line":68},"7":{"name":"(anonymous_7)","decl":{"start":{"line":83,"column":8},"end":{"line":83,"column":28}},"loc":{"start":{"line":83,"column":65},"end":{"line":94,"column":null}},"line":83},"8":{"name":"(anonymous_8)","decl":{"start":{"line":96,"column":8},"end":{"line":96,"column":15}},"loc":{"start":{"line":96,"column":64},"end":{"line":108,"column":null}},"line":96},"9":{"name":"(anonymous_9)","decl":{"start":{"line":110,"column":8},"end":{"line":110,"column":15}},"loc":{"start":{"line":110,"column":42},"end":{"line":116,"column":null}},"line":110}},"branchMap":{"0":{"loc":{"start":{"line":41,"column":11},"end":{"line":41,"column":null}},"type":"binary-expr","locations":[{"start":{"line":41,"column":11},"end":{"line":41,"column":24}},{"start":{"line":41,"column":24},"end":{"line":41,"column":null}}],"line":41},"1":{"loc":{"start":{"line":45,"column":4},"end":{"line":45,"column":null}},"type":"if","locations":[{"start":{"line":45,"column":4},"end":{"line":45,"column":null}},{"start":{},"end":{}}],"line":45},"2":{"loc":{"start":{"line":80,"column":11},"end":{"line":80,"column":null}},"type":"binary-expr","locations":[{"start":{"line":80,"column":11},"end":{"line":80,"column":24}},{"start":{"line":80,"column":24},"end":{"line":80,"column":null}}],"line":80},"3":{"loc":{"start":{"line":85,"column":4},"end":{"line":85,"column":null}},"type":"if","locations":[{"start":{"line":85,"column":4},"end":{"line":85,"column":null}},{"start":{},"end":{}}],"line":85},"4":{"loc":{"start":{"line":103,"column":4},"end":{"line":105,"column":null}},"type":"if","locations":[{"start":{"line":103,"column":4},"end":{"line":105,"column":null}},{"start":{},"end":{}}],"line":103},"5":{"loc":{"start":{"line":113,"column":4},"end":{"line":115,"column":null}},"type":"if","locations":[{"start":{"line":113,"column":4},"end":{"line":115,"column":null}},{"start":{},"end":{}}],"line":113}},"s":{"0":84,"1":4,"2":4,"3":4,"4":4,"5":2,"6":2,"7":0,"8":0,"9":0,"10":0,"11":0,"12":0,"13":0,"14":0,"15":0,"16":0,"17":0,"18":0,"19":0,"20":0,"21":0,"22":0,"23":0,"24":0},"f":{"0":84,"1":4,"2":2,"3":0,"4":0,"5":0,"6":0,"7":0,"8":0,"9":0},"b":{"0":[2,1],"1":[0,0],"2":[0,0],"3":[0,0],"4":[0,0],"5":[0,0]},"meta":{"lastBranch":6,"lastFunction":10,"lastStatement":25,"seen":{"f:18:2:18:22":0,"s:18:22:18:43":0,"f:20:8:20:15":1,"s:21:10:21:Infinity":1,"s:22:16:22:Infinity":2,"s:24:22:29:Infinity":3,"s:31:4:31:Infinity":4,"f:34:8:34:17":2,"s:35:19:39:Infinity":5,"s:41:4:41:Infinity":6,"b:41:11:41:24:41:24:41:Infinity":0,"f:44:8:44:18":3,"b:45:4:45:Infinity:undefined:undefined:undefined:undefined":1,"s:45:4:45:Infinity":7,"s:45:26:45:Infinity":8,"s:46:4:49:Infinity":9,"f:52:8:52:27":4,"s:53:4:57:Infinity":10,"f:60:8:60:27":5,"s:61:4:65:Infinity":11,"f:68:8:68:21":6,"s:69:19:78:Infinity":12,"s:80:4:80:Infinity":13,"b:80:11:80:24:80:24:80:Infinity":2,"f:83:8:83:28":7,"s:84:21:84:Infinity":14,"b:85:4:85:Infinity:undefined:undefined:undefined:undefined":3,"s:85:4:85:Infinity":15,"s:85:18:85:Infinity":16,"s:87:4:93:Infinity":17,"f:96:8:96:15":8,"s:97:22:101:Infinity":18,"b:103:4:105:Infinity:undefined:undefined:undefined:undefined":4,"s:103:4:105:Infinity":19,"s:104:6:104:Infinity":20,"s:107:4:107:Infinity":21,"f:110:8:110:15":9,"s:111:22:111:Infinity":22,"b:113:4:115:Infinity:undefined:undefined:undefined:undefined":5,"s:113:4:115:Infinity":23,"s:114:6:114:Infinity":24}}} +,"/Users/lukasmay/development/projects/codewalk-district/src/db/repositories/drizzle/phase.ts": {"path":"/Users/lukasmay/development/projects/codewalk-district/src/db/repositories/drizzle/phase.ts","statementMap":{"0":{"start":{"line":24,"column":22},"end":{"line":24,"column":43}},"1":{"start":{"line":27,"column":40},"end":{"line":27,"column":null}},"2":{"start":{"line":28,"column":15},"end":{"line":28,"column":null}},"3":{"start":{"line":29,"column":16},"end":{"line":29,"column":null}},"4":{"start":{"line":31,"column":22},"end":{"line":37,"column":null}},"5":{"start":{"line":39,"column":4},"end":{"line":39,"column":null}},"6":{"start":{"line":43,"column":19},"end":{"line":47,"column":null}},"7":{"start":{"line":49,"column":4},"end":{"line":49,"column":null}},"8":{"start":{"line":53,"column":4},"end":{"line":57,"column":null}},"9":{"start":{"line":61,"column":4},"end":{"line":65,"column":null}},"10":{"start":{"line":69,"column":22},"end":{"line":73,"column":null}},"11":{"start":{"line":75,"column":4},"end":{"line":77,"column":null}},"12":{"start":{"line":76,"column":6},"end":{"line":76,"column":null}},"13":{"start":{"line":79,"column":4},"end":{"line":79,"column":null}},"14":{"start":{"line":83,"column":22},"end":{"line":83,"column":null}},"15":{"start":{"line":85,"column":4},"end":{"line":87,"column":null}},"16":{"start":{"line":86,"column":6},"end":{"line":86,"column":null}},"17":{"start":{"line":91,"column":10},"end":{"line":91,"column":null}},"18":{"start":{"line":92,"column":16},"end":{"line":92,"column":null}},"19":{"start":{"line":94,"column":4},"end":{"line":99,"column":null}},"20":{"start":{"line":103,"column":19},"end":{"line":106,"column":null}},"21":{"start":{"line":108,"column":4},"end":{"line":108,"column":null}},"22":{"start":{"line":108,"column":31},"end":{"line":108,"column":51}},"23":{"start":{"line":112,"column":19},"end":{"line":115,"column":null}},"24":{"start":{"line":117,"column":4},"end":{"line":117,"column":null}},"25":{"start":{"line":117,"column":31},"end":{"line":117,"column":42}},"26":{"start":{"line":121,"column":4},"end":{"line":128,"column":null}}},"fnMap":{"0":{"name":"(anonymous_0)","decl":{"start":{"line":24,"column":2},"end":{"line":24,"column":22}},"loc":{"start":{"line":24,"column":43},"end":{"line":24,"column":null}},"line":24},"1":{"name":"(anonymous_1)","decl":{"start":{"line":26,"column":8},"end":{"line":26,"column":15}},"loc":{"start":{"line":26,"column":54},"end":{"line":40,"column":null}},"line":26},"2":{"name":"(anonymous_2)","decl":{"start":{"line":42,"column":8},"end":{"line":42,"column":17}},"loc":{"start":{"line":42,"column":52},"end":{"line":50,"column":null}},"line":42},"3":{"name":"(anonymous_3)","decl":{"start":{"line":52,"column":8},"end":{"line":52,"column":27}},"loc":{"start":{"line":52,"column":67},"end":{"line":58,"column":null}},"line":52},"4":{"name":"(anonymous_4)","decl":{"start":{"line":60,"column":8},"end":{"line":60,"column":39}},"loc":{"start":{"line":60,"column":124},"end":{"line":66,"column":null}},"line":60},"5":{"name":"(anonymous_5)","decl":{"start":{"line":68,"column":8},"end":{"line":68,"column":15}},"loc":{"start":{"line":68,"column":66},"end":{"line":80,"column":null}},"line":68},"6":{"name":"(anonymous_6)","decl":{"start":{"line":82,"column":8},"end":{"line":82,"column":15}},"loc":{"start":{"line":82,"column":42},"end":{"line":88,"column":null}},"line":82},"7":{"name":"(anonymous_7)","decl":{"start":{"line":90,"column":8},"end":{"line":90,"column":25}},"loc":{"start":{"line":90,"column":83},"end":{"line":100,"column":null}},"line":90},"8":{"name":"(anonymous_8)","decl":{"start":{"line":102,"column":8},"end":{"line":102,"column":24}},"loc":{"start":{"line":102,"column":60},"end":{"line":109,"column":null}},"line":102},"9":{"name":"(anonymous_9)","decl":{"start":{"line":108,"column":22},"end":{"line":108,"column":23}},"loc":{"start":{"line":108,"column":31},"end":{"line":108,"column":51}},"line":108},"10":{"name":"(anonymous_10)","decl":{"start":{"line":111,"column":8},"end":{"line":111,"column":22}},"loc":{"start":{"line":111,"column":58},"end":{"line":118,"column":null}},"line":111},"11":{"name":"(anonymous_11)","decl":{"start":{"line":117,"column":22},"end":{"line":117,"column":23}},"loc":{"start":{"line":117,"column":31},"end":{"line":117,"column":42}},"line":117},"12":{"name":"(anonymous_12)","decl":{"start":{"line":120,"column":8},"end":{"line":120,"column":25}},"loc":{"start":{"line":120,"column":83},"end":{"line":129,"column":null}},"line":120}},"branchMap":{"0":{"loc":{"start":{"line":28,"column":15},"end":{"line":28,"column":null}},"type":"binary-expr","locations":[{"start":{"line":28,"column":15},"end":{"line":28,"column":29}},{"start":{"line":28,"column":15},"end":{"line":28,"column":null}}],"line":28},"1":{"loc":{"start":{"line":34,"column":14},"end":{"line":34,"column":null}},"type":"binary-expr","locations":[{"start":{"line":34,"column":14},"end":{"line":34,"column":29}},{"start":{"line":34,"column":29},"end":{"line":34,"column":null}}],"line":34},"2":{"loc":{"start":{"line":49,"column":11},"end":{"line":49,"column":null}},"type":"binary-expr","locations":[{"start":{"line":49,"column":11},"end":{"line":49,"column":24}},{"start":{"line":49,"column":24},"end":{"line":49,"column":null}}],"line":49},"3":{"loc":{"start":{"line":75,"column":4},"end":{"line":77,"column":null}},"type":"if","locations":[{"start":{"line":75,"column":4},"end":{"line":77,"column":null}},{"start":{},"end":{}}],"line":75},"4":{"loc":{"start":{"line":85,"column":4},"end":{"line":87,"column":null}},"type":"if","locations":[{"start":{"line":85,"column":4},"end":{"line":87,"column":null}},{"start":{},"end":{}}],"line":85}},"s":{"0":275,"1":252,"2":252,"3":252,"4":252,"5":251,"6":154,"7":154,"8":20,"9":19,"10":65,"11":65,"12":1,"13":64,"14":3,"15":3,"16":1,"17":32,"18":32,"19":32,"20":38,"21":38,"22":21,"23":3,"24":3,"25":3,"26":0},"f":{"0":275,"1":252,"2":154,"3":20,"4":19,"5":65,"6":3,"7":32,"8":38,"9":21,"10":3,"11":3,"12":0},"b":{"0":[252,252],"1":[252,163],"2":[154,7],"3":[1,64],"4":[1,2]},"meta":{"lastBranch":5,"lastFunction":13,"lastStatement":27,"seen":{"f:24:2:24:22":0,"s:24:22:24:43":0,"f:26:8:26:15":1,"s:27:40:27:Infinity":1,"s:28:15:28:Infinity":2,"b:28:15:28:29:28:15:28:Infinity":0,"s:29:16:29:Infinity":3,"s:31:22:37:Infinity":4,"b:34:14:34:29:34:29:34:Infinity":1,"s:39:4:39:Infinity":5,"f:42:8:42:17":2,"s:43:19:47:Infinity":6,"s:49:4:49:Infinity":7,"b:49:11:49:24:49:24:49:Infinity":2,"f:52:8:52:27":3,"s:53:4:57:Infinity":8,"f:60:8:60:39":4,"s:61:4:65:Infinity":9,"f:68:8:68:15":5,"s:69:22:73:Infinity":10,"b:75:4:77:Infinity:undefined:undefined:undefined:undefined":3,"s:75:4:77:Infinity":11,"s:76:6:76:Infinity":12,"s:79:4:79:Infinity":13,"f:82:8:82:15":6,"s:83:22:83:Infinity":14,"b:85:4:87:Infinity:undefined:undefined:undefined:undefined":4,"s:85:4:87:Infinity":15,"s:86:6:86:Infinity":16,"f:90:8:90:25":7,"s:91:10:91:Infinity":17,"s:92:16:92:Infinity":18,"s:94:4:99:Infinity":19,"f:102:8:102:24":8,"s:103:19:106:Infinity":20,"s:108:4:108:Infinity":21,"f:108:22:108:23":9,"s:108:31:108:51":22,"f:111:8:111:22":10,"s:112:19:115:Infinity":23,"s:117:4:117:Infinity":24,"f:117:22:117:23":11,"s:117:31:117:42":25,"f:120:8:120:25":12,"s:121:4:128:Infinity":26}}} +,"/Users/lukasmay/development/projects/codewalk-district/src/db/repositories/drizzle/project.ts": {"path":"/Users/lukasmay/development/projects/codewalk-district/src/db/repositories/drizzle/project.ts","statementMap":{"0":{"start":{"line":18,"column":22},"end":{"line":18,"column":43}},"1":{"start":{"line":21,"column":10},"end":{"line":21,"column":null}},"2":{"start":{"line":22,"column":16},"end":{"line":22,"column":null}},"3":{"start":{"line":24,"column":22},"end":{"line":29,"column":null}},"4":{"start":{"line":31,"column":4},"end":{"line":31,"column":null}},"5":{"start":{"line":35,"column":19},"end":{"line":39,"column":null}},"6":{"start":{"line":41,"column":4},"end":{"line":41,"column":null}},"7":{"start":{"line":45,"column":19},"end":{"line":49,"column":null}},"8":{"start":{"line":51,"column":4},"end":{"line":51,"column":null}},"9":{"start":{"line":55,"column":4},"end":{"line":55,"column":null}},"10":{"start":{"line":59,"column":22},"end":{"line":63,"column":null}},"11":{"start":{"line":65,"column":4},"end":{"line":67,"column":null}},"12":{"start":{"line":66,"column":6},"end":{"line":66,"column":null}},"13":{"start":{"line":69,"column":4},"end":{"line":69,"column":null}},"14":{"start":{"line":73,"column":22},"end":{"line":73,"column":null}},"15":{"start":{"line":75,"column":4},"end":{"line":77,"column":null}},"16":{"start":{"line":76,"column":6},"end":{"line":76,"column":null}},"17":{"start":{"line":83,"column":10},"end":{"line":83,"column":null}},"18":{"start":{"line":84,"column":16},"end":{"line":84,"column":null}},"19":{"start":{"line":86,"column":4},"end":{"line":91,"column":null}},"20":{"start":{"line":95,"column":4},"end":{"line":102,"column":null}},"21":{"start":{"line":106,"column":17},"end":{"line":110,"column":null}},"22":{"start":{"line":112,"column":4},"end":{"line":112,"column":null}},"23":{"start":{"line":112,"column":27},"end":{"line":112,"column":36}},"24":{"start":{"line":117,"column":24},"end":{"line":120,"column":null}},"25":{"start":{"line":122,"column":23},"end":{"line":122,"column":null}},"26":{"start":{"line":122,"column":54},"end":{"line":122,"column":65}},"27":{"start":{"line":123,"column":23},"end":{"line":123,"column":null}},"28":{"start":{"line":126,"column":21},"end":{"line":126,"column":null}},"29":{"start":{"line":126,"column":52},"end":{"line":126,"column":71}},"30":{"start":{"line":127,"column":18},"end":{"line":127,"column":null}},"31":{"start":{"line":127,"column":49},"end":{"line":127,"column":68}},"32":{"start":{"line":130,"column":4},"end":{"line":139,"column":null}},"33":{"start":{"line":131,"column":6},"end":{"line":138,"column":null}},"34":{"start":{"line":142,"column":4},"end":{"line":152,"column":null}},"35":{"start":{"line":143,"column":18},"end":{"line":143,"column":null}},"36":{"start":{"line":144,"column":6},"end":{"line":151,"column":null}},"37":{"start":{"line":145,"column":34},"end":{"line":150,"column":10}}},"fnMap":{"0":{"name":"(anonymous_0)","decl":{"start":{"line":18,"column":2},"end":{"line":18,"column":22}},"loc":{"start":{"line":18,"column":43},"end":{"line":18,"column":null}},"line":18},"1":{"name":"(anonymous_1)","decl":{"start":{"line":20,"column":8},"end":{"line":20,"column":15}},"loc":{"start":{"line":20,"column":58},"end":{"line":32,"column":null}},"line":20},"2":{"name":"(anonymous_2)","decl":{"start":{"line":34,"column":8},"end":{"line":34,"column":17}},"loc":{"start":{"line":34,"column":54},"end":{"line":42,"column":null}},"line":34},"3":{"name":"(anonymous_3)","decl":{"start":{"line":44,"column":8},"end":{"line":44,"column":19}},"loc":{"start":{"line":44,"column":58},"end":{"line":52,"column":null}},"line":44},"4":{"name":"(anonymous_4)","decl":{"start":{"line":54,"column":8},"end":{"line":54,"column":38}},"loc":{"start":{"line":54,"column":38},"end":{"line":56,"column":null}},"line":54},"5":{"name":"(anonymous_5)","decl":{"start":{"line":58,"column":8},"end":{"line":58,"column":15}},"loc":{"start":{"line":58,"column":70},"end":{"line":70,"column":null}},"line":58},"6":{"name":"(anonymous_6)","decl":{"start":{"line":72,"column":8},"end":{"line":72,"column":15}},"loc":{"start":{"line":72,"column":42},"end":{"line":78,"column":null}},"line":72},"7":{"name":"(anonymous_7)","decl":{"start":{"line":82,"column":8},"end":{"line":82,"column":31}},"loc":{"start":{"line":82,"column":87},"end":{"line":92,"column":null}},"line":82},"8":{"name":"(anonymous_8)","decl":{"start":{"line":94,"column":8},"end":{"line":94,"column":36}},"loc":{"start":{"line":94,"column":92},"end":{"line":103,"column":null}},"line":94},"9":{"name":"(anonymous_9)","decl":{"start":{"line":105,"column":8},"end":{"line":105,"column":35}},"loc":{"start":{"line":105,"column":77},"end":{"line":113,"column":null}},"line":105},"10":{"name":"(anonymous_10)","decl":{"start":{"line":112,"column":20},"end":{"line":112,"column":21}},"loc":{"start":{"line":112,"column":27},"end":{"line":112,"column":36}},"line":112},"11":{"name":"(anonymous_11)","decl":{"start":{"line":115,"column":8},"end":{"line":115,"column":30}},"loc":{"start":{"line":115,"column":89},"end":{"line":153,"column":null}},"line":115},"12":{"name":"(anonymous_12)","decl":{"start":{"line":122,"column":47},"end":{"line":122,"column":48}},"loc":{"start":{"line":122,"column":54},"end":{"line":122,"column":65}},"line":122},"13":{"name":"(anonymous_13)","decl":{"start":{"line":126,"column":44},"end":{"line":126,"column":45}},"loc":{"start":{"line":126,"column":52},"end":{"line":126,"column":71}},"line":126},"14":{"name":"(anonymous_14)","decl":{"start":{"line":127,"column":41},"end":{"line":127,"column":42}},"loc":{"start":{"line":127,"column":49},"end":{"line":127,"column":68}},"line":127},"15":{"name":"(anonymous_15)","decl":{"start":{"line":145,"column":18},"end":{"line":145,"column":19}},"loc":{"start":{"line":145,"column":34},"end":{"line":150,"column":10}},"line":145}},"branchMap":{"0":{"loc":{"start":{"line":41,"column":11},"end":{"line":41,"column":null}},"type":"binary-expr","locations":[{"start":{"line":41,"column":11},"end":{"line":41,"column":24}},{"start":{"line":41,"column":24},"end":{"line":41,"column":null}}],"line":41},"1":{"loc":{"start":{"line":51,"column":11},"end":{"line":51,"column":null}},"type":"binary-expr","locations":[{"start":{"line":51,"column":11},"end":{"line":51,"column":24}},{"start":{"line":51,"column":24},"end":{"line":51,"column":null}}],"line":51},"2":{"loc":{"start":{"line":65,"column":4},"end":{"line":67,"column":null}},"type":"if","locations":[{"start":{"line":65,"column":4},"end":{"line":67,"column":null}},{"start":{},"end":{}}],"line":65},"3":{"loc":{"start":{"line":75,"column":4},"end":{"line":77,"column":null}},"type":"if","locations":[{"start":{"line":75,"column":4},"end":{"line":77,"column":null}},{"start":{},"end":{}}],"line":75},"4":{"loc":{"start":{"line":130,"column":4},"end":{"line":139,"column":null}},"type":"if","locations":[{"start":{"line":130,"column":4},"end":{"line":139,"column":null}},{"start":{},"end":{}}],"line":130},"5":{"loc":{"start":{"line":142,"column":4},"end":{"line":152,"column":null}},"type":"if","locations":[{"start":{"line":142,"column":4},"end":{"line":152,"column":null}},{"start":{},"end":{}}],"line":142}},"s":{"0":84,"1":4,"2":4,"3":4,"4":4,"5":1,"6":1,"7":0,"8":0,"9":0,"10":0,"11":0,"12":0,"13":0,"14":0,"15":0,"16":0,"17":0,"18":0,"19":0,"20":0,"21":2,"22":2,"23":1,"24":4,"25":4,"26":0,"27":4,"28":4,"29":0,"30":4,"31":4,"32":4,"33":0,"34":4,"35":4,"36":4,"37":4},"f":{"0":84,"1":4,"2":1,"3":0,"4":0,"5":0,"6":0,"7":0,"8":0,"9":2,"10":1,"11":4,"12":0,"13":0,"14":4,"15":4},"b":{"0":[1,0],"1":[0,0],"2":[0,0],"3":[0,0],"4":[0,4],"5":[4,0]},"meta":{"lastBranch":6,"lastFunction":16,"lastStatement":38,"seen":{"f:18:2:18:22":0,"s:18:22:18:43":0,"f:20:8:20:15":1,"s:21:10:21:Infinity":1,"s:22:16:22:Infinity":2,"s:24:22:29:Infinity":3,"s:31:4:31:Infinity":4,"f:34:8:34:17":2,"s:35:19:39:Infinity":5,"s:41:4:41:Infinity":6,"b:41:11:41:24:41:24:41:Infinity":0,"f:44:8:44:19":3,"s:45:19:49:Infinity":7,"s:51:4:51:Infinity":8,"b:51:11:51:24:51:24:51:Infinity":1,"f:54:8:54:38":4,"s:55:4:55:Infinity":9,"f:58:8:58:15":5,"s:59:22:63:Infinity":10,"b:65:4:67:Infinity:undefined:undefined:undefined:undefined":2,"s:65:4:67:Infinity":11,"s:66:6:66:Infinity":12,"s:69:4:69:Infinity":13,"f:72:8:72:15":6,"s:73:22:73:Infinity":14,"b:75:4:77:Infinity:undefined:undefined:undefined:undefined":3,"s:75:4:77:Infinity":15,"s:76:6:76:Infinity":16,"f:82:8:82:31":7,"s:83:10:83:Infinity":17,"s:84:16:84:Infinity":18,"s:86:4:91:Infinity":19,"f:94:8:94:36":8,"s:95:4:102:Infinity":20,"f:105:8:105:35":9,"s:106:17:110:Infinity":21,"s:112:4:112:Infinity":22,"f:112:20:112:21":10,"s:112:27:112:36":23,"f:115:8:115:30":11,"s:117:24:120:Infinity":24,"s:122:23:122:Infinity":25,"f:122:47:122:48":12,"s:122:54:122:65":26,"s:123:23:123:Infinity":27,"s:126:21:126:Infinity":28,"f:126:44:126:45":13,"s:126:52:126:71":29,"s:127:18:127:Infinity":30,"f:127:41:127:42":14,"s:127:49:127:68":31,"b:130:4:139:Infinity:undefined:undefined:undefined:undefined":4,"s:130:4:139:Infinity":32,"s:131:6:138:Infinity":33,"b:142:4:152:Infinity:undefined:undefined:undefined:undefined":5,"s:142:4:152:Infinity":34,"s:143:18:143:Infinity":35,"s:144:6:151:Infinity":36,"f:145:18:145:19":15,"s:145:34:150:10":37}}} +,"/Users/lukasmay/development/projects/codewalk-district/src/db/repositories/drizzle/task.ts": {"path":"/Users/lukasmay/development/projects/codewalk-district/src/db/repositories/drizzle/task.ts","statementMap":{"0":{"start":{"line":25,"column":22},"end":{"line":25,"column":43}},"1":{"start":{"line":28,"column":10},"end":{"line":28,"column":null}},"2":{"start":{"line":29,"column":16},"end":{"line":29,"column":null}},"3":{"start":{"line":31,"column":22},"end":{"line":41,"column":null}},"4":{"start":{"line":43,"column":4},"end":{"line":43,"column":null}},"5":{"start":{"line":47,"column":19},"end":{"line":51,"column":null}},"6":{"start":{"line":53,"column":4},"end":{"line":53,"column":null}},"7":{"start":{"line":57,"column":4},"end":{"line":61,"column":null}},"8":{"start":{"line":65,"column":4},"end":{"line":69,"column":null}},"9":{"start":{"line":73,"column":4},"end":{"line":77,"column":null}},"10":{"start":{"line":81,"column":23},"end":{"line":81,"column":null}},"11":{"start":{"line":83,"column":4},"end":{"line":85,"column":null}},"12":{"start":{"line":84,"column":6},"end":{"line":84,"column":null}},"13":{"start":{"line":86,"column":4},"end":{"line":88,"column":null}},"14":{"start":{"line":87,"column":6},"end":{"line":87,"column":null}},"15":{"start":{"line":89,"column":4},"end":{"line":91,"column":null}},"16":{"start":{"line":90,"column":6},"end":{"line":90,"column":null}},"17":{"start":{"line":93,"column":4},"end":{"line":97,"column":null}},"18":{"start":{"line":101,"column":22},"end":{"line":105,"column":null}},"19":{"start":{"line":107,"column":4},"end":{"line":109,"column":null}},"20":{"start":{"line":108,"column":6},"end":{"line":108,"column":null}},"21":{"start":{"line":111,"column":4},"end":{"line":111,"column":null}},"22":{"start":{"line":115,"column":22},"end":{"line":115,"column":null}},"23":{"start":{"line":117,"column":4},"end":{"line":119,"column":null}},"24":{"start":{"line":118,"column":6},"end":{"line":118,"column":null}},"25":{"start":{"line":123,"column":10},"end":{"line":123,"column":null}},"26":{"start":{"line":124,"column":16},"end":{"line":124,"column":null}},"27":{"start":{"line":126,"column":4},"end":{"line":131,"column":null}},"28":{"start":{"line":135,"column":17},"end":{"line":138,"column":null}},"29":{"start":{"line":140,"column":4},"end":{"line":140,"column":null}},"30":{"start":{"line":140,"column":27},"end":{"line":140,"column":44}}},"fnMap":{"0":{"name":"(anonymous_0)","decl":{"start":{"line":25,"column":2},"end":{"line":25,"column":22}},"loc":{"start":{"line":25,"column":43},"end":{"line":25,"column":null}},"line":25},"1":{"name":"(anonymous_1)","decl":{"start":{"line":27,"column":8},"end":{"line":27,"column":15}},"loc":{"start":{"line":27,"column":52},"end":{"line":44,"column":null}},"line":27},"2":{"name":"(anonymous_2)","decl":{"start":{"line":46,"column":8},"end":{"line":46,"column":17}},"loc":{"start":{"line":46,"column":51},"end":{"line":54,"column":null}},"line":46},"3":{"name":"(anonymous_3)","decl":{"start":{"line":56,"column":8},"end":{"line":56,"column":27}},"loc":{"start":{"line":56,"column":66},"end":{"line":62,"column":null}},"line":56},"4":{"name":"(anonymous_4)","decl":{"start":{"line":64,"column":8},"end":{"line":64,"column":27}},"loc":{"start":{"line":64,"column":66},"end":{"line":70,"column":null}},"line":64},"5":{"name":"(anonymous_5)","decl":{"start":{"line":72,"column":8},"end":{"line":72,"column":22}},"loc":{"start":{"line":72,"column":56},"end":{"line":78,"column":null}},"line":72},"6":{"name":"(anonymous_6)","decl":{"start":{"line":80,"column":8},"end":{"line":80,"column":28}},"loc":{"start":{"line":80,"column":79},"end":{"line":98,"column":null}},"line":80},"7":{"name":"(anonymous_7)","decl":{"start":{"line":100,"column":8},"end":{"line":100,"column":15}},"loc":{"start":{"line":100,"column":64},"end":{"line":112,"column":null}},"line":100},"8":{"name":"(anonymous_8)","decl":{"start":{"line":114,"column":8},"end":{"line":114,"column":15}},"loc":{"start":{"line":114,"column":42},"end":{"line":120,"column":null}},"line":114},"9":{"name":"(anonymous_9)","decl":{"start":{"line":122,"column":8},"end":{"line":122,"column":25}},"loc":{"start":{"line":122,"column":81},"end":{"line":132,"column":null}},"line":122},"10":{"name":"(anonymous_10)","decl":{"start":{"line":134,"column":8},"end":{"line":134,"column":24}},"loc":{"start":{"line":134,"column":59},"end":{"line":141,"column":null}},"line":134},"11":{"name":"(anonymous_11)","decl":{"start":{"line":140,"column":20},"end":{"line":140,"column":21}},"loc":{"start":{"line":140,"column":27},"end":{"line":140,"column":44}},"line":140}},"branchMap":{"0":{"loc":{"start":{"line":34,"column":12},"end":{"line":34,"column":null}},"type":"binary-expr","locations":[{"start":{"line":34,"column":12},"end":{"line":34,"column":25}},{"start":{"line":34,"column":25},"end":{"line":34,"column":null}}],"line":34},"1":{"loc":{"start":{"line":35,"column":16},"end":{"line":35,"column":null}},"type":"binary-expr","locations":[{"start":{"line":35,"column":16},"end":{"line":35,"column":33}},{"start":{"line":35,"column":33},"end":{"line":35,"column":null}}],"line":35},"2":{"loc":{"start":{"line":36,"column":16},"end":{"line":36,"column":null}},"type":"binary-expr","locations":[{"start":{"line":36,"column":16},"end":{"line":36,"column":33}},{"start":{"line":36,"column":33},"end":{"line":36,"column":null}}],"line":36},"3":{"loc":{"start":{"line":37,"column":14},"end":{"line":37,"column":null}},"type":"binary-expr","locations":[{"start":{"line":37,"column":14},"end":{"line":37,"column":29}},{"start":{"line":37,"column":29},"end":{"line":37,"column":null}}],"line":37},"4":{"loc":{"start":{"line":38,"column":13},"end":{"line":38,"column":null}},"type":"binary-expr","locations":[{"start":{"line":38,"column":13},"end":{"line":38,"column":27}},{"start":{"line":38,"column":27},"end":{"line":38,"column":null}}],"line":38},"5":{"loc":{"start":{"line":53,"column":11},"end":{"line":53,"column":null}},"type":"binary-expr","locations":[{"start":{"line":53,"column":11},"end":{"line":53,"column":24}},{"start":{"line":53,"column":24},"end":{"line":53,"column":null}}],"line":53},"6":{"loc":{"start":{"line":83,"column":4},"end":{"line":85,"column":null}},"type":"if","locations":[{"start":{"line":83,"column":4},"end":{"line":85,"column":null}},{"start":{},"end":{}}],"line":83},"7":{"loc":{"start":{"line":86,"column":4},"end":{"line":88,"column":null}},"type":"if","locations":[{"start":{"line":86,"column":4},"end":{"line":88,"column":null}},{"start":{},"end":{}}],"line":86},"8":{"loc":{"start":{"line":89,"column":4},"end":{"line":91,"column":null}},"type":"if","locations":[{"start":{"line":89,"column":4},"end":{"line":91,"column":null}},{"start":{},"end":{}}],"line":89},"9":{"loc":{"start":{"line":107,"column":4},"end":{"line":109,"column":null}},"type":"if","locations":[{"start":{"line":107,"column":4},"end":{"line":109,"column":null}},{"start":{},"end":{}}],"line":107},"10":{"loc":{"start":{"line":117,"column":4},"end":{"line":119,"column":null}},"type":"if","locations":[{"start":{"line":117,"column":4},"end":{"line":119,"column":null}},{"start":{},"end":{}}],"line":117}},"s":{"0":253,"1":415,"2":415,"3":415,"4":414,"5":343,"6":343,"7":5,"8":16,"9":34,"10":0,"11":0,"12":0,"13":0,"14":0,"15":0,"16":0,"17":0,"18":100,"19":100,"20":1,"21":99,"22":3,"23":3,"24":1,"25":12,"26":12,"27":12,"28":66,"29":66,"30":6},"f":{"0":253,"1":415,"2":343,"3":5,"4":16,"5":34,"6":0,"7":100,"8":3,"9":12,"10":66,"11":6},"b":{"0":[415,147],"1":[415,132],"2":[415,135],"3":[415,127],"4":[415,26],"5":[343,21],"6":[0,0],"7":[0,0],"8":[0,0],"9":[1,99],"10":[1,2]},"meta":{"lastBranch":11,"lastFunction":12,"lastStatement":31,"seen":{"f:25:2:25:22":0,"s:25:22:25:43":0,"f:27:8:27:15":1,"s:28:10:28:Infinity":1,"s:29:16:29:Infinity":2,"s:31:22:41:Infinity":3,"b:34:12:34:25:34:25:34:Infinity":0,"b:35:16:35:33:35:33:35:Infinity":1,"b:36:16:36:33:36:33:36:Infinity":2,"b:37:14:37:29:37:29:37:Infinity":3,"b:38:13:38:27:38:27:38:Infinity":4,"s:43:4:43:Infinity":4,"f:46:8:46:17":2,"s:47:19:51:Infinity":5,"s:53:4:53:Infinity":6,"b:53:11:53:24:53:24:53:Infinity":5,"f:56:8:56:27":3,"s:57:4:61:Infinity":7,"f:64:8:64:27":4,"s:65:4:69:Infinity":8,"f:72:8:72:22":5,"s:73:4:77:Infinity":9,"f:80:8:80:28":6,"s:81:23:81:Infinity":10,"b:83:4:85:Infinity:undefined:undefined:undefined:undefined":6,"s:83:4:85:Infinity":11,"s:84:6:84:Infinity":12,"b:86:4:88:Infinity:undefined:undefined:undefined:undefined":7,"s:86:4:88:Infinity":13,"s:87:6:87:Infinity":14,"b:89:4:91:Infinity:undefined:undefined:undefined:undefined":8,"s:89:4:91:Infinity":15,"s:90:6:90:Infinity":16,"s:93:4:97:Infinity":17,"f:100:8:100:15":7,"s:101:22:105:Infinity":18,"b:107:4:109:Infinity:undefined:undefined:undefined:undefined":9,"s:107:4:109:Infinity":19,"s:108:6:108:Infinity":20,"s:111:4:111:Infinity":21,"f:114:8:114:15":8,"s:115:22:115:Infinity":22,"b:117:4:119:Infinity:undefined:undefined:undefined:undefined":10,"s:117:4:119:Infinity":23,"s:118:6:118:Infinity":24,"f:122:8:122:25":9,"s:123:10:123:Infinity":25,"s:124:16:124:Infinity":26,"s:126:4:131:Infinity":27,"f:134:8:134:24":10,"s:135:17:138:Infinity":28,"s:140:4:140:Infinity":29,"f:140:20:140:21":11,"s:140:27:140:44":30}}} +,"/Users/lukasmay/development/projects/codewalk-district/src/db/repositories/drizzle/test-helpers.ts": {"path":"/Users/lukasmay/development/projects/codewalk-district/src/db/repositories/drizzle/test-helpers.ts","statementMap":{"0":{"start":{"line":19,"column":17},"end":{"line":19,"column":null}},"1":{"start":{"line":22,"column":2},"end":{"line":22,"column":null}},"2":{"start":{"line":24,"column":8},"end":{"line":24,"column":null}},"3":{"start":{"line":27,"column":2},"end":{"line":27,"column":null}},"4":{"start":{"line":29,"column":2},"end":{"line":29,"column":null}}},"fnMap":{"0":{"name":"createTestDatabase","decl":{"start":{"line":18,"column":16},"end":{"line":18,"column":54}},"loc":{"start":{"line":18,"column":54},"end":{"line":30,"column":null}},"line":18}},"branchMap":{},"s":{"0":239,"1":239,"2":239,"3":239,"4":239},"f":{"0":239},"b":{},"meta":{"lastBranch":0,"lastFunction":1,"lastStatement":5,"seen":{"f:18:16:18:54":0,"s:19:17:19:Infinity":0,"s:22:2:22:Infinity":1,"s:24:8:24:Infinity":2,"s:27:2:27:Infinity":3,"s:29:2:29:Infinity":4}}} +,"/Users/lukasmay/development/projects/codewalk-district/src/dispatch/manager.ts": {"path":"/Users/lukasmay/development/projects/codewalk-district/src/dispatch/manager.ts","statementMap":{"0":{"start":{"line":29,"column":6},"end":{"line":29,"column":null}},"1":{"start":{"line":55,"column":47},"end":{"line":55,"column":null}},"2":{"start":{"line":58,"column":51},"end":{"line":58,"column":null}},"3":{"start":{"line":61,"column":12},"end":{"line":61,"column":null}},"4":{"start":{"line":62,"column":12},"end":{"line":62,"column":null}},"5":{"start":{"line":63,"column":12},"end":{"line":63,"column":null}},"6":{"start":{"line":64,"column":12},"end":{"line":64,"column":null}},"7":{"start":{"line":65,"column":12},"end":{"line":65,"column":null}},"8":{"start":{"line":66,"column":12},"end":{"line":66,"column":null}},"9":{"start":{"line":76,"column":17},"end":{"line":76,"column":null}},"10":{"start":{"line":77,"column":4},"end":{"line":79,"column":null}},"11":{"start":{"line":78,"column":6},"end":{"line":78,"column":null}},"12":{"start":{"line":82,"column":22},"end":{"line":82,"column":null}},"13":{"start":{"line":84,"column":35},"end":{"line":89,"column":null}},"14":{"start":{"line":91,"column":4},"end":{"line":91,"column":null}},"15":{"start":{"line":93,"column":4},"end":{"line":93,"column":null}},"16":{"start":{"line":96,"column":35},"end":{"line":104,"column":null}},"17":{"start":{"line":105,"column":4},"end":{"line":105,"column":null}},"18":{"start":{"line":114,"column":24},"end":{"line":114,"column":null}},"19":{"start":{"line":116,"column":4},"end":{"line":118,"column":null}},"20":{"start":{"line":117,"column":6},"end":{"line":117,"column":null}},"21":{"start":{"line":121,"column":37},"end":{"line":121,"column":null}},"22":{"start":{"line":123,"column":4},"end":{"line":123,"column":null}},"23":{"start":{"line":125,"column":4},"end":{"line":146,"column":null}},"24":{"start":{"line":127,"column":30},"end":{"line":127,"column":null}},"25":{"start":{"line":128,"column":6},"end":{"line":130,"column":null}},"26":{"start":{"line":129,"column":8},"end":{"line":129,"column":null}},"27":{"start":{"line":133,"column":19},"end":{"line":133,"column":null}},"28":{"start":{"line":134,"column":6},"end":{"line":137,"column":null}},"29":{"start":{"line":135,"column":8},"end":{"line":135,"column":null}},"30":{"start":{"line":136,"column":8},"end":{"line":136,"column":null}},"31":{"start":{"line":140,"column":6},"end":{"line":143,"column":null}},"32":{"start":{"line":141,"column":8},"end":{"line":141,"column":null}},"33":{"start":{"line":142,"column":8},"end":{"line":142,"column":null}},"34":{"start":{"line":145,"column":6},"end":{"line":145,"column":null}},"35":{"start":{"line":148,"column":4},"end":{"line":148,"column":null}},"36":{"start":{"line":150,"column":4},"end":{"line":152,"column":null}},"37":{"start":{"line":151,"column":6},"end":{"line":151,"column":null}},"38":{"start":{"line":155,"column":50},"end":{"line":155,"column":null}},"39":{"start":{"line":157,"column":4},"end":{"line":163,"column":null}},"40":{"start":{"line":158,"column":27},"end":{"line":158,"column":null}},"41":{"start":{"line":159,"column":6},"end":{"line":161,"column":null}},"42":{"start":{"line":160,"column":8},"end":{"line":160,"column":null}},"43":{"start":{"line":162,"column":6},"end":{"line":162,"column":null}},"44":{"start":{"line":165,"column":4},"end":{"line":165,"column":null}},"45":{"start":{"line":177,"column":17},"end":{"line":177,"column":null}},"46":{"start":{"line":178,"column":4},"end":{"line":180,"column":null}},"47":{"start":{"line":179,"column":6},"end":{"line":179,"column":null}},"48":{"start":{"line":183,"column":29},"end":{"line":183,"column":null}},"49":{"start":{"line":185,"column":4},"end":{"line":227,"column":null}},"50":{"start":{"line":187,"column":6},"end":{"line":187,"column":null}},"51":{"start":{"line":190,"column":6},"end":{"line":190,"column":null}},"52":{"start":{"line":192,"column":6},"end":{"line":192,"column":null}},"53":{"start":{"line":195,"column":46},"end":{"line":204,"column":null}},"54":{"start":{"line":205,"column":6},"end":{"line":205,"column":null}},"55":{"start":{"line":208,"column":6},"end":{"line":208,"column":null}},"56":{"start":{"line":211,"column":6},"end":{"line":211,"column":null}},"57":{"start":{"line":213,"column":6},"end":{"line":213,"column":null}},"58":{"start":{"line":216,"column":40},"end":{"line":225,"column":null}},"59":{"start":{"line":226,"column":6},"end":{"line":226,"column":null}},"60":{"start":{"line":230,"column":4},"end":{"line":230,"column":null}},"61":{"start":{"line":238,"column":17},"end":{"line":238,"column":null}},"62":{"start":{"line":239,"column":4},"end":{"line":241,"column":null}},"63":{"start":{"line":240,"column":6},"end":{"line":240,"column":null}},"64":{"start":{"line":243,"column":4},"end":{"line":245,"column":null}},"65":{"start":{"line":244,"column":6},"end":{"line":244,"column":null}},"66":{"start":{"line":248,"column":4},"end":{"line":248,"column":null}},"67":{"start":{"line":250,"column":4},"end":{"line":250,"column":null}},"68":{"start":{"line":253,"column":38},"end":{"line":262,"column":null}},"69":{"start":{"line":263,"column":4},"end":{"line":263,"column":null}},"70":{"start":{"line":272,"column":4},"end":{"line":272,"column":null}},"71":{"start":{"line":275,"column":4},"end":{"line":275,"column":null}},"72":{"start":{"line":277,"column":4},"end":{"line":277,"column":null}},"73":{"start":{"line":280,"column":4},"end":{"line":280,"column":null}},"74":{"start":{"line":283,"column":36},"end":{"line":290,"column":null}},"75":{"start":{"line":291,"column":4},"end":{"line":291,"column":null}},"76":{"start":{"line":299,"column":21},"end":{"line":299,"column":null}},"77":{"start":{"line":301,"column":4},"end":{"line":308,"column":null}},"78":{"start":{"line":302,"column":6},"end":{"line":302,"column":null}},"79":{"start":{"line":303,"column":6},"end":{"line":307,"column":null}},"80":{"start":{"line":311,"column":19},"end":{"line":311,"column":null}},"81":{"start":{"line":312,"column":22},"end":{"line":312,"column":null}},"82":{"start":{"line":312,"column":41},"end":{"line":312,"column":60}},"83":{"start":{"line":314,"column":4},"end":{"line":321,"column":null}},"84":{"start":{"line":315,"column":6},"end":{"line":315,"column":null}},"85":{"start":{"line":316,"column":6},"end":{"line":320,"column":null}},"86":{"start":{"line":324,"column":17},"end":{"line":324,"column":null}},"87":{"start":{"line":325,"column":4},"end":{"line":331,"column":null}},"88":{"start":{"line":326,"column":6},"end":{"line":330,"column":null}},"89":{"start":{"line":337,"column":4},"end":{"line":368,"column":null}},"90":{"start":{"line":338,"column":6},"end":{"line":367,"column":null}},"91":{"start":{"line":339,"column":8},"end":{"line":364,"column":null}},"92":{"start":{"line":342,"column":8},"end":{"line":364,"column":null}},"93":{"start":{"line":344,"column":29},"end":{"line":344,"column":null}},"94":{"start":{"line":345,"column":10},"end":{"line":363,"column":null}},"95":{"start":{"line":346,"column":29},"end":{"line":346,"column":null}},"96":{"start":{"line":347,"column":12},"end":{"line":350,"column":null}},"97":{"start":{"line":348,"column":14},"end":{"line":348,"column":null}},"98":{"start":{"line":349,"column":14},"end":{"line":349,"column":null}},"99":{"start":{"line":352,"column":26},"end":{"line":352,"column":null}},"100":{"start":{"line":353,"column":12},"end":{"line":362,"column":null}},"101":{"start":{"line":354,"column":14},"end":{"line":361,"column":null}},"102":{"start":{"line":356,"column":16},"end":{"line":356,"column":null}},"103":{"start":{"line":357,"column":16},"end":{"line":357,"column":null}},"104":{"start":{"line":359,"column":16},"end":{"line":359,"column":null}},"105":{"start":{"line":360,"column":16},"end":{"line":360,"column":null}},"106":{"start":{"line":371,"column":18},"end":{"line":378,"column":null}},"107":{"start":{"line":380,"column":4},"end":{"line":380,"column":null}},"108":{"start":{"line":383,"column":4},"end":{"line":383,"column":null}},"109":{"start":{"line":386,"column":4},"end":{"line":386,"column":null}},"110":{"start":{"line":389,"column":39},"end":{"line":397,"column":null}},"111":{"start":{"line":398,"column":4},"end":{"line":398,"column":null}},"112":{"start":{"line":400,"column":4},"end":{"line":404,"column":null}},"113":{"start":{"line":415,"column":22},"end":{"line":415,"column":null}},"114":{"start":{"line":418,"column":32},"end":{"line":418,"column":null}},"115":{"start":{"line":419,"column":4},"end":{"line":424,"column":null}},"116":{"start":{"line":420,"column":30},"end":{"line":420,"column":null}},"117":{"start":{"line":421,"column":6},"end":{"line":423,"column":null}},"118":{"start":{"line":422,"column":8},"end":{"line":422,"column":null}},"119":{"start":{"line":426,"column":4},"end":{"line":430,"column":null}},"120":{"start":{"line":441,"column":4},"end":{"line":443,"column":null}},"121":{"start":{"line":442,"column":6},"end":{"line":442,"column":null}},"122":{"start":{"line":445,"column":4},"end":{"line":450,"column":null}},"123":{"start":{"line":446,"column":22},"end":{"line":446,"column":null}},"124":{"start":{"line":447,"column":6},"end":{"line":449,"column":null}},"125":{"start":{"line":448,"column":8},"end":{"line":448,"column":null}},"126":{"start":{"line":452,"column":4},"end":{"line":452,"column":null}},"127":{"start":{"line":460,"column":4},"end":{"line":460,"column":null}},"128":{"start":{"line":469,"column":4},"end":{"line":471,"column":null}},"129":{"start":{"line":470,"column":6},"end":{"line":470,"column":null}},"130":{"start":{"line":474,"column":4},"end":{"line":479,"column":null}},"131":{"start":{"line":475,"column":25},"end":{"line":475,"column":null}},"132":{"start":{"line":476,"column":6},"end":{"line":478,"column":null}},"133":{"start":{"line":477,"column":8},"end":{"line":477,"column":null}},"134":{"start":{"line":483,"column":4},"end":{"line":483,"column":null}}},"fnMap":{"0":{"name":"(anonymous_0)","decl":{"start":{"line":60,"column":2},"end":{"line":60,"column":null}},"loc":{"start":{"line":67,"column":4},"end":{"line":67,"column":null}},"line":67},"1":{"name":"(anonymous_1)","decl":{"start":{"line":74,"column":8},"end":{"line":74,"column":14}},"loc":{"start":{"line":74,"column":45},"end":{"line":106,"column":null}},"line":74},"2":{"name":"(anonymous_2)","decl":{"start":{"line":113,"column":8},"end":{"line":113,"column":58}},"loc":{"start":{"line":113,"column":58},"end":{"line":166,"column":null}},"line":113},"3":{"name":"(anonymous_3)","decl":{"start":{"line":157,"column":20},"end":{"line":157,"column":21}},"loc":{"start":{"line":157,"column":30},"end":{"line":163,"column":5}},"line":157},"4":{"name":"(anonymous_4)","decl":{"start":{"line":176,"column":8},"end":{"line":176,"column":21}},"loc":{"start":{"line":176,"column":70},"end":{"line":231,"column":null}},"line":176},"5":{"name":"(anonymous_5)","decl":{"start":{"line":237,"column":8},"end":{"line":237,"column":20}},"loc":{"start":{"line":237,"column":51},"end":{"line":264,"column":null}},"line":237},"6":{"name":"(anonymous_6)","decl":{"start":{"line":270,"column":8},"end":{"line":270,"column":18}},"loc":{"start":{"line":270,"column":65},"end":{"line":292,"column":null}},"line":270},"7":{"name":"(anonymous_7)","decl":{"start":{"line":297,"column":8},"end":{"line":297,"column":48}},"loc":{"start":{"line":297,"column":48},"end":{"line":405,"column":null}},"line":297},"8":{"name":"(anonymous_8)","decl":{"start":{"line":312,"column":34},"end":{"line":312,"column":35}},"loc":{"start":{"line":312,"column":41},"end":{"line":312,"column":60}},"line":312},"9":{"name":"(anonymous_9)","decl":{"start":{"line":410,"column":8},"end":{"line":410,"column":null}},"loc":{"start":{"line":414,"column":5},"end":{"line":431,"column":null}},"line":414},"10":{"name":"(anonymous_10)","decl":{"start":{"line":440,"column":16},"end":{"line":440,"column":43}},"loc":{"start":{"line":440,"column":82},"end":{"line":453,"column":null}},"line":440},"11":{"name":"(anonymous_11)","decl":{"start":{"line":459,"column":10},"end":{"line":459,"column":27}},"loc":{"start":{"line":459,"column":48},"end":{"line":461,"column":null}},"line":459},"12":{"name":"(anonymous_12)","decl":{"start":{"line":467,"column":16},"end":{"line":467,"column":37}},"loc":{"start":{"line":467,"column":67},"end":{"line":484,"column":null}},"line":467}},"branchMap":{"0":{"loc":{"start":{"line":77,"column":4},"end":{"line":79,"column":null}},"type":"if","locations":[{"start":{"line":77,"column":4},"end":{"line":79,"column":null}},{"start":{},"end":{}}],"line":77},"1":{"loc":{"start":{"line":116,"column":4},"end":{"line":118,"column":null}},"type":"if","locations":[{"start":{"line":116,"column":4},"end":{"line":118,"column":null}},{"start":{},"end":{}}],"line":116},"2":{"loc":{"start":{"line":128,"column":6},"end":{"line":130,"column":null}},"type":"if","locations":[{"start":{"line":128,"column":6},"end":{"line":130,"column":null}},{"start":{},"end":{}}],"line":128},"3":{"loc":{"start":{"line":134,"column":6},"end":{"line":137,"column":null}},"type":"if","locations":[{"start":{"line":134,"column":6},"end":{"line":137,"column":null}},{"start":{},"end":{}}],"line":134},"4":{"loc":{"start":{"line":134,"column":10},"end":{"line":134,"column":47}},"type":"binary-expr","locations":[{"start":{"line":134,"column":10},"end":{"line":134,"column":18}},{"start":{"line":134,"column":18},"end":{"line":134,"column":47}}],"line":134},"5":{"loc":{"start":{"line":140,"column":6},"end":{"line":143,"column":null}},"type":"if","locations":[{"start":{"line":140,"column":6},"end":{"line":143,"column":null}},{"start":{},"end":{}}],"line":140},"6":{"loc":{"start":{"line":140,"column":10},"end":{"line":140,"column":53}},"type":"binary-expr","locations":[{"start":{"line":140,"column":10},"end":{"line":140,"column":18}},{"start":{"line":140,"column":10},"end":{"line":140,"column":53}}],"line":140},"7":{"loc":{"start":{"line":150,"column":4},"end":{"line":152,"column":null}},"type":"if","locations":[{"start":{"line":150,"column":4},"end":{"line":152,"column":null}},{"start":{},"end":{}}],"line":150},"8":{"loc":{"start":{"line":159,"column":6},"end":{"line":161,"column":null}},"type":"if","locations":[{"start":{"line":159,"column":6},"end":{"line":161,"column":null}},{"start":{},"end":{}}],"line":159},"9":{"loc":{"start":{"line":178,"column":4},"end":{"line":180,"column":null}},"type":"if","locations":[{"start":{"line":178,"column":4},"end":{"line":180,"column":null}},{"start":{},"end":{}}],"line":178},"10":{"loc":{"start":{"line":185,"column":4},"end":{"line":227,"column":null}},"type":"if","locations":[{"start":{"line":185,"column":4},"end":{"line":227,"column":null}},{"start":{"line":206,"column":11},"end":{"line":227,"column":null}}],"line":185},"11":{"loc":{"start":{"line":200,"column":19},"end":{"line":200,"column":null}},"type":"binary-expr","locations":[{"start":{"line":200,"column":19},"end":{"line":200,"column":30}},{"start":{"line":200,"column":30},"end":{"line":200,"column":null}}],"line":200},"12":{"loc":{"start":{"line":221,"column":19},"end":{"line":221,"column":null}},"type":"binary-expr","locations":[{"start":{"line":221,"column":19},"end":{"line":221,"column":30}},{"start":{"line":221,"column":30},"end":{"line":221,"column":null}}],"line":221},"13":{"loc":{"start":{"line":239,"column":4},"end":{"line":241,"column":null}},"type":"if","locations":[{"start":{"line":239,"column":4},"end":{"line":241,"column":null}},{"start":{},"end":{}}],"line":239},"14":{"loc":{"start":{"line":243,"column":4},"end":{"line":245,"column":null}},"type":"if","locations":[{"start":{"line":243,"column":4},"end":{"line":245,"column":null}},{"start":{},"end":{}}],"line":243},"15":{"loc":{"start":{"line":301,"column":4},"end":{"line":308,"column":null}},"type":"if","locations":[{"start":{"line":301,"column":4},"end":{"line":308,"column":null}},{"start":{},"end":{}}],"line":301},"16":{"loc":{"start":{"line":314,"column":4},"end":{"line":321,"column":null}},"type":"if","locations":[{"start":{"line":314,"column":4},"end":{"line":321,"column":null}},{"start":{},"end":{}}],"line":314},"17":{"loc":{"start":{"line":325,"column":4},"end":{"line":331,"column":null}},"type":"if","locations":[{"start":{"line":325,"column":4},"end":{"line":331,"column":null}},{"start":{},"end":{}}],"line":325},"18":{"loc":{"start":{"line":337,"column":4},"end":{"line":368,"column":null}},"type":"if","locations":[{"start":{"line":337,"column":4},"end":{"line":368,"column":null}},{"start":{},"end":{}}],"line":337},"19":{"loc":{"start":{"line":337,"column":8},"end":{"line":337,"column":56}},"type":"binary-expr","locations":[{"start":{"line":337,"column":8},"end":{"line":337,"column":29}},{"start":{"line":337,"column":29},"end":{"line":337,"column":56}}],"line":337},"20":{"loc":{"start":{"line":339,"column":8},"end":{"line":364,"column":null}},"type":"if","locations":[{"start":{"line":339,"column":8},"end":{"line":364,"column":null}},{"start":{"line":342,"column":8},"end":{"line":364,"column":null}}],"line":339},"21":{"loc":{"start":{"line":342,"column":8},"end":{"line":364,"column":null}},"type":"if","locations":[{"start":{"line":342,"column":8},"end":{"line":364,"column":null}},{"start":{},"end":{}}],"line":342},"22":{"loc":{"start":{"line":342,"column":19},"end":{"line":342,"column":57}},"type":"binary-expr","locations":[{"start":{"line":342,"column":19},"end":{"line":342,"column":35}},{"start":{"line":342,"column":35},"end":{"line":342,"column":57}}],"line":342},"23":{"loc":{"start":{"line":345,"column":10},"end":{"line":363,"column":null}},"type":"if","locations":[{"start":{"line":345,"column":10},"end":{"line":363,"column":null}},{"start":{},"end":{}}],"line":345},"24":{"loc":{"start":{"line":347,"column":12},"end":{"line":350,"column":null}},"type":"if","locations":[{"start":{"line":347,"column":12},"end":{"line":350,"column":null}},{"start":{},"end":{}}],"line":347},"25":{"loc":{"start":{"line":353,"column":12},"end":{"line":362,"column":null}},"type":"if","locations":[{"start":{"line":353,"column":12},"end":{"line":362,"column":null}},{"start":{},"end":{}}],"line":353},"26":{"loc":{"start":{"line":354,"column":14},"end":{"line":361,"column":null}},"type":"if","locations":[{"start":{"line":354,"column":14},"end":{"line":361,"column":null}},{"start":{"line":358,"column":21},"end":{"line":361,"column":null}}],"line":354},"27":{"loc":{"start":{"line":373,"column":20},"end":{"line":373,"column":null}},"type":"binary-expr","locations":[{"start":{"line":373,"column":20},"end":{"line":373,"column":41}},{"start":{"line":373,"column":41},"end":{"line":373,"column":null}}],"line":373},"28":{"loc":{"start":{"line":374,"column":15},"end":{"line":374,"column":null}},"type":"binary-expr","locations":[{"start":{"line":374,"column":15},"end":{"line":374,"column":31}},{"start":{"line":374,"column":31},"end":{"line":374,"column":null}}],"line":374},"29":{"loc":{"start":{"line":375,"column":33},"end":{"line":375,"column":62}},"type":"binary-expr","locations":[{"start":{"line":375,"column":33},"end":{"line":375,"column":53}},{"start":{"line":375,"column":53},"end":{"line":375,"column":62}}],"line":375},"30":{"loc":{"start":{"line":421,"column":6},"end":{"line":423,"column":null}},"type":"if","locations":[{"start":{"line":421,"column":6},"end":{"line":423,"column":null}},{"start":{},"end":{}}],"line":421},"31":{"loc":{"start":{"line":441,"column":4},"end":{"line":443,"column":null}},"type":"if","locations":[{"start":{"line":441,"column":4},"end":{"line":443,"column":null}},{"start":{},"end":{}}],"line":441},"32":{"loc":{"start":{"line":447,"column":6},"end":{"line":449,"column":null}},"type":"if","locations":[{"start":{"line":447,"column":6},"end":{"line":449,"column":null}},{"start":{},"end":{}}],"line":447},"33":{"loc":{"start":{"line":447,"column":10},"end":{"line":447,"column":54}},"type":"binary-expr","locations":[{"start":{"line":447,"column":10},"end":{"line":447,"column":22}},{"start":{"line":447,"column":22},"end":{"line":447,"column":54}}],"line":447},"34":{"loc":{"start":{"line":469,"column":4},"end":{"line":471,"column":null}},"type":"if","locations":[{"start":{"line":469,"column":4},"end":{"line":471,"column":null}},{"start":{},"end":{}}],"line":469},"35":{"loc":{"start":{"line":474,"column":4},"end":{"line":479,"column":null}},"type":"if","locations":[{"start":{"line":474,"column":4},"end":{"line":479,"column":null}},{"start":{},"end":{}}],"line":474},"36":{"loc":{"start":{"line":474,"column":8},"end":{"line":474,"column":56}},"type":"binary-expr","locations":[{"start":{"line":474,"column":8},"end":{"line":474,"column":37}},{"start":{"line":474,"column":37},"end":{"line":474,"column":56}}],"line":474},"37":{"loc":{"start":{"line":476,"column":6},"end":{"line":478,"column":null}},"type":"if","locations":[{"start":{"line":476,"column":6},"end":{"line":478,"column":null}},{"start":{},"end":{}}],"line":476}},"s":{"0":9,"1":96,"2":96,"3":96,"4":96,"5":96,"6":96,"7":96,"8":96,"9":67,"10":67,"11":1,"12":66,"13":66,"14":66,"15":66,"16":66,"17":66,"18":47,"19":47,"20":4,"21":43,"22":43,"23":43,"24":75,"25":75,"26":12,"27":63,"28":63,"29":0,"30":0,"31":63,"32":0,"33":0,"34":63,"35":43,"36":43,"37":0,"38":43,"39":43,"40":30,"41":30,"42":25,"43":5,"44":43,"45":16,"46":16,"47":0,"48":16,"49":16,"50":0,"51":0,"52":0,"53":0,"54":0,"55":16,"56":16,"57":16,"58":16,"59":16,"60":16,"61":0,"62":0,"63":0,"64":0,"65":0,"66":0,"67":0,"68":0,"69":0,"70":7,"71":7,"72":7,"73":7,"74":7,"75":7,"76":39,"77":39,"78":2,"79":2,"80":37,"81":37,"82":35,"83":37,"84":2,"85":2,"86":35,"87":35,"88":0,"89":35,"90":0,"91":0,"92":0,"93":0,"94":0,"95":0,"96":0,"97":0,"98":0,"99":0,"100":0,"101":0,"102":0,"103":0,"104":0,"105":0,"106":35,"107":35,"108":35,"109":35,"110":35,"111":35,"112":35,"113":17,"114":17,"115":17,"116":31,"117":31,"118":22,"119":17,"120":106,"121":79,"122":27,"123":31,"124":31,"125":21,"126":6,"127":129,"128":16,"129":0,"130":16,"131":0,"132":0,"133":0,"134":16},"f":{"0":96,"1":67,"2":47,"3":30,"4":16,"5":0,"6":7,"7":39,"8":35,"9":17,"10":106,"11":129,"12":16},"b":{"0":[1,66],"1":[4,43],"2":[12,63],"3":[0,63],"4":[63,63],"5":[0,63],"6":[63,63],"7":[0,43],"8":[25,5],"9":[0,16],"10":[0,16],"11":[0,0],"12":[16,16],"13":[0,0],"14":[0,0],"15":[2,37],"16":[2,35],"17":[0,35],"18":[0,35],"19":[35,33],"20":[0,0],"21":[0,0],"22":[0,0],"23":[0,0],"24":[0,0],"25":[0,0],"26":[0,0],"27":[35,2],"28":[39,0],"29":[39,1],"30":[22,9],"31":[79,27],"32":[21,10],"33":[31,31],"34":[0,16],"35":[0,16],"36":[16,0],"37":[0,0]},"meta":{"lastBranch":38,"lastFunction":13,"lastStatement":135,"seen":{"s:29:6:29:Infinity":0,"s:55:47:55:Infinity":1,"s:58:51:58:Infinity":2,"f:60:2:60:Infinity":0,"s:61:12:61:Infinity":3,"s:62:12:62:Infinity":4,"s:63:12:63:Infinity":5,"s:64:12:64:Infinity":6,"s:65:12:65:Infinity":7,"s:66:12:66:Infinity":8,"f:74:8:74:14":1,"s:76:17:76:Infinity":9,"b:77:4:79:Infinity:undefined:undefined:undefined:undefined":0,"s:77:4:79:Infinity":10,"s:78:6:78:Infinity":11,"s:82:22:82:Infinity":12,"s:84:35:89:Infinity":13,"s:91:4:91:Infinity":14,"s:93:4:93:Infinity":15,"s:96:35:104:Infinity":16,"s:105:4:105:Infinity":17,"f:113:8:113:58":2,"s:114:24:114:Infinity":18,"b:116:4:118:Infinity:undefined:undefined:undefined:undefined":1,"s:116:4:118:Infinity":19,"s:117:6:117:Infinity":20,"s:121:37:121:Infinity":21,"s:123:4:123:Infinity":22,"s:125:4:146:Infinity":23,"s:127:30:127:Infinity":24,"b:128:6:130:Infinity:undefined:undefined:undefined:undefined":2,"s:128:6:130:Infinity":25,"s:129:8:129:Infinity":26,"s:133:19:133:Infinity":27,"b:134:6:137:Infinity:undefined:undefined:undefined:undefined":3,"s:134:6:137:Infinity":28,"b:134:10:134:18:134:18:134:47":4,"s:135:8:135:Infinity":29,"s:136:8:136:Infinity":30,"b:140:6:143:Infinity:undefined:undefined:undefined:undefined":5,"s:140:6:143:Infinity":31,"b:140:10:140:18:140:10:140:53":6,"s:141:8:141:Infinity":32,"s:142:8:142:Infinity":33,"s:145:6:145:Infinity":34,"s:148:4:148:Infinity":35,"b:150:4:152:Infinity:undefined:undefined:undefined:undefined":7,"s:150:4:152:Infinity":36,"s:151:6:151:Infinity":37,"s:155:50:155:Infinity":38,"s:157:4:163:Infinity":39,"f:157:20:157:21":3,"s:158:27:158:Infinity":40,"b:159:6:161:Infinity:undefined:undefined:undefined:undefined":8,"s:159:6:161:Infinity":41,"s:160:8:160:Infinity":42,"s:162:6:162:Infinity":43,"s:165:4:165:Infinity":44,"f:176:8:176:21":4,"s:177:17:177:Infinity":45,"b:178:4:180:Infinity:undefined:undefined:undefined:undefined":9,"s:178:4:180:Infinity":46,"s:179:6:179:Infinity":47,"s:183:29:183:Infinity":48,"b:185:4:227:Infinity:206:11:227:Infinity":10,"s:185:4:227:Infinity":49,"s:187:6:187:Infinity":50,"s:190:6:190:Infinity":51,"s:192:6:192:Infinity":52,"s:195:46:204:Infinity":53,"b:200:19:200:30:200:30:200:Infinity":11,"s:205:6:205:Infinity":54,"s:208:6:208:Infinity":55,"s:211:6:211:Infinity":56,"s:213:6:213:Infinity":57,"s:216:40:225:Infinity":58,"b:221:19:221:30:221:30:221:Infinity":12,"s:226:6:226:Infinity":59,"s:230:4:230:Infinity":60,"f:237:8:237:20":5,"s:238:17:238:Infinity":61,"b:239:4:241:Infinity:undefined:undefined:undefined:undefined":13,"s:239:4:241:Infinity":62,"s:240:6:240:Infinity":63,"b:243:4:245:Infinity:undefined:undefined:undefined:undefined":14,"s:243:4:245:Infinity":64,"s:244:6:244:Infinity":65,"s:248:4:248:Infinity":66,"s:250:4:250:Infinity":67,"s:253:38:262:Infinity":68,"s:263:4:263:Infinity":69,"f:270:8:270:18":6,"s:272:4:272:Infinity":70,"s:275:4:275:Infinity":71,"s:277:4:277:Infinity":72,"s:280:4:280:Infinity":73,"s:283:36:290:Infinity":74,"s:291:4:291:Infinity":75,"f:297:8:297:48":7,"s:299:21:299:Infinity":76,"b:301:4:308:Infinity:undefined:undefined:undefined:undefined":15,"s:301:4:308:Infinity":77,"s:302:6:302:Infinity":78,"s:303:6:307:Infinity":79,"s:311:19:311:Infinity":80,"s:312:22:312:Infinity":81,"f:312:34:312:35":8,"s:312:41:312:60":82,"b:314:4:321:Infinity:undefined:undefined:undefined:undefined":16,"s:314:4:321:Infinity":83,"s:315:6:315:Infinity":84,"s:316:6:320:Infinity":85,"s:324:17:324:Infinity":86,"b:325:4:331:Infinity:undefined:undefined:undefined:undefined":17,"s:325:4:331:Infinity":87,"s:326:6:330:Infinity":88,"b:337:4:368:Infinity:undefined:undefined:undefined:undefined":18,"s:337:4:368:Infinity":89,"b:337:8:337:29:337:29:337:56":19,"s:338:6:367:Infinity":90,"b:339:8:364:Infinity:342:8:364:Infinity":20,"s:339:8:364:Infinity":91,"b:342:8:364:Infinity:undefined:undefined:undefined:undefined":21,"s:342:8:364:Infinity":92,"b:342:19:342:35:342:35:342:57":22,"s:344:29:344:Infinity":93,"b:345:10:363:Infinity:undefined:undefined:undefined:undefined":23,"s:345:10:363:Infinity":94,"s:346:29:346:Infinity":95,"b:347:12:350:Infinity:undefined:undefined:undefined:undefined":24,"s:347:12:350:Infinity":96,"s:348:14:348:Infinity":97,"s:349:14:349:Infinity":98,"s:352:26:352:Infinity":99,"b:353:12:362:Infinity:undefined:undefined:undefined:undefined":25,"s:353:12:362:Infinity":100,"b:354:14:361:Infinity:358:21:361:Infinity":26,"s:354:14:361:Infinity":101,"s:356:16:356:Infinity":102,"s:357:16:357:Infinity":103,"s:359:16:359:Infinity":104,"s:360:16:360:Infinity":105,"s:371:18:378:Infinity":106,"b:373:20:373:41:373:41:373:Infinity":27,"b:374:15:374:31:374:31:374:Infinity":28,"b:375:33:375:53:375:53:375:62":29,"s:380:4:380:Infinity":107,"s:383:4:383:Infinity":108,"s:386:4:386:Infinity":109,"s:389:39:397:Infinity":110,"s:398:4:398:Infinity":111,"s:400:4:404:Infinity":112,"f:410:8:410:Infinity":9,"s:415:22:415:Infinity":113,"s:418:32:418:Infinity":114,"s:419:4:424:Infinity":115,"s:420:30:420:Infinity":116,"b:421:6:423:Infinity:undefined:undefined:undefined:undefined":30,"s:421:6:423:Infinity":117,"s:422:8:422:Infinity":118,"s:426:4:430:Infinity":119,"f:440:16:440:43":10,"b:441:4:443:Infinity:undefined:undefined:undefined:undefined":31,"s:441:4:443:Infinity":120,"s:442:6:442:Infinity":121,"s:445:4:450:Infinity":122,"s:446:22:446:Infinity":123,"b:447:6:449:Infinity:undefined:undefined:undefined:undefined":32,"s:447:6:449:Infinity":124,"b:447:10:447:22:447:22:447:54":33,"s:448:8:448:Infinity":125,"s:452:4:452:Infinity":126,"f:459:10:459:27":11,"s:460:4:460:Infinity":127,"f:467:16:467:37":12,"b:469:4:471:Infinity:undefined:undefined:undefined:undefined":34,"s:469:4:471:Infinity":128,"s:470:6:470:Infinity":129,"b:474:4:479:Infinity:undefined:undefined:undefined:undefined":35,"s:474:4:479:Infinity":130,"b:474:8:474:37:474:37:474:56":36,"s:475:25:475:Infinity":131,"b:476:6:478:Infinity:undefined:undefined:undefined:undefined":37,"s:476:6:478:Infinity":132,"s:477:8:477:Infinity":133,"s:483:4:483:Infinity":134}}} +,"/Users/lukasmay/development/projects/codewalk-district/src/dispatch/phase-manager.ts": {"path":"/Users/lukasmay/development/projects/codewalk-district/src/dispatch/phase-manager.ts","statementMap":{"0":{"start":{"line":27,"column":6},"end":{"line":27,"column":null}},"1":{"start":{"line":53,"column":49},"end":{"line":53,"column":null}},"2":{"start":{"line":56,"column":53},"end":{"line":56,"column":null}},"3":{"start":{"line":59,"column":12},"end":{"line":59,"column":null}},"4":{"start":{"line":60,"column":12},"end":{"line":60,"column":null}},"5":{"start":{"line":61,"column":12},"end":{"line":61,"column":null}},"6":{"start":{"line":62,"column":12},"end":{"line":62,"column":null}},"7":{"start":{"line":63,"column":12},"end":{"line":63,"column":null}},"8":{"start":{"line":64,"column":12},"end":{"line":64,"column":null}},"9":{"start":{"line":65,"column":12},"end":{"line":65,"column":null}},"10":{"start":{"line":66,"column":12},"end":{"line":66,"column":null}},"11":{"start":{"line":76,"column":18},"end":{"line":76,"column":null}},"12":{"start":{"line":77,"column":4},"end":{"line":79,"column":null}},"13":{"start":{"line":78,"column":6},"end":{"line":78,"column":null}},"14":{"start":{"line":82,"column":4},"end":{"line":84,"column":null}},"15":{"start":{"line":83,"column":6},"end":{"line":83,"column":null}},"16":{"start":{"line":87,"column":22},"end":{"line":87,"column":null}},"17":{"start":{"line":89,"column":37},"end":{"line":94,"column":null}},"18":{"start":{"line":96,"column":4},"end":{"line":96,"column":null}},"19":{"start":{"line":99,"column":36},"end":{"line":107,"column":null}},"20":{"start":{"line":108,"column":4},"end":{"line":108,"column":null}},"21":{"start":{"line":116,"column":25},"end":{"line":116,"column":null}},"22":{"start":{"line":118,"column":4},"end":{"line":120,"column":null}},"23":{"start":{"line":119,"column":6},"end":{"line":119,"column":null}},"24":{"start":{"line":123,"column":39},"end":{"line":123,"column":null}},"25":{"start":{"line":125,"column":4},"end":{"line":130,"column":null}},"26":{"start":{"line":126,"column":30},"end":{"line":126,"column":null}},"27":{"start":{"line":127,"column":6},"end":{"line":129,"column":null}},"28":{"start":{"line":128,"column":8},"end":{"line":128,"column":null}},"29":{"start":{"line":132,"column":4},"end":{"line":134,"column":null}},"30":{"start":{"line":133,"column":6},"end":{"line":133,"column":null}},"31":{"start":{"line":137,"column":4},"end":{"line":137,"column":null}},"32":{"start":{"line":137,"column":31},"end":{"line":137,"column":74}},"33":{"start":{"line":139,"column":4},"end":{"line":139,"column":null}},"34":{"start":{"line":148,"column":22},"end":{"line":148,"column":null}},"35":{"start":{"line":150,"column":4},"end":{"line":156,"column":null}},"36":{"start":{"line":151,"column":6},"end":{"line":155,"column":null}},"37":{"start":{"line":159,"column":18},"end":{"line":159,"column":null}},"38":{"start":{"line":160,"column":4},"end":{"line":166,"column":null}},"39":{"start":{"line":161,"column":6},"end":{"line":165,"column":null}},"40":{"start":{"line":169,"column":4},"end":{"line":169,"column":null}},"41":{"start":{"line":172,"column":4},"end":{"line":189,"column":null}},"42":{"start":{"line":173,"column":6},"end":{"line":188,"column":null}},"43":{"start":{"line":174,"column":27},"end":{"line":174,"column":null}},"44":{"start":{"line":175,"column":8},"end":{"line":185,"column":null}},"45":{"start":{"line":176,"column":29},"end":{"line":176,"column":null}},"46":{"start":{"line":177,"column":16},"end":{"line":177,"column":null}},"47":{"start":{"line":178,"column":27},"end":{"line":178,"column":null}},"48":{"start":{"line":179,"column":10},"end":{"line":183,"column":null}},"49":{"start":{"line":180,"column":30},"end":{"line":180,"column":null}},"50":{"start":{"line":181,"column":12},"end":{"line":181,"column":null}},"51":{"start":{"line":182,"column":12},"end":{"line":182,"column":null}},"52":{"start":{"line":184,"column":10},"end":{"line":184,"column":null}},"53":{"start":{"line":187,"column":8},"end":{"line":187,"column":null}},"54":{"start":{"line":192,"column":4},"end":{"line":192,"column":null}},"55":{"start":{"line":195,"column":23},"end":{"line":195,"column":null}},"56":{"start":{"line":196,"column":4},"end":{"line":200,"column":null}},"57":{"start":{"line":197,"column":6},"end":{"line":199,"column":null}},"58":{"start":{"line":198,"column":8},"end":{"line":198,"column":null}},"59":{"start":{"line":203,"column":37},"end":{"line":210,"column":null}},"60":{"start":{"line":211,"column":4},"end":{"line":211,"column":null}},"61":{"start":{"line":213,"column":4},"end":{"line":216,"column":null}},"62":{"start":{"line":225,"column":18},"end":{"line":225,"column":null}},"63":{"start":{"line":226,"column":4},"end":{"line":228,"column":null}},"64":{"start":{"line":227,"column":6},"end":{"line":227,"column":null}},"65":{"start":{"line":231,"column":4},"end":{"line":231,"column":null}},"66":{"start":{"line":234,"column":4},"end":{"line":234,"column":null}},"67":{"start":{"line":237,"column":4},"end":{"line":237,"column":null}},"68":{"start":{"line":240,"column":39},"end":{"line":249,"column":null}},"69":{"start":{"line":250,"column":4},"end":{"line":250,"column":null}},"70":{"start":{"line":259,"column":4},"end":{"line":259,"column":null}},"71":{"start":{"line":262,"column":4},"end":{"line":262,"column":null}},"72":{"start":{"line":265,"column":4},"end":{"line":265,"column":null}},"73":{"start":{"line":268,"column":37},"end":{"line":275,"column":null}},"74":{"start":{"line":276,"column":4},"end":{"line":276,"column":null}},"75":{"start":{"line":287,"column":22},"end":{"line":287,"column":null}},"76":{"start":{"line":290,"column":33},"end":{"line":290,"column":null}},"77":{"start":{"line":291,"column":4},"end":{"line":296,"column":null}},"78":{"start":{"line":292,"column":30},"end":{"line":292,"column":null}},"79":{"start":{"line":293,"column":6},"end":{"line":295,"column":null}},"80":{"start":{"line":294,"column":8},"end":{"line":294,"column":null}},"81":{"start":{"line":298,"column":4},"end":{"line":302,"column":null}},"82":{"start":{"line":313,"column":4},"end":{"line":315,"column":null}},"83":{"start":{"line":314,"column":6},"end":{"line":314,"column":null}},"84":{"start":{"line":317,"column":4},"end":{"line":322,"column":null}},"85":{"start":{"line":318,"column":23},"end":{"line":318,"column":null}},"86":{"start":{"line":319,"column":6},"end":{"line":321,"column":null}},"87":{"start":{"line":320,"column":8},"end":{"line":320,"column":null}},"88":{"start":{"line":324,"column":4},"end":{"line":324,"column":null}}},"fnMap":{"0":{"name":"(anonymous_0)","decl":{"start":{"line":58,"column":2},"end":{"line":58,"column":null}},"loc":{"start":{"line":67,"column":4},"end":{"line":67,"column":null}},"line":67},"1":{"name":"(anonymous_1)","decl":{"start":{"line":74,"column":8},"end":{"line":74,"column":19}},"loc":{"start":{"line":74,"column":51},"end":{"line":109,"column":null}},"line":74},"2":{"name":"(anonymous_2)","decl":{"start":{"line":115,"column":8},"end":{"line":115,"column":64}},"loc":{"start":{"line":115,"column":64},"end":{"line":140,"column":null}},"line":115},"3":{"name":"(anonymous_3)","decl":{"start":{"line":137,"column":21},"end":{"line":137,"column":22}},"loc":{"start":{"line":137,"column":31},"end":{"line":137,"column":74}},"line":137},"4":{"name":"(anonymous_4)","decl":{"start":{"line":146,"column":8},"end":{"line":146,"column":58}},"loc":{"start":{"line":146,"column":58},"end":{"line":217,"column":null}},"line":146},"5":{"name":"(anonymous_5)","decl":{"start":{"line":223,"column":8},"end":{"line":223,"column":22}},"loc":{"start":{"line":223,"column":54},"end":{"line":251,"column":null}},"line":223},"6":{"name":"(anonymous_6)","decl":{"start":{"line":257,"column":8},"end":{"line":257,"column":19}},"loc":{"start":{"line":257,"column":67},"end":{"line":277,"column":null}},"line":257},"7":{"name":"(anonymous_7)","decl":{"start":{"line":282,"column":8},"end":{"line":282,"column":null}},"loc":{"start":{"line":286,"column":5},"end":{"line":303,"column":null}},"line":286},"8":{"name":"(anonymous_8)","decl":{"start":{"line":312,"column":16},"end":{"line":312,"column":48}},"loc":{"start":{"line":312,"column":87},"end":{"line":325,"column":null}},"line":312}},"branchMap":{"0":{"loc":{"start":{"line":77,"column":4},"end":{"line":79,"column":null}},"type":"if","locations":[{"start":{"line":77,"column":4},"end":{"line":79,"column":null}},{"start":{},"end":{}}],"line":77},"1":{"loc":{"start":{"line":82,"column":4},"end":{"line":84,"column":null}},"type":"if","locations":[{"start":{"line":82,"column":4},"end":{"line":84,"column":null}},{"start":{},"end":{}}],"line":82},"2":{"loc":{"start":{"line":118,"column":4},"end":{"line":120,"column":null}},"type":"if","locations":[{"start":{"line":118,"column":4},"end":{"line":120,"column":null}},{"start":{},"end":{}}],"line":118},"3":{"loc":{"start":{"line":127,"column":6},"end":{"line":129,"column":null}},"type":"if","locations":[{"start":{"line":127,"column":6},"end":{"line":129,"column":null}},{"start":{},"end":{}}],"line":127},"4":{"loc":{"start":{"line":132,"column":4},"end":{"line":134,"column":null}},"type":"if","locations":[{"start":{"line":132,"column":4},"end":{"line":134,"column":null}},{"start":{},"end":{}}],"line":132},"5":{"loc":{"start":{"line":150,"column":4},"end":{"line":156,"column":null}},"type":"if","locations":[{"start":{"line":150,"column":4},"end":{"line":156,"column":null}},{"start":{},"end":{}}],"line":150},"6":{"loc":{"start":{"line":160,"column":4},"end":{"line":166,"column":null}},"type":"if","locations":[{"start":{"line":160,"column":4},"end":{"line":166,"column":null}},{"start":{},"end":{}}],"line":160},"7":{"loc":{"start":{"line":172,"column":4},"end":{"line":189,"column":null}},"type":"if","locations":[{"start":{"line":172,"column":4},"end":{"line":189,"column":null}},{"start":{},"end":{}}],"line":172},"8":{"loc":{"start":{"line":172,"column":8},"end":{"line":172,"column":105}},"type":"binary-expr","locations":[{"start":{"line":172,"column":8},"end":{"line":172,"column":37}},{"start":{"line":172,"column":37},"end":{"line":172,"column":63}},{"start":{"line":172,"column":63},"end":{"line":172,"column":85}},{"start":{"line":172,"column":85},"end":{"line":172,"column":105}}],"line":172},"9":{"loc":{"start":{"line":175,"column":8},"end":{"line":185,"column":null}},"type":"if","locations":[{"start":{"line":175,"column":8},"end":{"line":185,"column":null}},{"start":{},"end":{}}],"line":175},"10":{"loc":{"start":{"line":187,"column":53},"end":{"line":187,"column":102}},"type":"cond-expr","locations":[{"start":{"line":187,"column":76},"end":{"line":187,"column":90}},{"start":{"line":187,"column":90},"end":{"line":187,"column":102}}],"line":187},"11":{"loc":{"start":{"line":197,"column":6},"end":{"line":199,"column":null}},"type":"if","locations":[{"start":{"line":197,"column":6},"end":{"line":199,"column":null}},{"start":{},"end":{}}],"line":197},"12":{"loc":{"start":{"line":197,"column":10},"end":{"line":197,"column":75}},"type":"binary-expr","locations":[{"start":{"line":197,"column":10},"end":{"line":197,"column":39}},{"start":{"line":197,"column":39},"end":{"line":197,"column":75}}],"line":197},"13":{"loc":{"start":{"line":226,"column":4},"end":{"line":228,"column":null}},"type":"if","locations":[{"start":{"line":226,"column":4},"end":{"line":228,"column":null}},{"start":{},"end":{}}],"line":226},"14":{"loc":{"start":{"line":293,"column":6},"end":{"line":295,"column":null}},"type":"if","locations":[{"start":{"line":293,"column":6},"end":{"line":295,"column":null}},{"start":{},"end":{}}],"line":293},"15":{"loc":{"start":{"line":313,"column":4},"end":{"line":315,"column":null}},"type":"if","locations":[{"start":{"line":313,"column":4},"end":{"line":315,"column":null}},{"start":{},"end":{}}],"line":313},"16":{"loc":{"start":{"line":319,"column":6},"end":{"line":321,"column":null}},"type":"if","locations":[{"start":{"line":319,"column":6},"end":{"line":321,"column":null}},{"start":{},"end":{}}],"line":319},"17":{"loc":{"start":{"line":319,"column":10},"end":{"line":319,"column":56}},"type":"binary-expr","locations":[{"start":{"line":319,"column":10},"end":{"line":319,"column":23}},{"start":{"line":319,"column":23},"end":{"line":319,"column":56}}],"line":319}},"s":{"0":9,"1":103,"2":103,"3":103,"4":103,"5":103,"6":103,"7":103,"8":103,"9":103,"10":103,"11":38,"12":38,"13":1,"14":37,"15":4,"16":33,"17":33,"18":33,"19":33,"20":33,"21":23,"22":23,"23":3,"24":20,"25":20,"26":37,"27":37,"28":20,"29":20,"30":4,"31":16,"32":4,"33":16,"34":19,"35":19,"36":5,"37":14,"38":14,"39":0,"40":14,"41":14,"42":0,"43":0,"44":0,"45":0,"46":0,"47":0,"48":0,"49":0,"50":0,"51":0,"52":0,"53":0,"54":14,"55":14,"56":14,"57":0,"58":0,"59":14,"60":14,"61":14,"62":11,"63":11,"64":1,"65":10,"66":10,"67":10,"68":10,"69":10,"70":6,"71":6,"72":6,"73":6,"74":6,"75":22,"76":22,"77":22,"78":31,"79":31,"80":14,"81":22,"82":68,"83":18,"84":50,"85":56,"86":56,"87":34,"88":16},"f":{"0":103,"1":38,"2":23,"3":4,"4":19,"5":11,"6":6,"7":22,"8":68},"b":{"0":[1,37],"1":[4,33],"2":[3,20],"3":[20,17],"4":[4,16],"5":[5,14],"6":[0,14],"7":[0,14],"8":[14,0,0,0],"9":[0,0],"10":[0,0],"11":[0,0],"12":[0,0],"13":[1,10],"14":[14,17],"15":[18,50],"16":[34,22],"17":[56,56]},"meta":{"lastBranch":18,"lastFunction":9,"lastStatement":89,"seen":{"s:27:6:27:Infinity":0,"s:53:49:53:Infinity":1,"s:56:53:56:Infinity":2,"f:58:2:58:Infinity":0,"s:59:12:59:Infinity":3,"s:60:12:60:Infinity":4,"s:61:12:61:Infinity":5,"s:62:12:62:Infinity":6,"s:63:12:63:Infinity":7,"s:64:12:64:Infinity":8,"s:65:12:65:Infinity":9,"s:66:12:66:Infinity":10,"f:74:8:74:19":1,"s:76:18:76:Infinity":11,"b:77:4:79:Infinity:undefined:undefined:undefined:undefined":0,"s:77:4:79:Infinity":12,"s:78:6:78:Infinity":13,"b:82:4:84:Infinity:undefined:undefined:undefined:undefined":1,"s:82:4:84:Infinity":14,"s:83:6:83:Infinity":15,"s:87:22:87:Infinity":16,"s:89:37:94:Infinity":17,"s:96:4:96:Infinity":18,"s:99:36:107:Infinity":19,"s:108:4:108:Infinity":20,"f:115:8:115:64":2,"s:116:25:116:Infinity":21,"b:118:4:120:Infinity:undefined:undefined:undefined:undefined":2,"s:118:4:120:Infinity":22,"s:119:6:119:Infinity":23,"s:123:39:123:Infinity":24,"s:125:4:130:Infinity":25,"s:126:30:126:Infinity":26,"b:127:6:129:Infinity:undefined:undefined:undefined:undefined":3,"s:127:6:129:Infinity":27,"s:128:8:128:Infinity":28,"b:132:4:134:Infinity:undefined:undefined:undefined:undefined":4,"s:132:4:134:Infinity":29,"s:133:6:133:Infinity":30,"s:137:4:137:Infinity":31,"f:137:21:137:22":3,"s:137:31:137:74":32,"s:139:4:139:Infinity":33,"f:146:8:146:58":4,"s:148:22:148:Infinity":34,"b:150:4:156:Infinity:undefined:undefined:undefined:undefined":5,"s:150:4:156:Infinity":35,"s:151:6:155:Infinity":36,"s:159:18:159:Infinity":37,"b:160:4:166:Infinity:undefined:undefined:undefined:undefined":6,"s:160:4:166:Infinity":38,"s:161:6:165:Infinity":39,"s:169:4:169:Infinity":40,"b:172:4:189:Infinity:undefined:undefined:undefined:undefined":7,"s:172:4:189:Infinity":41,"b:172:8:172:37:172:37:172:63:172:63:172:85:172:85:172:105":8,"s:173:6:188:Infinity":42,"s:174:27:174:Infinity":43,"b:175:8:185:Infinity:undefined:undefined:undefined:undefined":9,"s:175:8:185:Infinity":44,"s:176:29:176:Infinity":45,"s:177:16:177:Infinity":46,"s:178:27:178:Infinity":47,"s:179:10:183:Infinity":48,"s:180:30:180:Infinity":49,"s:181:12:181:Infinity":50,"s:182:12:182:Infinity":51,"s:184:10:184:Infinity":52,"s:187:8:187:Infinity":53,"b:187:76:187:90:187:90:187:102":10,"s:192:4:192:Infinity":54,"s:195:23:195:Infinity":55,"s:196:4:200:Infinity":56,"b:197:6:199:Infinity:undefined:undefined:undefined:undefined":11,"s:197:6:199:Infinity":57,"b:197:10:197:39:197:39:197:75":12,"s:198:8:198:Infinity":58,"s:203:37:210:Infinity":59,"s:211:4:211:Infinity":60,"s:213:4:216:Infinity":61,"f:223:8:223:22":5,"s:225:18:225:Infinity":62,"b:226:4:228:Infinity:undefined:undefined:undefined:undefined":13,"s:226:4:228:Infinity":63,"s:227:6:227:Infinity":64,"s:231:4:231:Infinity":65,"s:234:4:234:Infinity":66,"s:237:4:237:Infinity":67,"s:240:39:249:Infinity":68,"s:250:4:250:Infinity":69,"f:257:8:257:19":6,"s:259:4:259:Infinity":70,"s:262:4:262:Infinity":71,"s:265:4:265:Infinity":72,"s:268:37:275:Infinity":73,"s:276:4:276:Infinity":74,"f:282:8:282:Infinity":7,"s:287:22:287:Infinity":75,"s:290:33:290:Infinity":76,"s:291:4:296:Infinity":77,"s:292:30:292:Infinity":78,"b:293:6:295:Infinity:undefined:undefined:undefined:undefined":14,"s:293:6:295:Infinity":79,"s:294:8:294:Infinity":80,"s:298:4:302:Infinity":81,"f:312:16:312:48":8,"b:313:4:315:Infinity:undefined:undefined:undefined:undefined":15,"s:313:4:315:Infinity":82,"s:314:6:314:Infinity":83,"s:317:4:322:Infinity":84,"s:318:23:318:Infinity":85,"b:319:6:321:Infinity:undefined:undefined:undefined:undefined":16,"s:319:6:321:Infinity":86,"b:319:10:319:23:319:23:319:56":17,"s:320:8:320:Infinity":87,"s:324:4:324:Infinity":88}}} +,"/Users/lukasmay/development/projects/codewalk-district/src/events/bus.ts": {"path":"/Users/lukasmay/development/projects/codewalk-district/src/events/bus.ts","statementMap":{"0":{"start":{"line":24,"column":4},"end":{"line":24,"column":null}},"1":{"start":{"line":26,"column":4},"end":{"line":26,"column":null}},"2":{"start":{"line":34,"column":4},"end":{"line":34,"column":null}},"3":{"start":{"line":44,"column":4},"end":{"line":44,"column":null}},"4":{"start":{"line":54,"column":4},"end":{"line":54,"column":null}},"5":{"start":{"line":65,"column":4},"end":{"line":65,"column":null}}},"fnMap":{"0":{"name":"(anonymous_0)","decl":{"start":{"line":23,"column":2},"end":{"line":23,"column":16}},"loc":{"start":{"line":23,"column":16},"end":{"line":27,"column":null}},"line":23},"1":{"name":"(anonymous_1)","decl":{"start":{"line":33,"column":2},"end":{"line":33,"column":30}},"loc":{"start":{"line":33,"column":46},"end":{"line":35,"column":null}},"line":33},"2":{"name":"(anonymous_2)","decl":{"start":{"line":40,"column":2},"end":{"line":40,"column":null}},"loc":{"start":{"line":43,"column":10},"end":{"line":45,"column":null}},"line":43},"3":{"name":"(anonymous_3)","decl":{"start":{"line":50,"column":2},"end":{"line":50,"column":null}},"loc":{"start":{"line":53,"column":10},"end":{"line":55,"column":null}},"line":53},"4":{"name":"(anonymous_4)","decl":{"start":{"line":61,"column":2},"end":{"line":61,"column":null}},"loc":{"start":{"line":64,"column":10},"end":{"line":66,"column":null}},"line":64}},"branchMap":{},"s":{"0":143,"1":143,"2":429,"3":246,"4":1,"5":1},"f":{"0":143,"1":429,"2":246,"3":1,"4":1},"b":{},"meta":{"lastBranch":0,"lastFunction":5,"lastStatement":6,"seen":{"f:23:2:23:16":0,"s:24:4:24:Infinity":0,"s:26:4:26:Infinity":1,"f:33:2:33:30":1,"s:34:4:34:Infinity":2,"f:40:2:40:Infinity":2,"s:44:4:44:Infinity":3,"f:50:2:50:Infinity":3,"s:54:4:54:Infinity":4,"f:61:2:61:Infinity":4,"s:65:4:65:Infinity":5}}} +,"/Users/lukasmay/development/projects/codewalk-district/src/events/index.ts": {"path":"/Users/lukasmay/development/projects/codewalk-district/src/events/index.ts","statementMap":{"0":{"start":{"line":71,"column":2},"end":{"line":71,"column":null}}},"fnMap":{"0":{"name":"createEventBus","decl":{"start":{"line":70,"column":16},"end":{"line":70,"column":43}},"loc":{"start":{"line":70,"column":43},"end":{"line":72,"column":null}},"line":70}},"branchMap":{},"s":{"0":9},"f":{"0":9},"b":{},"meta":{"lastBranch":0,"lastFunction":1,"lastStatement":1,"seen":{"f:70:16:70:43":0,"s:71:2:71:Infinity":0}}} +,"/Users/lukasmay/development/projects/codewalk-district/src/execution/orchestrator.ts": {"path":"/Users/lukasmay/development/projects/codewalk-district/src/execution/orchestrator.ts","statementMap":{"0":{"start":{"line":26,"column":6},"end":{"line":26,"column":null}},"1":{"start":{"line":30,"column":56},"end":{"line":30,"column":null}},"2":{"start":{"line":33,"column":12},"end":{"line":33,"column":null}},"3":{"start":{"line":34,"column":12},"end":{"line":34,"column":null}},"4":{"start":{"line":35,"column":12},"end":{"line":35,"column":null}},"5":{"start":{"line":36,"column":12},"end":{"line":36,"column":null}},"6":{"start":{"line":37,"column":12},"end":{"line":37,"column":null}},"7":{"start":{"line":38,"column":12},"end":{"line":38,"column":null}},"8":{"start":{"line":39,"column":12},"end":{"line":39,"column":null}},"9":{"start":{"line":40,"column":12},"end":{"line":40,"column":null}},"10":{"start":{"line":41,"column":12},"end":{"line":41,"column":null}},"11":{"start":{"line":48,"column":4},"end":{"line":52,"column":null}},"12":{"start":{"line":49,"column":6},"end":{"line":51,"column":null}},"13":{"start":{"line":50,"column":8},"end":{"line":50,"column":null}},"14":{"start":{"line":53,"column":4},"end":{"line":53,"column":null}},"15":{"start":{"line":61,"column":23},"end":{"line":61,"column":null}},"16":{"start":{"line":63,"column":17},"end":{"line":63,"column":null}},"17":{"start":{"line":64,"column":4},"end":{"line":64,"column":null}},"18":{"start":{"line":64,"column":46},"end":{"line":64,"column":null}},"19":{"start":{"line":66,"column":23},"end":{"line":66,"column":null}},"20":{"start":{"line":67,"column":4},"end":{"line":67,"column":null}},"21":{"start":{"line":67,"column":29},"end":{"line":67,"column":null}},"22":{"start":{"line":69,"column":18},"end":{"line":69,"column":null}},"23":{"start":{"line":70,"column":4},"end":{"line":70,"column":null}},"24":{"start":{"line":70,"column":16},"end":{"line":70,"column":null}},"25":{"start":{"line":73,"column":4},"end":{"line":73,"column":null}},"26":{"start":{"line":73,"column":35},"end":{"line":73,"column":null}},"27":{"start":{"line":75,"column":23},"end":{"line":75,"column":null}},"28":{"start":{"line":76,"column":10},"end":{"line":76,"column":null}},"29":{"start":{"line":77,"column":10},"end":{"line":77,"column":null}},"30":{"start":{"line":80,"column":17},"end":{"line":80,"column":null}},"31":{"start":{"line":81,"column":20},"end":{"line":83,"column":null}},"32":{"start":{"line":82,"column":6},"end":{"line":82,"column":null}},"33":{"start":{"line":84,"column":4},"end":{"line":84,"column":null}},"34":{"start":{"line":85,"column":4},"end":{"line":85,"column":null}},"35":{"start":{"line":88,"column":23},"end":{"line":88,"column":null}},"36":{"start":{"line":89,"column":20},"end":{"line":89,"column":null}},"37":{"start":{"line":89,"column":44},"end":{"line":89,"column":68}},"38":{"start":{"line":90,"column":4},"end":{"line":92,"column":null}},"39":{"start":{"line":91,"column":6},"end":{"line":91,"column":null}},"40":{"start":{"line":104,"column":18},"end":{"line":104,"column":null}},"41":{"start":{"line":105,"column":4},"end":{"line":105,"column":null}},"42":{"start":{"line":105,"column":16},"end":{"line":105,"column":null}},"43":{"start":{"line":107,"column":21},"end":{"line":107,"column":null}},"44":{"start":{"line":109,"column":4},"end":{"line":131,"column":null}},"45":{"start":{"line":110,"column":24},"end":{"line":110,"column":null}},"46":{"start":{"line":113,"column":21},"end":{"line":113,"column":null}},"47":{"start":{"line":114,"column":6},"end":{"line":117,"column":null}},"48":{"start":{"line":115,"column":8},"end":{"line":115,"column":null}},"49":{"start":{"line":116,"column":8},"end":{"line":116,"column":null}},"50":{"start":{"line":119,"column":21},"end":{"line":119,"column":null}},"51":{"start":{"line":121,"column":6},"end":{"line":128,"column":null}},"52":{"start":{"line":122,"column":8},"end":{"line":122,"column":null}},"53":{"start":{"line":123,"column":8},"end":{"line":126,"column":null}},"54":{"start":{"line":127,"column":8},"end":{"line":127,"column":null}},"55":{"start":{"line":130,"column":6},"end":{"line":130,"column":null}},"56":{"start":{"line":134,"column":41},"end":{"line":138,"column":null}},"57":{"start":{"line":139,"column":4},"end":{"line":139,"column":null}},"58":{"start":{"line":148,"column":18},"end":{"line":148,"column":null}},"59":{"start":{"line":149,"column":4},"end":{"line":149,"column":null}},"60":{"start":{"line":149,"column":16},"end":{"line":149,"column":null}},"61":{"start":{"line":151,"column":23},"end":{"line":151,"column":null}},"62":{"start":{"line":152,"column":4},"end":{"line":152,"column":null}},"63":{"start":{"line":152,"column":29},"end":{"line":152,"column":null}},"64":{"start":{"line":154,"column":4},"end":{"line":170,"column":null}},"65":{"start":{"line":155,"column":6},"end":{"line":155,"column":null}},"66":{"start":{"line":156,"column":6},"end":{"line":156,"column":null}},"67":{"start":{"line":157,"column":6},"end":{"line":157,"column":null}},"68":{"start":{"line":160,"column":6},"end":{"line":160,"column":null}},"69":{"start":{"line":162,"column":45},"end":{"line":166,"column":null}},"70":{"start":{"line":167,"column":6},"end":{"line":167,"column":null}},"71":{"start":{"line":169,"column":6},"end":{"line":169,"column":null}},"72":{"start":{"line":177,"column":18},"end":{"line":177,"column":null}},"73":{"start":{"line":178,"column":4},"end":{"line":178,"column":null}},"74":{"start":{"line":178,"column":16},"end":{"line":178,"column":null}},"75":{"start":{"line":180,"column":23},"end":{"line":180,"column":null}},"76":{"start":{"line":181,"column":4},"end":{"line":181,"column":null}},"77":{"start":{"line":181,"column":29},"end":{"line":181,"column":null}},"78":{"start":{"line":183,"column":23},"end":{"line":183,"column":null}},"79":{"start":{"line":184,"column":10},"end":{"line":184,"column":null}},"80":{"start":{"line":186,"column":21},"end":{"line":186,"column":null}},"81":{"start":{"line":188,"column":4},"end":{"line":198,"column":null}},"82":{"start":{"line":189,"column":24},"end":{"line":189,"column":null}},"83":{"start":{"line":190,"column":21},"end":{"line":190,"column":null}},"84":{"start":{"line":192,"column":6},"end":{"line":195,"column":null}},"85":{"start":{"line":193,"column":8},"end":{"line":193,"column":null}},"86":{"start":{"line":194,"column":8},"end":{"line":194,"column":null}},"87":{"start":{"line":197,"column":6},"end":{"line":197,"column":null}},"88":{"start":{"line":201,"column":42},"end":{"line":205,"column":null}},"89":{"start":{"line":206,"column":4},"end":{"line":206,"column":null}},"90":{"start":{"line":214,"column":18},"end":{"line":214,"column":null}},"91":{"start":{"line":215,"column":4},"end":{"line":215,"column":null}},"92":{"start":{"line":215,"column":16},"end":{"line":215,"column":null}},"93":{"start":{"line":216,"column":4},"end":{"line":218,"column":null}},"94":{"start":{"line":217,"column":6},"end":{"line":217,"column":null}},"95":{"start":{"line":220,"column":4},"end":{"line":220,"column":null}},"96":{"start":{"line":221,"column":4},"end":{"line":221,"column":null}},"97":{"start":{"line":222,"column":4},"end":{"line":222,"column":null}},"98":{"start":{"line":224,"column":4},"end":{"line":224,"column":null}}},"fnMap":{"0":{"name":"(anonymous_0)","decl":{"start":{"line":32,"column":2},"end":{"line":32,"column":null}},"loc":{"start":{"line":42,"column":4},"end":{"line":42,"column":null}},"line":42},"1":{"name":"(anonymous_1)","decl":{"start":{"line":47,"column":2},"end":{"line":47,"column":16}},"loc":{"start":{"line":47,"column":16},"end":{"line":54,"column":null}},"line":47},"2":{"name":"(anonymous_2)","decl":{"start":{"line":48,"column":59},"end":{"line":48,"column":60}},"loc":{"start":{"line":48,"column":70},"end":{"line":52,"column":5}},"line":48},"3":{"name":"(anonymous_3)","decl":{"start":{"line":49,"column":44},"end":{"line":49,"column":45}},"loc":{"start":{"line":49,"column":53},"end":{"line":51,"column":7}},"line":49},"4":{"name":"(anonymous_4)","decl":{"start":{"line":60,"column":16},"end":{"line":60,"column":36}},"loc":{"start":{"line":60,"column":78},"end":{"line":93,"column":null}},"line":60},"5":{"name":"(anonymous_5)","decl":{"start":{"line":81,"column":30},"end":{"line":81,"column":42}},"loc":{"start":{"line":81,"column":42},"end":{"line":83,"column":5}},"line":81},"6":{"name":"(anonymous_6)","decl":{"start":{"line":84,"column":57},"end":{"line":84,"column":63}},"loc":{"start":{"line":84,"column":63},"end":{"line":84,"column":65}},"line":84},"7":{"name":"(anonymous_7)","decl":{"start":{"line":89,"column":37},"end":{"line":89,"column":38}},"loc":{"start":{"line":89,"column":44},"end":{"line":89,"column":68}},"line":89},"8":{"name":"(anonymous_8)","decl":{"start":{"line":98,"column":16},"end":{"line":98,"column":null}},"loc":{"start":{"line":103,"column":19},"end":{"line":140,"column":null}},"line":103},"9":{"name":"(anonymous_9)","decl":{"start":{"line":147,"column":16},"end":{"line":147,"column":40}},"loc":{"start":{"line":147,"column":72},"end":{"line":171,"column":null}},"line":147},"10":{"name":"(anonymous_10)","decl":{"start":{"line":176,"column":16},"end":{"line":176,"column":41}},"loc":{"start":{"line":176,"column":73},"end":{"line":207,"column":null}},"line":176},"11":{"name":"(anonymous_11)","decl":{"start":{"line":213,"column":8},"end":{"line":213,"column":29}},"loc":{"start":{"line":213,"column":61},"end":{"line":225,"column":null}},"line":213}},"branchMap":{"0":{"loc":{"start":{"line":50,"column":25},"end":{"line":50,"column":74}},"type":"cond-expr","locations":[{"start":{"line":50,"column":48},"end":{"line":50,"column":62}},{"start":{"line":50,"column":62},"end":{"line":50,"column":74}}],"line":50},"1":{"loc":{"start":{"line":64,"column":4},"end":{"line":64,"column":null}},"type":"if","locations":[{"start":{"line":64,"column":4},"end":{"line":64,"column":null}},{"start":{},"end":{}}],"line":64},"2":{"loc":{"start":{"line":64,"column":8},"end":{"line":64,"column":46}},"type":"binary-expr","locations":[{"start":{"line":64,"column":8},"end":{"line":64,"column":26}},{"start":{"line":64,"column":26},"end":{"line":64,"column":46}}],"line":64},"3":{"loc":{"start":{"line":67,"column":4},"end":{"line":67,"column":null}},"type":"if","locations":[{"start":{"line":67,"column":4},"end":{"line":67,"column":null}},{"start":{},"end":{}}],"line":67},"4":{"loc":{"start":{"line":70,"column":4},"end":{"line":70,"column":null}},"type":"if","locations":[{"start":{"line":70,"column":4},"end":{"line":70,"column":null}},{"start":{},"end":{}}],"line":70},"5":{"loc":{"start":{"line":73,"column":4},"end":{"line":73,"column":null}},"type":"if","locations":[{"start":{"line":73,"column":4},"end":{"line":73,"column":null}},{"start":{},"end":{}}],"line":73},"6":{"loc":{"start":{"line":80,"column":17},"end":{"line":80,"column":null}},"type":"binary-expr","locations":[{"start":{"line":80,"column":17},"end":{"line":80,"column":59}},{"start":{"line":80,"column":59},"end":{"line":80,"column":null}}],"line":80},"7":{"loc":{"start":{"line":90,"column":4},"end":{"line":92,"column":null}},"type":"if","locations":[{"start":{"line":90,"column":4},"end":{"line":92,"column":null}},{"start":{},"end":{}}],"line":90},"8":{"loc":{"start":{"line":105,"column":4},"end":{"line":105,"column":null}},"type":"if","locations":[{"start":{"line":105,"column":4},"end":{"line":105,"column":null}},{"start":{},"end":{}}],"line":105},"9":{"loc":{"start":{"line":114,"column":6},"end":{"line":117,"column":null}},"type":"if","locations":[{"start":{"line":114,"column":6},"end":{"line":117,"column":null}},{"start":{},"end":{}}],"line":114},"10":{"loc":{"start":{"line":121,"column":6},"end":{"line":128,"column":null}},"type":"if","locations":[{"start":{"line":121,"column":6},"end":{"line":128,"column":null}},{"start":{},"end":{}}],"line":121},"11":{"loc":{"start":{"line":121,"column":10},"end":{"line":121,"column":47}},"type":"binary-expr","locations":[{"start":{"line":121,"column":10},"end":{"line":121,"column":29}},{"start":{"line":121,"column":29},"end":{"line":121,"column":47}}],"line":121},"12":{"loc":{"start":{"line":149,"column":4},"end":{"line":149,"column":null}},"type":"if","locations":[{"start":{"line":149,"column":4},"end":{"line":149,"column":null}},{"start":{},"end":{}}],"line":149},"13":{"loc":{"start":{"line":152,"column":4},"end":{"line":152,"column":null}},"type":"if","locations":[{"start":{"line":152,"column":4},"end":{"line":152,"column":null}},{"start":{},"end":{}}],"line":152},"14":{"loc":{"start":{"line":154,"column":4},"end":{"line":170,"column":null}},"type":"if","locations":[{"start":{"line":154,"column":4},"end":{"line":170,"column":null}},{"start":{"line":158,"column":11},"end":{"line":170,"column":null}}],"line":154},"15":{"loc":{"start":{"line":178,"column":4},"end":{"line":178,"column":null}},"type":"if","locations":[{"start":{"line":178,"column":4},"end":{"line":178,"column":null}},{"start":{},"end":{}}],"line":178},"16":{"loc":{"start":{"line":181,"column":4},"end":{"line":181,"column":null}},"type":"if","locations":[{"start":{"line":181,"column":4},"end":{"line":181,"column":null}},{"start":{},"end":{}}],"line":181},"17":{"loc":{"start":{"line":192,"column":6},"end":{"line":195,"column":null}},"type":"if","locations":[{"start":{"line":192,"column":6},"end":{"line":195,"column":null}},{"start":{},"end":{}}],"line":192},"18":{"loc":{"start":{"line":215,"column":4},"end":{"line":215,"column":null}},"type":"if","locations":[{"start":{"line":215,"column":4},"end":{"line":215,"column":null}},{"start":{},"end":{}}],"line":215},"19":{"loc":{"start":{"line":216,"column":4},"end":{"line":218,"column":null}},"type":"if","locations":[{"start":{"line":216,"column":4},"end":{"line":218,"column":null}},{"start":{},"end":{}}],"line":216}},"s":{"0":8,"1":0,"2":0,"3":0,"4":0,"5":0,"6":0,"7":0,"8":0,"9":0,"10":0,"11":0,"12":0,"13":0,"14":0,"15":0,"16":0,"17":0,"18":0,"19":0,"20":0,"21":0,"22":0,"23":0,"24":0,"25":0,"26":0,"27":0,"28":0,"29":0,"30":0,"31":0,"32":0,"33":0,"34":0,"35":0,"36":0,"37":0,"38":0,"39":0,"40":0,"41":0,"42":0,"43":0,"44":0,"45":0,"46":0,"47":0,"48":0,"49":0,"50":0,"51":0,"52":0,"53":0,"54":0,"55":0,"56":0,"57":0,"58":0,"59":0,"60":0,"61":0,"62":0,"63":0,"64":0,"65":0,"66":0,"67":0,"68":0,"69":0,"70":0,"71":0,"72":0,"73":0,"74":0,"75":0,"76":0,"77":0,"78":0,"79":0,"80":0,"81":0,"82":0,"83":0,"84":0,"85":0,"86":0,"87":0,"88":0,"89":0,"90":0,"91":0,"92":0,"93":0,"94":0,"95":0,"96":0,"97":0,"98":0},"f":{"0":0,"1":0,"2":0,"3":0,"4":0,"5":0,"6":0,"7":0,"8":0,"9":0,"10":0,"11":0},"b":{"0":[0,0],"1":[0,0],"2":[0,0],"3":[0,0],"4":[0,0],"5":[0,0],"6":[0,0],"7":[0,0],"8":[0,0],"9":[0,0],"10":[0,0],"11":[0,0],"12":[0,0],"13":[0,0],"14":[0,0],"15":[0,0],"16":[0,0],"17":[0,0],"18":[0,0],"19":[0,0]},"meta":{"lastBranch":20,"lastFunction":12,"lastStatement":99,"seen":{"s:26:6:26:Infinity":0,"s:30:56:30:Infinity":1,"f:32:2:32:Infinity":0,"s:33:12:33:Infinity":2,"s:34:12:34:Infinity":3,"s:35:12:35:Infinity":4,"s:36:12:36:Infinity":5,"s:37:12:37:Infinity":6,"s:38:12:38:Infinity":7,"s:39:12:39:Infinity":8,"s:40:12:40:Infinity":9,"s:41:12:41:Infinity":10,"f:47:2:47:16":1,"s:48:4:52:Infinity":11,"f:48:59:48:60":2,"s:49:6:51:Infinity":12,"f:49:44:49:45":3,"s:50:8:50:Infinity":13,"b:50:48:50:62:50:62:50:74":0,"s:53:4:53:Infinity":14,"f:60:16:60:36":4,"s:61:23:61:Infinity":15,"s:63:17:63:Infinity":16,"b:64:4:64:Infinity:undefined:undefined:undefined:undefined":1,"s:64:4:64:Infinity":17,"b:64:8:64:26:64:26:64:46":2,"s:64:46:64:Infinity":18,"s:66:23:66:Infinity":19,"b:67:4:67:Infinity:undefined:undefined:undefined:undefined":3,"s:67:4:67:Infinity":20,"s:67:29:67:Infinity":21,"s:69:18:69:Infinity":22,"b:70:4:70:Infinity:undefined:undefined:undefined:undefined":4,"s:70:4:70:Infinity":23,"s:70:16:70:Infinity":24,"b:73:4:73:Infinity:undefined:undefined:undefined:undefined":5,"s:73:4:73:Infinity":25,"s:73:35:73:Infinity":26,"s:75:23:75:Infinity":27,"s:76:10:76:Infinity":28,"s:77:10:77:Infinity":29,"s:80:17:80:Infinity":30,"b:80:17:80:59:80:59:80:Infinity":6,"s:81:20:83:Infinity":31,"f:81:30:81:42":5,"s:82:6:82:Infinity":32,"s:84:4:84:Infinity":33,"f:84:57:84:63":6,"s:85:4:85:Infinity":34,"s:88:23:88:Infinity":35,"s:89:20:89:Infinity":36,"f:89:37:89:38":7,"s:89:44:89:68":37,"b:90:4:92:Infinity:undefined:undefined:undefined:undefined":7,"s:90:4:92:Infinity":38,"s:91:6:91:Infinity":39,"f:98:16:98:Infinity":8,"s:104:18:104:Infinity":40,"b:105:4:105:Infinity:undefined:undefined:undefined:undefined":8,"s:105:4:105:Infinity":41,"s:105:16:105:Infinity":42,"s:107:21:107:Infinity":43,"s:109:4:131:Infinity":44,"s:110:24:110:Infinity":45,"s:113:21:113:Infinity":46,"b:114:6:117:Infinity:undefined:undefined:undefined:undefined":9,"s:114:6:117:Infinity":47,"s:115:8:115:Infinity":48,"s:116:8:116:Infinity":49,"s:119:21:119:Infinity":50,"b:121:6:128:Infinity:undefined:undefined:undefined:undefined":10,"s:121:6:128:Infinity":51,"b:121:10:121:29:121:29:121:47":11,"s:122:8:122:Infinity":52,"s:123:8:126:Infinity":53,"s:127:8:127:Infinity":54,"s:130:6:130:Infinity":55,"s:134:41:138:Infinity":56,"s:139:4:139:Infinity":57,"f:147:16:147:40":9,"s:148:18:148:Infinity":58,"b:149:4:149:Infinity:undefined:undefined:undefined:undefined":12,"s:149:4:149:Infinity":59,"s:149:16:149:Infinity":60,"s:151:23:151:Infinity":61,"b:152:4:152:Infinity:undefined:undefined:undefined:undefined":13,"s:152:4:152:Infinity":62,"s:152:29:152:Infinity":63,"b:154:4:170:Infinity:158:11:170:Infinity":14,"s:154:4:170:Infinity":64,"s:155:6:155:Infinity":65,"s:156:6:156:Infinity":66,"s:157:6:157:Infinity":67,"s:160:6:160:Infinity":68,"s:162:45:166:Infinity":69,"s:167:6:167:Infinity":70,"s:169:6:169:Infinity":71,"f:176:16:176:41":10,"s:177:18:177:Infinity":72,"b:178:4:178:Infinity:undefined:undefined:undefined:undefined":15,"s:178:4:178:Infinity":73,"s:178:16:178:Infinity":74,"s:180:23:180:Infinity":75,"b:181:4:181:Infinity:undefined:undefined:undefined:undefined":16,"s:181:4:181:Infinity":76,"s:181:29:181:Infinity":77,"s:183:23:183:Infinity":78,"s:184:10:184:Infinity":79,"s:186:21:186:Infinity":80,"s:188:4:198:Infinity":81,"s:189:24:189:Infinity":82,"s:190:21:190:Infinity":83,"b:192:6:195:Infinity:undefined:undefined:undefined:undefined":17,"s:192:6:195:Infinity":84,"s:193:8:193:Infinity":85,"s:194:8:194:Infinity":86,"s:197:6:197:Infinity":87,"s:201:42:205:Infinity":88,"s:206:4:206:Infinity":89,"f:213:8:213:29":11,"s:214:18:214:Infinity":90,"b:215:4:215:Infinity:undefined:undefined:undefined:undefined":18,"s:215:4:215:Infinity":91,"s:215:16:215:Infinity":92,"b:216:4:218:Infinity:undefined:undefined:undefined:undefined":19,"s:216:4:218:Infinity":93,"s:217:6:217:Infinity":94,"s:220:4:220:Infinity":95,"s:221:4:221:Infinity":96,"s:222:4:222:Infinity":97,"s:224:4:224:Infinity":98}}} +,"/Users/lukasmay/development/projects/codewalk-district/src/git/branch-naming.ts": {"path":"/Users/lukasmay/development/projects/codewalk-district/src/git/branch-naming.ts","statementMap":{"0":{"start":{"line":11,"column":35},"end":{"line":11,"column":null}},"1":{"start":{"line":16,"column":36},"end":{"line":16,"column":null}},"2":{"start":{"line":22,"column":2},"end":{"line":22,"column":null}},"3":{"start":{"line":30,"column":2},"end":{"line":33,"column":null}},"4":{"start":{"line":41,"column":2},"end":{"line":41,"column":null}},"5":{"start":{"line":49,"column":2},"end":{"line":49,"column":null}},"6":{"start":{"line":57,"column":2},"end":{"line":57,"column":null}},"7":{"start":{"line":66,"column":2},"end":{"line":66,"column":null}}},"fnMap":{"0":{"name":"isPlanningCategory","decl":{"start":{"line":21,"column":16},"end":{"line":21,"column":35}},"loc":{"start":{"line":21,"column":62},"end":{"line":23,"column":null}},"line":21},"1":{"name":"slugify","decl":{"start":{"line":29,"column":16},"end":{"line":29,"column":24}},"loc":{"start":{"line":29,"column":46},"end":{"line":34,"column":null}},"line":29},"2":{"name":"generateInitiativeBranch","decl":{"start":{"line":40,"column":16},"end":{"line":40,"column":41}},"loc":{"start":{"line":40,"column":63},"end":{"line":42,"column":null}},"line":40},"3":{"name":"initiativeBranchName","decl":{"start":{"line":48,"column":16},"end":{"line":48,"column":37}},"loc":{"start":{"line":48,"column":75},"end":{"line":50,"column":null}},"line":48},"4":{"name":"phaseBranchName","decl":{"start":{"line":56,"column":16},"end":{"line":56,"column":32}},"loc":{"start":{"line":56,"column":85},"end":{"line":58,"column":null}},"line":56},"5":{"name":"taskBranchName","decl":{"start":{"line":65,"column":16},"end":{"line":65,"column":31}},"loc":{"start":{"line":65,"column":81},"end":{"line":67,"column":null}},"line":65}},"branchMap":{},"s":{"0":13,"1":13,"2":87,"3":0,"4":0,"5":0,"6":0,"7":0},"f":{"0":87,"1":0,"2":0,"3":0,"4":0,"5":0},"b":{},"meta":{"lastBranch":0,"lastFunction":6,"lastStatement":8,"seen":{"s:11:35:11:Infinity":0,"s:16:36:16:Infinity":1,"f:21:16:21:35":0,"s:22:2:22:Infinity":2,"f:29:16:29:24":1,"s:30:2:33:Infinity":3,"f:40:16:40:41":2,"s:41:2:41:Infinity":4,"f:48:16:48:37":3,"s:49:2:49:Infinity":5,"f:56:16:56:32":4,"s:57:2:57:Infinity":6,"f:65:16:65:31":5,"s:66:2:66:Infinity":7}}} +,"/Users/lukasmay/development/projects/codewalk-district/src/git/clone.ts": {"path":"/Users/lukasmay/development/projects/codewalk-district/src/git/clone.ts","statementMap":{"0":{"start":{"line":12,"column":6},"end":{"line":12,"column":null}},"1":{"start":{"line":21,"column":8},"end":{"line":21,"column":null}},"2":{"start":{"line":22,"column":2},"end":{"line":22,"column":null}},"3":{"start":{"line":23,"column":2},"end":{"line":23,"column":null}}},"fnMap":{"0":{"name":"cloneProject","decl":{"start":{"line":20,"column":22},"end":{"line":20,"column":35}},"loc":{"start":{"line":20,"column":81},"end":{"line":24,"column":null}},"line":20}},"branchMap":{},"s":{"0":20,"1":0,"2":0,"3":0},"f":{"0":0},"b":{},"meta":{"lastBranch":0,"lastFunction":1,"lastStatement":4,"seen":{"s:12:6:12:Infinity":0,"f:20:22:20:35":0,"s:21:8:21:Infinity":1,"s:22:2:22:Infinity":2,"s:23:2:23:Infinity":3}}} +,"/Users/lukasmay/development/projects/codewalk-district/src/git/manager.ts": {"path":"/Users/lukasmay/development/projects/codewalk-district/src/git/manager.ts","statementMap":{"0":{"start":{"line":22,"column":6},"end":{"line":22,"column":null}},"1":{"start":{"line":44,"column":4},"end":{"line":44,"column":null}},"2":{"start":{"line":45,"column":4},"end":{"line":45,"column":null}},"3":{"start":{"line":46,"column":4},"end":{"line":46,"column":null}},"4":{"start":{"line":47,"column":4},"end":{"line":47,"column":null}},"5":{"start":{"line":61,"column":25},"end":{"line":61,"column":null}},"6":{"start":{"line":62,"column":4},"end":{"line":62,"column":null}},"7":{"start":{"line":66,"column":4},"end":{"line":73,"column":null}},"8":{"start":{"line":75,"column":31},"end":{"line":80,"column":null}},"9":{"start":{"line":83,"column":4},"end":{"line":91,"column":null}},"10":{"start":{"line":93,"column":4},"end":{"line":93,"column":null}},"11":{"start":{"line":102,"column":21},"end":{"line":102,"column":null}},"12":{"start":{"line":103,"column":4},"end":{"line":105,"column":null}},"13":{"start":{"line":104,"column":6},"end":{"line":104,"column":null}},"14":{"start":{"line":107,"column":19},"end":{"line":107,"column":null}},"15":{"start":{"line":108,"column":4},"end":{"line":108,"column":null}},"16":{"start":{"line":112,"column":4},"end":{"line":112,"column":null}},"17":{"start":{"line":115,"column":4},"end":{"line":122,"column":null}},"18":{"start":{"line":132,"column":19},"end":{"line":132,"column":null}},"19":{"start":{"line":134,"column":4},"end":{"line":134,"column":null}},"20":{"start":{"line":143,"column":22},"end":{"line":143,"column":null}},"21":{"start":{"line":144,"column":4},"end":{"line":144,"column":null}},"22":{"start":{"line":144,"column":34},"end":{"line":144,"column":54}},"23":{"start":{"line":153,"column":21},"end":{"line":153,"column":null}},"24":{"start":{"line":154,"column":4},"end":{"line":156,"column":null}},"25":{"start":{"line":155,"column":6},"end":{"line":155,"column":null}},"26":{"start":{"line":159,"column":10},"end":{"line":159,"column":null}},"27":{"start":{"line":164,"column":4},"end":{"line":169,"column":null}},"28":{"start":{"line":165,"column":6},"end":{"line":165,"column":null}},"29":{"start":{"line":168,"column":6},"end":{"line":168,"column":null}},"30":{"start":{"line":173,"column":4},"end":{"line":181,"column":null}},"31":{"start":{"line":174,"column":6},"end":{"line":178,"column":null}},"32":{"start":{"line":180,"column":6},"end":{"line":180,"column":null}},"33":{"start":{"line":184,"column":21},"end":{"line":184,"column":null}},"34":{"start":{"line":185,"column":18},"end":{"line":185,"column":null}},"35":{"start":{"line":188,"column":22},"end":{"line":188,"column":null}},"36":{"start":{"line":190,"column":6},"end":{"line":190,"column":null}},"37":{"start":{"line":192,"column":4},"end":{"line":192,"column":null}},"38":{"start":{"line":202,"column":21},"end":{"line":202,"column":null}},"39":{"start":{"line":203,"column":4},"end":{"line":205,"column":null}},"40":{"start":{"line":204,"column":6},"end":{"line":204,"column":null}},"41":{"start":{"line":206,"column":4},"end":{"line":206,"column":null}},"42":{"start":{"line":209,"column":26},"end":{"line":209,"column":null}},"43":{"start":{"line":211,"column":4},"end":{"line":275,"column":null}},"44":{"start":{"line":213,"column":6},"end":{"line":213,"column":null}},"45":{"start":{"line":216,"column":6},"end":{"line":216,"column":null}},"46":{"start":{"line":219,"column":6},"end":{"line":227,"column":null}},"47":{"start":{"line":229,"column":6},"end":{"line":232,"column":null}},"48":{"start":{"line":235,"column":21},"end":{"line":235,"column":null}},"49":{"start":{"line":237,"column":6},"end":{"line":261,"column":null}},"50":{"start":{"line":238,"column":26},"end":{"line":238,"column":null}},"51":{"start":{"line":239,"column":8},"end":{"line":239,"column":null}},"52":{"start":{"line":242,"column":8},"end":{"line":251,"column":null}},"53":{"start":{"line":254,"column":8},"end":{"line":254,"column":null}},"54":{"start":{"line":256,"column":8},"end":{"line":260,"column":null}},"55":{"start":{"line":264,"column":6},"end":{"line":264,"column":null}},"56":{"start":{"line":267,"column":6},"end":{"line":274,"column":null}},"57":{"start":{"line":268,"column":26},"end":{"line":268,"column":null}},"58":{"start":{"line":269,"column":8},"end":{"line":271,"column":null}},"59":{"start":{"line":270,"column":10},"end":{"line":270,"column":null}},"60":{"start":{"line":282,"column":34},"end":{"line":282,"column":null}},"61":{"start":{"line":283,"column":18},"end":{"line":283,"column":null}},"62":{"start":{"line":285,"column":45},"end":{"line":285,"column":null}},"63":{"start":{"line":286,"column":18},"end":{"line":286,"column":null}},"64":{"start":{"line":288,"column":4},"end":{"line":314,"column":null}},"65":{"start":{"line":289,"column":6},"end":{"line":313,"column":null}},"66":{"start":{"line":291,"column":8},"end":{"line":301,"column":null}},"67":{"start":{"line":293,"column":21},"end":{"line":293,"column":null}},"68":{"start":{"line":294,"column":10},"end":{"line":299,"column":null}},"69":{"start":{"line":300,"column":10},"end":{"line":300,"column":null}},"70":{"start":{"line":302,"column":8},"end":{"line":302,"column":null}},"71":{"start":{"line":303,"column":6},"end":{"line":313,"column":null}},"72":{"start":{"line":305,"column":26},"end":{"line":305,"column":null}},"73":{"start":{"line":306,"column":8},"end":{"line":306,"column":null}},"74":{"start":{"line":307,"column":6},"end":{"line":313,"column":null}},"75":{"start":{"line":309,"column":6},"end":{"line":313,"column":null}},"76":{"start":{"line":311,"column":6},"end":{"line":313,"column":null}},"77":{"start":{"line":317,"column":4},"end":{"line":325,"column":null}},"78":{"start":{"line":318,"column":17},"end":{"line":318,"column":null}},"79":{"start":{"line":319,"column":6},"end":{"line":324,"column":null}},"80":{"start":{"line":327,"column":4},"end":{"line":327,"column":null}},"81":{"start":{"line":336,"column":4},"end":{"line":338,"column":null}},"82":{"start":{"line":337,"column":6},"end":{"line":337,"column":null}},"83":{"start":{"line":340,"column":18},"end":{"line":340,"column":null}},"84":{"start":{"line":344,"column":9},"end":{"line":344,"column":null}},"85":{"start":{"line":345,"column":17},"end":{"line":345,"column":null}},"86":{"start":{"line":347,"column":4},"end":{"line":376,"column":null}},"87":{"start":{"line":348,"column":6},"end":{"line":348,"column":null}},"88":{"start":{"line":348,"column":24},"end":{"line":348,"column":null}},"89":{"start":{"line":351,"column":20},"end":{"line":351,"column":null}},"90":{"start":{"line":352,"column":6},"end":{"line":375,"column":null}},"91":{"start":{"line":353,"column":43},"end":{"line":353,"column":null}},"92":{"start":{"line":356,"column":8},"end":{"line":356,"column":null}},"93":{"start":{"line":356,"column":32},"end":{"line":356,"column":null}},"94":{"start":{"line":357,"column":8},"end":{"line":357,"column":null}},"95":{"start":{"line":360,"column":8},"end":{"line":372,"column":null}},"96":{"start":{"line":362,"column":12},"end":{"line":362,"column":null}},"97":{"start":{"line":363,"column":12},"end":{"line":363,"column":null}},"98":{"start":{"line":365,"column":12},"end":{"line":365,"column":null}},"99":{"start":{"line":366,"column":12},"end":{"line":366,"column":null}},"100":{"start":{"line":368,"column":12},"end":{"line":368,"column":null}},"101":{"start":{"line":369,"column":12},"end":{"line":369,"column":null}},"102":{"start":{"line":371,"column":12},"end":{"line":371,"column":null}},"103":{"start":{"line":374,"column":8},"end":{"line":374,"column":null}},"104":{"start":{"line":378,"column":4},"end":{"line":378,"column":null}}},"fnMap":{"0":{"name":"(anonymous_0)","decl":{"start":{"line":43,"column":2},"end":{"line":43,"column":14}},"loc":{"start":{"line":43,"column":80},"end":{"line":48,"column":null}},"line":43},"1":{"name":"(anonymous_1)","decl":{"start":{"line":56,"column":8},"end":{"line":56,"column":null}},"loc":{"start":{"line":60,"column":23},"end":{"line":94,"column":null}},"line":60},"2":{"name":"(anonymous_2)","decl":{"start":{"line":101,"column":8},"end":{"line":101,"column":15}},"loc":{"start":{"line":101,"column":42},"end":{"line":123,"column":null}},"line":101},"3":{"name":"(anonymous_3)","decl":{"start":{"line":130,"column":8},"end":{"line":130,"column":36}},"loc":{"start":{"line":130,"column":36},"end":{"line":135,"column":null}},"line":130},"4":{"name":"(anonymous_4)","decl":{"start":{"line":142,"column":8},"end":{"line":142,"column":12}},"loc":{"start":{"line":142,"column":50},"end":{"line":145,"column":null}},"line":142},"5":{"name":"(anonymous_5)","decl":{"start":{"line":144,"column":26},"end":{"line":144,"column":27}},"loc":{"start":{"line":144,"column":34},"end":{"line":144,"column":54}},"line":144},"6":{"name":"(anonymous_6)","decl":{"start":{"line":152,"column":8},"end":{"line":152,"column":13}},"loc":{"start":{"line":152,"column":48},"end":{"line":193,"column":null}},"line":152},"7":{"name":"(anonymous_7)","decl":{"start":{"line":201,"column":8},"end":{"line":201,"column":14}},"loc":{"start":{"line":201,"column":70},"end":{"line":276,"column":null}},"line":201},"8":{"name":"(anonymous_8)","decl":{"start":{"line":281,"column":10},"end":{"line":281,"column":28}},"loc":{"start":{"line":281,"column":56},"end":{"line":328,"column":null}},"line":281},"9":{"name":"(anonymous_9)","decl":{"start":{"line":333,"column":10},"end":{"line":333,"column":null}},"loc":{"start":{"line":335,"column":71},"end":{"line":379,"column":null}},"line":335}},"branchMap":{"0":{"loc":{"start":{"line":46,"column":24},"end":{"line":46,"column":null}},"type":"binary-expr","locations":[{"start":{"line":46,"column":24},"end":{"line":46,"column":44}},{"start":{"line":46,"column":44},"end":{"line":46,"column":null}}],"line":46},"1":{"loc":{"start":{"line":59,"column":4},"end":{"line":59,"column":null}},"type":"default-arg","locations":[{"start":{"line":59,"column":25},"end":{"line":59,"column":null}}],"line":59},"2":{"loc":{"start":{"line":103,"column":4},"end":{"line":105,"column":null}},"type":"if","locations":[{"start":{"line":103,"column":4},"end":{"line":105,"column":null}},{"start":{},"end":{}}],"line":103},"3":{"loc":{"start":{"line":144,"column":11},"end":{"line":144,"column":null}},"type":"binary-expr","locations":[{"start":{"line":144,"column":11},"end":{"line":144,"column":59}},{"start":{"line":144,"column":59},"end":{"line":144,"column":null}}],"line":144},"4":{"loc":{"start":{"line":154,"column":4},"end":{"line":156,"column":null}},"type":"if","locations":[{"start":{"line":154,"column":4},"end":{"line":156,"column":null}},{"start":{},"end":{}}],"line":154},"5":{"loc":{"start":{"line":190,"column":6},"end":{"line":190,"column":null}},"type":"cond-expr","locations":[{"start":{"line":190,"column":24},"end":{"line":190,"column":39}},{"start":{"line":190,"column":39},"end":{"line":190,"column":null}}],"line":190},"6":{"loc":{"start":{"line":203,"column":4},"end":{"line":205,"column":null}},"type":"if","locations":[{"start":{"line":203,"column":4},"end":{"line":205,"column":null}},{"start":{},"end":{}}],"line":203},"7":{"loc":{"start":{"line":237,"column":6},"end":{"line":261,"column":null}},"type":"if","locations":[{"start":{"line":237,"column":6},"end":{"line":261,"column":null}},{"start":{},"end":{}}],"line":237},"8":{"loc":{"start":{"line":269,"column":8},"end":{"line":271,"column":null}},"type":"if","locations":[{"start":{"line":269,"column":8},"end":{"line":271,"column":null}},{"start":{},"end":{}}],"line":269},"9":{"loc":{"start":{"line":289,"column":6},"end":{"line":313,"column":null}},"type":"if","locations":[{"start":{"line":289,"column":6},"end":{"line":313,"column":null}},{"start":{"line":303,"column":6},"end":{"line":313,"column":null}}],"line":289},"10":{"loc":{"start":{"line":291,"column":8},"end":{"line":301,"column":null}},"type":"if","locations":[{"start":{"line":291,"column":8},"end":{"line":301,"column":null}},{"start":{},"end":{}}],"line":291},"11":{"loc":{"start":{"line":293,"column":21},"end":{"line":293,"column":null}},"type":"cond-expr","locations":[{"start":{"line":293,"column":31},"end":{"line":293,"column":40}},{"start":{"line":293,"column":40},"end":{"line":293,"column":null}}],"line":293},"12":{"loc":{"start":{"line":296,"column":20},"end":{"line":296,"column":null}},"type":"binary-expr","locations":[{"start":{"line":296,"column":20},"end":{"line":296,"column":46}},{"start":{"line":296,"column":46},"end":{"line":296,"column":null}}],"line":296},"13":{"loc":{"start":{"line":303,"column":6},"end":{"line":313,"column":null}},"type":"if","locations":[{"start":{"line":303,"column":6},"end":{"line":313,"column":null}},{"start":{"line":307,"column":6},"end":{"line":313,"column":null}}],"line":303},"14":{"loc":{"start":{"line":307,"column":6},"end":{"line":313,"column":null}},"type":"if","locations":[{"start":{"line":307,"column":6},"end":{"line":313,"column":null}},{"start":{"line":309,"column":6},"end":{"line":313,"column":null}}],"line":307},"15":{"loc":{"start":{"line":309,"column":6},"end":{"line":313,"column":null}},"type":"if","locations":[{"start":{"line":309,"column":6},"end":{"line":313,"column":null}},{"start":{"line":311,"column":6},"end":{"line":313,"column":null}}],"line":309},"16":{"loc":{"start":{"line":311,"column":6},"end":{"line":313,"column":null}},"type":"if","locations":[{"start":{"line":311,"column":6},"end":{"line":313,"column":null}},{"start":{},"end":{}}],"line":311},"17":{"loc":{"start":{"line":317,"column":4},"end":{"line":325,"column":null}},"type":"if","locations":[{"start":{"line":317,"column":4},"end":{"line":325,"column":null}},{"start":{},"end":{}}],"line":317},"18":{"loc":{"start":{"line":318,"column":17},"end":{"line":318,"column":null}},"type":"cond-expr","locations":[{"start":{"line":318,"column":27},"end":{"line":318,"column":36}},{"start":{"line":318,"column":36},"end":{"line":318,"column":null}}],"line":318},"19":{"loc":{"start":{"line":321,"column":16},"end":{"line":321,"column":null}},"type":"binary-expr","locations":[{"start":{"line":321,"column":16},"end":{"line":321,"column":42}},{"start":{"line":321,"column":42},"end":{"line":321,"column":null}}],"line":321},"20":{"loc":{"start":{"line":336,"column":4},"end":{"line":338,"column":null}},"type":"if","locations":[{"start":{"line":336,"column":4},"end":{"line":338,"column":null}},{"start":{},"end":{}}],"line":336},"21":{"loc":{"start":{"line":348,"column":6},"end":{"line":348,"column":null}},"type":"if","locations":[{"start":{"line":348,"column":6},"end":{"line":348,"column":null}},{"start":{},"end":{}}],"line":348},"22":{"loc":{"start":{"line":352,"column":6},"end":{"line":375,"column":null}},"type":"if","locations":[{"start":{"line":352,"column":6},"end":{"line":375,"column":null}},{"start":{},"end":{}}],"line":352},"23":{"loc":{"start":{"line":356,"column":8},"end":{"line":356,"column":null}},"type":"if","locations":[{"start":{"line":356,"column":8},"end":{"line":356,"column":null}},{"start":{},"end":{}}],"line":356},"24":{"loc":{"start":{"line":360,"column":8},"end":{"line":372,"column":null}},"type":"switch","locations":[{"start":{"line":361,"column":10},"end":{"line":363,"column":null}},{"start":{"line":364,"column":10},"end":{"line":366,"column":null}},{"start":{"line":367,"column":10},"end":{"line":369,"column":null}},{"start":{"line":370,"column":10},"end":{"line":371,"column":null}}],"line":360}},"s":{"0":15,"1":24,"2":24,"3":24,"4":24,"5":20,"6":20,"7":20,"8":20,"9":20,"10":20,"11":5,"12":5,"13":1,"14":4,"15":4,"16":4,"17":4,"18":23,"19":23,"20":18,"21":18,"22":32,"23":5,"24":5,"25":1,"26":4,"27":4,"28":4,"29":0,"30":4,"31":4,"32":0,"33":4,"34":4,"35":4,"36":4,"37":5,"38":6,"39":6,"40":1,"41":5,"42":5,"43":5,"44":5,"45":5,"46":2,"47":6,"48":3,"49":3,"50":3,"51":3,"52":3,"53":3,"54":3,"55":0,"56":5,"57":5,"58":5,"59":0,"60":23,"61":23,"62":23,"63":23,"64":23,"65":141,"66":41,"67":18,"68":18,"69":18,"70":41,"71":100,"72":41,"73":41,"74":59,"75":18,"76":18,"77":23,"78":23,"79":23,"80":23,"81":4,"82":1,"83":3,"84":3,"85":3,"86":3,"87":5,"88":0,"89":5,"90":5,"91":5,"92":5,"93":2,"94":3,"95":3,"96":1,"97":1,"98":1,"99":1,"100":1,"101":1,"102":0,"103":3,"104":3},"f":{"0":24,"1":20,"2":5,"3":23,"4":18,"5":32,"6":5,"7":6,"8":23,"9":4},"b":{"0":[24,24],"1":[20],"2":[1,4],"3":[18,4],"4":[1,4],"5":[1,3],"6":[1,5],"7":[3,0],"8":[0,5],"9":[41,100],"10":[18,23],"11":[17,1],"12":[18,0],"13":[41,59],"14":[41,18],"15":[0,18],"16":[18,0],"17":[23,0],"18":[6,17],"19":[23,0],"20":[1,3],"21":[0,5],"22":[5,0],"23":[2,3],"24":[1,1,1,0]},"meta":{"lastBranch":25,"lastFunction":10,"lastStatement":105,"seen":{"s:22:6:22:Infinity":0,"f:43:2:43:14":0,"s:44:4:44:Infinity":1,"s:45:4:45:Infinity":2,"s:46:4:46:Infinity":3,"b:46:24:46:44:46:44:46:Infinity":0,"s:47:4:47:Infinity":4,"f:56:8:56:Infinity":1,"b:59:25:59:Infinity":1,"s:61:25:61:Infinity":5,"s:62:4:62:Infinity":6,"s:66:4:73:Infinity":7,"s:75:31:80:Infinity":8,"s:83:4:91:Infinity":9,"s:93:4:93:Infinity":10,"f:101:8:101:15":2,"s:102:21:102:Infinity":11,"b:103:4:105:Infinity:undefined:undefined:undefined:undefined":2,"s:103:4:105:Infinity":12,"s:104:6:104:Infinity":13,"s:107:19:107:Infinity":14,"s:108:4:108:Infinity":15,"s:112:4:112:Infinity":16,"s:115:4:122:Infinity":17,"f:130:8:130:36":3,"s:132:19:132:Infinity":18,"s:134:4:134:Infinity":19,"f:142:8:142:12":4,"s:143:22:143:Infinity":20,"s:144:4:144:Infinity":21,"b:144:11:144:59:144:59:144:Infinity":3,"f:144:26:144:27":5,"s:144:34:144:54":22,"f:152:8:152:13":6,"s:153:21:153:Infinity":23,"b:154:4:156:Infinity:undefined:undefined:undefined:undefined":4,"s:154:4:156:Infinity":24,"s:155:6:155:Infinity":25,"s:159:10:159:Infinity":26,"s:164:4:169:Infinity":27,"s:165:6:165:Infinity":28,"s:168:6:168:Infinity":29,"s:173:4:181:Infinity":30,"s:174:6:178:Infinity":31,"s:180:6:180:Infinity":32,"s:184:21:184:Infinity":33,"s:185:18:185:Infinity":34,"s:188:22:188:Infinity":35,"s:190:6:190:Infinity":36,"b:190:24:190:39:190:39:190:Infinity":5,"s:192:4:192:Infinity":37,"f:201:8:201:14":7,"s:202:21:202:Infinity":38,"b:203:4:205:Infinity:undefined:undefined:undefined:undefined":6,"s:203:4:205:Infinity":39,"s:204:6:204:Infinity":40,"s:206:4:206:Infinity":41,"s:209:26:209:Infinity":42,"s:211:4:275:Infinity":43,"s:213:6:213:Infinity":44,"s:216:6:216:Infinity":45,"s:219:6:227:Infinity":46,"s:229:6:232:Infinity":47,"s:235:21:235:Infinity":48,"b:237:6:261:Infinity:undefined:undefined:undefined:undefined":7,"s:237:6:261:Infinity":49,"s:238:26:238:Infinity":50,"s:239:8:239:Infinity":51,"s:242:8:251:Infinity":52,"s:254:8:254:Infinity":53,"s:256:8:260:Infinity":54,"s:264:6:264:Infinity":55,"s:267:6:274:Infinity":56,"s:268:26:268:Infinity":57,"b:269:8:271:Infinity:undefined:undefined:undefined:undefined":8,"s:269:8:271:Infinity":58,"s:270:10:270:Infinity":59,"f:281:10:281:28":8,"s:282:34:282:Infinity":60,"s:283:18:283:Infinity":61,"s:285:45:285:Infinity":62,"s:286:18:286:Infinity":63,"s:288:4:314:Infinity":64,"b:289:6:313:Infinity:303:6:313:Infinity":9,"s:289:6:313:Infinity":65,"b:291:8:301:Infinity:undefined:undefined:undefined:undefined":10,"s:291:8:301:Infinity":66,"s:293:21:293:Infinity":67,"b:293:31:293:40:293:40:293:Infinity":11,"s:294:10:299:Infinity":68,"b:296:20:296:46:296:46:296:Infinity":12,"s:300:10:300:Infinity":69,"s:302:8:302:Infinity":70,"b:303:6:313:Infinity:307:6:313:Infinity":13,"s:303:6:313:Infinity":71,"s:305:26:305:Infinity":72,"s:306:8:306:Infinity":73,"b:307:6:313:Infinity:309:6:313:Infinity":14,"s:307:6:313:Infinity":74,"b:309:6:313:Infinity:311:6:313:Infinity":15,"s:309:6:313:Infinity":75,"b:311:6:313:Infinity:undefined:undefined:undefined:undefined":16,"s:311:6:313:Infinity":76,"b:317:4:325:Infinity:undefined:undefined:undefined:undefined":17,"s:317:4:325:Infinity":77,"s:318:17:318:Infinity":78,"b:318:27:318:36:318:36:318:Infinity":18,"s:319:6:324:Infinity":79,"b:321:16:321:42:321:42:321:Infinity":19,"s:327:4:327:Infinity":80,"f:333:10:333:Infinity":9,"b:336:4:338:Infinity:undefined:undefined:undefined:undefined":20,"s:336:4:338:Infinity":81,"s:337:6:337:Infinity":82,"s:340:18:340:Infinity":83,"s:344:9:344:Infinity":84,"s:345:17:345:Infinity":85,"s:347:4:376:Infinity":86,"b:348:6:348:Infinity:undefined:undefined:undefined:undefined":21,"s:348:6:348:Infinity":87,"s:348:24:348:Infinity":88,"s:351:20:351:Infinity":89,"b:352:6:375:Infinity:undefined:undefined:undefined:undefined":22,"s:352:6:375:Infinity":90,"s:353:43:353:Infinity":91,"b:356:8:356:Infinity:undefined:undefined:undefined:undefined":23,"s:356:8:356:Infinity":92,"s:356:32:356:Infinity":93,"s:357:8:357:Infinity":94,"b:361:10:363:Infinity:364:10:366:Infinity:367:10:369:Infinity:370:10:371:Infinity":24,"s:360:8:372:Infinity":95,"s:362:12:362:Infinity":96,"s:363:12:363:Infinity":97,"s:365:12:365:Infinity":98,"s:366:12:366:Infinity":99,"s:368:12:368:Infinity":100,"s:369:12:369:Infinity":101,"s:371:12:371:Infinity":102,"s:374:8:374:Infinity":103,"s:378:4:378:Infinity":104}}} +,"/Users/lukasmay/development/projects/codewalk-district/src/git/project-clones.ts": {"path":"/Users/lukasmay/development/projects/codewalk-district/src/git/project-clones.ts","statementMap":{"0":{"start":{"line":13,"column":6},"end":{"line":13,"column":null}},"1":{"start":{"line":20,"column":20},"end":{"line":20,"column":null}},"2":{"start":{"line":21,"column":2},"end":{"line":21,"column":null}},"3":{"start":{"line":36,"column":18},"end":{"line":36,"column":null}},"4":{"start":{"line":37,"column":8},"end":{"line":37,"column":null}},"5":{"start":{"line":39,"column":2},"end":{"line":47,"column":null}},"6":{"start":{"line":40,"column":4},"end":{"line":40,"column":null}},"7":{"start":{"line":41,"column":4},"end":{"line":41,"column":null}},"8":{"start":{"line":42,"column":4},"end":{"line":42,"column":null}},"9":{"start":{"line":44,"column":4},"end":{"line":44,"column":null}},"10":{"start":{"line":45,"column":4},"end":{"line":45,"column":null}},"11":{"start":{"line":46,"column":4},"end":{"line":46,"column":null}}},"fnMap":{"0":{"name":"getProjectCloneDir","decl":{"start":{"line":19,"column":16},"end":{"line":19,"column":35}},"loc":{"start":{"line":19,"column":83},"end":{"line":22,"column":null}},"line":19},"1":{"name":"ensureProjectClone","decl":{"start":{"line":32,"column":22},"end":{"line":32,"column":null}},"loc":{"start":{"line":35,"column":19},"end":{"line":48,"column":null}},"line":35}},"branchMap":{},"s":{"0":20,"1":5,"2":5,"3":0,"4":0,"5":0,"6":0,"7":0,"8":0,"9":0,"10":0,"11":0},"f":{"0":5,"1":0},"b":{},"meta":{"lastBranch":0,"lastFunction":2,"lastStatement":12,"seen":{"s:13:6:13:Infinity":0,"f:19:16:19:35":0,"s:20:20:20:Infinity":1,"s:21:2:21:Infinity":2,"f:32:22:32:Infinity":1,"s:36:18:36:Infinity":3,"s:37:8:37:Infinity":4,"s:39:2:47:Infinity":5,"s:40:4:40:Infinity":6,"s:41:4:41:Infinity":7,"s:42:4:42:Infinity":8,"s:44:4:44:Infinity":9,"s:45:4:45:Infinity":10,"s:46:4:46:Infinity":11}}} +,"/Users/lukasmay/development/projects/codewalk-district/src/git/simple-git-branch-manager.ts": {"path":"/Users/lukasmay/development/projects/codewalk-district/src/git/simple-git-branch-manager.ts","statementMap":{"0":{"start":{"line":17,"column":6},"end":{"line":17,"column":null}},"1":{"start":{"line":21,"column":10},"end":{"line":21,"column":null}},"2":{"start":{"line":23,"column":19},"end":{"line":23,"column":null}},"3":{"start":{"line":24,"column":4},"end":{"line":27,"column":null}},"4":{"start":{"line":25,"column":6},"end":{"line":25,"column":null}},"5":{"start":{"line":26,"column":6},"end":{"line":26,"column":null}},"6":{"start":{"line":29,"column":4},"end":{"line":29,"column":null}},"7":{"start":{"line":30,"column":4},"end":{"line":30,"column":null}},"8":{"start":{"line":35,"column":10},"end":{"line":35,"column":null}},"9":{"start":{"line":36,"column":10},"end":{"line":36,"column":null}},"10":{"start":{"line":38,"column":4},"end":{"line":76,"column":null}},"11":{"start":{"line":40,"column":6},"end":{"line":40,"column":null}},"12":{"start":{"line":42,"column":12},"end":{"line":42,"column":null}},"13":{"start":{"line":44,"column":6},"end":{"line":66,"column":null}},"14":{"start":{"line":45,"column":8},"end":{"line":45,"column":null}},"15":{"start":{"line":47,"column":8},"end":{"line":47,"column":null}},"16":{"start":{"line":48,"column":8},"end":{"line":48,"column":null}},"17":{"start":{"line":51,"column":23},"end":{"line":51,"column":null}},"18":{"start":{"line":52,"column":26},"end":{"line":52,"column":null}},"19":{"start":{"line":54,"column":8},"end":{"line":62,"column":null}},"20":{"start":{"line":55,"column":10},"end":{"line":55,"column":null}},"21":{"start":{"line":56,"column":10},"end":{"line":56,"column":null}},"22":{"start":{"line":57,"column":10},"end":{"line":61,"column":null}},"23":{"start":{"line":65,"column":8},"end":{"line":65,"column":null}},"24":{"start":{"line":69,"column":6},"end":{"line":75,"column":null}},"25":{"start":{"line":70,"column":8},"end":{"line":70,"column":null}},"26":{"start":{"line":73,"column":8},"end":{"line":73,"column":null}},"27":{"start":{"line":73,"column":14},"end":{"line":73,"column":65}},"28":{"start":{"line":74,"column":8},"end":{"line":74,"column":null}},"29":{"start":{"line":74,"column":14},"end":{"line":74,"column":56}},"30":{"start":{"line":80,"column":10},"end":{"line":80,"column":null}},"31":{"start":{"line":81,"column":17},"end":{"line":81,"column":null}},"32":{"start":{"line":82,"column":4},"end":{"line":82,"column":null}},"33":{"start":{"line":86,"column":10},"end":{"line":86,"column":null}},"34":{"start":{"line":87,"column":19},"end":{"line":87,"column":null}},"35":{"start":{"line":88,"column":4},"end":{"line":88,"column":null}},"36":{"start":{"line":88,"column":17},"end":{"line":88,"column":null}},"37":{"start":{"line":90,"column":4},"end":{"line":95,"column":null}},"38":{"start":{"line":91,"column":6},"end":{"line":91,"column":null}},"39":{"start":{"line":92,"column":6},"end":{"line":92,"column":null}},"40":{"start":{"line":94,"column":6},"end":{"line":94,"column":null}},"41":{"start":{"line":99,"column":10},"end":{"line":99,"column":null}},"42":{"start":{"line":100,"column":4},"end":{"line":105,"column":null}},"43":{"start":{"line":101,"column":23},"end":{"line":101,"column":null}},"44":{"start":{"line":102,"column":6},"end":{"line":102,"column":null}},"45":{"start":{"line":104,"column":6},"end":{"line":104,"column":null}},"46":{"start":{"line":109,"column":4},"end":{"line":117,"column":null}},"47":{"start":{"line":110,"column":12},"end":{"line":110,"column":null}},"48":{"start":{"line":111,"column":21},"end":{"line":111,"column":null}},"49":{"start":{"line":112,"column":6},"end":{"line":114,"column":null}},"50":{"start":{"line":113,"column":17},"end":{"line":113,"column":null}},"51":{"start":{"line":116,"column":6},"end":{"line":116,"column":null}}},"fnMap":{"0":{"name":"(anonymous_0)","decl":{"start":{"line":20,"column":8},"end":{"line":20,"column":21}},"loc":{"start":{"line":20,"column":90},"end":{"line":31,"column":null}},"line":20},"1":{"name":"(anonymous_1)","decl":{"start":{"line":33,"column":8},"end":{"line":33,"column":20}},"loc":{"start":{"line":33,"column":104},"end":{"line":77,"column":null}},"line":33},"2":{"name":"(anonymous_2)","decl":{"start":{"line":79,"column":8},"end":{"line":79,"column":21}},"loc":{"start":{"line":79,"column":96},"end":{"line":83,"column":null}},"line":79},"3":{"name":"(anonymous_3)","decl":{"start":{"line":85,"column":8},"end":{"line":85,"column":21}},"loc":{"start":{"line":85,"column":70},"end":{"line":96,"column":null}},"line":85},"4":{"name":"(anonymous_4)","decl":{"start":{"line":98,"column":8},"end":{"line":98,"column":21}},"loc":{"start":{"line":98,"column":73},"end":{"line":106,"column":null}},"line":98},"5":{"name":"(anonymous_5)","decl":{"start":{"line":108,"column":8},"end":{"line":108,"column":27}},"loc":{"start":{"line":108,"column":79},"end":{"line":118,"column":null}},"line":108},"6":{"name":"(anonymous_6)","decl":{"start":{"line":113,"column":8},"end":{"line":113,"column":9}},"loc":{"start":{"line":113,"column":17},"end":{"line":113,"column":null}},"line":113}},"branchMap":{"0":{"loc":{"start":{"line":24,"column":4},"end":{"line":27,"column":null}},"type":"if","locations":[{"start":{"line":24,"column":4},"end":{"line":27,"column":null}},{"start":{},"end":{}}],"line":24},"1":{"loc":{"start":{"line":54,"column":8},"end":{"line":62,"column":null}},"type":"if","locations":[{"start":{"line":54,"column":8},"end":{"line":62,"column":null}},{"start":{},"end":{}}],"line":54},"2":{"loc":{"start":{"line":88,"column":4},"end":{"line":88,"column":null}},"type":"if","locations":[{"start":{"line":88,"column":4},"end":{"line":88,"column":null}},{"start":{},"end":{}}],"line":88},"3":{"loc":{"start":{"line":94,"column":40},"end":{"line":94,"column":89}},"type":"cond-expr","locations":[{"start":{"line":94,"column":63},"end":{"line":94,"column":77}},{"start":{"line":94,"column":77},"end":{"line":94,"column":89}}],"line":94},"4":{"loc":{"start":{"line":113,"column":17},"end":{"line":113,"column":null}},"type":"binary-expr","locations":[{"start":{"line":113,"column":17},"end":{"line":113,"column":47}},{"start":{"line":113,"column":47},"end":{"line":113,"column":null}}],"line":113}},"s":{"0":9,"1":0,"2":0,"3":0,"4":0,"5":0,"6":0,"7":0,"8":0,"9":0,"10":0,"11":0,"12":0,"13":0,"14":0,"15":0,"16":0,"17":0,"18":0,"19":0,"20":0,"21":0,"22":0,"23":0,"24":0,"25":0,"26":0,"27":0,"28":0,"29":0,"30":0,"31":0,"32":0,"33":0,"34":0,"35":0,"36":0,"37":0,"38":0,"39":0,"40":0,"41":1,"42":1,"43":1,"44":1,"45":0,"46":7,"47":7,"48":7,"49":6,"50":13,"51":1},"f":{"0":0,"1":0,"2":0,"3":0,"4":1,"5":7,"6":13},"b":{"0":[0,0],"1":[0,0],"2":[0,0],"3":[0,0],"4":[13,9]},"meta":{"lastBranch":5,"lastFunction":7,"lastStatement":52,"seen":{"s:17:6:17:Infinity":0,"f:20:8:20:21":0,"s:21:10:21:Infinity":1,"s:23:19:23:Infinity":2,"b:24:4:27:Infinity:undefined:undefined:undefined:undefined":0,"s:24:4:27:Infinity":3,"s:25:6:25:Infinity":4,"s:26:6:26:Infinity":5,"s:29:4:29:Infinity":6,"s:30:4:30:Infinity":7,"f:33:8:33:20":1,"s:35:10:35:Infinity":8,"s:36:10:36:Infinity":9,"s:38:4:76:Infinity":10,"s:40:6:40:Infinity":11,"s:42:12:42:Infinity":12,"s:44:6:66:Infinity":13,"s:45:8:45:Infinity":14,"s:47:8:47:Infinity":15,"s:48:8:48:Infinity":16,"s:51:23:51:Infinity":17,"s:52:26:52:Infinity":18,"b:54:8:62:Infinity:undefined:undefined:undefined:undefined":1,"s:54:8:62:Infinity":19,"s:55:10:55:Infinity":20,"s:56:10:56:Infinity":21,"s:57:10:61:Infinity":22,"s:65:8:65:Infinity":23,"s:69:6:75:Infinity":24,"s:70:8:70:Infinity":25,"s:73:8:73:Infinity":26,"s:73:14:73:65":27,"s:74:8:74:Infinity":28,"s:74:14:74:56":29,"f:79:8:79:21":2,"s:80:10:80:Infinity":30,"s:81:17:81:Infinity":31,"s:82:4:82:Infinity":32,"f:85:8:85:21":3,"s:86:10:86:Infinity":33,"s:87:19:87:Infinity":34,"b:88:4:88:Infinity:undefined:undefined:undefined:undefined":2,"s:88:4:88:Infinity":35,"s:88:17:88:Infinity":36,"s:90:4:95:Infinity":37,"s:91:6:91:Infinity":38,"s:92:6:92:Infinity":39,"s:94:6:94:Infinity":40,"b:94:63:94:77:94:77:94:89":3,"f:98:8:98:21":4,"s:99:10:99:Infinity":41,"s:100:4:105:Infinity":42,"s:101:23:101:Infinity":43,"s:102:6:102:Infinity":44,"s:104:6:104:Infinity":45,"f:108:8:108:27":5,"s:109:4:117:Infinity":46,"s:110:12:110:Infinity":47,"s:111:21:111:Infinity":48,"s:112:6:114:Infinity":49,"f:113:8:113:9":6,"s:113:17:113:Infinity":50,"b:113:17:113:47:113:47:113:Infinity":4,"s:116:6:116:Infinity":51}}} +,"/Users/lukasmay/development/projects/codewalk-district/src/logger/index.ts": {"path":"/Users/lukasmay/development/projects/codewalk-district/src/logger/index.ts","statementMap":{"0":{"start":{"line":4,"column":2},"end":{"line":4,"column":null}},"1":{"start":{"line":4,"column":32},"end":{"line":4,"column":null}},"2":{"start":{"line":5,"column":2},"end":{"line":5,"column":null}},"3":{"start":{"line":8,"column":13},"end":{"line":24,"column":null}},"4":{"start":{"line":27,"column":2},"end":{"line":27,"column":null}}},"fnMap":{"0":{"name":"resolveLevel","decl":{"start":{"line":3,"column":9},"end":{"line":3,"column":32}},"loc":{"start":{"line":3,"column":32},"end":{"line":6,"column":null}},"line":3},"1":{"name":"createModuleLogger","decl":{"start":{"line":26,"column":16},"end":{"line":26,"column":35}},"loc":{"start":{"line":26,"column":51},"end":{"line":28,"column":null}},"line":26}},"branchMap":{"0":{"loc":{"start":{"line":4,"column":2},"end":{"line":4,"column":null}},"type":"if","locations":[{"start":{"line":4,"column":2},"end":{"line":4,"column":null}},{"start":{},"end":{}}],"line":4},"1":{"loc":{"start":{"line":5,"column":9},"end":{"line":5,"column":null}},"type":"cond-expr","locations":[{"start":{"line":5,"column":50},"end":{"line":5,"column":60}},{"start":{"line":5,"column":60},"end":{"line":5,"column":null}}],"line":5},"2":{"loc":{"start":{"line":12,"column":8},"end":{"line":21,"column":null}},"type":"binary-expr","locations":[{"start":{"line":12,"column":8},"end":{"line":12,"column":45}},{"start":{"line":12,"column":45},"end":{"line":21,"column":null}}],"line":12},"3":{"loc":{"start":{"line":23,"column":2},"end":{"line":23,"column":null}},"type":"cond-expr","locations":[{"start":{"line":23,"column":38},"end":{"line":23,"column":50}},{"start":{"line":23,"column":50},"end":{"line":23,"column":null}}],"line":23}},"s":{"0":42,"1":42,"2":0,"3":42,"4":358},"f":{"0":42,"1":358},"b":{"0":[42,0],"1":[0,0],"2":[42,0],"3":[0,42]},"meta":{"lastBranch":4,"lastFunction":2,"lastStatement":5,"seen":{"f:3:9:3:32":0,"b:4:2:4:Infinity:undefined:undefined:undefined:undefined":0,"s:4:2:4:Infinity":0,"s:4:32:4:Infinity":1,"s:5:2:5:Infinity":2,"b:5:50:5:60:5:60:5:Infinity":1,"s:8:13:24:Infinity":3,"b:12:8:12:45:12:45:21:Infinity":2,"b:23:38:23:50:23:50:23:Infinity":3,"f:26:16:26:35":1,"s:27:2:27:Infinity":4}}} +,"/Users/lukasmay/development/projects/codewalk-district/src/logging/index.ts": {"path":"/Users/lukasmay/development/projects/codewalk-district/src/logging/index.ts","statementMap":{"0":{"start":{"line":48,"column":18},"end":{"line":48,"column":null}},"1":{"start":{"line":49,"column":2},"end":{"line":49,"column":null}}},"fnMap":{"0":{"name":"createLogger","decl":{"start":{"line":47,"column":16},"end":{"line":47,"column":29}},"loc":{"start":{"line":47,"column":87},"end":{"line":50,"column":null}},"line":47}},"branchMap":{},"s":{"0":0,"1":0},"f":{"0":0},"b":{},"meta":{"lastBranch":0,"lastFunction":1,"lastStatement":2,"seen":{"f:47:16:47:29":0,"s:48:18:48:Infinity":0,"s:49:2:49:Infinity":1}}} +,"/Users/lukasmay/development/projects/codewalk-district/src/logging/manager.ts": {"path":"/Users/lukasmay/development/projects/codewalk-district/src/logging/manager.ts","statementMap":{"0":{"start":{"line":15,"column":6},"end":{"line":15,"column":null}},"1":{"start":{"line":29,"column":4},"end":{"line":29,"column":null}},"2":{"start":{"line":30,"column":4},"end":{"line":30,"column":null}},"3":{"start":{"line":38,"column":4},"end":{"line":38,"column":null}},"4":{"start":{"line":46,"column":23},"end":{"line":46,"column":null}},"5":{"start":{"line":47,"column":4},"end":{"line":47,"column":null}},"6":{"start":{"line":55,"column":4},"end":{"line":55,"column":null}},"7":{"start":{"line":64,"column":4},"end":{"line":64,"column":null}},"8":{"start":{"line":72,"column":4},"end":{"line":83,"column":null}},"9":{"start":{"line":73,"column":22},"end":{"line":73,"column":null}},"10":{"start":{"line":74,"column":6},"end":{"line":76,"column":null}},"11":{"start":{"line":75,"column":27},"end":{"line":75,"column":46}},"12":{"start":{"line":76,"column":24},"end":{"line":76,"column":34}},"13":{"start":{"line":79,"column":6},"end":{"line":81,"column":null}},"14":{"start":{"line":80,"column":8},"end":{"line":80,"column":null}},"15":{"start":{"line":82,"column":6},"end":{"line":82,"column":null}},"16":{"start":{"line":92,"column":17},"end":{"line":92,"column":null}},"17":{"start":{"line":93,"column":4},"end":{"line":95,"column":null}},"18":{"start":{"line":94,"column":6},"end":{"line":94,"column":null}},"19":{"start":{"line":97,"column":23},"end":{"line":97,"column":null}},"20":{"start":{"line":98,"column":23},"end":{"line":98,"column":null}},"21":{"start":{"line":99,"column":23},"end":{"line":99,"column":null}},"22":{"start":{"line":101,"column":4},"end":{"line":112,"column":null}},"23":{"start":{"line":102,"column":25},"end":{"line":102,"column":null}},"24":{"start":{"line":103,"column":6},"end":{"line":111,"column":null}},"25":{"start":{"line":104,"column":22},"end":{"line":104,"column":null}},"26":{"start":{"line":105,"column":8},"end":{"line":108,"column":null}},"27":{"start":{"line":106,"column":10},"end":{"line":106,"column":null}},"28":{"start":{"line":107,"column":10},"end":{"line":107,"column":null}},"29":{"start":{"line":114,"column":4},"end":{"line":114,"column":null}},"30":{"start":{"line":121,"column":4},"end":{"line":121,"column":null}}},"fnMap":{"0":{"name":"(anonymous_0)","decl":{"start":{"line":28,"column":2},"end":{"line":28,"column":14}},"loc":{"start":{"line":28,"column":43},"end":{"line":31,"column":null}},"line":28},"1":{"name":"(anonymous_1)","decl":{"start":{"line":37,"column":8},"end":{"line":37,"column":38}},"loc":{"start":{"line":37,"column":38},"end":{"line":39,"column":null}},"line":37},"2":{"name":"(anonymous_2)","decl":{"start":{"line":45,"column":8},"end":{"line":45,"column":25}},"loc":{"start":{"line":45,"column":59},"end":{"line":48,"column":null}},"line":45},"3":{"name":"(anonymous_3)","decl":{"start":{"line":54,"column":2},"end":{"line":54,"column":16}},"loc":{"start":{"line":54,"column":43},"end":{"line":56,"column":null}},"line":54},"4":{"name":"(anonymous_4)","decl":{"start":{"line":63,"column":2},"end":{"line":63,"column":13}},"loc":{"start":{"line":63,"column":59},"end":{"line":65,"column":null}},"line":63},"5":{"name":"(anonymous_5)","decl":{"start":{"line":71,"column":8},"end":{"line":71,"column":38}},"loc":{"start":{"line":71,"column":38},"end":{"line":84,"column":null}},"line":71},"6":{"name":"(anonymous_6)","decl":{"start":{"line":75,"column":16},"end":{"line":75,"column":17}},"loc":{"start":{"line":75,"column":27},"end":{"line":75,"column":46}},"line":75},"7":{"name":"(anonymous_7)","decl":{"start":{"line":76,"column":13},"end":{"line":76,"column":14}},"loc":{"start":{"line":76,"column":24},"end":{"line":76,"column":34}},"line":76},"8":{"name":"(anonymous_8)","decl":{"start":{"line":91,"column":8},"end":{"line":91,"column":21}},"loc":{"start":{"line":91,"column":59},"end":{"line":115,"column":null}},"line":91},"9":{"name":"(anonymous_9)","decl":{"start":{"line":120,"column":2},"end":{"line":120,"column":23}},"loc":{"start":{"line":120,"column":23},"end":{"line":122,"column":null}},"line":120}},"branchMap":{"0":{"loc":{"start":{"line":29,"column":19},"end":{"line":29,"column":null}},"type":"binary-expr","locations":[{"start":{"line":29,"column":19},"end":{"line":29,"column":38}},{"start":{"line":29,"column":38},"end":{"line":29,"column":null}}],"line":29},"1":{"loc":{"start":{"line":79,"column":6},"end":{"line":81,"column":null}},"type":"if","locations":[{"start":{"line":79,"column":6},"end":{"line":81,"column":null}},{"start":{},"end":{}}],"line":79},"2":{"loc":{"start":{"line":92,"column":17},"end":{"line":92,"column":null}},"type":"binary-expr","locations":[{"start":{"line":92,"column":17},"end":{"line":92,"column":31}},{"start":{"line":92,"column":31},"end":{"line":92,"column":null}}],"line":92},"3":{"loc":{"start":{"line":93,"column":4},"end":{"line":95,"column":null}},"type":"if","locations":[{"start":{"line":93,"column":4},"end":{"line":95,"column":null}},{"start":{},"end":{}}],"line":93},"4":{"loc":{"start":{"line":105,"column":8},"end":{"line":108,"column":null}},"type":"if","locations":[{"start":{"line":105,"column":8},"end":{"line":108,"column":null}},{"start":{},"end":{}}],"line":105}},"s":{"0":11,"1":47,"2":47,"3":2,"4":24,"5":24,"6":30,"7":58,"8":8,"9":8,"10":6,"11":9,"12":8,"13":2,"14":2,"15":0,"16":5,"17":5,"18":1,"19":4,"20":4,"21":4,"22":4,"23":4,"24":4,"25":4,"26":4,"27":2,"28":2,"29":4,"30":3},"f":{"0":47,"1":2,"2":24,"3":30,"4":58,"5":8,"6":9,"7":8,"8":5,"9":3},"b":{"0":[47,2],"1":[2,0],"2":[5,4],"3":[1,4],"4":[2,2]},"meta":{"lastBranch":5,"lastFunction":10,"lastStatement":31,"seen":{"s:15:6:15:Infinity":0,"f:28:2:28:14":0,"s:29:4:29:Infinity":1,"b:29:19:29:38:29:38:29:Infinity":0,"s:30:4:30:Infinity":2,"f:37:8:37:38":1,"s:38:4:38:Infinity":3,"f:45:8:45:25":2,"s:46:23:46:Infinity":4,"s:47:4:47:Infinity":5,"f:54:2:54:16":3,"s:55:4:55:Infinity":6,"f:63:2:63:13":4,"s:64:4:64:Infinity":7,"f:71:8:71:38":5,"s:72:4:83:Infinity":8,"s:73:22:73:Infinity":9,"s:74:6:76:Infinity":10,"f:75:16:75:17":6,"s:75:27:75:46":11,"f:76:13:76:14":7,"s:76:24:76:34":12,"b:79:6:81:Infinity:undefined:undefined:undefined:undefined":1,"s:79:6:81:Infinity":13,"s:80:8:80:Infinity":14,"s:82:6:82:Infinity":15,"f:91:8:91:21":8,"s:92:17:92:Infinity":16,"b:92:17:92:31:92:31:92:Infinity":2,"b:93:4:95:Infinity:undefined:undefined:undefined:undefined":3,"s:93:4:95:Infinity":17,"s:94:6:94:Infinity":18,"s:97:23:97:Infinity":19,"s:98:23:98:Infinity":20,"s:99:23:99:Infinity":21,"s:101:4:112:Infinity":22,"s:102:25:102:Infinity":23,"s:103:6:111:Infinity":24,"s:104:22:104:Infinity":25,"b:105:8:108:Infinity:undefined:undefined:undefined:undefined":4,"s:105:8:108:Infinity":26,"s:106:10:106:Infinity":27,"s:107:10:107:Infinity":28,"s:114:4:114:Infinity":29,"f:120:2:120:23":9,"s:121:4:121:Infinity":30}}} +,"/Users/lukasmay/development/projects/codewalk-district/src/logging/writer.ts": {"path":"/Users/lukasmay/development/projects/codewalk-district/src/logging/writer.ts","statementMap":{"0":{"start":{"line":17,"column":14},"end":{"line":17,"column":null}},"1":{"start":{"line":17,"column":36},"end":{"line":17,"column":null}},"2":{"start":{"line":18,"column":15},"end":{"line":18,"column":null}},"3":{"start":{"line":19,"column":16},"end":{"line":19,"column":null}},"4":{"start":{"line":20,"column":14},"end":{"line":20,"column":null}},"5":{"start":{"line":21,"column":16},"end":{"line":21,"column":null}},"6":{"start":{"line":22,"column":18},"end":{"line":22,"column":null}},"7":{"start":{"line":23,"column":18},"end":{"line":23,"column":null}},"8":{"start":{"line":24,"column":13},"end":{"line":24,"column":null}},"9":{"start":{"line":25,"column":2},"end":{"line":25,"column":null}},"10":{"start":{"line":38,"column":45},"end":{"line":38,"column":null}},"11":{"start":{"line":39,"column":45},"end":{"line":39,"column":null}},"12":{"start":{"line":48,"column":4},"end":{"line":48,"column":null}},"13":{"start":{"line":49,"column":4},"end":{"line":49,"column":null}},"14":{"start":{"line":50,"column":4},"end":{"line":50,"column":null}},"15":{"start":{"line":59,"column":4},"end":{"line":59,"column":null}},"16":{"start":{"line":62,"column":23},"end":{"line":62,"column":null}},"17":{"start":{"line":63,"column":23},"end":{"line":63,"column":null}},"18":{"start":{"line":65,"column":4},"end":{"line":65,"column":null}},"19":{"start":{"line":66,"column":4},"end":{"line":66,"column":null}},"20":{"start":{"line":69,"column":4},"end":{"line":78,"column":null}},"21":{"start":{"line":71,"column":8},"end":{"line":71,"column":null}},"22":{"start":{"line":71,"column":46},"end":{"line":71,"column":55}},"23":{"start":{"line":72,"column":8},"end":{"line":72,"column":null}},"24":{"start":{"line":75,"column":8},"end":{"line":75,"column":null}},"25":{"start":{"line":75,"column":46},"end":{"line":75,"column":55}},"26":{"start":{"line":76,"column":8},"end":{"line":76,"column":null}},"27":{"start":{"line":88,"column":4},"end":{"line":90,"column":null}},"28":{"start":{"line":89,"column":6},"end":{"line":89,"column":null}},"29":{"start":{"line":91,"column":4},"end":{"line":91,"column":null}},"30":{"start":{"line":94,"column":4},"end":{"line":106,"column":null}},"31":{"start":{"line":95,"column":22},"end":{"line":95,"column":null}},"32":{"start":{"line":96,"column":35},"end":{"line":104,"column":null}},"33":{"start":{"line":105,"column":6},"end":{"line":105,"column":null}},"34":{"start":{"line":116,"column":4},"end":{"line":118,"column":null}},"35":{"start":{"line":117,"column":6},"end":{"line":117,"column":null}},"36":{"start":{"line":119,"column":4},"end":{"line":119,"column":null}},"37":{"start":{"line":122,"column":4},"end":{"line":134,"column":null}},"38":{"start":{"line":123,"column":22},"end":{"line":123,"column":null}},"39":{"start":{"line":124,"column":35},"end":{"line":132,"column":null}},"40":{"start":{"line":133,"column":6},"end":{"line":133,"column":null}},"41":{"start":{"line":144,"column":20},"end":{"line":144,"column":null}},"42":{"start":{"line":145,"column":22},"end":{"line":145,"column":null}},"43":{"start":{"line":148,"column":18},"end":{"line":148,"column":null}},"44":{"start":{"line":149,"column":29},"end":{"line":157,"column":null}},"45":{"start":{"line":152,"column":8},"end":{"line":154,"column":null}},"46":{"start":{"line":153,"column":10},"end":{"line":153,"column":null}},"47":{"start":{"line":155,"column":8},"end":{"line":155,"column":null}},"48":{"start":{"line":160,"column":21},"end":{"line":160,"column":null}},"49":{"start":{"line":161,"column":4},"end":{"line":166,"column":null}},"50":{"start":{"line":163,"column":6},"end":{"line":165,"column":null}},"51":{"start":{"line":164,"column":8},"end":{"line":164,"column":null}},"52":{"start":{"line":173,"column":43},"end":{"line":173,"column":null}},"53":{"start":{"line":175,"column":4},"end":{"line":185,"column":null}},"54":{"start":{"line":176,"column":6},"end":{"line":184,"column":null}},"55":{"start":{"line":178,"column":10},"end":{"line":181,"column":null}},"56":{"start":{"line":179,"column":12},"end":{"line":179,"column":null}},"57":{"start":{"line":180,"column":12},"end":{"line":180,"column":null}},"58":{"start":{"line":182,"column":10},"end":{"line":182,"column":null}},"59":{"start":{"line":187,"column":4},"end":{"line":197,"column":null}},"60":{"start":{"line":188,"column":6},"end":{"line":196,"column":null}},"61":{"start":{"line":190,"column":10},"end":{"line":193,"column":null}},"62":{"start":{"line":191,"column":12},"end":{"line":191,"column":null}},"63":{"start":{"line":192,"column":12},"end":{"line":192,"column":null}},"64":{"start":{"line":194,"column":10},"end":{"line":194,"column":null}},"65":{"start":{"line":199,"column":4},"end":{"line":199,"column":null}},"66":{"start":{"line":207,"column":4},"end":{"line":207,"column":null}},"67":{"start":{"line":215,"column":4},"end":{"line":215,"column":null}},"68":{"start":{"line":222,"column":4},"end":{"line":222,"column":null}}},"fnMap":{"0":{"name":"formatTimestamp","decl":{"start":{"line":16,"column":9},"end":{"line":16,"column":25}},"loc":{"start":{"line":16,"column":45},"end":{"line":26,"column":null}},"line":16},"1":{"name":"(anonymous_1)","decl":{"start":{"line":17,"column":14},"end":{"line":17,"column":15}},"loc":{"start":{"line":17,"column":36},"end":{"line":17,"column":null}},"line":17},"2":{"name":"(anonymous_2)","decl":{"start":{"line":47,"column":2},"end":{"line":47,"column":14}},"loc":{"start":{"line":47,"column":78},"end":{"line":51,"column":null}},"line":47},"3":{"name":"(anonymous_3)","decl":{"start":{"line":57,"column":8},"end":{"line":57,"column":30}},"loc":{"start":{"line":57,"column":30},"end":{"line":79,"column":null}},"line":57},"4":{"name":"(anonymous_4)","decl":{"start":{"line":70,"column":24},"end":{"line":70,"column":25}},"loc":{"start":{"line":70,"column":45},"end":{"line":73,"column":7}},"line":70},"5":{"name":"(anonymous_5)","decl":{"start":{"line":71,"column":40},"end":{"line":71,"column":46}},"loc":{"start":{"line":71,"column":46},"end":{"line":71,"column":55}},"line":71},"6":{"name":"(anonymous_6)","decl":{"start":{"line":74,"column":24},"end":{"line":74,"column":25}},"loc":{"start":{"line":74,"column":45},"end":{"line":77,"column":7}},"line":74},"7":{"name":"(anonymous_7)","decl":{"start":{"line":75,"column":40},"end":{"line":75,"column":46}},"loc":{"start":{"line":75,"column":46},"end":{"line":75,"column":55}},"line":75},"8":{"name":"(anonymous_8)","decl":{"start":{"line":87,"column":8},"end":{"line":87,"column":20}},"loc":{"start":{"line":87,"column":58},"end":{"line":107,"column":null}},"line":87},"9":{"name":"(anonymous_9)","decl":{"start":{"line":115,"column":8},"end":{"line":115,"column":20}},"loc":{"start":{"line":115,"column":58},"end":{"line":135,"column":null}},"line":115},"10":{"name":"(anonymous_10)","decl":{"start":{"line":140,"column":16},"end":{"line":140,"column":null}},"loc":{"start":{"line":143,"column":19},"end":{"line":167,"column":null}},"line":143},"11":{"name":"(anonymous_11)","decl":{"start":{"line":150,"column":11},"end":{"line":150,"column":12}},"loc":{"start":{"line":150,"column":28},"end":{"line":156,"column":7}},"line":150},"12":{"name":"(anonymous_12)","decl":{"start":{"line":163,"column":30},"end":{"line":163,"column":31}},"loc":{"start":{"line":163,"column":43},"end":{"line":165,"column":7}},"line":163},"13":{"name":"(anonymous_13)","decl":{"start":{"line":172,"column":8},"end":{"line":172,"column":31}},"loc":{"start":{"line":172,"column":31},"end":{"line":200,"column":null}},"line":172},"14":{"name":"(anonymous_14)","decl":{"start":{"line":177,"column":26},"end":{"line":177,"column":27}},"loc":{"start":{"line":177,"column":47},"end":{"line":183,"column":9}},"line":177},"15":{"name":"(anonymous_15)","decl":{"start":{"line":178,"column":33},"end":{"line":178,"column":39}},"loc":{"start":{"line":178,"column":39},"end":{"line":181,"column":11}},"line":178},"16":{"name":"(anonymous_16)","decl":{"start":{"line":189,"column":26},"end":{"line":189,"column":27}},"loc":{"start":{"line":189,"column":47},"end":{"line":195,"column":9}},"line":189},"17":{"name":"(anonymous_17)","decl":{"start":{"line":190,"column":33},"end":{"line":190,"column":39}},"loc":{"start":{"line":190,"column":39},"end":{"line":193,"column":11}},"line":190},"18":{"name":"(anonymous_18)","decl":{"start":{"line":206,"column":2},"end":{"line":206,"column":40}},"loc":{"start":{"line":206,"column":40},"end":{"line":208,"column":null}},"line":206},"19":{"name":"(anonymous_19)","decl":{"start":{"line":214,"column":2},"end":{"line":214,"column":40}},"loc":{"start":{"line":214,"column":40},"end":{"line":216,"column":null}},"line":214},"20":{"name":"(anonymous_20)","decl":{"start":{"line":221,"column":2},"end":{"line":221,"column":25}},"loc":{"start":{"line":221,"column":25},"end":{"line":223,"column":null}},"line":221}},"branchMap":{"0":{"loc":{"start":{"line":17,"column":26},"end":{"line":17,"column":36}},"type":"default-arg","locations":[{"start":{"line":17,"column":30},"end":{"line":17,"column":36}}],"line":17},"1":{"loc":{"start":{"line":88,"column":4},"end":{"line":90,"column":null}},"type":"if","locations":[{"start":{"line":88,"column":4},"end":{"line":90,"column":null}},{"start":{},"end":{}}],"line":88},"2":{"loc":{"start":{"line":94,"column":4},"end":{"line":106,"column":null}},"type":"if","locations":[{"start":{"line":94,"column":4},"end":{"line":106,"column":null}},{"start":{},"end":{}}],"line":94},"3":{"loc":{"start":{"line":95,"column":22},"end":{"line":95,"column":null}},"type":"cond-expr","locations":[{"start":{"line":95,"column":49},"end":{"line":95,"column":56}},{"start":{"line":95,"column":56},"end":{"line":95,"column":null}}],"line":95},"4":{"loc":{"start":{"line":116,"column":4},"end":{"line":118,"column":null}},"type":"if","locations":[{"start":{"line":116,"column":4},"end":{"line":118,"column":null}},{"start":{},"end":{}}],"line":116},"5":{"loc":{"start":{"line":122,"column":4},"end":{"line":134,"column":null}},"type":"if","locations":[{"start":{"line":122,"column":4},"end":{"line":134,"column":null}},{"start":{},"end":{}}],"line":122},"6":{"loc":{"start":{"line":123,"column":22},"end":{"line":123,"column":null}},"type":"cond-expr","locations":[{"start":{"line":123,"column":49},"end":{"line":123,"column":56}},{"start":{"line":123,"column":56},"end":{"line":123,"column":null}}],"line":123},"7":{"loc":{"start":{"line":144,"column":20},"end":{"line":144,"column":null}},"type":"cond-expr","locations":[{"start":{"line":144,"column":47},"end":{"line":144,"column":54}},{"start":{"line":144,"column":54},"end":{"line":144,"column":null}}],"line":144},"8":{"loc":{"start":{"line":152,"column":8},"end":{"line":154,"column":null}},"type":"if","locations":[{"start":{"line":152,"column":8},"end":{"line":154,"column":null}},{"start":{},"end":{}}],"line":152},"9":{"loc":{"start":{"line":152,"column":12},"end":{"line":152,"column":55}},"type":"binary-expr","locations":[{"start":{"line":152,"column":12},"end":{"line":152,"column":42}},{"start":{"line":152,"column":42},"end":{"line":152,"column":55}}],"line":152},"10":{"loc":{"start":{"line":161,"column":4},"end":{"line":166,"column":null}},"type":"if","locations":[{"start":{"line":161,"column":4},"end":{"line":166,"column":null}},{"start":{},"end":{}}],"line":161},"11":{"loc":{"start":{"line":175,"column":4},"end":{"line":185,"column":null}},"type":"if","locations":[{"start":{"line":175,"column":4},"end":{"line":185,"column":null}},{"start":{},"end":{}}],"line":175},"12":{"loc":{"start":{"line":187,"column":4},"end":{"line":197,"column":null}},"type":"if","locations":[{"start":{"line":187,"column":4},"end":{"line":197,"column":null}},{"start":{},"end":{}}],"line":187}},"s":{"0":19,"1":114,"2":19,"3":19,"4":19,"5":19,"6":19,"7":19,"8":19,"9":19,"10":27,"11":27,"12":27,"13":27,"14":27,"15":22,"16":22,"17":22,"18":22,"19":22,"20":22,"21":22,"22":22,"23":22,"24":22,"25":22,"26":22,"27":15,"28":2,"29":13,"30":13,"31":4,"32":4,"33":4,"34":8,"35":2,"36":6,"37":6,"38":2,"39":2,"40":2,"41":19,"42":19,"43":19,"44":19,"45":40,"46":19,"47":21,"48":19,"49":19,"50":0,"51":0,"52":40,"53":40,"54":22,"55":22,"56":22,"57":22,"58":22,"59":40,"60":22,"61":22,"62":22,"63":22,"64":22,"65":40,"66":3,"67":3,"68":1},"f":{"0":19,"1":114,"2":27,"3":22,"4":22,"5":22,"6":22,"7":22,"8":15,"9":8,"10":19,"11":40,"12":0,"13":40,"14":22,"15":22,"16":22,"17":22,"18":3,"19":3,"20":1},"b":{"0":[114],"1":[2,13],"2":[4,9],"3":[3,1],"4":[2,6],"5":[2,4],"6":[2,0],"7":[16,3],"8":[19,21],"9":[40,19],"10":[0,19],"11":[22,18],"12":[22,18]},"meta":{"lastBranch":13,"lastFunction":21,"lastStatement":69,"seen":{"f:16:9:16:25":0,"s:17:14:17:Infinity":0,"f:17:14:17:15":1,"s:17:36:17:Infinity":1,"b:17:30:17:36":0,"s:18:15:18:Infinity":2,"s:19:16:19:Infinity":3,"s:20:14:20:Infinity":4,"s:21:16:21:Infinity":5,"s:22:18:22:Infinity":6,"s:23:18:23:Infinity":7,"s:24:13:24:Infinity":8,"s:25:2:25:Infinity":9,"s:38:45:38:Infinity":10,"s:39:45:39:Infinity":11,"f:47:2:47:14":2,"s:48:4:48:Infinity":12,"s:49:4:49:Infinity":13,"s:50:4:50:Infinity":14,"f:57:8:57:30":3,"s:59:4:59:Infinity":15,"s:62:23:62:Infinity":16,"s:63:23:63:Infinity":17,"s:65:4:65:Infinity":18,"s:66:4:66:Infinity":19,"s:69:4:78:Infinity":20,"f:70:24:70:25":4,"s:71:8:71:Infinity":21,"f:71:40:71:46":5,"s:71:46:71:55":22,"s:72:8:72:Infinity":23,"f:74:24:74:25":6,"s:75:8:75:Infinity":24,"f:75:40:75:46":7,"s:75:46:75:55":25,"s:76:8:76:Infinity":26,"f:87:8:87:20":8,"b:88:4:90:Infinity:undefined:undefined:undefined:undefined":1,"s:88:4:90:Infinity":27,"s:89:6:89:Infinity":28,"s:91:4:91:Infinity":29,"b:94:4:106:Infinity:undefined:undefined:undefined:undefined":2,"s:94:4:106:Infinity":30,"s:95:22:95:Infinity":31,"b:95:49:95:56:95:56:95:Infinity":3,"s:96:35:104:Infinity":32,"s:105:6:105:Infinity":33,"f:115:8:115:20":9,"b:116:4:118:Infinity:undefined:undefined:undefined:undefined":4,"s:116:4:118:Infinity":34,"s:117:6:117:Infinity":35,"s:119:4:119:Infinity":36,"b:122:4:134:Infinity:undefined:undefined:undefined:undefined":5,"s:122:4:134:Infinity":37,"s:123:22:123:Infinity":38,"b:123:49:123:56:123:56:123:Infinity":6,"s:124:35:132:Infinity":39,"s:133:6:133:Infinity":40,"f:140:16:140:Infinity":10,"s:144:20:144:Infinity":41,"b:144:47:144:54:144:54:144:Infinity":7,"s:145:22:145:Infinity":42,"s:148:18:148:Infinity":43,"s:149:29:157:Infinity":44,"f:150:11:150:12":11,"b:152:8:154:Infinity:undefined:undefined:undefined:undefined":8,"s:152:8:154:Infinity":45,"b:152:12:152:42:152:42:152:55":9,"s:153:10:153:Infinity":46,"s:155:8:155:Infinity":47,"s:160:21:160:Infinity":48,"b:161:4:166:Infinity:undefined:undefined:undefined:undefined":10,"s:161:4:166:Infinity":49,"s:163:6:165:Infinity":50,"f:163:30:163:31":12,"s:164:8:164:Infinity":51,"f:172:8:172:31":13,"s:173:43:173:Infinity":52,"b:175:4:185:Infinity:undefined:undefined:undefined:undefined":11,"s:175:4:185:Infinity":53,"s:176:6:184:Infinity":54,"f:177:26:177:27":14,"s:178:10:181:Infinity":55,"f:178:33:178:39":15,"s:179:12:179:Infinity":56,"s:180:12:180:Infinity":57,"s:182:10:182:Infinity":58,"b:187:4:197:Infinity:undefined:undefined:undefined:undefined":12,"s:187:4:197:Infinity":59,"s:188:6:196:Infinity":60,"f:189:26:189:27":16,"s:190:10:193:Infinity":61,"f:190:33:190:39":17,"s:191:12:191:Infinity":62,"s:192:12:192:Infinity":63,"s:194:10:194:Infinity":64,"s:199:4:199:Infinity":65,"f:206:2:206:40":18,"s:207:4:207:Infinity":66,"f:214:2:214:40":19,"s:215:4:215:Infinity":67,"f:221:2:221:25":20,"s:222:4:222:Infinity":68}}} +,"/Users/lukasmay/development/projects/codewalk-district/src/preview/compose-generator.ts": {"path":"/Users/lukasmay/development/projects/codewalk-district/src/preview/compose-generator.ts","statementMap":{"0":{"start":{"line":46,"column":31},"end":{"line":51,"column":null}},"1":{"start":{"line":53,"column":33},"end":{"line":53,"column":null}},"2":{"start":{"line":56,"column":2},"end":{"line":93,"column":null}},"3":{"start":{"line":57,"column":4},"end":{"line":57,"column":null}},"4":{"start":{"line":58,"column":36},"end":{"line":61,"column":null}},"5":{"start":{"line":64,"column":4},"end":{"line":80,"column":null}},"6":{"start":{"line":65,"column":6},"end":{"line":77,"column":null}},"7":{"start":{"line":66,"column":8},"end":{"line":69,"column":null}},"8":{"start":{"line":71,"column":8},"end":{"line":76,"column":null}},"9":{"start":{"line":78,"column":4},"end":{"line":80,"column":null}},"10":{"start":{"line":79,"column":6},"end":{"line":79,"column":null}},"11":{"start":{"line":83,"column":4},"end":{"line":85,"column":null}},"12":{"start":{"line":84,"column":6},"end":{"line":84,"column":null}},"13":{"start":{"line":88,"column":4},"end":{"line":90,"column":null}},"14":{"start":{"line":89,"column":6},"end":{"line":89,"column":null}},"15":{"start":{"line":92,"column":4},"end":{"line":92,"column":null}},"16":{"start":{"line":96,"column":20},"end":{"line":96,"column":null}},"17":{"start":{"line":97,"column":39},"end":{"line":101,"column":null}},"18":{"start":{"line":104,"column":3},"end":{"line":104,"column":null}},"19":{"start":{"line":107,"column":3},"end":{"line":107,"column":null}},"20":{"start":{"line":110,"column":3},"end":{"line":110,"column":null}},"21":{"start":{"line":112,"column":2},"end":{"line":114,"column":null}},"22":{"start":{"line":113,"column":4},"end":{"line":113,"column":null}},"23":{"start":{"line":116,"column":2},"end":{"line":116,"column":null}},"24":{"start":{"line":118,"column":2},"end":{"line":118,"column":null}},"25":{"start":{"line":128,"column":71},"end":{"line":128,"column":null}},"26":{"start":{"line":130,"column":2},"end":{"line":137,"column":null}},"27":{"start":{"line":131,"column":4},"end":{"line":131,"column":null}},"28":{"start":{"line":131,"column":22},"end":{"line":131,"column":null}},"29":{"start":{"line":132,"column":4},"end":{"line":136,"column":null}},"30":{"start":{"line":140,"column":2},"end":{"line":144,"column":null}},"31":{"start":{"line":141,"column":4},"end":{"line":141,"column":null}},"32":{"start":{"line":141,"column":25},"end":{"line":141,"column":null}},"33":{"start":{"line":142,"column":4},"end":{"line":142,"column":null}},"34":{"start":{"line":142,"column":25},"end":{"line":142,"column":null}},"35":{"start":{"line":143,"column":4},"end":{"line":143,"column":null}},"36":{"start":{"line":146,"column":26},"end":{"line":146,"column":null}},"37":{"start":{"line":148,"column":2},"end":{"line":160,"column":null}},"38":{"start":{"line":149,"column":4},"end":{"line":159,"column":null}},"39":{"start":{"line":150,"column":6},"end":{"line":150,"column":null}},"40":{"start":{"line":151,"column":6},"end":{"line":151,"column":null}},"41":{"start":{"line":152,"column":6},"end":{"line":152,"column":null}},"42":{"start":{"line":155,"column":19},"end":{"line":155,"column":null}},"43":{"start":{"line":156,"column":6},"end":{"line":156,"column":null}},"44":{"start":{"line":157,"column":6},"end":{"line":157,"column":null}},"45":{"start":{"line":158,"column":6},"end":{"line":158,"column":null}},"46":{"start":{"line":162,"column":2},"end":{"line":162,"column":null}},"47":{"start":{"line":163,"column":2},"end":{"line":163,"column":null}},"48":{"start":{"line":177,"column":41},"end":{"line":184,"column":null}},"49":{"start":{"line":186,"column":2},"end":{"line":188,"column":null}},"50":{"start":{"line":187,"column":4},"end":{"line":187,"column":null}},"51":{"start":{"line":190,"column":2},"end":{"line":190,"column":null}}},"fnMap":{"0":{"name":"generateComposeFile","decl":{"start":{"line":42,"column":16},"end":{"line":42,"column":null}},"loc":{"start":{"line":45,"column":10},"end":{"line":119,"column":null}},"line":45},"1":{"name":"generateCaddyfile","decl":{"start":{"line":127,"column":16},"end":{"line":127,"column":34}},"loc":{"start":{"line":127,"column":65},"end":{"line":164,"column":null}},"line":127},"2":{"name":"(anonymous_2)","decl":{"start":{"line":140,"column":14},"end":{"line":140,"column":15}},"loc":{"start":{"line":140,"column":24},"end":{"line":144,"column":3}},"line":140},"3":{"name":"generateLabels","decl":{"start":{"line":169,"column":16},"end":{"line":169,"column":31}},"loc":{"start":{"line":176,"column":27},"end":{"line":191,"column":null}},"line":176}},"branchMap":{"0":{"loc":{"start":{"line":64,"column":4},"end":{"line":80,"column":null}},"type":"if","locations":[{"start":{"line":64,"column":4},"end":{"line":80,"column":null}},{"start":{"line":78,"column":4},"end":{"line":80,"column":null}}],"line":64},"1":{"loc":{"start":{"line":65,"column":6},"end":{"line":77,"column":null}},"type":"if","locations":[{"start":{"line":65,"column":6},"end":{"line":77,"column":null}},{"start":{"line":70,"column":13},"end":{"line":77,"column":null}}],"line":65},"2":{"loc":{"start":{"line":68,"column":22},"end":{"line":68,"column":null}},"type":"cond-expr","locations":[{"start":{"line":68,"column":42},"end":{"line":68,"column":57}},{"start":{"line":68,"column":57},"end":{"line":68,"column":null}}],"line":68},"3":{"loc":{"start":{"line":72,"column":19},"end":{"line":74,"column":null}},"type":"cond-expr","locations":[{"start":{"line":73,"column":14},"end":{"line":73,"column":null}},{"start":{"line":74,"column":14},"end":{"line":74,"column":null}}],"line":72},"4":{"loc":{"start":{"line":78,"column":4},"end":{"line":80,"column":null}},"type":"if","locations":[{"start":{"line":78,"column":4},"end":{"line":80,"column":null}},{"start":{},"end":{}}],"line":78},"5":{"loc":{"start":{"line":83,"column":4},"end":{"line":85,"column":null}},"type":"if","locations":[{"start":{"line":83,"column":4},"end":{"line":85,"column":null}},{"start":{},"end":{}}],"line":83},"6":{"loc":{"start":{"line":83,"column":8},"end":{"line":83,"column":52}},"type":"binary-expr","locations":[{"start":{"line":83,"column":8},"end":{"line":83,"column":19}},{"start":{"line":83,"column":19},"end":{"line":83,"column":52}}],"line":83},"7":{"loc":{"start":{"line":88,"column":4},"end":{"line":90,"column":null}},"type":"if","locations":[{"start":{"line":88,"column":4},"end":{"line":90,"column":null}},{"start":{},"end":{}}],"line":88},"8":{"loc":{"start":{"line":88,"column":8},"end":{"line":88,"column":47}},"type":"binary-expr","locations":[{"start":{"line":88,"column":8},"end":{"line":88,"column":23}},{"start":{"line":88,"column":23},"end":{"line":88,"column":47}}],"line":88},"9":{"loc":{"start":{"line":112,"column":2},"end":{"line":114,"column":null}},"type":"if","locations":[{"start":{"line":112,"column":2},"end":{"line":114,"column":null}},{"start":{},"end":{}}],"line":112},"10":{"loc":{"start":{"line":131,"column":4},"end":{"line":131,"column":null}},"type":"if","locations":[{"start":{"line":131,"column":4},"end":{"line":131,"column":null}},{"start":{},"end":{}}],"line":131},"11":{"loc":{"start":{"line":134,"column":13},"end":{"line":134,"column":null}},"type":"binary-expr","locations":[{"start":{"line":134,"column":13},"end":{"line":134,"column":26}},{"start":{"line":134,"column":26},"end":{"line":134,"column":null}}],"line":134},"12":{"loc":{"start":{"line":141,"column":4},"end":{"line":141,"column":null}},"type":"if","locations":[{"start":{"line":141,"column":4},"end":{"line":141,"column":null}},{"start":{},"end":{}}],"line":141},"13":{"loc":{"start":{"line":142,"column":4},"end":{"line":142,"column":null}},"type":"if","locations":[{"start":{"line":142,"column":4},"end":{"line":142,"column":null}},{"start":{},"end":{}}],"line":142},"14":{"loc":{"start":{"line":149,"column":4},"end":{"line":159,"column":null}},"type":"if","locations":[{"start":{"line":149,"column":4},"end":{"line":159,"column":null}},{"start":{"line":153,"column":11},"end":{"line":159,"column":null}}],"line":149},"15":{"loc":{"start":{"line":155,"column":19},"end":{"line":155,"column":null}},"type":"cond-expr","locations":[{"start":{"line":155,"column":47},"end":{"line":155,"column":74}},{"start":{"line":155,"column":74},"end":{"line":155,"column":null}}],"line":155},"16":{"loc":{"start":{"line":186,"column":2},"end":{"line":188,"column":null}},"type":"if","locations":[{"start":{"line":186,"column":2},"end":{"line":188,"column":null}},{"start":{},"end":{}}],"line":186}},"s":{"0":9,"1":9,"2":9,"3":10,"4":10,"5":10,"6":9,"7":8,"8":1,"9":1,"10":1,"11":10,"12":1,"13":10,"14":0,"15":10,"16":9,"17":9,"18":9,"19":9,"20":9,"21":9,"22":9,"23":9,"24":9,"25":18,"26":18,"27":23,"28":2,"29":21,"30":18,"31":4,"32":1,"33":3,"34":2,"35":1,"36":18,"37":18,"38":21,"39":18,"40":18,"41":18,"42":3,"43":3,"44":3,"45":3,"46":18,"47":18,"48":7,"49":7,"50":2,"51":7},"f":{"0":9,"1":18,"2":4,"3":7},"b":{"0":[9,1],"1":[8,1],"2":[8,0],"3":[0,1],"4":[1,0],"5":[1,9],"6":[10,1],"7":[0,10],"8":[10,0],"9":[9,0],"10":[2,21],"11":[21,16],"12":[1,3],"13":[2,1],"14":[18,3],"15":[0,3],"16":[2,5]},"meta":{"lastBranch":17,"lastFunction":4,"lastStatement":52,"seen":{"f:42:16:42:Infinity":0,"s:46:31:51:Infinity":0,"s:53:33:53:Infinity":1,"s:56:2:93:Infinity":2,"s:57:4:57:Infinity":3,"s:58:36:61:Infinity":4,"b:64:4:80:Infinity:78:4:80:Infinity":0,"s:64:4:80:Infinity":5,"b:65:6:77:Infinity:70:13:77:Infinity":1,"s:65:6:77:Infinity":6,"s:66:8:69:Infinity":7,"b:68:42:68:57:68:57:68:Infinity":2,"s:71:8:76:Infinity":8,"b:73:14:73:Infinity:74:14:74:Infinity":3,"b:78:4:80:Infinity:undefined:undefined:undefined:undefined":4,"s:78:4:80:Infinity":9,"s:79:6:79:Infinity":10,"b:83:4:85:Infinity:undefined:undefined:undefined:undefined":5,"s:83:4:85:Infinity":11,"b:83:8:83:19:83:19:83:52":6,"s:84:6:84:Infinity":12,"b:88:4:90:Infinity:undefined:undefined:undefined:undefined":7,"s:88:4:90:Infinity":13,"b:88:8:88:23:88:23:88:47":8,"s:89:6:89:Infinity":14,"s:92:4:92:Infinity":15,"s:96:20:96:Infinity":16,"s:97:39:101:Infinity":17,"s:104:3:104:Infinity":18,"s:107:3:107:Infinity":19,"s:110:3:110:Infinity":20,"b:112:2:114:Infinity:undefined:undefined:undefined:undefined":9,"s:112:2:114:Infinity":21,"s:113:4:113:Infinity":22,"s:116:2:116:Infinity":23,"s:118:2:118:Infinity":24,"f:127:16:127:34":1,"s:128:71:128:Infinity":25,"s:130:2:137:Infinity":26,"b:131:4:131:Infinity:undefined:undefined:undefined:undefined":10,"s:131:4:131:Infinity":27,"s:131:22:131:Infinity":28,"s:132:4:136:Infinity":29,"b:134:13:134:26:134:26:134:Infinity":11,"s:140:2:144:Infinity":30,"f:140:14:140:15":2,"b:141:4:141:Infinity:undefined:undefined:undefined:undefined":12,"s:141:4:141:Infinity":31,"s:141:25:141:Infinity":32,"b:142:4:142:Infinity:undefined:undefined:undefined:undefined":13,"s:142:4:142:Infinity":33,"s:142:25:142:Infinity":34,"s:143:4:143:Infinity":35,"s:146:26:146:Infinity":36,"s:148:2:160:Infinity":37,"b:149:4:159:Infinity:153:11:159:Infinity":14,"s:149:4:159:Infinity":38,"s:150:6:150:Infinity":39,"s:151:6:151:Infinity":40,"s:152:6:152:Infinity":41,"s:155:19:155:Infinity":42,"b:155:47:155:74:155:74:155:Infinity":15,"s:156:6:156:Infinity":43,"s:157:6:157:Infinity":44,"s:158:6:158:Infinity":45,"s:162:2:162:Infinity":46,"s:163:2:163:Infinity":47,"f:169:16:169:31":3,"s:177:41:184:Infinity":48,"b:186:2:188:Infinity:undefined:undefined:undefined:undefined":16,"s:186:2:188:Infinity":49,"s:187:4:187:Infinity":50,"s:190:2:190:Infinity":51}}} +,"/Users/lukasmay/development/projects/codewalk-district/src/preview/config-reader.ts": {"path":"/Users/lukasmay/development/projects/codewalk-district/src/preview/config-reader.ts","statementMap":{"0":{"start":{"line":14,"column":6},"end":{"line":14,"column":null}},"1":{"start":{"line":17,"column":22},"end":{"line":22,"column":null}},"2":{"start":{"line":38,"column":8},"end":{"line":38,"column":null}},"3":{"start":{"line":39,"column":2},"end":{"line":43,"column":null}},"4":{"start":{"line":40,"column":4},"end":{"line":40,"column":null}},"5":{"start":{"line":41,"column":16},"end":{"line":41,"column":null}},"6":{"start":{"line":42,"column":4},"end":{"line":42,"column":null}},"7":{"start":{"line":46,"column":2},"end":{"line":52,"column":null}},"8":{"start":{"line":47,"column":10},"end":{"line":47,"column":null}},"9":{"start":{"line":48,"column":4},"end":{"line":51,"column":null}},"10":{"start":{"line":49,"column":6},"end":{"line":49,"column":null}},"11":{"start":{"line":50,"column":6},"end":{"line":50,"column":null}},"12":{"start":{"line":55,"column":8},"end":{"line":55,"column":null}},"13":{"start":{"line":56,"column":2},"end":{"line":59,"column":null}},"14":{"start":{"line":57,"column":4},"end":{"line":57,"column":null}},"15":{"start":{"line":58,"column":4},"end":{"line":58,"column":null}},"16":{"start":{"line":61,"column":2},"end":{"line":64,"column":null}},"17":{"start":{"line":71,"column":17},"end":{"line":71,"column":null}},"18":{"start":{"line":73,"column":2},"end":{"line":75,"column":null}},"19":{"start":{"line":74,"column":4},"end":{"line":74,"column":null}},"20":{"start":{"line":77,"column":2},"end":{"line":79,"column":null}},"21":{"start":{"line":78,"column":4},"end":{"line":78,"column":null}},"22":{"start":{"line":81,"column":57},"end":{"line":81,"column":null}},"23":{"start":{"line":82,"column":22},"end":{"line":82,"column":null}},"24":{"start":{"line":84,"column":2},"end":{"line":105,"column":null}},"25":{"start":{"line":85,"column":4},"end":{"line":87,"column":null}},"26":{"start":{"line":86,"column":6},"end":{"line":86,"column":null}},"27":{"start":{"line":89,"column":17},"end":{"line":89,"column":null}},"28":{"start":{"line":90,"column":4},"end":{"line":92,"column":null}},"29":{"start":{"line":91,"column":6},"end":{"line":91,"column":null}},"30":{"start":{"line":94,"column":4},"end":{"line":104,"column":null}},"31":{"start":{"line":107,"column":2},"end":{"line":110,"column":null}},"32":{"start":{"line":117,"column":2},"end":{"line":121,"column":null}},"33":{"start":{"line":128,"column":2},"end":{"line":137,"column":null}},"34":{"start":{"line":144,"column":2},"end":{"line":146,"column":null}},"35":{"start":{"line":145,"column":4},"end":{"line":145,"column":null}},"36":{"start":{"line":147,"column":2},"end":{"line":153,"column":null}},"37":{"start":{"line":148,"column":14},"end":{"line":148,"column":null}},"38":{"start":{"line":149,"column":4},"end":{"line":152,"column":null}},"39":{"start":{"line":154,"column":2},"end":{"line":154,"column":null}},"40":{"start":{"line":158,"column":2},"end":{"line":163,"column":null}},"41":{"start":{"line":159,"column":4},"end":{"line":159,"column":null}},"42":{"start":{"line":160,"column":4},"end":{"line":160,"column":null}},"43":{"start":{"line":162,"column":4},"end":{"line":162,"column":null}}},"fnMap":{"0":{"name":"discoverConfig","decl":{"start":{"line":36,"column":22},"end":{"line":36,"column":37}},"loc":{"start":{"line":36,"column":82},"end":{"line":65,"column":null}},"line":36},"1":{"name":"parseCwPreviewConfig","decl":{"start":{"line":70,"column":16},"end":{"line":70,"column":37}},"loc":{"start":{"line":70,"column":65},"end":{"line":111,"column":null}},"line":70},"2":{"name":"parseExistingCompose","decl":{"start":{"line":116,"column":9},"end":{"line":116,"column":30}},"loc":{"start":{"line":116,"column":87},"end":{"line":122,"column":null}},"line":116},"3":{"name":"createDockerfileFallback","decl":{"start":{"line":127,"column":9},"end":{"line":127,"column":51}},"loc":{"start":{"line":127,"column":51},"end":{"line":138,"column":null}},"line":127},"4":{"name":"normalizeBuild","decl":{"start":{"line":143,"column":9},"end":{"line":143,"column":24}},"loc":{"start":{"line":143,"column":71},"end":{"line":155,"column":null}},"line":143},"5":{"name":"fileExists","decl":{"start":{"line":157,"column":15},"end":{"line":157,"column":26}},"loc":{"start":{"line":157,"column":58},"end":{"line":164,"column":null}},"line":157}},"branchMap":{"0":{"loc":{"start":{"line":39,"column":2},"end":{"line":43,"column":null}},"type":"if","locations":[{"start":{"line":39,"column":2},"end":{"line":43,"column":null}},{"start":{},"end":{}}],"line":39},"1":{"loc":{"start":{"line":48,"column":4},"end":{"line":51,"column":null}},"type":"if","locations":[{"start":{"line":48,"column":4},"end":{"line":51,"column":null}},{"start":{},"end":{}}],"line":48},"2":{"loc":{"start":{"line":56,"column":2},"end":{"line":59,"column":null}},"type":"if","locations":[{"start":{"line":56,"column":2},"end":{"line":59,"column":null}},{"start":{},"end":{}}],"line":56},"3":{"loc":{"start":{"line":73,"column":2},"end":{"line":75,"column":null}},"type":"if","locations":[{"start":{"line":73,"column":2},"end":{"line":75,"column":null}},{"start":{},"end":{}}],"line":73},"4":{"loc":{"start":{"line":73,"column":6},"end":{"line":73,"column":45}},"type":"binary-expr","locations":[{"start":{"line":73,"column":6},"end":{"line":73,"column":17}},{"start":{"line":73,"column":17},"end":{"line":73,"column":45}}],"line":73},"5":{"loc":{"start":{"line":77,"column":2},"end":{"line":79,"column":null}},"type":"if","locations":[{"start":{"line":77,"column":2},"end":{"line":79,"column":null}},{"start":{},"end":{}}],"line":77},"6":{"loc":{"start":{"line":77,"column":6},"end":{"line":77,"column":63}},"type":"binary-expr","locations":[{"start":{"line":77,"column":6},"end":{"line":77,"column":26}},{"start":{"line":77,"column":26},"end":{"line":77,"column":63}}],"line":77},"7":{"loc":{"start":{"line":85,"column":4},"end":{"line":87,"column":null}},"type":"if","locations":[{"start":{"line":85,"column":4},"end":{"line":87,"column":null}},{"start":{},"end":{}}],"line":85},"8":{"loc":{"start":{"line":85,"column":8},"end":{"line":85,"column":41}},"type":"binary-expr","locations":[{"start":{"line":85,"column":8},"end":{"line":85,"column":16}},{"start":{"line":85,"column":16},"end":{"line":85,"column":41}}],"line":85},"9":{"loc":{"start":{"line":90,"column":4},"end":{"line":92,"column":null}},"type":"if","locations":[{"start":{"line":90,"column":4},"end":{"line":92,"column":null}},{"start":{},"end":{}}],"line":90},"10":{"loc":{"start":{"line":90,"column":8},"end":{"line":90,"column":45}},"type":"binary-expr","locations":[{"start":{"line":90,"column":8},"end":{"line":90,"column":30}},{"start":{"line":90,"column":30},"end":{"line":90,"column":45}}],"line":90},"11":{"loc":{"start":{"line":96,"column":12},"end":{"line":96,"column":null}},"type":"binary-expr","locations":[{"start":{"line":96,"column":12},"end":{"line":96,"column":20}},{"start":{"line":96,"column":20},"end":{"line":96,"column":null}}],"line":96},"12":{"loc":{"start":{"line":97,"column":10},"end":{"line":97,"column":null}},"type":"binary-expr","locations":[{"start":{"line":97,"column":10},"end":{"line":97,"column":37}},{"start":{"line":97,"column":37},"end":{"line":97,"column":null}}],"line":97},"13":{"loc":{"start":{"line":98,"column":10},"end":{"line":98,"column":null}},"type":"binary-expr","locations":[{"start":{"line":98,"column":10},"end":{"line":98,"column":37}},{"start":{"line":98,"column":37},"end":{"line":98,"column":null}}],"line":98},"14":{"loc":{"start":{"line":99,"column":10},"end":{"line":99,"column":null}},"type":"binary-expr","locations":[{"start":{"line":99,"column":10},"end":{"line":99,"column":37}},{"start":{"line":99,"column":37},"end":{"line":99,"column":null}}],"line":99},"15":{"loc":{"start":{"line":100,"column":10},"end":{"line":100,"column":null}},"type":"binary-expr","locations":[{"start":{"line":100,"column":10},"end":{"line":100,"column":40}},{"start":{"line":100,"column":40},"end":{"line":100,"column":null}}],"line":100},"16":{"loc":{"start":{"line":101,"column":10},"end":{"line":101,"column":null}},"type":"binary-expr","locations":[{"start":{"line":101,"column":10},"end":{"line":101,"column":43}},{"start":{"line":101,"column":43},"end":{"line":101,"column":null}}],"line":101},"17":{"loc":{"start":{"line":102,"column":10},"end":{"line":102,"column":null}},"type":"binary-expr","locations":[{"start":{"line":102,"column":10},"end":{"line":102,"column":35}},{"start":{"line":102,"column":35},"end":{"line":102,"column":null}}],"line":102},"18":{"loc":{"start":{"line":103,"column":10},"end":{"line":103,"column":null}},"type":"binary-expr","locations":[{"start":{"line":103,"column":10},"end":{"line":103,"column":39}},{"start":{"line":103,"column":39},"end":{"line":103,"column":null}}],"line":103},"19":{"loc":{"start":{"line":144,"column":2},"end":{"line":146,"column":null}},"type":"if","locations":[{"start":{"line":144,"column":2},"end":{"line":146,"column":null}},{"start":{},"end":{}}],"line":144},"20":{"loc":{"start":{"line":147,"column":2},"end":{"line":153,"column":null}},"type":"if","locations":[{"start":{"line":147,"column":2},"end":{"line":153,"column":null}},{"start":{},"end":{}}],"line":147},"21":{"loc":{"start":{"line":147,"column":6},"end":{"line":147,"column":51}},"type":"binary-expr","locations":[{"start":{"line":147,"column":6},"end":{"line":147,"column":35}},{"start":{"line":147,"column":35},"end":{"line":147,"column":51}}],"line":147},"22":{"loc":{"start":{"line":150,"column":16},"end":{"line":150,"column":null}},"type":"binary-expr","locations":[{"start":{"line":150,"column":16},"end":{"line":150,"column":40}},{"start":{"line":150,"column":40},"end":{"line":150,"column":null}}],"line":150},"23":{"loc":{"start":{"line":151,"column":19},"end":{"line":151,"column":null}},"type":"binary-expr","locations":[{"start":{"line":151,"column":19},"end":{"line":151,"column":46}},{"start":{"line":151,"column":46},"end":{"line":151,"column":null}}],"line":151}},"s":{"0":9,"1":9,"2":0,"3":0,"4":0,"5":0,"6":0,"7":0,"8":0,"9":0,"10":0,"11":0,"12":0,"13":0,"14":0,"15":0,"16":0,"17":6,"18":6,"19":0,"20":6,"21":1,"22":5,"23":5,"24":5,"25":7,"26":0,"27":7,"28":7,"29":1,"30":6,"31":4,"32":0,"33":0,"34":4,"35":2,"36":2,"37":2,"38":2,"39":0,"40":0,"41":0,"42":0,"43":0},"f":{"0":0,"1":6,"2":0,"3":0,"4":4,"5":0},"b":{"0":[0,0],"1":[0,0],"2":[0,0],"3":[0,6],"4":[6,6],"5":[1,5],"6":[6,5],"7":[0,7],"8":[7,7],"9":[1,6],"10":[7,2],"11":[6,1],"12":[7,4],"13":[7,2],"14":[7,2],"15":[7,2],"16":[7,2],"17":[7,3],"18":[7,0],"19":[2,2],"20":[2,0],"21":[2,2],"22":[2,0],"23":[2,0]},"meta":{"lastBranch":24,"lastFunction":6,"lastStatement":44,"seen":{"s:14:6:14:Infinity":0,"s:17:22:22:Infinity":1,"f:36:22:36:37":0,"s:38:8:38:Infinity":2,"b:39:2:43:Infinity:undefined:undefined:undefined:undefined":0,"s:39:2:43:Infinity":3,"s:40:4:40:Infinity":4,"s:41:16:41:Infinity":5,"s:42:4:42:Infinity":6,"s:46:2:52:Infinity":7,"s:47:10:47:Infinity":8,"b:48:4:51:Infinity:undefined:undefined:undefined:undefined":1,"s:48:4:51:Infinity":9,"s:49:6:49:Infinity":10,"s:50:6:50:Infinity":11,"s:55:8:55:Infinity":12,"b:56:2:59:Infinity:undefined:undefined:undefined:undefined":2,"s:56:2:59:Infinity":13,"s:57:4:57:Infinity":14,"s:58:4:58:Infinity":15,"s:61:2:64:Infinity":16,"f:70:16:70:37":1,"s:71:17:71:Infinity":17,"b:73:2:75:Infinity:undefined:undefined:undefined:undefined":3,"s:73:2:75:Infinity":18,"b:73:6:73:17:73:17:73:45":4,"s:74:4:74:Infinity":19,"b:77:2:79:Infinity:undefined:undefined:undefined:undefined":5,"s:77:2:79:Infinity":20,"b:77:6:77:26:77:26:77:63":6,"s:78:4:78:Infinity":21,"s:81:57:81:Infinity":22,"s:82:22:82:Infinity":23,"s:84:2:105:Infinity":24,"b:85:4:87:Infinity:undefined:undefined:undefined:undefined":7,"s:85:4:87:Infinity":25,"b:85:8:85:16:85:16:85:41":8,"s:86:6:86:Infinity":26,"s:89:17:89:Infinity":27,"b:90:4:92:Infinity:undefined:undefined:undefined:undefined":9,"s:90:4:92:Infinity":28,"b:90:8:90:30:90:30:90:45":10,"s:91:6:91:Infinity":29,"s:94:4:104:Infinity":30,"b:96:12:96:20:96:20:96:Infinity":11,"b:97:10:97:37:97:37:97:Infinity":12,"b:98:10:98:37:98:37:98:Infinity":13,"b:99:10:99:37:99:37:99:Infinity":14,"b:100:10:100:40:100:40:100:Infinity":15,"b:101:10:101:43:101:43:101:Infinity":16,"b:102:10:102:35:102:35:102:Infinity":17,"b:103:10:103:39:103:39:103:Infinity":18,"s:107:2:110:Infinity":31,"f:116:9:116:30":2,"s:117:2:121:Infinity":32,"f:127:9:127:51":3,"s:128:2:137:Infinity":33,"f:143:9:143:24":4,"b:144:2:146:Infinity:undefined:undefined:undefined:undefined":19,"s:144:2:146:Infinity":34,"s:145:4:145:Infinity":35,"b:147:2:153:Infinity:undefined:undefined:undefined:undefined":20,"s:147:2:153:Infinity":36,"b:147:6:147:35:147:35:147:51":21,"s:148:14:148:Infinity":37,"s:149:4:152:Infinity":38,"b:150:16:150:40:150:40:150:Infinity":22,"b:151:19:151:46:151:46:151:Infinity":23,"s:154:2:154:Infinity":39,"f:157:15:157:26":5,"s:158:2:163:Infinity":40,"s:159:4:159:Infinity":41,"s:160:4:160:Infinity":42,"s:162:4:162:Infinity":43}}} +,"/Users/lukasmay/development/projects/codewalk-district/src/preview/docker-client.ts": {"path":"/Users/lukasmay/development/projects/codewalk-district/src/preview/docker-client.ts","statementMap":{"0":{"start":{"line":12,"column":6},"end":{"line":12,"column":null}},"1":{"start":{"line":36,"column":2},"end":{"line":41,"column":null}},"2":{"start":{"line":37,"column":4},"end":{"line":37,"column":null}},"3":{"start":{"line":38,"column":4},"end":{"line":38,"column":null}},"4":{"start":{"line":40,"column":4},"end":{"line":40,"column":null}},"5":{"start":{"line":48,"column":2},"end":{"line":48,"column":null}},"6":{"start":{"line":49,"column":14},"end":{"line":49,"column":null}},"7":{"start":{"line":51,"column":2},"end":{"line":61,"column":null}},"8":{"start":{"line":68,"column":2},"end":{"line":68,"column":null}},"9":{"start":{"line":69,"column":2},"end":{"line":77,"column":null}},"10":{"start":{"line":84,"column":2},"end":{"line":111,"column":null}},"11":{"start":{"line":85,"column":19},"end":{"line":92,"column":null}},"12":{"start":{"line":94,"column":4},"end":{"line":96,"column":null}},"13":{"start":{"line":95,"column":6},"end":{"line":95,"column":null}},"14":{"start":{"line":99,"column":18},"end":{"line":99,"column":null}},"15":{"start":{"line":100,"column":4},"end":{"line":107,"column":null}},"16":{"start":{"line":101,"column":24},"end":{"line":101,"column":null}},"17":{"start":{"line":102,"column":6},"end":{"line":106,"column":null}},"18":{"start":{"line":109,"column":4},"end":{"line":109,"column":null}},"19":{"start":{"line":110,"column":4},"end":{"line":110,"column":null}},"20":{"start":{"line":118,"column":2},"end":{"line":136,"column":null}},"21":{"start":{"line":119,"column":19},"end":{"line":126,"column":null}},"22":{"start":{"line":128,"column":4},"end":{"line":130,"column":null}},"23":{"start":{"line":129,"column":6},"end":{"line":129,"column":null}},"24":{"start":{"line":132,"column":4},"end":{"line":132,"column":null}},"25":{"start":{"line":134,"column":4},"end":{"line":134,"column":null}},"26":{"start":{"line":135,"column":4},"end":{"line":135,"column":null}},"27":{"start":{"line":144,"column":2},"end":{"line":178,"column":null}},"28":{"start":{"line":145,"column":19},"end":{"line":152,"column":null}},"29":{"start":{"line":154,"column":4},"end":{"line":156,"column":null}},"30":{"start":{"line":155,"column":6},"end":{"line":155,"column":null}},"31":{"start":{"line":159,"column":22},"end":{"line":159,"column":null}},"32":{"start":{"line":160,"column":21},"end":{"line":160,"column":null}},"33":{"start":{"line":161,"column":43},"end":{"line":161,"column":null}},"34":{"start":{"line":163,"column":4},"end":{"line":172,"column":null}},"35":{"start":{"line":164,"column":20},"end":{"line":164,"column":null}},"36":{"start":{"line":165,"column":6},"end":{"line":171,"column":null}},"37":{"start":{"line":166,"column":20},"end":{"line":166,"column":null}},"38":{"start":{"line":167,"column":22},"end":{"line":167,"column":null}},"39":{"start":{"line":168,"column":8},"end":{"line":170,"column":null}},"40":{"start":{"line":169,"column":10},"end":{"line":169,"column":null}},"41":{"start":{"line":174,"column":4},"end":{"line":174,"column":null}},"42":{"start":{"line":176,"column":4},"end":{"line":176,"column":null}},"43":{"start":{"line":177,"column":4},"end":{"line":177,"column":null}},"44":{"start":{"line":185,"column":2},"end":{"line":205,"column":null}},"45":{"start":{"line":186,"column":19},"end":{"line":192,"column":null}},"46":{"start":{"line":194,"column":4},"end":{"line":196,"column":null}},"47":{"start":{"line":195,"column":6},"end":{"line":195,"column":null}},"48":{"start":{"line":198,"column":4},"end":{"line":202,"column":null}},"49":{"start":{"line":201,"column":18},"end":{"line":201,"column":33}},"50":{"start":{"line":202,"column":21},"end":{"line":202,"column":30}},"51":{"start":{"line":204,"column":4},"end":{"line":204,"column":null}}},"fnMap":{"0":{"name":"isDockerAvailable","decl":{"start":{"line":35,"column":22},"end":{"line":35,"column":60}},"loc":{"start":{"line":35,"column":60},"end":{"line":42,"column":null}},"line":35},"1":{"name":"composeUp","decl":{"start":{"line":47,"column":22},"end":{"line":47,"column":32}},"loc":{"start":{"line":47,"column":89},"end":{"line":62,"column":null}},"line":47},"2":{"name":"composeDown","decl":{"start":{"line":67,"column":22},"end":{"line":67,"column":34}},"loc":{"start":{"line":67,"column":70},"end":{"line":78,"column":null}},"line":67},"3":{"name":"composePs","decl":{"start":{"line":83,"column":22},"end":{"line":83,"column":32}},"loc":{"start":{"line":83,"column":79},"end":{"line":112,"column":null}},"line":83},"4":{"name":"(anonymous_4)","decl":{"start":{"line":100,"column":21},"end":{"line":100,"column":22}},"loc":{"start":{"line":100,"column":31},"end":{"line":107,"column":5}},"line":100},"5":{"name":"listPreviewProjects","decl":{"start":{"line":117,"column":22},"end":{"line":117,"column":71}},"loc":{"start":{"line":117,"column":71},"end":{"line":137,"column":null}},"line":117},"6":{"name":"getContainerLabels","decl":{"start":{"line":143,"column":22},"end":{"line":143,"column":41}},"loc":{"start":{"line":143,"column":95},"end":{"line":179,"column":null}},"line":143},"7":{"name":"getPreviewPorts","decl":{"start":{"line":184,"column":22},"end":{"line":184,"column":59}},"loc":{"start":{"line":184,"column":59},"end":{"line":206,"column":null}},"line":184},"8":{"name":"(anonymous_8)","decl":{"start":{"line":201,"column":11},"end":{"line":201,"column":12}},"loc":{"start":{"line":201,"column":18},"end":{"line":201,"column":33}},"line":201},"9":{"name":"(anonymous_9)","decl":{"start":{"line":202,"column":14},"end":{"line":202,"column":15}},"loc":{"start":{"line":202,"column":21},"end":{"line":202,"column":30}},"line":202}},"branchMap":{"0":{"loc":{"start":{"line":94,"column":4},"end":{"line":96,"column":null}},"type":"if","locations":[{"start":{"line":94,"column":4},"end":{"line":96,"column":null}},{"start":{},"end":{}}],"line":94},"1":{"loc":{"start":{"line":103,"column":14},"end":{"line":103,"column":null}},"type":"binary-expr","locations":[{"start":{"line":103,"column":14},"end":{"line":103,"column":35}},{"start":{"line":103,"column":35},"end":{"line":103,"column":53}},{"start":{"line":103,"column":53},"end":{"line":103,"column":null}}],"line":103},"2":{"loc":{"start":{"line":104,"column":15},"end":{"line":104,"column":null}},"type":"binary-expr","locations":[{"start":{"line":104,"column":15},"end":{"line":104,"column":34}},{"start":{"line":104,"column":34},"end":{"line":104,"column":null}}],"line":104},"3":{"loc":{"start":{"line":105,"column":16},"end":{"line":105,"column":null}},"type":"binary-expr","locations":[{"start":{"line":105,"column":16},"end":{"line":105,"column":36}},{"start":{"line":105,"column":36},"end":{"line":105,"column":null}}],"line":105},"4":{"loc":{"start":{"line":128,"column":4},"end":{"line":130,"column":null}},"type":"if","locations":[{"start":{"line":128,"column":4},"end":{"line":130,"column":null}},{"start":{},"end":{}}],"line":128},"5":{"loc":{"start":{"line":154,"column":4},"end":{"line":156,"column":null}},"type":"if","locations":[{"start":{"line":154,"column":4},"end":{"line":156,"column":null}},{"start":{},"end":{}}],"line":154},"6":{"loc":{"start":{"line":165,"column":6},"end":{"line":171,"column":null}},"type":"if","locations":[{"start":{"line":165,"column":6},"end":{"line":171,"column":null}},{"start":{},"end":{}}],"line":165},"7":{"loc":{"start":{"line":168,"column":8},"end":{"line":170,"column":null}},"type":"if","locations":[{"start":{"line":168,"column":8},"end":{"line":170,"column":null}},{"start":{},"end":{}}],"line":168},"8":{"loc":{"start":{"line":194,"column":4},"end":{"line":196,"column":null}},"type":"if","locations":[{"start":{"line":194,"column":4},"end":{"line":196,"column":null}},{"start":{},"end":{}}],"line":194}},"s":{"0":8,"1":0,"2":0,"3":0,"4":0,"5":0,"6":0,"7":0,"8":0,"9":0,"10":0,"11":0,"12":0,"13":0,"14":0,"15":0,"16":0,"17":0,"18":0,"19":0,"20":0,"21":0,"22":0,"23":0,"24":0,"25":0,"26":0,"27":0,"28":0,"29":0,"30":0,"31":0,"32":0,"33":0,"34":0,"35":0,"36":0,"37":0,"38":0,"39":0,"40":0,"41":0,"42":0,"43":0,"44":0,"45":0,"46":0,"47":0,"48":0,"49":0,"50":0,"51":0},"f":{"0":0,"1":0,"2":0,"3":0,"4":0,"5":0,"6":0,"7":0,"8":0,"9":0},"b":{"0":[0,0],"1":[0,0,0],"2":[0,0],"3":[0,0],"4":[0,0],"5":[0,0],"6":[0,0],"7":[0,0],"8":[0,0]},"meta":{"lastBranch":9,"lastFunction":10,"lastStatement":52,"seen":{"s:12:6:12:Infinity":0,"f:35:22:35:60":0,"s:36:2:41:Infinity":1,"s:37:4:37:Infinity":2,"s:38:4:38:Infinity":3,"s:40:4:40:Infinity":4,"f:47:22:47:32":1,"s:48:2:48:Infinity":5,"s:49:14:49:Infinity":6,"s:51:2:61:Infinity":7,"f:67:22:67:34":2,"s:68:2:68:Infinity":8,"s:69:2:77:Infinity":9,"f:83:22:83:32":3,"s:84:2:111:Infinity":10,"s:85:19:92:Infinity":11,"b:94:4:96:Infinity:undefined:undefined:undefined:undefined":0,"s:94:4:96:Infinity":12,"s:95:6:95:Infinity":13,"s:99:18:99:Infinity":14,"s:100:4:107:Infinity":15,"f:100:21:100:22":4,"s:101:24:101:Infinity":16,"s:102:6:106:Infinity":17,"b:103:14:103:35:103:35:103:53:103:53:103:Infinity":1,"b:104:15:104:34:104:34:104:Infinity":2,"b:105:16:105:36:105:36:105:Infinity":3,"s:109:4:109:Infinity":18,"s:110:4:110:Infinity":19,"f:117:22:117:71":5,"s:118:2:136:Infinity":20,"s:119:19:126:Infinity":21,"b:128:4:130:Infinity:undefined:undefined:undefined:undefined":4,"s:128:4:130:Infinity":22,"s:129:6:129:Infinity":23,"s:132:4:132:Infinity":24,"s:134:4:134:Infinity":25,"s:135:4:135:Infinity":26,"f:143:22:143:41":6,"s:144:2:178:Infinity":27,"s:145:19:152:Infinity":28,"b:154:4:156:Infinity:undefined:undefined:undefined:undefined":5,"s:154:4:156:Infinity":29,"s:155:6:155:Infinity":30,"s:159:22:159:Infinity":31,"s:160:21:160:Infinity":32,"s:161:43:161:Infinity":33,"s:163:4:172:Infinity":34,"s:164:20:164:Infinity":35,"b:165:6:171:Infinity:undefined:undefined:undefined:undefined":6,"s:165:6:171:Infinity":36,"s:166:20:166:Infinity":37,"s:167:22:167:Infinity":38,"b:168:8:170:Infinity:undefined:undefined:undefined:undefined":7,"s:168:8:170:Infinity":39,"s:169:10:169:Infinity":40,"s:174:4:174:Infinity":41,"s:176:4:176:Infinity":42,"s:177:4:177:Infinity":43,"f:184:22:184:59":7,"s:185:2:205:Infinity":44,"s:186:19:192:Infinity":45,"b:194:4:196:Infinity:undefined:undefined:undefined:undefined":8,"s:194:4:196:Infinity":46,"s:195:6:195:Infinity":47,"s:198:4:202:Infinity":48,"f:201:11:201:12":8,"s:201:18:201:33":49,"f:202:14:202:15":9,"s:202:21:202:30":50,"s:204:4:204:Infinity":51}}} +,"/Users/lukasmay/development/projects/codewalk-district/src/preview/health-checker.ts": {"path":"/Users/lukasmay/development/projects/codewalk-district/src/preview/health-checker.ts","statementMap":{"0":{"start":{"line":11,"column":6},"end":{"line":11,"column":null}},"1":{"start":{"line":14,"column":27},"end":{"line":14,"column":null}},"2":{"start":{"line":17,"column":28},"end":{"line":17,"column":null}},"3":{"start":{"line":33,"column":19},"end":{"line":37,"column":null}},"4":{"start":{"line":34,"column":4},"end":{"line":34,"column":null}},"5":{"start":{"line":34,"column":22},"end":{"line":34,"column":null}},"6":{"start":{"line":35,"column":4},"end":{"line":35,"column":null}},"7":{"start":{"line":35,"column":32},"end":{"line":35,"column":null}},"8":{"start":{"line":36,"column":4},"end":{"line":36,"column":null}},"9":{"start":{"line":39,"column":2},"end":{"line":42,"column":null}},"10":{"start":{"line":40,"column":4},"end":{"line":40,"column":null}},"11":{"start":{"line":41,"column":4},"end":{"line":41,"column":null}},"12":{"start":{"line":44,"column":19},"end":{"line":44,"column":null}},"13":{"start":{"line":45,"column":18},"end":{"line":45,"column":null}},"14":{"start":{"line":48,"column":2},"end":{"line":50,"column":null}},"15":{"start":{"line":49,"column":4},"end":{"line":49,"column":null}},"16":{"start":{"line":52,"column":2},"end":{"line":86,"column":null}},"17":{"start":{"line":53,"column":20},"end":{"line":53,"column":null}},"18":{"start":{"line":53,"column":45},"end":{"line":53,"column":76}},"19":{"start":{"line":54,"column":4},"end":{"line":54,"column":null}},"20":{"start":{"line":54,"column":30},"end":{"line":54,"column":null}},"21":{"start":{"line":56,"column":4},"end":{"line":76,"column":null}},"22":{"start":{"line":58,"column":22},"end":{"line":58,"column":null}},"23":{"start":{"line":59,"column":27},"end":{"line":59,"column":null}},"24":{"start":{"line":61,"column":25},"end":{"line":61,"column":null}},"25":{"start":{"line":62,"column":20},"end":{"line":62,"column":null}},"26":{"start":{"line":64,"column":8},"end":{"line":74,"column":null}},"27":{"start":{"line":65,"column":27},"end":{"line":67,"column":null}},"28":{"start":{"line":68,"column":10},"end":{"line":71,"column":null}},"29":{"start":{"line":69,"column":12},"end":{"line":69,"column":null}},"30":{"start":{"line":70,"column":12},"end":{"line":70,"column":null}},"31":{"start":{"line":78,"column":25},"end":{"line":78,"column":null}},"32":{"start":{"line":78,"column":50},"end":{"line":78,"column":81}},"33":{"start":{"line":79,"column":4},"end":{"line":79,"column":null}},"34":{"start":{"line":79,"column":35},"end":{"line":79,"column":null}},"35":{"start":{"line":81,"column":4},"end":{"line":84,"column":null}},"36":{"start":{"line":82,"column":41},"end":{"line":82,"column":47}},"37":{"start":{"line":85,"column":4},"end":{"line":85,"column":null}},"38":{"start":{"line":89,"column":2},"end":{"line":95,"column":null}},"39":{"start":{"line":90,"column":19},"end":{"line":90,"column":null}},"40":{"start":{"line":91,"column":4},"end":{"line":94,"column":null}},"41":{"start":{"line":92,"column":6},"end":{"line":92,"column":null}},"42":{"start":{"line":93,"column":6},"end":{"line":93,"column":null}},"43":{"start":{"line":97,"column":2},"end":{"line":97,"column":null}},"44":{"start":{"line":101,"column":2},"end":{"line":101,"column":null}},"45":{"start":{"line":101,"column":34},"end":{"line":101,"column":57}}},"fnMap":{"0":{"name":"waitForHealthy","decl":{"start":{"line":28,"column":22},"end":{"line":28,"column":null}},"loc":{"start":{"line":32,"column":27},"end":{"line":98,"column":null}},"line":32},"1":{"name":"(anonymous_1)","decl":{"start":{"line":33,"column":57},"end":{"line":33,"column":58}},"loc":{"start":{"line":33,"column":66},"end":{"line":37,"column":3}},"line":33},"2":{"name":"(anonymous_2)","decl":{"start":{"line":53,"column":36},"end":{"line":53,"column":37}},"loc":{"start":{"line":53,"column":45},"end":{"line":53,"column":76}},"line":53},"3":{"name":"(anonymous_3)","decl":{"start":{"line":57,"column":18},"end":{"line":57,"column":25}},"loc":{"start":{"line":57,"column":33},"end":{"line":75,"column":7}},"line":57},"4":{"name":"(anonymous_4)","decl":{"start":{"line":78,"column":41},"end":{"line":78,"column":42}},"loc":{"start":{"line":78,"column":50},"end":{"line":78,"column":81}},"line":78},"5":{"name":"(anonymous_5)","decl":{"start":{"line":82,"column":34},"end":{"line":82,"column":35}},"loc":{"start":{"line":82,"column":41},"end":{"line":82,"column":47}},"line":82},"6":{"name":"sleep","decl":{"start":{"line":100,"column":9},"end":{"line":100,"column":15}},"loc":{"start":{"line":100,"column":42},"end":{"line":102,"column":null}},"line":100},"7":{"name":"(anonymous_7)","decl":{"start":{"line":101,"column":21},"end":{"line":101,"column":22}},"loc":{"start":{"line":101,"column":34},"end":{"line":101,"column":57}},"line":101}},"branchMap":{"0":{"loc":{"start":{"line":31,"column":2},"end":{"line":31,"column":null}},"type":"default-arg","locations":[{"start":{"line":31,"column":14},"end":{"line":31,"column":null}}],"line":31},"1":{"loc":{"start":{"line":34,"column":4},"end":{"line":34,"column":null}},"type":"if","locations":[{"start":{"line":34,"column":4},"end":{"line":34,"column":null}},{"start":{},"end":{}}],"line":34},"2":{"loc":{"start":{"line":35,"column":4},"end":{"line":35,"column":null}},"type":"if","locations":[{"start":{"line":35,"column":4},"end":{"line":35,"column":null}},{"start":{},"end":{}}],"line":35},"3":{"loc":{"start":{"line":39,"column":2},"end":{"line":42,"column":null}},"type":"if","locations":[{"start":{"line":39,"column":2},"end":{"line":42,"column":null}},{"start":{},"end":{}}],"line":39},"4":{"loc":{"start":{"line":54,"column":4},"end":{"line":54,"column":null}},"type":"if","locations":[{"start":{"line":54,"column":4},"end":{"line":54,"column":null}},{"start":{},"end":{}}],"line":54},"5":{"loc":{"start":{"line":58,"column":22},"end":{"line":58,"column":null}},"type":"binary-expr","locations":[{"start":{"line":58,"column":22},"end":{"line":58,"column":35}},{"start":{"line":58,"column":35},"end":{"line":58,"column":null}}],"line":58},"6":{"loc":{"start":{"line":61,"column":25},"end":{"line":61,"column":null}},"type":"cond-expr","locations":[{"start":{"line":61,"column":41},"end":{"line":61,"column":46}},{"start":{"line":61,"column":46},"end":{"line":61,"column":null}}],"line":61},"7":{"loc":{"start":{"line":68,"column":10},"end":{"line":71,"column":null}},"type":"if","locations":[{"start":{"line":68,"column":10},"end":{"line":71,"column":null}},{"start":{},"end":{}}],"line":68},"8":{"loc":{"start":{"line":79,"column":4},"end":{"line":79,"column":null}},"type":"if","locations":[{"start":{"line":79,"column":4},"end":{"line":79,"column":null}},{"start":{},"end":{}}],"line":79},"9":{"loc":{"start":{"line":91,"column":4},"end":{"line":94,"column":null}},"type":"if","locations":[{"start":{"line":91,"column":4},"end":{"line":94,"column":null}},{"start":{},"end":{}}],"line":91}},"s":{"0":8,"1":8,"2":8,"3":0,"4":0,"5":0,"6":0,"7":0,"8":0,"9":0,"10":0,"11":0,"12":0,"13":0,"14":0,"15":0,"16":0,"17":0,"18":0,"19":0,"20":0,"21":0,"22":0,"23":0,"24":0,"25":0,"26":0,"27":0,"28":0,"29":0,"30":0,"31":0,"32":0,"33":0,"34":0,"35":0,"36":0,"37":0,"38":0,"39":0,"40":0,"41":0,"42":0,"43":0,"44":0,"45":0},"f":{"0":0,"1":0,"2":0,"3":0,"4":0,"5":0,"6":0,"7":0},"b":{"0":[0],"1":[0,0],"2":[0,0],"3":[0,0],"4":[0,0],"5":[0,0],"6":[0,0],"7":[0,0],"8":[0,0],"9":[0,0]},"meta":{"lastBranch":10,"lastFunction":8,"lastStatement":46,"seen":{"s:11:6:11:Infinity":0,"s:14:27:14:Infinity":1,"s:17:28:17:Infinity":2,"f:28:22:28:Infinity":0,"b:31:14:31:Infinity":0,"s:33:19:37:Infinity":3,"f:33:57:33:58":1,"b:34:4:34:Infinity:undefined:undefined:undefined:undefined":1,"s:34:4:34:Infinity":4,"s:34:22:34:Infinity":5,"b:35:4:35:Infinity:undefined:undefined:undefined:undefined":2,"s:35:4:35:Infinity":6,"s:35:32:35:Infinity":7,"s:36:4:36:Infinity":8,"b:39:2:42:Infinity:undefined:undefined:undefined:undefined":3,"s:39:2:42:Infinity":9,"s:40:4:40:Infinity":10,"s:41:4:41:Infinity":11,"s:44:19:44:Infinity":12,"s:45:18:45:Infinity":13,"s:48:2:50:Infinity":14,"s:49:4:49:Infinity":15,"s:52:2:86:Infinity":16,"s:53:20:53:Infinity":17,"f:53:36:53:37":2,"s:53:45:53:76":18,"b:54:4:54:Infinity:undefined:undefined:undefined:undefined":4,"s:54:4:54:Infinity":19,"s:54:30:54:Infinity":20,"s:56:4:76:Infinity":21,"f:57:18:57:25":3,"s:58:22:58:Infinity":22,"b:58:22:58:35:58:35:58:Infinity":5,"s:59:27:59:Infinity":23,"s:61:25:61:Infinity":24,"b:61:41:61:46:61:46:61:Infinity":6,"s:62:20:62:Infinity":25,"s:64:8:74:Infinity":26,"s:65:27:67:Infinity":27,"b:68:10:71:Infinity:undefined:undefined:undefined:undefined":7,"s:68:10:71:Infinity":28,"s:69:12:69:Infinity":29,"s:70:12:70:Infinity":30,"s:78:25:78:Infinity":31,"f:78:41:78:42":4,"s:78:50:78:81":32,"b:79:4:79:Infinity:undefined:undefined:undefined:undefined":8,"s:79:4:79:Infinity":33,"s:79:35:79:Infinity":34,"s:81:4:84:Infinity":35,"f:82:34:82:35":5,"s:82:41:82:47":36,"s:85:4:85:Infinity":37,"s:89:2:95:Infinity":38,"s:90:19:90:Infinity":39,"b:91:4:94:Infinity:undefined:undefined:undefined:undefined":9,"s:91:4:94:Infinity":40,"s:92:6:92:Infinity":41,"s:93:6:93:Infinity":42,"s:97:2:97:Infinity":43,"f:100:9:100:15":6,"s:101:2:101:Infinity":44,"f:101:21:101:22":7,"s:101:34:101:57":45}}} +,"/Users/lukasmay/development/projects/codewalk-district/src/preview/index.ts": {"path":"/Users/lukasmay/development/projects/codewalk-district/src/preview/index.ts","statementMap":{},"fnMap":{},"branchMap":{},"s":{},"f":{},"b":{},"meta":{"lastBranch":0,"lastFunction":0,"lastStatement":0,"seen":{}}} +,"/Users/lukasmay/development/projects/codewalk-district/src/preview/manager.ts": {"path":"/Users/lukasmay/development/projects/codewalk-district/src/preview/manager.ts","statementMap":{"0":{"start":{"line":39,"column":6},"end":{"line":39,"column":null}},"1":{"start":{"line":42,"column":21},"end":{"line":42,"column":null}},"2":{"start":{"line":54,"column":4},"end":{"line":54,"column":null}},"3":{"start":{"line":55,"column":4},"end":{"line":55,"column":null}},"4":{"start":{"line":56,"column":4},"end":{"line":56,"column":null}},"5":{"start":{"line":72,"column":4},"end":{"line":76,"column":null}},"6":{"start":{"line":73,"column":6},"end":{"line":75,"column":null}},"7":{"start":{"line":79,"column":20},"end":{"line":79,"column":null}},"8":{"start":{"line":80,"column":4},"end":{"line":82,"column":null}},"9":{"start":{"line":81,"column":6},"end":{"line":81,"column":null}},"10":{"start":{"line":84,"column":10},"end":{"line":87,"column":null}},"11":{"start":{"line":90,"column":19},"end":{"line":90,"column":null}},"12":{"start":{"line":93,"column":17},"end":{"line":93,"column":null}},"13":{"start":{"line":94,"column":10},"end":{"line":94,"column":null}},"14":{"start":{"line":95,"column":24},"end":{"line":95,"column":null}},"15":{"start":{"line":98,"column":10},"end":{"line":105,"column":null}},"16":{"start":{"line":107,"column":10},"end":{"line":112,"column":null}},"17":{"start":{"line":113,"column":10},"end":{"line":113,"column":null}},"18":{"start":{"line":116,"column":10},"end":{"line":116,"column":null}},"19":{"start":{"line":117,"column":4},"end":{"line":117,"column":null}},"20":{"start":{"line":119,"column":10},"end":{"line":119,"column":null}},"21":{"start":{"line":120,"column":4},"end":{"line":120,"column":null}},"22":{"start":{"line":121,"column":4},"end":{"line":121,"column":null}},"23":{"start":{"line":123,"column":4},"end":{"line":123,"column":null}},"24":{"start":{"line":126,"column":4},"end":{"line":130,"column":null}},"25":{"start":{"line":133,"column":4},"end":{"line":153,"column":null}},"26":{"start":{"line":134,"column":6},"end":{"line":134,"column":null}},"27":{"start":{"line":136,"column":6},"end":{"line":136,"column":null}},"28":{"start":{"line":138,"column":6},"end":{"line":146,"column":null}},"29":{"start":{"line":149,"column":6},"end":{"line":149,"column":null}},"30":{"start":{"line":150,"column":6},"end":{"line":150,"column":null}},"31":{"start":{"line":152,"column":6},"end":{"line":152,"column":null}},"32":{"start":{"line":156,"column":26},"end":{"line":156,"column":null}},"33":{"start":{"line":157,"column":23},"end":{"line":157,"column":null}},"34":{"start":{"line":157,"column":50},"end":{"line":157,"column":59}},"35":{"start":{"line":159,"column":4},"end":{"line":181,"column":null}},"36":{"start":{"line":160,"column":29},"end":{"line":162,"column":null}},"37":{"start":{"line":161,"column":23},"end":{"line":161,"column":33}},"38":{"start":{"line":162,"column":20},"end":{"line":162,"column":26}},"39":{"start":{"line":163,"column":6},"end":{"line":163,"column":null}},"40":{"start":{"line":165,"column":6},"end":{"line":173,"column":null}},"41":{"start":{"line":175,"column":6},"end":{"line":175,"column":null}},"42":{"start":{"line":176,"column":6},"end":{"line":176,"column":null}},"43":{"start":{"line":178,"column":6},"end":{"line":180,"column":null}},"44":{"start":{"line":184,"column":16},"end":{"line":184,"column":null}},"45":{"start":{"line":185,"column":4},"end":{"line":185,"column":null}},"46":{"start":{"line":187,"column":4},"end":{"line":197,"column":null}},"47":{"start":{"line":199,"column":21},"end":{"line":199,"column":null}},"48":{"start":{"line":201,"column":4},"end":{"line":212,"column":null}},"49":{"start":{"line":219,"column":24},"end":{"line":219,"column":null}},"50":{"start":{"line":222,"column":19},"end":{"line":222,"column":null}},"51":{"start":{"line":223,"column":25},"end":{"line":223,"column":null}},"52":{"start":{"line":225,"column":4},"end":{"line":225,"column":null}},"53":{"start":{"line":228,"column":10},"end":{"line":228,"column":null}},"54":{"start":{"line":229,"column":4},"end":{"line":229,"column":null}},"55":{"start":{"line":231,"column":4},"end":{"line":231,"column":null}},"56":{"start":{"line":233,"column":4},"end":{"line":237,"column":null}},"57":{"start":{"line":244,"column":21},"end":{"line":244,"column":null}},"58":{"start":{"line":245,"column":38},"end":{"line":245,"column":null}},"59":{"start":{"line":247,"column":4},"end":{"line":259,"column":null}},"60":{"start":{"line":248,"column":21},"end":{"line":248,"column":null}},"61":{"start":{"line":249,"column":6},"end":{"line":249,"column":null}},"62":{"start":{"line":249,"column":43},"end":{"line":249,"column":null}},"63":{"start":{"line":251,"column":22},"end":{"line":251,"column":null}},"64":{"start":{"line":252,"column":6},"end":{"line":252,"column":null}},"65":{"start":{"line":252,"column":20},"end":{"line":252,"column":null}},"66":{"start":{"line":254,"column":6},"end":{"line":254,"column":null}},"67":{"start":{"line":254,"column":65},"end":{"line":254,"column":null}},"68":{"start":{"line":257,"column":6},"end":{"line":257,"column":null}},"69":{"start":{"line":258,"column":6},"end":{"line":258,"column":null}},"70":{"start":{"line":261,"column":4},"end":{"line":261,"column":null}},"71":{"start":{"line":268,"column":24},"end":{"line":268,"column":null}},"72":{"start":{"line":269,"column":19},"end":{"line":269,"column":null}},"73":{"start":{"line":271,"column":4},"end":{"line":273,"column":null}},"74":{"start":{"line":272,"column":6},"end":{"line":272,"column":null}},"75":{"start":{"line":275,"column":20},"end":{"line":275,"column":null}},"76":{"start":{"line":276,"column":4},"end":{"line":276,"column":null}},"77":{"start":{"line":276,"column":18},"end":{"line":276,"column":null}},"78":{"start":{"line":278,"column":4},"end":{"line":278,"column":null}},"79":{"start":{"line":281,"column":4},"end":{"line":289,"column":null}},"80":{"start":{"line":282,"column":6},"end":{"line":282,"column":null}},"81":{"start":{"line":283,"column":4},"end":{"line":289,"column":null}},"82":{"start":{"line":283,"column":45},"end":{"line":283,"column":66}},"83":{"start":{"line":284,"column":6},"end":{"line":284,"column":null}},"84":{"start":{"line":285,"column":4},"end":{"line":289,"column":null}},"85":{"start":{"line":285,"column":44},"end":{"line":285,"column":86}},"86":{"start":{"line":286,"column":6},"end":{"line":286,"column":null}},"87":{"start":{"line":288,"column":6},"end":{"line":288,"column":null}},"88":{"start":{"line":291,"column":4},"end":{"line":291,"column":null}},"89":{"start":{"line":298,"column":21},"end":{"line":298,"column":null}},"90":{"start":{"line":299,"column":4},"end":{"line":299,"column":null}},"91":{"start":{"line":301,"column":4},"end":{"line":308,"column":null}},"92":{"start":{"line":303,"column":19},"end":{"line":303,"column":null}},"93":{"start":{"line":304,"column":8},"end":{"line":306,"column":null}},"94":{"start":{"line":305,"column":10},"end":{"line":305,"column":null}},"95":{"start":{"line":319,"column":22},"end":{"line":319,"column":null}},"96":{"start":{"line":320,"column":25},"end":{"line":320,"column":null}},"97":{"start":{"line":321,"column":22},"end":{"line":321,"column":null}},"98":{"start":{"line":322,"column":19},"end":{"line":322,"column":null}},"99":{"start":{"line":323,"column":17},"end":{"line":323,"column":null}},"100":{"start":{"line":325,"column":4},"end":{"line":327,"column":null}},"101":{"start":{"line":326,"column":6},"end":{"line":326,"column":null}},"102":{"start":{"line":329,"column":4},"end":{"line":340,"column":null}}},"fnMap":{"0":{"name":"(anonymous_0)","decl":{"start":{"line":49,"column":2},"end":{"line":49,"column":null}},"loc":{"start":{"line":53,"column":4},"end":{"line":57,"column":null}},"line":53},"1":{"name":"(anonymous_1)","decl":{"start":{"line":70,"column":8},"end":{"line":70,"column":14}},"loc":{"start":{"line":70,"column":68},"end":{"line":213,"column":null}},"line":70},"2":{"name":"(anonymous_2)","decl":{"start":{"line":149,"column":43},"end":{"line":149,"column":49}},"loc":{"start":{"line":149,"column":49},"end":{"line":149,"column":51}},"line":149},"3":{"name":"(anonymous_3)","decl":{"start":{"line":150,"column":66},"end":{"line":150,"column":72}},"loc":{"start":{"line":150,"column":72},"end":{"line":150,"column":74}},"line":150},"4":{"name":"(anonymous_4)","decl":{"start":{"line":157,"column":43},"end":{"line":157,"column":44}},"loc":{"start":{"line":157,"column":50},"end":{"line":157,"column":59}},"line":157},"5":{"name":"(anonymous_5)","decl":{"start":{"line":161,"column":16},"end":{"line":161,"column":17}},"loc":{"start":{"line":161,"column":23},"end":{"line":161,"column":33}},"line":161},"6":{"name":"(anonymous_6)","decl":{"start":{"line":162,"column":13},"end":{"line":162,"column":14}},"loc":{"start":{"line":162,"column":20},"end":{"line":162,"column":26}},"line":162},"7":{"name":"(anonymous_7)","decl":{"start":{"line":175,"column":43},"end":{"line":175,"column":49}},"loc":{"start":{"line":175,"column":49},"end":{"line":175,"column":51}},"line":175},"8":{"name":"(anonymous_8)","decl":{"start":{"line":176,"column":66},"end":{"line":176,"column":72}},"loc":{"start":{"line":176,"column":72},"end":{"line":176,"column":74}},"line":176},"9":{"name":"(anonymous_9)","decl":{"start":{"line":218,"column":8},"end":{"line":218,"column":13}},"loc":{"start":{"line":218,"column":47},"end":{"line":238,"column":null}},"line":218},"10":{"name":"(anonymous_10)","decl":{"start":{"line":229,"column":64},"end":{"line":229,"column":70}},"loc":{"start":{"line":229,"column":70},"end":{"line":229,"column":72}},"line":229},"11":{"name":"(anonymous_11)","decl":{"start":{"line":243,"column":8},"end":{"line":243,"column":13}},"loc":{"start":{"line":243,"column":62},"end":{"line":262,"column":null}},"line":243},"12":{"name":"(anonymous_12)","decl":{"start":{"line":267,"column":8},"end":{"line":267,"column":18}},"loc":{"start":{"line":267,"column":68},"end":{"line":292,"column":null}},"line":267},"13":{"name":"(anonymous_13)","decl":{"start":{"line":283,"column":38},"end":{"line":283,"column":39}},"loc":{"start":{"line":283,"column":45},"end":{"line":283,"column":66}},"line":283},"14":{"name":"(anonymous_14)","decl":{"start":{"line":285,"column":37},"end":{"line":285,"column":38}},"loc":{"start":{"line":285,"column":44},"end":{"line":285,"column":86}},"line":285},"15":{"name":"(anonymous_15)","decl":{"start":{"line":297,"column":8},"end":{"line":297,"column":33}},"loc":{"start":{"line":297,"column":33},"end":{"line":309,"column":null}},"line":297},"16":{"name":"(anonymous_16)","decl":{"start":{"line":302,"column":19},"end":{"line":302,"column":26}},"loc":{"start":{"line":302,"column":38},"end":{"line":307,"column":7}},"line":302},"17":{"name":"(anonymous_17)","decl":{"start":{"line":304,"column":34},"end":{"line":304,"column":35}},"loc":{"start":{"line":304,"column":43},"end":{"line":306,"column":9}},"line":304},"18":{"name":"(anonymous_18)","decl":{"start":{"line":314,"column":10},"end":{"line":314,"column":null}},"loc":{"start":{"line":318,"column":26},"end":{"line":341,"column":null}},"line":318}},"branchMap":{"0":{"loc":{"start":{"line":72,"column":4},"end":{"line":76,"column":null}},"type":"if","locations":[{"start":{"line":72,"column":4},"end":{"line":76,"column":null}},{"start":{},"end":{}}],"line":72},"1":{"loc":{"start":{"line":80,"column":4},"end":{"line":82,"column":null}},"type":"if","locations":[{"start":{"line":80,"column":4},"end":{"line":82,"column":null}},{"start":{},"end":{}}],"line":80},"2":{"loc":{"start":{"line":159,"column":4},"end":{"line":181,"column":null}},"type":"if","locations":[{"start":{"line":159,"column":4},"end":{"line":181,"column":null}},{"start":{},"end":{}}],"line":159},"3":{"loc":{"start":{"line":159,"column":8},"end":{"line":159,"column":49}},"type":"binary-expr","locations":[{"start":{"line":159,"column":8},"end":{"line":159,"column":23}},{"start":{"line":159,"column":23},"end":{"line":159,"column":49}}],"line":159},"4":{"loc":{"start":{"line":223,"column":25},"end":{"line":223,"column":null}},"type":"binary-expr","locations":[{"start":{"line":223,"column":25},"end":{"line":223,"column":64}},{"start":{"line":223,"column":64},"end":{"line":223,"column":null}}],"line":223},"5":{"loc":{"start":{"line":249,"column":6},"end":{"line":249,"column":null}},"type":"if","locations":[{"start":{"line":249,"column":6},"end":{"line":249,"column":null}},{"start":{},"end":{}}],"line":249},"6":{"loc":{"start":{"line":252,"column":6},"end":{"line":252,"column":null}},"type":"if","locations":[{"start":{"line":252,"column":6},"end":{"line":252,"column":null}},{"start":{},"end":{}}],"line":252},"7":{"loc":{"start":{"line":254,"column":6},"end":{"line":254,"column":null}},"type":"if","locations":[{"start":{"line":254,"column":6},"end":{"line":254,"column":null}},{"start":{},"end":{}}],"line":254},"8":{"loc":{"start":{"line":254,"column":10},"end":{"line":254,"column":65}},"type":"binary-expr","locations":[{"start":{"line":254,"column":10},"end":{"line":254,"column":26}},{"start":{"line":254,"column":26},"end":{"line":254,"column":65}}],"line":254},"9":{"loc":{"start":{"line":271,"column":4},"end":{"line":273,"column":null}},"type":"if","locations":[{"start":{"line":271,"column":4},"end":{"line":273,"column":null}},{"start":{},"end":{}}],"line":271},"10":{"loc":{"start":{"line":276,"column":4},"end":{"line":276,"column":null}},"type":"if","locations":[{"start":{"line":276,"column":4},"end":{"line":276,"column":null}},{"start":{},"end":{}}],"line":276},"11":{"loc":{"start":{"line":281,"column":4},"end":{"line":289,"column":null}},"type":"if","locations":[{"start":{"line":281,"column":4},"end":{"line":289,"column":null}},{"start":{"line":283,"column":4},"end":{"line":289,"column":null}}],"line":281},"12":{"loc":{"start":{"line":283,"column":4},"end":{"line":289,"column":null}},"type":"if","locations":[{"start":{"line":283,"column":4},"end":{"line":289,"column":null}},{"start":{"line":285,"column":4},"end":{"line":289,"column":null}}],"line":283},"13":{"loc":{"start":{"line":285,"column":4},"end":{"line":289,"column":null}},"type":"if","locations":[{"start":{"line":285,"column":4},"end":{"line":289,"column":null}},{"start":{"line":287,"column":11},"end":{"line":289,"column":null}}],"line":285},"14":{"loc":{"start":{"line":285,"column":44},"end":{"line":285,"column":86}},"type":"binary-expr","locations":[{"start":{"line":285,"column":44},"end":{"line":285,"column":68}},{"start":{"line":285,"column":68},"end":{"line":285,"column":86}}],"line":285},"15":{"loc":{"start":{"line":319,"column":22},"end":{"line":319,"column":null}},"type":"binary-expr","locations":[{"start":{"line":319,"column":22},"end":{"line":319,"column":58}},{"start":{"line":319,"column":58},"end":{"line":319,"column":null}}],"line":319},"16":{"loc":{"start":{"line":323,"column":26},"end":{"line":323,"column":62}},"type":"binary-expr","locations":[{"start":{"line":323,"column":26},"end":{"line":323,"column":57}},{"start":{"line":323,"column":57},"end":{"line":323,"column":62}}],"line":323},"17":{"loc":{"start":{"line":325,"column":4},"end":{"line":327,"column":null}},"type":"if","locations":[{"start":{"line":325,"column":4},"end":{"line":327,"column":null}},{"start":{},"end":{}}],"line":325},"18":{"loc":{"start":{"line":325,"column":8},"end":{"line":325,"column":48}},"type":"binary-expr","locations":[{"start":{"line":325,"column":8},"end":{"line":325,"column":25}},{"start":{"line":325,"column":25},"end":{"line":325,"column":39}},{"start":{"line":325,"column":39},"end":{"line":325,"column":48}}],"line":325}},"s":{"0":9,"1":9,"2":22,"3":22,"4":22,"5":7,"6":1,"7":6,"8":6,"9":1,"10":5,"11":5,"12":5,"13":5,"14":5,"15":5,"16":5,"17":5,"18":5,"19":5,"20":5,"21":5,"22":5,"23":5,"24":5,"25":5,"26":5,"27":1,"28":1,"29":1,"30":1,"31":1,"32":4,"33":4,"34":2,"35":4,"36":1,"37":1,"38":1,"39":1,"40":1,"41":1,"42":1,"43":1,"44":3,"45":3,"46":3,"47":3,"48":3,"49":6,"50":6,"51":6,"52":6,"53":5,"54":5,"55":5,"56":5,"57":4,"58":4,"59":4,"60":6,"61":6,"62":1,"63":5,"64":5,"65":1,"66":4,"67":1,"68":3,"69":3,"70":4,"71":5,"72":5,"73":5,"74":1,"75":4,"76":4,"77":0,"78":4,"79":4,"80":1,"81":3,"82":4,"83":1,"84":2,"85":2,"86":1,"87":1,"88":4,"89":3,"90":3,"91":3,"92":4,"93":4,"94":1,"95":9,"96":9,"97":9,"98":9,"99":9,"100":9,"101":1,"102":8},"f":{"0":22,"1":7,"2":0,"3":0,"4":2,"5":1,"6":1,"7":0,"8":0,"9":6,"10":0,"11":4,"12":5,"13":4,"14":2,"15":3,"16":4,"17":1,"18":9},"b":{"0":[1,6],"1":[1,5],"2":[1,3],"3":[4,1],"4":[6,1],"5":[1,5],"6":[1,4],"7":[1,3],"8":[4,2],"9":[1,4],"10":[0,4],"11":[1,3],"12":[1,2],"13":[1,1],"14":[2,1],"15":[9,1],"16":[9,1],"17":[1,8],"18":[9,8,8]},"meta":{"lastBranch":19,"lastFunction":19,"lastStatement":103,"seen":{"s:39:6:39:Infinity":0,"s:42:21:42:Infinity":1,"f:49:2:49:Infinity":0,"s:54:4:54:Infinity":2,"s:55:4:55:Infinity":3,"s:56:4:56:Infinity":4,"f:70:8:70:14":1,"b:72:4:76:Infinity:undefined:undefined:undefined:undefined":0,"s:72:4:76:Infinity":5,"s:73:6:75:Infinity":6,"s:79:20:79:Infinity":7,"b:80:4:82:Infinity:undefined:undefined:undefined:undefined":1,"s:80:4:82:Infinity":8,"s:81:6:81:Infinity":9,"s:84:10:87:Infinity":10,"s:90:19:90:Infinity":11,"s:93:17:93:Infinity":12,"s:94:10:94:Infinity":13,"s:95:24:95:Infinity":14,"s:98:10:105:Infinity":15,"s:107:10:112:Infinity":16,"s:113:10:113:Infinity":17,"s:116:10:116:Infinity":18,"s:117:4:117:Infinity":19,"s:119:10:119:Infinity":20,"s:120:4:120:Infinity":21,"s:121:4:121:Infinity":22,"s:123:4:123:Infinity":23,"s:126:4:130:Infinity":24,"s:133:4:153:Infinity":25,"s:134:6:134:Infinity":26,"s:136:6:136:Infinity":27,"s:138:6:146:Infinity":28,"s:149:6:149:Infinity":29,"f:149:43:149:49":2,"s:150:6:150:Infinity":30,"f:150:66:150:72":3,"s:152:6:152:Infinity":31,"s:156:26:156:Infinity":32,"s:157:23:157:Infinity":33,"f:157:43:157:44":4,"s:157:50:157:59":34,"b:159:4:181:Infinity:undefined:undefined:undefined:undefined":2,"s:159:4:181:Infinity":35,"b:159:8:159:23:159:23:159:49":3,"s:160:29:162:Infinity":36,"f:161:16:161:17":5,"s:161:23:161:33":37,"f:162:13:162:14":6,"s:162:20:162:26":38,"s:163:6:163:Infinity":39,"s:165:6:173:Infinity":40,"s:175:6:175:Infinity":41,"f:175:43:175:49":7,"s:176:6:176:Infinity":42,"f:176:66:176:72":8,"s:178:6:180:Infinity":43,"s:184:16:184:Infinity":44,"s:185:4:185:Infinity":45,"s:187:4:197:Infinity":46,"s:199:21:199:Infinity":47,"s:201:4:212:Infinity":48,"f:218:8:218:13":9,"s:219:24:219:Infinity":49,"s:222:19:222:Infinity":50,"s:223:25:223:Infinity":51,"b:223:25:223:64:223:64:223:Infinity":4,"s:225:4:225:Infinity":52,"s:228:10:228:Infinity":53,"s:229:4:229:Infinity":54,"f:229:64:229:70":10,"s:231:4:231:Infinity":55,"s:233:4:237:Infinity":56,"f:243:8:243:13":11,"s:244:21:244:Infinity":57,"s:245:38:245:Infinity":58,"s:247:4:259:Infinity":59,"s:248:21:248:Infinity":60,"b:249:6:249:Infinity:undefined:undefined:undefined:undefined":5,"s:249:6:249:Infinity":61,"s:249:43:249:Infinity":62,"s:251:22:251:Infinity":63,"b:252:6:252:Infinity:undefined:undefined:undefined:undefined":6,"s:252:6:252:Infinity":64,"s:252:20:252:Infinity":65,"b:254:6:254:Infinity:undefined:undefined:undefined:undefined":7,"s:254:6:254:Infinity":66,"b:254:10:254:26:254:26:254:65":8,"s:254:65:254:Infinity":67,"s:257:6:257:Infinity":68,"s:258:6:258:Infinity":69,"s:261:4:261:Infinity":70,"f:267:8:267:18":12,"s:268:24:268:Infinity":71,"s:269:19:269:Infinity":72,"b:271:4:273:Infinity:undefined:undefined:undefined:undefined":9,"s:271:4:273:Infinity":73,"s:272:6:272:Infinity":74,"s:275:20:275:Infinity":75,"b:276:4:276:Infinity:undefined:undefined:undefined:undefined":10,"s:276:4:276:Infinity":76,"s:276:18:276:Infinity":77,"s:278:4:278:Infinity":78,"b:281:4:289:Infinity:283:4:289:Infinity":11,"s:281:4:289:Infinity":79,"s:282:6:282:Infinity":80,"b:283:4:289:Infinity:285:4:289:Infinity":12,"s:283:4:289:Infinity":81,"f:283:38:283:39":13,"s:283:45:283:66":82,"s:284:6:284:Infinity":83,"b:285:4:289:Infinity:287:11:289:Infinity":13,"s:285:4:289:Infinity":84,"f:285:37:285:38":14,"s:285:44:285:86":85,"b:285:44:285:68:285:68:285:86":14,"s:286:6:286:Infinity":86,"s:288:6:288:Infinity":87,"s:291:4:291:Infinity":88,"f:297:8:297:33":15,"s:298:21:298:Infinity":89,"s:299:4:299:Infinity":90,"s:301:4:308:Infinity":91,"f:302:19:302:26":16,"s:303:19:303:Infinity":92,"s:304:8:306:Infinity":93,"f:304:34:304:35":17,"s:305:10:305:Infinity":94,"f:314:10:314:Infinity":18,"s:319:22:319:Infinity":95,"b:319:22:319:58:319:58:319:Infinity":15,"s:320:25:320:Infinity":96,"s:321:22:321:Infinity":97,"s:322:19:322:Infinity":98,"s:323:17:323:Infinity":99,"b:323:26:323:57:323:57:323:62":16,"b:325:4:327:Infinity:undefined:undefined:undefined:undefined":17,"s:325:4:327:Infinity":100,"b:325:8:325:25:325:25:325:39:325:39:325:48":18,"s:326:6:326:Infinity":101,"s:329:4:340:Infinity":102}}} +,"/Users/lukasmay/development/projects/codewalk-district/src/preview/port-allocator.ts": {"path":"/Users/lukasmay/development/projects/codewalk-district/src/preview/port-allocator.ts","statementMap":{"0":{"start":{"line":12,"column":6},"end":{"line":12,"column":null}},"1":{"start":{"line":15,"column":18},"end":{"line":15,"column":null}},"2":{"start":{"line":18,"column":17},"end":{"line":18,"column":null}},"3":{"start":{"line":31,"column":20},"end":{"line":31,"column":null}},"4":{"start":{"line":32,"column":2},"end":{"line":32,"column":null}},"5":{"start":{"line":34,"column":2},"end":{"line":41,"column":null}},"6":{"start":{"line":34,"column":18},"end":{"line":34,"column":29}},"7":{"start":{"line":35,"column":4},"end":{"line":35,"column":null}},"8":{"start":{"line":35,"column":29},"end":{"line":35,"column":null}},"9":{"start":{"line":37,"column":4},"end":{"line":40,"column":null}},"10":{"start":{"line":38,"column":6},"end":{"line":38,"column":null}},"11":{"start":{"line":39,"column":6},"end":{"line":39,"column":null}},"12":{"start":{"line":43,"column":2},"end":{"line":43,"column":null}},"13":{"start":{"line":50,"column":2},"end":{"line":62,"column":null}},"14":{"start":{"line":51,"column":10},"end":{"line":51,"column":null}},"15":{"start":{"line":53,"column":4},"end":{"line":55,"column":null}},"16":{"start":{"line":54,"column":6},"end":{"line":54,"column":null}},"17":{"start":{"line":57,"column":4},"end":{"line":61,"column":null}},"18":{"start":{"line":58,"column":6},"end":{"line":60,"column":null}},"19":{"start":{"line":59,"column":8},"end":{"line":59,"column":null}}},"fnMap":{"0":{"name":"allocatePort","decl":{"start":{"line":30,"column":22},"end":{"line":30,"column":54}},"loc":{"start":{"line":30,"column":54},"end":{"line":44,"column":null}},"line":30},"1":{"name":"isPortAvailable","decl":{"start":{"line":49,"column":15},"end":{"line":49,"column":31}},"loc":{"start":{"line":49,"column":63},"end":{"line":63,"column":null}},"line":49},"2":{"name":"(anonymous_2)","decl":{"start":{"line":50,"column":21},"end":{"line":50,"column":22}},"loc":{"start":{"line":50,"column":34},"end":{"line":62,"column":3}},"line":50},"3":{"name":"(anonymous_3)","decl":{"start":{"line":53,"column":25},"end":{"line":53,"column":31}},"loc":{"start":{"line":53,"column":31},"end":{"line":55,"column":5}},"line":53},"4":{"name":"(anonymous_4)","decl":{"start":{"line":57,"column":37},"end":{"line":57,"column":43}},"loc":{"start":{"line":57,"column":43},"end":{"line":61,"column":5}},"line":57},"5":{"name":"(anonymous_5)","decl":{"start":{"line":58,"column":19},"end":{"line":58,"column":25}},"loc":{"start":{"line":58,"column":25},"end":{"line":60,"column":7}},"line":58}},"branchMap":{"0":{"loc":{"start":{"line":35,"column":4},"end":{"line":35,"column":null}},"type":"if","locations":[{"start":{"line":35,"column":4},"end":{"line":35,"column":null}},{"start":{},"end":{}}],"line":35},"1":{"loc":{"start":{"line":37,"column":4},"end":{"line":40,"column":null}},"type":"if","locations":[{"start":{"line":37,"column":4},"end":{"line":40,"column":null}},{"start":{},"end":{}}],"line":37}},"s":{"0":9,"1":9,"2":9,"3":4,"4":4,"5":4,"6":4,"7":8,"8":3,"9":5,"10":4,"11":4,"12":0,"13":5,"14":5,"15":5,"16":1,"17":5,"18":4,"19":4},"f":{"0":4,"1":5,"2":5,"3":1,"4":4,"5":4},"b":{"0":[3,5],"1":[4,1]},"meta":{"lastBranch":2,"lastFunction":6,"lastStatement":20,"seen":{"s:12:6:12:Infinity":0,"s:15:18:15:Infinity":1,"s:18:17:18:Infinity":2,"f:30:22:30:54":0,"s:31:20:31:Infinity":3,"s:32:2:32:Infinity":4,"s:34:2:41:Infinity":5,"s:34:18:34:29":6,"b:35:4:35:Infinity:undefined:undefined:undefined:undefined":0,"s:35:4:35:Infinity":7,"s:35:29:35:Infinity":8,"b:37:4:40:Infinity:undefined:undefined:undefined:undefined":1,"s:37:4:40:Infinity":9,"s:38:6:38:Infinity":10,"s:39:6:39:Infinity":11,"s:43:2:43:Infinity":12,"f:49:15:49:31":1,"s:50:2:62:Infinity":13,"f:50:21:50:22":2,"s:51:10:51:Infinity":14,"s:53:4:55:Infinity":15,"f:53:25:53:31":3,"s:54:6:54:Infinity":16,"s:57:4:61:Infinity":17,"f:57:37:57:43":4,"s:58:6:60:Infinity":18,"f:58:19:58:25":5,"s:59:8:59:Infinity":19}}} +,"/Users/lukasmay/development/projects/codewalk-district/src/preview/types.ts": {"path":"/Users/lukasmay/development/projects/codewalk-district/src/preview/types.ts","statementMap":{"0":{"start":{"line":53,"column":36},"end":{"line":53,"column":null}},"1":{"start":{"line":54,"column":30},"end":{"line":62,"column":null}},"2":{"start":{"line":67,"column":38},"end":{"line":67,"column":null}}},"fnMap":{},"branchMap":{},"s":{"0":10,"1":10,"2":10},"f":{},"b":{},"meta":{"lastBranch":0,"lastFunction":0,"lastStatement":3,"seen":{"s:53:36:53:Infinity":0,"s:54:30:62:Infinity":1,"s:67:38:67:Infinity":2}}} +,"/Users/lukasmay/development/projects/codewalk-district/src/process/index.ts": {"path":"/Users/lukasmay/development/projects/codewalk-district/src/process/index.ts","statementMap":{},"fnMap":{},"branchMap":{},"s":{},"f":{},"b":{},"meta":{"lastBranch":0,"lastFunction":0,"lastStatement":0,"seen":{}}} +,"/Users/lukasmay/development/projects/codewalk-district/src/process/manager.ts": {"path":"/Users/lukasmay/development/projects/codewalk-district/src/process/manager.ts","statementMap":{"0":{"start":{"line":15,"column":24},"end":{"line":15,"column":null}},"1":{"start":{"line":30,"column":48},"end":{"line":30,"column":null}},"2":{"start":{"line":38,"column":12},"end":{"line":38,"column":null}},"3":{"start":{"line":39,"column":12},"end":{"line":39,"column":null}},"4":{"start":{"line":49,"column":49},"end":{"line":49,"column":null}},"5":{"start":{"line":52,"column":21},"end":{"line":52,"column":null}},"6":{"start":{"line":53,"column":4},"end":{"line":55,"column":null}},"7":{"start":{"line":54,"column":6},"end":{"line":54,"column":null}},"8":{"start":{"line":58,"column":10},"end":{"line":63,"column":null}},"9":{"start":{"line":66,"column":16},"end":{"line":66,"column":null}},"10":{"start":{"line":67,"column":4},"end":{"line":69,"column":null}},"11":{"start":{"line":68,"column":6},"end":{"line":68,"column":null}},"12":{"start":{"line":72,"column":30},"end":{"line":79,"column":null}},"13":{"start":{"line":82,"column":4},"end":{"line":82,"column":null}},"14":{"start":{"line":85,"column":4},"end":{"line":85,"column":null}},"15":{"start":{"line":88,"column":4},"end":{"line":99,"column":null}},"16":{"start":{"line":89,"column":41},"end":{"line":97,"column":null}},"17":{"start":{"line":98,"column":6},"end":{"line":98,"column":null}},"18":{"start":{"line":102,"column":4},"end":{"line":134,"column":null}},"19":{"start":{"line":103,"column":21},"end":{"line":103,"column":null}},"20":{"start":{"line":104,"column":6},"end":{"line":104,"column":null}},"21":{"start":{"line":105,"column":6},"end":{"line":105,"column":null}},"22":{"start":{"line":108,"column":6},"end":{"line":133,"column":null}},"23":{"start":{"line":109,"column":8},"end":{"line":132,"column":null}},"24":{"start":{"line":110,"column":45},"end":{"line":118,"column":null}},"25":{"start":{"line":119,"column":10},"end":{"line":119,"column":null}},"26":{"start":{"line":121,"column":45},"end":{"line":130,"column":null}},"27":{"start":{"line":131,"column":10},"end":{"line":131,"column":null}},"28":{"start":{"line":138,"column":4},"end":{"line":140,"column":null}},"29":{"start":{"line":143,"column":4},"end":{"line":143,"column":null}},"30":{"start":{"line":145,"column":4},"end":{"line":145,"column":null}},"31":{"start":{"line":155,"column":19},"end":{"line":155,"column":null}},"32":{"start":{"line":156,"column":17},"end":{"line":156,"column":null}},"33":{"start":{"line":158,"column":4},"end":{"line":160,"column":null}},"34":{"start":{"line":159,"column":6},"end":{"line":159,"column":null}},"35":{"start":{"line":162,"column":4},"end":{"line":166,"column":null}},"36":{"start":{"line":164,"column":6},"end":{"line":164,"column":null}},"37":{"start":{"line":165,"column":6},"end":{"line":165,"column":null}},"38":{"start":{"line":168,"column":4},"end":{"line":179,"column":null}},"39":{"start":{"line":171,"column":6},"end":{"line":176,"column":null}},"40":{"start":{"line":172,"column":8},"end":{"line":172,"column":null}},"41":{"start":{"line":173,"column":8},"end":{"line":173,"column":null}},"42":{"start":{"line":177,"column":6},"end":{"line":177,"column":null}},"43":{"start":{"line":178,"column":6},"end":{"line":178,"column":null}},"44":{"start":{"line":182,"column":4},"end":{"line":182,"column":null}},"45":{"start":{"line":185,"column":19},"end":{"line":185,"column":null}},"46":{"start":{"line":187,"column":4},"end":{"line":191,"column":null}},"47":{"start":{"line":189,"column":6},"end":{"line":189,"column":null}},"48":{"start":{"line":190,"column":6},"end":{"line":190,"column":null}},"49":{"start":{"line":194,"column":4},"end":{"line":194,"column":null}},"50":{"start":{"line":195,"column":4},"end":{"line":195,"column":null}},"51":{"start":{"line":202,"column":22},"end":{"line":202,"column":null}},"52":{"start":{"line":202,"column":57},"end":{"line":202,"column":79}},"53":{"start":{"line":203,"column":4},"end":{"line":203,"column":null}},"54":{"start":{"line":203,"column":41},"end":{"line":203,"column":72}},"55":{"start":{"line":213,"column":19},"end":{"line":213,"column":null}},"56":{"start":{"line":214,"column":17},"end":{"line":214,"column":null}},"57":{"start":{"line":216,"column":4},"end":{"line":218,"column":null}},"58":{"start":{"line":217,"column":6},"end":{"line":217,"column":null}},"59":{"start":{"line":222,"column":4},"end":{"line":231,"column":null}},"60":{"start":{"line":223,"column":6},"end":{"line":223,"column":null}},"61":{"start":{"line":226,"column":6},"end":{"line":230,"column":null}},"62":{"start":{"line":234,"column":4},"end":{"line":236,"column":null}},"63":{"start":{"line":235,"column":6},"end":{"line":235,"column":null}},"64":{"start":{"line":239,"column":4},"end":{"line":239,"column":null}},"65":{"start":{"line":242,"column":4},"end":{"line":242,"column":null}},"66":{"start":{"line":251,"column":17},"end":{"line":251,"column":null}},"67":{"start":{"line":252,"column":4},"end":{"line":254,"column":null}},"68":{"start":{"line":253,"column":6},"end":{"line":253,"column":null}},"69":{"start":{"line":257,"column":4},"end":{"line":265,"column":null}},"70":{"start":{"line":258,"column":6},"end":{"line":258,"column":null}},"71":{"start":{"line":259,"column":6},"end":{"line":259,"column":null}},"72":{"start":{"line":262,"column":6},"end":{"line":262,"column":null}},"73":{"start":{"line":263,"column":6},"end":{"line":263,"column":null}},"74":{"start":{"line":264,"column":6},"end":{"line":264,"column":null}},"75":{"start":{"line":273,"column":4},"end":{"line":289,"column":null}},"76":{"start":{"line":274,"column":22},"end":{"line":276,"column":null}},"77":{"start":{"line":275,"column":8},"end":{"line":275,"column":null}},"78":{"start":{"line":279,"column":6},"end":{"line":288,"column":null}},"79":{"start":{"line":281,"column":10},"end":{"line":281,"column":null}},"80":{"start":{"line":282,"column":10},"end":{"line":282,"column":null}},"81":{"start":{"line":286,"column":10},"end":{"line":286,"column":null}},"82":{"start":{"line":287,"column":10},"end":{"line":287,"column":null}},"83":{"start":{"line":297,"column":4},"end":{"line":314,"column":null}},"84":{"start":{"line":298,"column":20},"end":{"line":298,"column":null}},"85":{"start":{"line":299,"column":20},"end":{"line":312,"column":null}},"86":{"start":{"line":300,"column":8},"end":{"line":311,"column":null}},"87":{"start":{"line":301,"column":10},"end":{"line":301,"column":null}},"88":{"start":{"line":303,"column":10},"end":{"line":307,"column":null}},"89":{"start":{"line":304,"column":12},"end":{"line":304,"column":null}},"90":{"start":{"line":306,"column":12},"end":{"line":306,"column":null}},"91":{"start":{"line":310,"column":10},"end":{"line":310,"column":null}},"92":{"start":{"line":313,"column":6},"end":{"line":313,"column":null}}},"fnMap":{"0":{"name":"(anonymous_0)","decl":{"start":{"line":37,"column":2},"end":{"line":37,"column":null}},"loc":{"start":{"line":40,"column":4},"end":{"line":40,"column":null}},"line":40},"1":{"name":"(anonymous_1)","decl":{"start":{"line":48,"column":8},"end":{"line":48,"column":14}},"loc":{"start":{"line":48,"column":59},"end":{"line":146,"column":null}},"line":48},"2":{"name":"(anonymous_2)","decl":{"start":{"line":102,"column":26},"end":{"line":102,"column":27}},"loc":{"start":{"line":102,"column":44},"end":{"line":134,"column":5}},"line":102},"3":{"name":"(anonymous_3)","decl":{"start":{"line":138,"column":21},"end":{"line":138,"column":27}},"loc":{"start":{"line":138,"column":27},"end":{"line":140,"column":5}},"line":138},"4":{"name":"(anonymous_4)","decl":{"start":{"line":154,"column":8},"end":{"line":154,"column":13}},"loc":{"start":{"line":154,"column":40},"end":{"line":196,"column":null}},"line":154},"5":{"name":"(anonymous_5)","decl":{"start":{"line":190,"column":67},"end":{"line":190,"column":73}},"loc":{"start":{"line":190,"column":73},"end":{"line":190,"column":75}},"line":190},"6":{"name":"(anonymous_6)","decl":{"start":{"line":201,"column":8},"end":{"line":201,"column":33}},"loc":{"start":{"line":201,"column":33},"end":{"line":204,"column":null}},"line":201},"7":{"name":"(anonymous_7)","decl":{"start":{"line":202,"column":52},"end":{"line":202,"column":57}},"loc":{"start":{"line":202,"column":57},"end":{"line":202,"column":79}},"line":202},"8":{"name":"(anonymous_8)","decl":{"start":{"line":203,"column":36},"end":{"line":203,"column":41}},"loc":{"start":{"line":203,"column":41},"end":{"line":203,"column":72}},"line":203},"9":{"name":"(anonymous_9)","decl":{"start":{"line":203,"column":63},"end":{"line":203,"column":69}},"loc":{"start":{"line":203,"column":69},"end":{"line":203,"column":71}},"line":203},"10":{"name":"(anonymous_10)","decl":{"start":{"line":212,"column":8},"end":{"line":212,"column":16}},"loc":{"start":{"line":212,"column":50},"end":{"line":243,"column":null}},"line":212},"11":{"name":"(anonymous_11)","decl":{"start":{"line":250,"column":2},"end":{"line":250,"column":12}},"loc":{"start":{"line":250,"column":33},"end":{"line":266,"column":null}},"line":250},"12":{"name":"(anonymous_12)","decl":{"start":{"line":272,"column":10},"end":{"line":272,"column":29}},"loc":{"start":{"line":272,"column":93},"end":{"line":290,"column":null}},"line":272},"13":{"name":"(anonymous_13)","decl":{"start":{"line":273,"column":23},"end":{"line":273,"column":34}},"loc":{"start":{"line":273,"column":34},"end":{"line":289,"column":5}},"line":273},"14":{"name":"(anonymous_14)","decl":{"start":{"line":274,"column":33},"end":{"line":274,"column":39}},"loc":{"start":{"line":274,"column":39},"end":{"line":276,"column":9}},"line":274},"15":{"name":"(anonymous_15)","decl":{"start":{"line":280,"column":14},"end":{"line":280,"column":20}},"loc":{"start":{"line":280,"column":20},"end":{"line":283,"column":9}},"line":280},"16":{"name":"(anonymous_16)","decl":{"start":{"line":284,"column":15},"end":{"line":284,"column":21}},"loc":{"start":{"line":284,"column":21},"end":{"line":288,"column":9}},"line":284},"17":{"name":"(anonymous_17)","decl":{"start":{"line":296,"column":10},"end":{"line":296,"column":22}},"loc":{"start":{"line":296,"column":72},"end":{"line":315,"column":null}},"line":296},"18":{"name":"(anonymous_18)","decl":{"start":{"line":297,"column":23},"end":{"line":297,"column":34}},"loc":{"start":{"line":297,"column":34},"end":{"line":314,"column":5}},"line":297},"19":{"name":"(anonymous_19)","decl":{"start":{"line":299,"column":20},"end":{"line":299,"column":26}},"loc":{"start":{"line":299,"column":26},"end":{"line":312,"column":null}},"line":299}},"branchMap":{"0":{"loc":{"start":{"line":49,"column":25},"end":{"line":49,"column":36}},"type":"default-arg","locations":[{"start":{"line":49,"column":32},"end":{"line":49,"column":36}}],"line":49},"1":{"loc":{"start":{"line":53,"column":4},"end":{"line":55,"column":null}},"type":"if","locations":[{"start":{"line":53,"column":4},"end":{"line":55,"column":null}},{"start":{},"end":{}}],"line":53},"2":{"loc":{"start":{"line":53,"column":8},"end":{"line":53,"column":51}},"type":"binary-expr","locations":[{"start":{"line":53,"column":8},"end":{"line":53,"column":20}},{"start":{"line":53,"column":20},"end":{"line":53,"column":51}}],"line":53},"3":{"loc":{"start":{"line":60,"column":11},"end":{"line":60,"column":null}},"type":"cond-expr","locations":[{"start":{"line":60,"column":17},"end":{"line":60,"column":46}},{"start":{"line":60,"column":46},"end":{"line":60,"column":null}}],"line":60},"4":{"loc":{"start":{"line":67,"column":4},"end":{"line":69,"column":null}},"type":"if","locations":[{"start":{"line":67,"column":4},"end":{"line":69,"column":null}},{"start":{},"end":{}}],"line":67},"5":{"loc":{"start":{"line":88,"column":4},"end":{"line":99,"column":null}},"type":"if","locations":[{"start":{"line":88,"column":4},"end":{"line":99,"column":null}},{"start":{},"end":{}}],"line":88},"6":{"loc":{"start":{"line":103,"column":21},"end":{"line":103,"column":null}},"type":"cond-expr","locations":[{"start":{"line":103,"column":34},"end":{"line":103,"column":46}},{"start":{"line":103,"column":46},"end":{"line":103,"column":null}}],"line":103},"7":{"loc":{"start":{"line":108,"column":6},"end":{"line":133,"column":null}},"type":"if","locations":[{"start":{"line":108,"column":6},"end":{"line":133,"column":null}},{"start":{},"end":{}}],"line":108},"8":{"loc":{"start":{"line":109,"column":8},"end":{"line":132,"column":null}},"type":"if","locations":[{"start":{"line":109,"column":8},"end":{"line":132,"column":null}},{"start":{"line":120,"column":15},"end":{"line":132,"column":null}}],"line":109},"9":{"loc":{"start":{"line":158,"column":4},"end":{"line":160,"column":null}},"type":"if","locations":[{"start":{"line":158,"column":4},"end":{"line":160,"column":null}},{"start":{},"end":{}}],"line":158},"10":{"loc":{"start":{"line":162,"column":4},"end":{"line":166,"column":null}},"type":"if","locations":[{"start":{"line":162,"column":4},"end":{"line":166,"column":null}},{"start":{},"end":{}}],"line":162},"11":{"loc":{"start":{"line":168,"column":4},"end":{"line":179,"column":null}},"type":"if","locations":[{"start":{"line":168,"column":4},"end":{"line":179,"column":null}},{"start":{},"end":{}}],"line":168},"12":{"loc":{"start":{"line":187,"column":4},"end":{"line":191,"column":null}},"type":"if","locations":[{"start":{"line":187,"column":4},"end":{"line":191,"column":null}},{"start":{},"end":{}}],"line":187},"13":{"loc":{"start":{"line":216,"column":4},"end":{"line":218,"column":null}},"type":"if","locations":[{"start":{"line":216,"column":4},"end":{"line":218,"column":null}},{"start":{},"end":{}}],"line":216},"14":{"loc":{"start":{"line":222,"column":4},"end":{"line":231,"column":null}},"type":"if","locations":[{"start":{"line":222,"column":4},"end":{"line":231,"column":null}},{"start":{"line":224,"column":11},"end":{"line":231,"column":null}}],"line":222},"15":{"loc":{"start":{"line":234,"column":4},"end":{"line":236,"column":null}},"type":"if","locations":[{"start":{"line":234,"column":4},"end":{"line":236,"column":null}},{"start":{},"end":{}}],"line":234},"16":{"loc":{"start":{"line":252,"column":4},"end":{"line":254,"column":null}},"type":"if","locations":[{"start":{"line":252,"column":4},"end":{"line":254,"column":null}},{"start":{},"end":{}}],"line":252},"17":{"loc":{"start":{"line":252,"column":8},"end":{"line":252,"column":44}},"type":"binary-expr","locations":[{"start":{"line":252,"column":8},"end":{"line":252,"column":17}},{"start":{"line":252,"column":17},"end":{"line":252,"column":44}}],"line":252},"18":{"loc":{"start":{"line":303,"column":10},"end":{"line":307,"column":null}},"type":"if","locations":[{"start":{"line":303,"column":10},"end":{"line":307,"column":null}},{"start":{"line":305,"column":17},"end":{"line":307,"column":null}}],"line":303}},"s":{"0":10,"1":25,"2":25,"3":25,"4":21,"5":21,"6":21,"7":1,"8":20,"9":21,"10":21,"11":1,"12":19,"13":19,"14":19,"15":19,"16":3,"17":3,"18":19,"19":7,"20":7,"21":7,"22":7,"23":2,"24":1,"25":1,"26":1,"27":1,"28":19,"29":19,"30":19,"31":7,"32":7,"33":7,"34":1,"35":6,"36":1,"37":1,"38":5,"39":0,"40":0,"41":0,"42":0,"43":0,"44":5,"45":5,"46":5,"47":0,"48":0,"49":5,"50":5,"51":1,"52":3,"53":1,"54":3,"55":2,"56":2,"57":2,"58":1,"59":1,"60":1,"61":0,"62":1,"63":1,"64":1,"65":1,"66":4,"67":4,"68":2,"69":2,"70":2,"71":2,"72":1,"73":1,"74":1,"75":5,"76":5,"77":0,"78":5,"79":5,"80":5,"81":0,"82":0,"83":0,"84":0,"85":0,"86":0,"87":0,"88":0,"89":0,"90":0,"91":0,"92":0},"f":{"0":25,"1":21,"2":7,"3":0,"4":7,"5":0,"6":1,"7":3,"8":3,"9":0,"10":2,"11":4,"12":5,"13":5,"14":0,"15":5,"16":0,"17":0,"18":0,"19":0},"b":{"0":[21],"1":[1,20],"2":[21,1],"3":[1,19],"4":[1,20],"5":[3,16],"6":[5,2],"7":[2,5],"8":[1,1],"9":[1,6],"10":[1,5],"11":[0,5],"12":[0,5],"13":[1,1],"14":[1,0],"15":[1,0],"16":[2,2],"17":[4,3],"18":[0,0]},"meta":{"lastBranch":19,"lastFunction":20,"lastStatement":93,"seen":{"s:15:24:15:Infinity":0,"s:30:48:30:Infinity":1,"f:37:2:37:Infinity":0,"s:38:12:38:Infinity":2,"s:39:12:39:Infinity":3,"f:48:8:48:14":1,"s:49:49:49:Infinity":4,"b:49:32:49:36":0,"s:52:21:52:Infinity":5,"b:53:4:55:Infinity:undefined:undefined:undefined:undefined":1,"s:53:4:55:Infinity":6,"b:53:8:53:20:53:20:53:51":2,"s:54:6:54:Infinity":7,"s:58:10:63:Infinity":8,"b:60:17:60:46:60:46:60:Infinity":3,"s:66:16:66:Infinity":9,"b:67:4:69:Infinity:undefined:undefined:undefined:undefined":4,"s:67:4:69:Infinity":10,"s:68:6:68:Infinity":11,"s:72:30:79:Infinity":12,"s:82:4:82:Infinity":13,"s:85:4:85:Infinity":14,"b:88:4:99:Infinity:undefined:undefined:undefined:undefined":5,"s:88:4:99:Infinity":15,"s:89:41:97:Infinity":16,"s:98:6:98:Infinity":17,"s:102:4:134:Infinity":18,"f:102:26:102:27":2,"s:103:21:103:Infinity":19,"b:103:34:103:46:103:46:103:Infinity":6,"s:104:6:104:Infinity":20,"s:105:6:105:Infinity":21,"b:108:6:133:Infinity:undefined:undefined:undefined:undefined":7,"s:108:6:133:Infinity":22,"b:109:8:132:Infinity:120:15:132:Infinity":8,"s:109:8:132:Infinity":23,"s:110:45:118:Infinity":24,"s:119:10:119:Infinity":25,"s:121:45:130:Infinity":26,"s:131:10:131:Infinity":27,"s:138:4:140:Infinity":28,"f:138:21:138:27":3,"s:143:4:143:Infinity":29,"s:145:4:145:Infinity":30,"f:154:8:154:13":4,"s:155:19:155:Infinity":31,"s:156:17:156:Infinity":32,"b:158:4:160:Infinity:undefined:undefined:undefined:undefined":9,"s:158:4:160:Infinity":33,"s:159:6:159:Infinity":34,"b:162:4:166:Infinity:undefined:undefined:undefined:undefined":10,"s:162:4:166:Infinity":35,"s:164:6:164:Infinity":36,"s:165:6:165:Infinity":37,"b:168:4:179:Infinity:undefined:undefined:undefined:undefined":11,"s:168:4:179:Infinity":38,"s:171:6:176:Infinity":39,"s:172:8:172:Infinity":40,"s:173:8:173:Infinity":41,"s:177:6:177:Infinity":42,"s:178:6:178:Infinity":43,"s:182:4:182:Infinity":44,"s:185:19:185:Infinity":45,"b:187:4:191:Infinity:undefined:undefined:undefined:undefined":12,"s:187:4:191:Infinity":46,"s:189:6:189:Infinity":47,"s:190:6:190:Infinity":48,"f:190:67:190:73":5,"s:194:4:194:Infinity":49,"s:195:4:195:Infinity":50,"f:201:8:201:33":6,"s:202:22:202:Infinity":51,"f:202:52:202:57":7,"s:202:57:202:79":52,"s:203:4:203:Infinity":53,"f:203:36:203:41":8,"s:203:41:203:72":54,"f:203:63:203:69":9,"f:212:8:212:16":10,"s:213:19:213:Infinity":55,"s:214:17:214:Infinity":56,"b:216:4:218:Infinity:undefined:undefined:undefined:undefined":13,"s:216:4:218:Infinity":57,"s:217:6:217:Infinity":58,"b:222:4:231:Infinity:224:11:231:Infinity":14,"s:222:4:231:Infinity":59,"s:223:6:223:Infinity":60,"s:226:6:230:Infinity":61,"b:234:4:236:Infinity:undefined:undefined:undefined:undefined":15,"s:234:4:236:Infinity":62,"s:235:6:235:Infinity":63,"s:239:4:239:Infinity":64,"s:242:4:242:Infinity":65,"f:250:2:250:12":11,"s:251:17:251:Infinity":66,"b:252:4:254:Infinity:undefined:undefined:undefined:undefined":16,"s:252:4:254:Infinity":67,"b:252:8:252:17:252:17:252:44":17,"s:253:6:253:Infinity":68,"s:257:4:265:Infinity":69,"s:258:6:258:Infinity":70,"s:259:6:259:Infinity":71,"s:262:6:262:Infinity":72,"s:263:6:263:Infinity":73,"s:264:6:264:Infinity":74,"f:272:10:272:29":12,"s:273:4:289:Infinity":75,"f:273:23:273:34":13,"s:274:22:276:Infinity":76,"f:274:33:274:39":14,"s:275:8:275:Infinity":77,"s:279:6:288:Infinity":78,"f:280:14:280:20":15,"s:281:10:281:Infinity":79,"s:282:10:282:Infinity":80,"f:284:15:284:21":16,"s:286:10:286:Infinity":81,"s:287:10:287:Infinity":82,"f:296:10:296:22":17,"s:297:4:314:Infinity":83,"f:297:23:297:34":18,"s:298:20:298:Infinity":84,"s:299:20:312:Infinity":85,"f:299:20:299:26":19,"s:300:8:311:Infinity":86,"s:301:10:301:Infinity":87,"b:303:10:307:Infinity:305:17:307:Infinity":18,"s:303:10:307:Infinity":88,"s:304:12:304:Infinity":89,"s:306:12:306:Infinity":90,"s:310:10:310:Infinity":91,"s:313:6:313:Infinity":92}}} +,"/Users/lukasmay/development/projects/codewalk-district/src/process/registry.ts": {"path":"/Users/lukasmay/development/projects/codewalk-district/src/process/registry.ts","statementMap":{"0":{"start":{"line":17,"column":48},"end":{"line":17,"column":null}},"1":{"start":{"line":24,"column":4},"end":{"line":24,"column":null}},"2":{"start":{"line":32,"column":4},"end":{"line":32,"column":null}},"3":{"start":{"line":41,"column":4},"end":{"line":41,"column":null}},"4":{"start":{"line":49,"column":4},"end":{"line":49,"column":null}},"5":{"start":{"line":58,"column":4},"end":{"line":62,"column":null}},"6":{"start":{"line":59,"column":6},"end":{"line":61,"column":null}},"7":{"start":{"line":60,"column":8},"end":{"line":60,"column":null}},"8":{"start":{"line":63,"column":4},"end":{"line":63,"column":null}},"9":{"start":{"line":70,"column":4},"end":{"line":70,"column":null}},"10":{"start":{"line":80,"column":20},"end":{"line":80,"column":null}},"11":{"start":{"line":81,"column":4},"end":{"line":84,"column":null}},"12":{"start":{"line":82,"column":6},"end":{"line":82,"column":null}},"13":{"start":{"line":83,"column":6},"end":{"line":83,"column":null}},"14":{"start":{"line":85,"column":4},"end":{"line":85,"column":null}},"15":{"start":{"line":93,"column":4},"end":{"line":93,"column":null}}},"fnMap":{"0":{"name":"(anonymous_0)","decl":{"start":{"line":23,"column":2},"end":{"line":23,"column":11}},"loc":{"start":{"line":23,"column":36},"end":{"line":25,"column":null}},"line":23},"1":{"name":"(anonymous_1)","decl":{"start":{"line":31,"column":2},"end":{"line":31,"column":13}},"loc":{"start":{"line":31,"column":31},"end":{"line":33,"column":null}},"line":31},"2":{"name":"(anonymous_2)","decl":{"start":{"line":40,"column":2},"end":{"line":40,"column":6}},"loc":{"start":{"line":40,"column":43},"end":{"line":42,"column":null}},"line":40},"3":{"name":"(anonymous_3)","decl":{"start":{"line":48,"column":2},"end":{"line":48,"column":26}},"loc":{"start":{"line":48,"column":26},"end":{"line":50,"column":null}},"line":48},"4":{"name":"(anonymous_4)","decl":{"start":{"line":57,"column":2},"end":{"line":57,"column":11}},"loc":{"start":{"line":57,"column":49},"end":{"line":64,"column":null}},"line":57},"5":{"name":"(anonymous_5)","decl":{"start":{"line":69,"column":2},"end":{"line":69,"column":16}},"loc":{"start":{"line":69,"column":16},"end":{"line":71,"column":null}},"line":69},"6":{"name":"(anonymous_6)","decl":{"start":{"line":79,"column":2},"end":{"line":79,"column":15}},"loc":{"start":{"line":79,"column":67},"end":{"line":86,"column":null}},"line":79},"7":{"name":"(anonymous_7)","decl":{"start":{"line":92,"column":6},"end":{"line":92,"column":21}},"loc":{"start":{"line":92,"column":21},"end":{"line":94,"column":null}},"line":92}},"branchMap":{"0":{"loc":{"start":{"line":59,"column":6},"end":{"line":61,"column":null}},"type":"if","locations":[{"start":{"line":59,"column":6},"end":{"line":61,"column":null}},{"start":{},"end":{}}],"line":59},"1":{"loc":{"start":{"line":81,"column":4},"end":{"line":84,"column":null}},"type":"if","locations":[{"start":{"line":81,"column":4},"end":{"line":84,"column":null}},{"start":{},"end":{}}],"line":81}},"s":{"0":36,"1":37,"2":4,"3":45,"4":4,"5":2,"6":2,"7":1,"8":1,"9":1,"10":16,"11":16,"12":15,"13":15,"14":1,"15":11},"f":{"0":37,"1":4,"2":45,"3":4,"4":2,"5":1,"6":16,"7":11},"b":{"0":[1,1],"1":[15,1]},"meta":{"lastBranch":2,"lastFunction":8,"lastStatement":16,"seen":{"s:17:48:17:Infinity":0,"f:23:2:23:11":0,"s:24:4:24:Infinity":1,"f:31:2:31:13":1,"s:32:4:32:Infinity":2,"f:40:2:40:6":2,"s:41:4:41:Infinity":3,"f:48:2:48:26":3,"s:49:4:49:Infinity":4,"f:57:2:57:11":4,"s:58:4:62:Infinity":5,"b:59:6:61:Infinity:undefined:undefined:undefined:undefined":0,"s:59:6:61:Infinity":6,"s:60:8:60:Infinity":7,"s:63:4:63:Infinity":8,"f:69:2:69:16":5,"s:70:4:70:Infinity":9,"f:79:2:79:15":6,"s:80:20:80:Infinity":10,"b:81:4:84:Infinity:undefined:undefined:undefined:undefined":1,"s:81:4:84:Infinity":11,"s:82:6:82:Infinity":12,"s:83:6:83:Infinity":13,"s:85:4:85:Infinity":14,"f:92:6:92:21":7,"s:93:4:93:Infinity":15}}} +,"/Users/lukasmay/development/projects/codewalk-district/src/server/index.ts": {"path":"/Users/lukasmay/development/projects/codewalk-district/src/server/index.ts","statementMap":{"0":{"start":{"line":27,"column":6},"end":{"line":27,"column":null}},"1":{"start":{"line":30,"column":21},"end":{"line":30,"column":null}},"2":{"start":{"line":33,"column":21},"end":{"line":33,"column":null}},"3":{"start":{"line":36,"column":6},"end":{"line":36,"column":null}},"4":{"start":{"line":51,"column":34},"end":{"line":51,"column":null}},"5":{"start":{"line":52,"column":38},"end":{"line":52,"column":null}},"6":{"start":{"line":61,"column":4},"end":{"line":65,"column":null}},"7":{"start":{"line":66,"column":4},"end":{"line":66,"column":null}},"8":{"start":{"line":67,"column":4},"end":{"line":67,"column":null}},"9":{"start":{"line":68,"column":4},"end":{"line":68,"column":null}},"10":{"start":{"line":69,"column":4},"end":{"line":69,"column":null}},"11":{"start":{"line":78,"column":4},"end":{"line":80,"column":null}},"12":{"start":{"line":79,"column":6},"end":{"line":79,"column":null}},"13":{"start":{"line":83,"column":24},"end":{"line":83,"column":null}},"14":{"start":{"line":84,"column":4},"end":{"line":89,"column":null}},"15":{"start":{"line":85,"column":6},"end":{"line":88,"column":null}},"16":{"start":{"line":92,"column":4},"end":{"line":92,"column":null}},"17":{"start":{"line":92,"column":45},"end":{"line":92,"column":73}},"18":{"start":{"line":95,"column":4},"end":{"line":101,"column":null}},"19":{"start":{"line":96,"column":6},"end":{"line":96,"column":null}},"20":{"start":{"line":97,"column":6},"end":{"line":100,"column":null}},"21":{"start":{"line":98,"column":8},"end":{"line":98,"column":null}},"22":{"start":{"line":99,"column":8},"end":{"line":99,"column":null}},"23":{"start":{"line":104,"column":4},"end":{"line":107,"column":null}},"24":{"start":{"line":110,"column":4},"end":{"line":110,"column":null}},"25":{"start":{"line":113,"column":4},"end":{"line":124,"column":null}},"26":{"start":{"line":114,"column":40},"end":{"line":122,"column":null}},"27":{"start":{"line":123,"column":6},"end":{"line":123,"column":null}},"28":{"start":{"line":126,"column":4},"end":{"line":126,"column":null}},"29":{"start":{"line":127,"column":4},"end":{"line":127,"column":null}},"30":{"start":{"line":134,"column":4},"end":{"line":136,"column":null}},"31":{"start":{"line":135,"column":6},"end":{"line":135,"column":null}},"32":{"start":{"line":139,"column":19},"end":{"line":141,"column":null}},"33":{"start":{"line":144,"column":4},"end":{"line":153,"column":null}},"34":{"start":{"line":145,"column":40},"end":{"line":151,"column":null}},"35":{"start":{"line":152,"column":6},"end":{"line":152,"column":null}},"36":{"start":{"line":156,"column":4},"end":{"line":164,"column":null}},"37":{"start":{"line":157,"column":6},"end":{"line":163,"column":null}},"38":{"start":{"line":158,"column":8},"end":{"line":162,"column":null}},"39":{"start":{"line":159,"column":10},"end":{"line":159,"column":null}},"40":{"start":{"line":161,"column":10},"end":{"line":161,"column":null}},"41":{"start":{"line":166,"column":4},"end":{"line":166,"column":null}},"42":{"start":{"line":167,"column":4},"end":{"line":167,"column":null}},"43":{"start":{"line":170,"column":4},"end":{"line":170,"column":null}},"44":{"start":{"line":177,"column":4},"end":{"line":177,"column":null}},"45":{"start":{"line":184,"column":4},"end":{"line":184,"column":null}},"46":{"start":{"line":191,"column":4},"end":{"line":191,"column":null}},"47":{"start":{"line":198,"column":16},"end":{"line":198,"column":null}},"48":{"start":{"line":201,"column":4},"end":{"line":204,"column":null}},"49":{"start":{"line":202,"column":6},"end":{"line":202,"column":null}},"50":{"start":{"line":203,"column":6},"end":{"line":203,"column":null}},"51":{"start":{"line":207,"column":4},"end":{"line":210,"column":null}},"52":{"start":{"line":208,"column":6},"end":{"line":208,"column":null}},"53":{"start":{"line":209,"column":6},"end":{"line":209,"column":null}},"54":{"start":{"line":213,"column":4},"end":{"line":222,"column":null}},"55":{"start":{"line":215,"column":8},"end":{"line":215,"column":null}},"56":{"start":{"line":216,"column":8},"end":{"line":216,"column":null}},"57":{"start":{"line":218,"column":8},"end":{"line":218,"column":null}},"58":{"start":{"line":219,"column":8},"end":{"line":219,"column":null}},"59":{"start":{"line":221,"column":8},"end":{"line":221,"column":null}},"60":{"start":{"line":229,"column":4},"end":{"line":232,"column":null}},"61":{"start":{"line":230,"column":6},"end":{"line":230,"column":null}},"62":{"start":{"line":231,"column":6},"end":{"line":231,"column":null}},"63":{"start":{"line":234,"column":10},"end":{"line":239,"column":null}},"64":{"start":{"line":241,"column":4},"end":{"line":244,"column":null}},"65":{"start":{"line":242,"column":6},"end":{"line":242,"column":null}},"66":{"start":{"line":243,"column":6},"end":{"line":243,"column":null}},"67":{"start":{"line":251,"column":4},"end":{"line":254,"column":null}},"68":{"start":{"line":252,"column":6},"end":{"line":252,"column":null}},"69":{"start":{"line":253,"column":6},"end":{"line":253,"column":null}},"70":{"start":{"line":256,"column":19},"end":{"line":256,"column":null}},"71":{"start":{"line":257,"column":37},"end":{"line":261,"column":null}},"72":{"start":{"line":263,"column":4},"end":{"line":263,"column":null}},"73":{"start":{"line":270,"column":4},"end":{"line":273,"column":null}},"74":{"start":{"line":271,"column":6},"end":{"line":271,"column":null}},"75":{"start":{"line":272,"column":6},"end":{"line":272,"column":null}},"76":{"start":{"line":275,"column":19},"end":{"line":275,"column":null}},"77":{"start":{"line":279,"column":37},"end":{"line":286,"column":null}},"78":{"start":{"line":288,"column":4},"end":{"line":288,"column":null}},"79":{"start":{"line":295,"column":4},"end":{"line":295,"column":null}},"80":{"start":{"line":296,"column":4},"end":{"line":296,"column":null}},"81":{"start":{"line":304,"column":4},"end":{"line":328,"column":null}},"82":{"start":{"line":305,"column":22},"end":{"line":305,"column":null}},"83":{"start":{"line":306,"column":18},"end":{"line":306,"column":null}},"84":{"start":{"line":308,"column":6},"end":{"line":310,"column":null}},"85":{"start":{"line":309,"column":8},"end":{"line":309,"column":null}},"86":{"start":{"line":313,"column":6},"end":{"line":321,"column":null}},"87":{"start":{"line":314,"column":8},"end":{"line":314,"column":null}},"88":{"start":{"line":315,"column":8},"end":{"line":315,"column":null}},"89":{"start":{"line":318,"column":8},"end":{"line":318,"column":null}},"90":{"start":{"line":319,"column":8},"end":{"line":319,"column":null}},"91":{"start":{"line":320,"column":8},"end":{"line":320,"column":null}},"92":{"start":{"line":324,"column":6},"end":{"line":326,"column":null}},"93":{"start":{"line":325,"column":8},"end":{"line":325,"column":null}},"94":{"start":{"line":327,"column":6},"end":{"line":327,"column":null}},"95":{"start":{"line":336,"column":4},"end":{"line":336,"column":null}},"96":{"start":{"line":337,"column":4},"end":{"line":337,"column":null}},"97":{"start":{"line":344,"column":4},"end":{"line":351,"column":null}},"98":{"start":{"line":345,"column":6},"end":{"line":345,"column":null}},"99":{"start":{"line":348,"column":6},"end":{"line":350,"column":null}},"100":{"start":{"line":349,"column":8},"end":{"line":349,"column":null}}},"fnMap":{"0":{"name":"(anonymous_0)","decl":{"start":{"line":54,"column":2},"end":{"line":54,"column":null}},"loc":{"start":{"line":60,"column":4},"end":{"line":70,"column":null}},"line":60},"1":{"name":"(anonymous_1)","decl":{"start":{"line":76,"column":8},"end":{"line":76,"column":31}},"loc":{"start":{"line":76,"column":31},"end":{"line":128,"column":null}},"line":76},"2":{"name":"(anonymous_2)","decl":{"start":{"line":92,"column":31},"end":{"line":92,"column":32}},"loc":{"start":{"line":92,"column":45},"end":{"line":92,"column":73}},"line":92},"3":{"name":"(anonymous_3)","decl":{"start":{"line":95,"column":28},"end":{"line":95,"column":29}},"loc":{"start":{"line":95,"column":49},"end":{"line":101,"column":5}},"line":95},"4":{"name":"(anonymous_4)","decl":{"start":{"line":97,"column":62},"end":{"line":97,"column":68}},"loc":{"start":{"line":97,"column":68},"end":{"line":100,"column":7}},"line":97},"5":{"name":"(anonymous_5)","decl":{"start":{"line":133,"column":8},"end":{"line":133,"column":30}},"loc":{"start":{"line":133,"column":30},"end":{"line":171,"column":null}},"line":133},"6":{"name":"(anonymous_6)","decl":{"start":{"line":156,"column":28},"end":{"line":156,"column":29}},"loc":{"start":{"line":156,"column":49},"end":{"line":164,"column":5}},"line":156},"7":{"name":"(anonymous_7)","decl":{"start":{"line":157,"column":25},"end":{"line":157,"column":26}},"loc":{"start":{"line":157,"column":34},"end":{"line":163,"column":7}},"line":157},"8":{"name":"(anonymous_8)","decl":{"start":{"line":176,"column":2},"end":{"line":176,"column":23}},"loc":{"start":{"line":176,"column":23},"end":{"line":178,"column":null}},"line":176},"9":{"name":"(anonymous_9)","decl":{"start":{"line":183,"column":2},"end":{"line":183,"column":20}},"loc":{"start":{"line":183,"column":20},"end":{"line":185,"column":null}},"line":183},"10":{"name":"(anonymous_10)","decl":{"start":{"line":190,"column":2},"end":{"line":190,"column":23}},"loc":{"start":{"line":190,"column":23},"end":{"line":192,"column":null}},"line":190},"11":{"name":"(anonymous_11)","decl":{"start":{"line":197,"column":10},"end":{"line":197,"column":24}},"loc":{"start":{"line":197,"column":73},"end":{"line":223,"column":null}},"line":197},"12":{"name":"(anonymous_12)","decl":{"start":{"line":228,"column":10},"end":{"line":228,"column":21}},"loc":{"start":{"line":228,"column":70},"end":{"line":245,"column":null}},"line":228},"13":{"name":"(anonymous_13)","decl":{"start":{"line":241,"column":32},"end":{"line":241,"column":33}},"loc":{"start":{"line":241,"column":50},"end":{"line":244,"column":5}},"line":241},"14":{"name":"(anonymous_14)","decl":{"start":{"line":250,"column":10},"end":{"line":250,"column":23}},"loc":{"start":{"line":250,"column":50},"end":{"line":264,"column":null}},"line":250},"15":{"name":"(anonymous_15)","decl":{"start":{"line":269,"column":10},"end":{"line":269,"column":23}},"loc":{"start":{"line":269,"column":50},"end":{"line":289,"column":null}},"line":269},"16":{"name":"(anonymous_16)","decl":{"start":{"line":294,"column":10},"end":{"line":294,"column":19}},"loc":{"start":{"line":294,"column":81},"end":{"line":297,"column":null}},"line":294},"17":{"name":"(anonymous_17)","decl":{"start":{"line":303,"column":16},"end":{"line":303,"column":62}},"loc":{"start":{"line":303,"column":62},"end":{"line":329,"column":null}},"line":303},"18":{"name":"(anonymous_18)","decl":{"start":{"line":334,"column":16},"end":{"line":334,"column":46}},"loc":{"start":{"line":334,"column":46},"end":{"line":338,"column":null}},"line":334},"19":{"name":"(anonymous_19)","decl":{"start":{"line":343,"column":16},"end":{"line":343,"column":47}},"loc":{"start":{"line":343,"column":47},"end":{"line":352,"column":null}},"line":343}},"branchMap":{"0":{"loc":{"start":{"line":62,"column":12},"end":{"line":62,"column":null}},"type":"binary-expr","locations":[{"start":{"line":62,"column":12},"end":{"line":62,"column":27}},{"start":{"line":62,"column":27},"end":{"line":62,"column":null}}],"line":62},"1":{"loc":{"start":{"line":63,"column":12},"end":{"line":63,"column":null}},"type":"binary-expr","locations":[{"start":{"line":63,"column":12},"end":{"line":63,"column":27}},{"start":{"line":63,"column":27},"end":{"line":63,"column":null}}],"line":63},"2":{"loc":{"start":{"line":64,"column":15},"end":{"line":64,"column":null}},"type":"binary-expr","locations":[{"start":{"line":64,"column":15},"end":{"line":64,"column":33}},{"start":{"line":64,"column":33},"end":{"line":64,"column":null}}],"line":64},"3":{"loc":{"start":{"line":69,"column":23},"end":{"line":69,"column":null}},"type":"binary-expr","locations":[{"start":{"line":69,"column":23},"end":{"line":69,"column":38}},{"start":{"line":69,"column":38},"end":{"line":69,"column":null}}],"line":69},"4":{"loc":{"start":{"line":78,"column":4},"end":{"line":80,"column":null}},"type":"if","locations":[{"start":{"line":78,"column":4},"end":{"line":80,"column":null}},{"start":{},"end":{}}],"line":78},"5":{"loc":{"start":{"line":84,"column":4},"end":{"line":89,"column":null}},"type":"if","locations":[{"start":{"line":84,"column":4},"end":{"line":89,"column":null}},{"start":{},"end":{}}],"line":84},"6":{"loc":{"start":{"line":113,"column":4},"end":{"line":124,"column":null}},"type":"if","locations":[{"start":{"line":113,"column":4},"end":{"line":124,"column":null}},{"start":{},"end":{}}],"line":113},"7":{"loc":{"start":{"line":134,"column":4},"end":{"line":136,"column":null}},"type":"if","locations":[{"start":{"line":134,"column":4},"end":{"line":136,"column":null}},{"start":{},"end":{}}],"line":134},"8":{"loc":{"start":{"line":139,"column":19},"end":{"line":141,"column":null}},"type":"cond-expr","locations":[{"start":{"line":140,"column":8},"end":{"line":140,"column":null}},{"start":{"line":141,"column":8},"end":{"line":141,"column":null}}],"line":139},"9":{"loc":{"start":{"line":144,"column":4},"end":{"line":153,"column":null}},"type":"if","locations":[{"start":{"line":144,"column":4},"end":{"line":153,"column":null}},{"start":{},"end":{}}],"line":144},"10":{"loc":{"start":{"line":158,"column":8},"end":{"line":162,"column":null}},"type":"if","locations":[{"start":{"line":158,"column":8},"end":{"line":162,"column":null}},{"start":{"line":160,"column":15},"end":{"line":162,"column":null}}],"line":158},"11":{"loc":{"start":{"line":177,"column":11},"end":{"line":177,"column":null}},"type":"binary-expr","locations":[{"start":{"line":177,"column":11},"end":{"line":177,"column":35}},{"start":{"line":177,"column":35},"end":{"line":177,"column":null}}],"line":177},"12":{"loc":{"start":{"line":198,"column":16},"end":{"line":198,"column":null}},"type":"binary-expr","locations":[{"start":{"line":198,"column":16},"end":{"line":198,"column":27}},{"start":{"line":198,"column":27},"end":{"line":198,"column":null}}],"line":198},"13":{"loc":{"start":{"line":201,"column":4},"end":{"line":204,"column":null}},"type":"if","locations":[{"start":{"line":201,"column":4},"end":{"line":204,"column":null}},{"start":{},"end":{}}],"line":201},"14":{"loc":{"start":{"line":207,"column":4},"end":{"line":210,"column":null}},"type":"if","locations":[{"start":{"line":207,"column":4},"end":{"line":210,"column":null}},{"start":{},"end":{}}],"line":207},"15":{"loc":{"start":{"line":213,"column":4},"end":{"line":222,"column":null}},"type":"switch","locations":[{"start":{"line":214,"column":6},"end":{"line":216,"column":null}},{"start":{"line":217,"column":6},"end":{"line":219,"column":null}},{"start":{"line":220,"column":6},"end":{"line":221,"column":null}}],"line":213},"16":{"loc":{"start":{"line":229,"column":4},"end":{"line":232,"column":null}},"type":"if","locations":[{"start":{"line":229,"column":4},"end":{"line":232,"column":null}},{"start":{},"end":{}}],"line":229},"17":{"loc":{"start":{"line":229,"column":8},"end":{"line":229,"column":39}},"type":"binary-expr","locations":[{"start":{"line":229,"column":8},"end":{"line":229,"column":23}},{"start":{"line":229,"column":23},"end":{"line":229,"column":39}}],"line":229},"18":{"loc":{"start":{"line":251,"column":4},"end":{"line":254,"column":null}},"type":"if","locations":[{"start":{"line":251,"column":4},"end":{"line":254,"column":null}},{"start":{},"end":{}}],"line":251},"19":{"loc":{"start":{"line":270,"column":4},"end":{"line":273,"column":null}},"type":"if","locations":[{"start":{"line":270,"column":4},"end":{"line":273,"column":null}},{"start":{},"end":{}}],"line":270},"20":{"loc":{"start":{"line":308,"column":6},"end":{"line":310,"column":null}},"type":"if","locations":[{"start":{"line":308,"column":6},"end":{"line":310,"column":null}},{"start":{},"end":{}}],"line":308},"21":{"loc":{"start":{"line":324,"column":6},"end":{"line":326,"column":null}},"type":"if","locations":[{"start":{"line":324,"column":6},"end":{"line":326,"column":null}},{"start":{},"end":{}}],"line":324},"22":{"loc":{"start":{"line":348,"column":6},"end":{"line":350,"column":null}},"type":"if","locations":[{"start":{"line":348,"column":6},"end":{"line":350,"column":null}},{"start":{},"end":{}}],"line":348}},"s":{"0":2,"1":2,"2":2,"3":2,"4":20,"5":20,"6":20,"7":20,"8":20,"9":20,"10":20,"11":17,"12":1,"13":16,"14":16,"15":1,"16":15,"17":11,"18":15,"19":15,"20":15,"21":15,"22":15,"23":15,"24":15,"25":15,"26":3,"27":3,"28":15,"29":15,"30":16,"31":1,"32":15,"33":16,"34":3,"35":3,"36":15,"37":15,"38":15,"39":0,"40":15,"41":15,"42":15,"43":15,"44":28,"45":1,"46":0,"47":11,"48":11,"49":7,"50":7,"51":4,"52":1,"53":1,"54":3,"55":1,"56":1,"57":1,"58":1,"59":1,"60":7,"61":0,"62":0,"63":7,"64":7,"65":0,"66":0,"67":1,"68":0,"69":0,"70":1,"71":1,"72":1,"73":1,"74":0,"75":0,"76":1,"77":1,"78":1,"79":4,"80":4,"81":16,"82":16,"83":2,"84":2,"85":0,"86":2,"87":2,"88":2,"89":1,"90":1,"91":1,"92":14,"93":14,"94":0,"95":15,"96":15,"97":16,"98":16,"99":0,"100":0},"f":{"0":20,"1":17,"2":11,"3":15,"4":15,"5":16,"6":15,"7":15,"8":28,"9":1,"10":0,"11":11,"12":7,"13":0,"14":1,"15":1,"16":4,"17":16,"18":15,"19":16},"b":{"0":[20,0],"1":[20,20],"2":[20,0],"3":[20,20],"4":[1,16],"5":[1,15],"6":[3,12],"7":[1,15],"8":[15,0],"9":[3,13],"10":[0,15],"11":[28,13],"12":[11,0],"13":[7,4],"14":[1,3],"15":[3,1,1],"16":[0,7],"17":[7,7],"18":[0,1],"19":[0,1],"20":[0,2],"21":[14,0],"22":[0,0]},"meta":{"lastBranch":23,"lastFunction":20,"lastStatement":101,"seen":{"s:27:6:27:Infinity":0,"s:30:21:30:Infinity":1,"s:33:21:33:Infinity":2,"s:36:6:36:Infinity":3,"s:51:34:51:Infinity":4,"s:52:38:52:Infinity":5,"f:54:2:54:Infinity":0,"s:61:4:65:Infinity":6,"b:62:12:62:27:62:27:62:Infinity":0,"b:63:12:63:27:63:27:63:Infinity":1,"b:64:15:64:33:64:33:64:Infinity":2,"s:66:4:66:Infinity":7,"s:67:4:67:Infinity":8,"s:68:4:68:Infinity":9,"s:69:4:69:Infinity":10,"b:69:23:69:38:69:38:69:Infinity":3,"f:76:8:76:31":1,"b:78:4:80:Infinity:undefined:undefined:undefined:undefined":4,"s:78:4:80:Infinity":11,"s:79:6:79:Infinity":12,"s:83:24:83:Infinity":13,"b:84:4:89:Infinity:undefined:undefined:undefined:undefined":5,"s:84:4:89:Infinity":14,"s:85:6:88:Infinity":15,"s:92:4:92:Infinity":16,"f:92:31:92:32":2,"s:92:45:92:73":17,"s:95:4:101:Infinity":18,"f:95:28:95:29":3,"s:96:6:96:Infinity":19,"s:97:6:100:Infinity":20,"f:97:62:97:68":4,"s:98:8:98:Infinity":21,"s:99:8:99:Infinity":22,"s:104:4:107:Infinity":23,"s:110:4:110:Infinity":24,"b:113:4:124:Infinity:undefined:undefined:undefined:undefined":6,"s:113:4:124:Infinity":25,"s:114:40:122:Infinity":26,"s:123:6:123:Infinity":27,"s:126:4:126:Infinity":28,"s:127:4:127:Infinity":29,"f:133:8:133:30":5,"b:134:4:136:Infinity:undefined:undefined:undefined:undefined":7,"s:134:4:136:Infinity":30,"s:135:6:135:Infinity":31,"s:139:19:141:Infinity":32,"b:140:8:140:Infinity:141:8:141:Infinity":8,"b:144:4:153:Infinity:undefined:undefined:undefined:undefined":9,"s:144:4:153:Infinity":33,"s:145:40:151:Infinity":34,"s:152:6:152:Infinity":35,"s:156:4:164:Infinity":36,"f:156:28:156:29":6,"s:157:6:163:Infinity":37,"f:157:25:157:26":7,"b:158:8:162:Infinity:160:15:162:Infinity":10,"s:158:8:162:Infinity":38,"s:159:10:159:Infinity":39,"s:161:10:161:Infinity":40,"s:166:4:166:Infinity":41,"s:167:4:167:Infinity":42,"s:170:4:170:Infinity":43,"f:176:2:176:23":8,"s:177:4:177:Infinity":44,"b:177:11:177:35:177:35:177:Infinity":11,"f:183:2:183:20":9,"s:184:4:184:Infinity":45,"f:190:2:190:23":10,"s:191:4:191:Infinity":46,"f:197:10:197:24":11,"s:198:16:198:Infinity":47,"b:198:16:198:27:198:27:198:Infinity":12,"b:201:4:204:Infinity:undefined:undefined:undefined:undefined":13,"s:201:4:204:Infinity":48,"s:202:6:202:Infinity":49,"s:203:6:203:Infinity":50,"b:207:4:210:Infinity:undefined:undefined:undefined:undefined":14,"s:207:4:210:Infinity":51,"s:208:6:208:Infinity":52,"s:209:6:209:Infinity":53,"b:214:6:216:Infinity:217:6:219:Infinity:220:6:221:Infinity":15,"s:213:4:222:Infinity":54,"s:215:8:215:Infinity":55,"s:216:8:216:Infinity":56,"s:218:8:218:Infinity":57,"s:219:8:219:Infinity":58,"s:221:8:221:Infinity":59,"f:228:10:228:21":12,"b:229:4:232:Infinity:undefined:undefined:undefined:undefined":16,"s:229:4:232:Infinity":60,"b:229:8:229:23:229:23:229:39":17,"s:230:6:230:Infinity":61,"s:231:6:231:Infinity":62,"s:234:10:239:Infinity":63,"s:241:4:244:Infinity":64,"f:241:32:241:33":13,"s:242:6:242:Infinity":65,"s:243:6:243:Infinity":66,"f:250:10:250:23":14,"b:251:4:254:Infinity:undefined:undefined:undefined:undefined":18,"s:251:4:254:Infinity":67,"s:252:6:252:Infinity":68,"s:253:6:253:Infinity":69,"s:256:19:256:Infinity":70,"s:257:37:261:Infinity":71,"s:263:4:263:Infinity":72,"f:269:10:269:23":15,"b:270:4:273:Infinity:undefined:undefined:undefined:undefined":19,"s:270:4:273:Infinity":73,"s:271:6:271:Infinity":74,"s:272:6:272:Infinity":75,"s:275:19:275:Infinity":76,"s:279:37:286:Infinity":77,"s:288:4:288:Infinity":78,"f:294:10:294:19":16,"s:295:4:295:Infinity":79,"s:296:4:296:Infinity":80,"f:303:16:303:62":17,"s:304:4:328:Infinity":81,"s:305:22:305:Infinity":82,"s:306:18:306:Infinity":83,"b:308:6:310:Infinity:undefined:undefined:undefined:undefined":20,"s:308:6:310:Infinity":84,"s:309:8:309:Infinity":85,"s:313:6:321:Infinity":86,"s:314:8:314:Infinity":87,"s:315:8:315:Infinity":88,"s:318:8:318:Infinity":89,"s:319:8:319:Infinity":90,"s:320:8:320:Infinity":91,"b:324:6:326:Infinity:undefined:undefined:undefined:undefined":21,"s:324:6:326:Infinity":92,"s:325:8:325:Infinity":93,"s:327:6:327:Infinity":94,"f:334:16:334:46":18,"s:336:4:336:Infinity":95,"s:337:4:337:Infinity":96,"f:343:16:343:47":19,"s:344:4:351:Infinity":97,"s:345:6:345:Infinity":98,"b:348:6:350:Infinity:undefined:undefined:undefined:undefined":22,"s:348:6:350:Infinity":99,"s:349:8:349:Infinity":100}}} +,"/Users/lukasmay/development/projects/codewalk-district/src/server/shutdown.ts": {"path":"/Users/lukasmay/development/projects/codewalk-district/src/server/shutdown.ts","statementMap":{"0":{"start":{"line":14,"column":28},"end":{"line":14,"column":null}},"1":{"start":{"line":35,"column":27},"end":{"line":35,"column":null}},"2":{"start":{"line":36,"column":27},"end":{"line":36,"column":null}},"3":{"start":{"line":44,"column":4},"end":{"line":44,"column":null}},"4":{"start":{"line":45,"column":4},"end":{"line":45,"column":null}},"5":{"start":{"line":46,"column":4},"end":{"line":46,"column":null}},"6":{"start":{"line":47,"column":4},"end":{"line":47,"column":null}},"7":{"start":{"line":56,"column":4},"end":{"line":56,"column":null}},"8":{"start":{"line":56,"column":32},"end":{"line":56,"column":60}},"9":{"start":{"line":59,"column":4},"end":{"line":59,"column":null}},"10":{"start":{"line":59,"column":31},"end":{"line":59,"column":58}},"11":{"start":{"line":62,"column":4},"end":{"line":62,"column":null}},"12":{"start":{"line":62,"column":31},"end":{"line":62,"column":58}},"13":{"start":{"line":71,"column":4},"end":{"line":77,"column":null}},"14":{"start":{"line":72,"column":6},"end":{"line":72,"column":null}},"15":{"start":{"line":73,"column":6},"end":{"line":76,"column":null}},"16":{"start":{"line":74,"column":8},"end":{"line":74,"column":null}},"17":{"start":{"line":75,"column":8},"end":{"line":75,"column":null}},"18":{"start":{"line":80,"column":4},"end":{"line":83,"column":null}},"19":{"start":{"line":81,"column":6},"end":{"line":81,"column":null}},"20":{"start":{"line":82,"column":6},"end":{"line":82,"column":null}},"21":{"start":{"line":85,"column":4},"end":{"line":85,"column":null}},"22":{"start":{"line":86,"column":4},"end":{"line":86,"column":null}},"23":{"start":{"line":89,"column":27},"end":{"line":92,"column":null}},"24":{"start":{"line":90,"column":6},"end":{"line":90,"column":null}},"25":{"start":{"line":91,"column":6},"end":{"line":91,"column":null}},"26":{"start":{"line":95,"column":4},"end":{"line":95,"column":null}},"27":{"start":{"line":97,"column":4},"end":{"line":106,"column":null}},"28":{"start":{"line":98,"column":6},"end":{"line":98,"column":null}},"29":{"start":{"line":99,"column":6},"end":{"line":99,"column":null}},"30":{"start":{"line":100,"column":6},"end":{"line":100,"column":null}},"31":{"start":{"line":101,"column":6},"end":{"line":101,"column":null}},"32":{"start":{"line":103,"column":6},"end":{"line":103,"column":null}},"33":{"start":{"line":104,"column":6},"end":{"line":104,"column":null}},"34":{"start":{"line":105,"column":6},"end":{"line":105,"column":null}},"35":{"start":{"line":114,"column":4},"end":{"line":114,"column":null}},"36":{"start":{"line":115,"column":4},"end":{"line":115,"column":null}},"37":{"start":{"line":118,"column":4},"end":{"line":118,"column":null}},"38":{"start":{"line":119,"column":4},"end":{"line":119,"column":null}},"39":{"start":{"line":122,"column":4},"end":{"line":125,"column":null}},"40":{"start":{"line":123,"column":6},"end":{"line":123,"column":null}},"41":{"start":{"line":124,"column":6},"end":{"line":124,"column":null}},"42":{"start":{"line":130,"column":4},"end":{"line":130,"column":null}}},"fnMap":{"0":{"name":"(anonymous_0)","decl":{"start":{"line":38,"column":2},"end":{"line":38,"column":null}},"loc":{"start":{"line":43,"column":4},"end":{"line":48,"column":null}},"line":43},"1":{"name":"(anonymous_1)","decl":{"start":{"line":54,"column":2},"end":{"line":54,"column":18}},"loc":{"start":{"line":54,"column":18},"end":{"line":63,"column":null}},"line":54},"2":{"name":"(anonymous_2)","decl":{"start":{"line":56,"column":26},"end":{"line":56,"column":32}},"loc":{"start":{"line":56,"column":32},"end":{"line":56,"column":60}},"line":56},"3":{"name":"(anonymous_3)","decl":{"start":{"line":59,"column":25},"end":{"line":59,"column":31}},"loc":{"start":{"line":59,"column":31},"end":{"line":59,"column":58}},"line":59},"4":{"name":"(anonymous_4)","decl":{"start":{"line":62,"column":25},"end":{"line":62,"column":31}},"loc":{"start":{"line":62,"column":31},"end":{"line":62,"column":58}},"line":62},"5":{"name":"(anonymous_5)","decl":{"start":{"line":69,"column":16},"end":{"line":69,"column":29}},"loc":{"start":{"line":69,"column":60},"end":{"line":107,"column":null}},"line":69},"6":{"name":"(anonymous_6)","decl":{"start":{"line":89,"column":38},"end":{"line":89,"column":44}},"loc":{"start":{"line":89,"column":44},"end":{"line":92,"column":7}},"line":89},"7":{"name":"(anonymous_7)","decl":{"start":{"line":112,"column":8},"end":{"line":112,"column":34}},"loc":{"start":{"line":112,"column":34},"end":{"line":134,"column":null}},"line":112}},"branchMap":{"0":{"loc":{"start":{"line":71,"column":4},"end":{"line":77,"column":null}},"type":"if","locations":[{"start":{"line":71,"column":4},"end":{"line":77,"column":null}},{"start":{},"end":{}}],"line":71},"1":{"loc":{"start":{"line":71,"column":8},"end":{"line":71,"column":52}},"type":"binary-expr","locations":[{"start":{"line":71,"column":8},"end":{"line":71,"column":31}},{"start":{"line":71,"column":31},"end":{"line":71,"column":52}}],"line":71},"2":{"loc":{"start":{"line":73,"column":6},"end":{"line":76,"column":null}},"type":"if","locations":[{"start":{"line":73,"column":6},"end":{"line":76,"column":null}},{"start":{},"end":{}}],"line":73},"3":{"loc":{"start":{"line":80,"column":4},"end":{"line":83,"column":null}},"type":"if","locations":[{"start":{"line":80,"column":4},"end":{"line":83,"column":null}},{"start":{},"end":{}}],"line":80},"4":{"loc":{"start":{"line":122,"column":4},"end":{"line":125,"column":null}},"type":"if","locations":[{"start":{"line":122,"column":4},"end":{"line":125,"column":null}},{"start":{},"end":{}}],"line":122}},"s":{"0":1,"1":6,"2":6,"3":6,"4":6,"5":6,"6":6,"7":3,"8":0,"9":3,"10":0,"11":3,"12":0,"13":0,"14":0,"15":0,"16":0,"17":0,"18":0,"19":0,"20":0,"21":0,"22":0,"23":0,"24":0,"25":0,"26":0,"27":0,"28":0,"29":0,"30":0,"31":0,"32":0,"33":0,"34":0,"35":3,"36":3,"37":3,"38":3,"39":3,"40":0,"41":0,"42":3},"f":{"0":6,"1":3,"2":0,"3":0,"4":0,"5":0,"6":0,"7":3},"b":{"0":[0,0],"1":[0,0],"2":[0,0],"3":[0,0],"4":[0,3]},"meta":{"lastBranch":5,"lastFunction":8,"lastStatement":43,"seen":{"s:14:28:14:Infinity":0,"s:35:27:35:Infinity":1,"s:36:27:36:Infinity":2,"f:38:2:38:Infinity":0,"s:44:4:44:Infinity":3,"s:45:4:45:Infinity":4,"s:46:4:46:Infinity":5,"s:47:4:47:Infinity":6,"f:54:2:54:18":1,"s:56:4:56:Infinity":7,"f:56:26:56:32":2,"s:56:32:56:60":8,"s:59:4:59:Infinity":9,"f:59:25:59:31":3,"s:59:31:59:58":10,"s:62:4:62:Infinity":11,"f:62:25:62:31":4,"s:62:31:62:58":12,"f:69:16:69:29":5,"b:71:4:77:Infinity:undefined:undefined:undefined:undefined":0,"s:71:4:77:Infinity":13,"b:71:8:71:31:71:31:71:52":1,"s:72:6:72:Infinity":14,"b:73:6:76:Infinity:undefined:undefined:undefined:undefined":2,"s:73:6:76:Infinity":15,"s:74:8:74:Infinity":16,"s:75:8:75:Infinity":17,"b:80:4:83:Infinity:undefined:undefined:undefined:undefined":3,"s:80:4:83:Infinity":18,"s:81:6:81:Infinity":19,"s:82:6:82:Infinity":20,"s:85:4:85:Infinity":21,"s:86:4:86:Infinity":22,"s:89:27:92:Infinity":23,"f:89:38:89:44":6,"s:90:6:90:Infinity":24,"s:91:6:91:Infinity":25,"s:95:4:95:Infinity":26,"s:97:4:106:Infinity":27,"s:98:6:98:Infinity":28,"s:99:6:99:Infinity":29,"s:100:6:100:Infinity":30,"s:101:6:101:Infinity":31,"s:103:6:103:Infinity":32,"s:104:6:104:Infinity":33,"s:105:6:105:Infinity":34,"f:112:8:112:34":7,"s:114:4:114:Infinity":35,"s:115:4:115:Infinity":36,"s:118:4:118:Infinity":37,"s:119:4:119:Infinity":38,"b:122:4:125:Infinity:undefined:undefined:undefined:undefined":4,"s:122:4:125:Infinity":39,"s:123:6:123:Infinity":40,"s:124:6:124:Infinity":41,"s:130:4:130:Infinity":42}}} +,"/Users/lukasmay/development/projects/codewalk-district/src/server/trpc-adapter.ts": {"path":"/Users/lukasmay/development/projects/codewalk-district/src/server/trpc-adapter.ts","statementMap":{"0":{"start":{"line":90,"column":2},"end":{"line":187,"column":null}},"1":{"start":{"line":92,"column":21},"end":{"line":92,"column":null}},"2":{"start":{"line":93,"column":17},"end":{"line":93,"column":null}},"3":{"start":{"line":94,"column":16},"end":{"line":94,"column":null}},"4":{"start":{"line":98,"column":4},"end":{"line":108,"column":null}},"5":{"start":{"line":99,"column":6},"end":{"line":107,"column":null}},"6":{"start":{"line":100,"column":19},"end":{"line":100,"column":null}},"7":{"start":{"line":101,"column":8},"end":{"line":103,"column":null}},"8":{"start":{"line":102,"column":10},"end":{"line":102,"column":null}},"9":{"start":{"line":104,"column":8},"end":{"line":106,"column":null}},"10":{"start":{"line":105,"column":10},"end":{"line":105,"column":null}},"11":{"start":{"line":111,"column":20},"end":{"line":111,"column":null}},"12":{"start":{"line":112,"column":4},"end":{"line":120,"column":null}},"13":{"start":{"line":113,"column":6},"end":{"line":119,"column":null}},"14":{"start":{"line":114,"column":8},"end":{"line":118,"column":null}},"15":{"start":{"line":115,"column":10},"end":{"line":115,"column":null}},"16":{"start":{"line":115,"column":31},"end":{"line":115,"column":53}},"17":{"start":{"line":117,"column":10},"end":{"line":117,"column":null}},"18":{"start":{"line":123,"column":25},"end":{"line":127,"column":null}},"19":{"start":{"line":130,"column":26},"end":{"line":159,"column":null}},"20":{"start":{"line":134,"column":21},"end":{"line":158,"column":null}},"21":{"start":{"line":162,"column":4},"end":{"line":162,"column":null}},"22":{"start":{"line":165,"column":4},"end":{"line":167,"column":null}},"23":{"start":{"line":166,"column":6},"end":{"line":166,"column":null}},"24":{"start":{"line":170,"column":4},"end":{"line":186,"column":null}},"25":{"start":{"line":171,"column":21},"end":{"line":171,"column":null}},"26":{"start":{"line":172,"column":19},"end":{"line":181,"column":null}},"27":{"start":{"line":173,"column":8},"end":{"line":180,"column":null}},"28":{"start":{"line":174,"column":34},"end":{"line":174,"column":null}},"29":{"start":{"line":175,"column":10},"end":{"line":178,"column":null}},"30":{"start":{"line":176,"column":12},"end":{"line":176,"column":null}},"31":{"start":{"line":177,"column":12},"end":{"line":177,"column":null}},"32":{"start":{"line":179,"column":10},"end":{"line":179,"column":null}},"33":{"start":{"line":182,"column":6},"end":{"line":182,"column":null}},"34":{"start":{"line":182,"column":25},"end":{"line":182,"column":34}},"35":{"start":{"line":184,"column":27},"end":{"line":184,"column":null}},"36":{"start":{"line":185,"column":6},"end":{"line":185,"column":null}}},"fnMap":{"0":{"name":"createTrpcHandler","decl":{"start":{"line":89,"column":16},"end":{"line":89,"column":34}},"loc":{"start":{"line":89,"column":63},"end":{"line":188,"column":null}},"line":89},"1":{"name":"(anonymous_1)","decl":{"start":{"line":90,"column":9},"end":{"line":90,"column":16}},"loc":{"start":{"line":90,"column":77},"end":{"line":187,"column":null}},"line":90},"2":{"name":"(anonymous_2)","decl":{"start":{"line":99,"column":39},"end":{"line":99,"column":40}},"loc":{"start":{"line":99,"column":52},"end":{"line":107,"column":7}},"line":99},"3":{"name":"(anonymous_3)","decl":{"start":{"line":101,"column":23},"end":{"line":101,"column":24}},"loc":{"start":{"line":101,"column":42},"end":{"line":103,"column":9}},"line":101},"4":{"name":"(anonymous_4)","decl":{"start":{"line":104,"column":22},"end":{"line":104,"column":28}},"loc":{"start":{"line":104,"column":28},"end":{"line":106,"column":9}},"line":104},"5":{"name":"(anonymous_5)","decl":{"start":{"line":115,"column":24},"end":{"line":115,"column":25}},"loc":{"start":{"line":115,"column":31},"end":{"line":115,"column":53}},"line":115},"6":{"name":"(anonymous_6)","decl":{"start":{"line":134,"column":21},"end":{"line":134,"column":null}},"loc":{"start":{"line":134,"column":21},"end":{"line":158,"column":null}},"line":134},"7":{"name":"(anonymous_7)","decl":{"start":{"line":165,"column":34},"end":{"line":165,"column":35}},"loc":{"start":{"line":165,"column":50},"end":{"line":167,"column":5}},"line":165},"8":{"name":"(anonymous_8)","decl":{"start":{"line":172,"column":19},"end":{"line":172,"column":31}},"loc":{"start":{"line":172,"column":31},"end":{"line":181,"column":null}},"line":172},"9":{"name":"(anonymous_9)","decl":{"start":{"line":182,"column":19},"end":{"line":182,"column":25}},"loc":{"start":{"line":182,"column":25},"end":{"line":182,"column":34}},"line":182}},"branchMap":{"0":{"loc":{"start":{"line":93,"column":17},"end":{"line":93,"column":null}},"type":"binary-expr","locations":[{"start":{"line":93,"column":17},"end":{"line":93,"column":37}},{"start":{"line":93,"column":37},"end":{"line":93,"column":null}}],"line":93},"1":{"loc":{"start":{"line":94,"column":24},"end":{"line":94,"column":40}},"type":"binary-expr","locations":[{"start":{"line":94,"column":24},"end":{"line":94,"column":35}},{"start":{"line":94,"column":35},"end":{"line":94,"column":40}}],"line":94},"2":{"loc":{"start":{"line":98,"column":4},"end":{"line":108,"column":null}},"type":"if","locations":[{"start":{"line":98,"column":4},"end":{"line":108,"column":null}},{"start":{},"end":{}}],"line":98},"3":{"loc":{"start":{"line":98,"column":8},"end":{"line":98,"column":55}},"type":"binary-expr","locations":[{"start":{"line":98,"column":8},"end":{"line":98,"column":32}},{"start":{"line":98,"column":32},"end":{"line":98,"column":55}}],"line":98},"4":{"loc":{"start":{"line":113,"column":6},"end":{"line":119,"column":null}},"type":"if","locations":[{"start":{"line":113,"column":6},"end":{"line":119,"column":null}},{"start":{},"end":{}}],"line":113},"5":{"loc":{"start":{"line":114,"column":8},"end":{"line":118,"column":null}},"type":"if","locations":[{"start":{"line":114,"column":8},"end":{"line":118,"column":null}},{"start":{"line":116,"column":15},"end":{"line":118,"column":null}}],"line":114},"6":{"loc":{"start":{"line":126,"column":12},"end":{"line":126,"column":null}},"type":"binary-expr","locations":[{"start":{"line":126,"column":12},"end":{"line":126,"column":20}},{"start":{"line":126,"column":20},"end":{"line":126,"column":null}}],"line":126},"7":{"loc":{"start":{"line":170,"column":4},"end":{"line":186,"column":null}},"type":"if","locations":[{"start":{"line":170,"column":4},"end":{"line":186,"column":null}},{"start":{"line":183,"column":11},"end":{"line":186,"column":null}}],"line":170},"8":{"loc":{"start":{"line":175,"column":10},"end":{"line":178,"column":null}},"type":"if","locations":[{"start":{"line":175,"column":10},"end":{"line":178,"column":null}},{"start":{},"end":{}}],"line":175}},"s":{"0":7,"1":7,"2":7,"3":7,"4":7,"5":0,"6":0,"7":0,"8":0,"9":0,"10":0,"11":7,"12":7,"13":49,"14":49,"15":0,"16":0,"17":49,"18":7,"19":7,"20":7,"21":7,"22":7,"23":14,"24":7,"25":7,"26":7,"27":7,"28":14,"29":14,"30":7,"31":7,"32":7,"33":7,"34":0,"35":0,"36":0},"f":{"0":7,"1":7,"2":0,"3":0,"4":0,"5":0,"6":7,"7":14,"8":7,"9":0},"b":{"0":[7,0],"1":[7,0],"2":[0,7],"3":[7,0],"4":[49,0],"5":[0,49],"6":[7,7],"7":[7,0],"8":[7,7]},"meta":{"lastBranch":9,"lastFunction":10,"lastStatement":37,"seen":{"f:89:16:89:34":0,"s:90:2:187:Infinity":0,"f:90:9:90:16":1,"s:92:21:92:Infinity":1,"s:93:17:93:Infinity":2,"b:93:17:93:37:93:37:93:Infinity":0,"s:94:16:94:Infinity":3,"b:94:24:94:35:94:35:94:40":1,"b:98:4:108:Infinity:undefined:undefined:undefined:undefined":2,"s:98:4:108:Infinity":4,"b:98:8:98:32:98:32:98:55":3,"s:99:6:107:Infinity":5,"f:99:39:99:40":2,"s:100:19:100:Infinity":6,"s:101:8:103:Infinity":7,"f:101:23:101:24":3,"s:102:10:102:Infinity":8,"s:104:8:106:Infinity":9,"f:104:22:104:28":4,"s:105:10:105:Infinity":10,"s:111:20:111:Infinity":11,"s:112:4:120:Infinity":12,"b:113:6:119:Infinity:undefined:undefined:undefined:undefined":4,"s:113:6:119:Infinity":13,"b:114:8:118:Infinity:116:15:118:Infinity":5,"s:114:8:118:Infinity":14,"s:115:10:115:Infinity":15,"f:115:24:115:25":5,"s:115:31:115:53":16,"s:117:10:117:Infinity":17,"s:123:25:127:Infinity":18,"b:126:12:126:20:126:20:126:Infinity":6,"s:130:26:159:Infinity":19,"f:134:21:134:Infinity":6,"s:134:21:158:Infinity":20,"s:162:4:162:Infinity":21,"s:165:4:167:Infinity":22,"f:165:34:165:35":7,"s:166:6:166:Infinity":23,"b:170:4:186:Infinity:183:11:186:Infinity":7,"s:170:4:186:Infinity":24,"s:171:21:171:Infinity":25,"s:172:19:181:Infinity":26,"f:172:19:172:31":8,"s:173:8:180:Infinity":27,"s:174:34:174:Infinity":28,"b:175:10:178:Infinity:undefined:undefined:undefined:undefined":8,"s:175:10:178:Infinity":29,"s:176:12:176:Infinity":30,"s:177:12:177:Infinity":31,"s:179:10:179:Infinity":32,"s:182:6:182:Infinity":33,"f:182:19:182:25":9,"s:182:25:182:34":34,"s:184:27:184:Infinity":35,"s:185:6:185:Infinity":36}}} +,"/Users/lukasmay/development/projects/codewalk-district/src/test/fixtures.ts": {"path":"/Users/lukasmay/development/projects/codewalk-district/src/test/fixtures.ts","statementMap":{"0":{"start":{"line":102,"column":25},"end":{"line":102,"column":null}},"1":{"start":{"line":103,"column":20},"end":{"line":103,"column":null}},"2":{"start":{"line":104,"column":19},"end":{"line":104,"column":null}},"3":{"start":{"line":107,"column":20},"end":{"line":107,"column":null}},"4":{"start":{"line":108,"column":24},"end":{"line":108,"column":null}},"5":{"start":{"line":109,"column":19},"end":{"line":109,"column":null}},"6":{"start":{"line":112,"column":83},"end":{"line":112,"column":null}},"7":{"start":{"line":115,"column":21},"end":{"line":118,"column":null}},"8":{"start":{"line":121,"column":2},"end":{"line":172,"column":null}},"9":{"start":{"line":122,"column":18},"end":{"line":126,"column":null}},"10":{"start":{"line":127,"column":4},"end":{"line":127,"column":null}},"11":{"start":{"line":130,"column":20},"end":{"line":130,"column":null}},"12":{"start":{"line":131,"column":4},"end":{"line":171,"column":null}},"13":{"start":{"line":133,"column":25},"end":{"line":143,"column":null}},"14":{"start":{"line":144,"column":6},"end":{"line":144,"column":null}},"15":{"start":{"line":147,"column":23},"end":{"line":147,"column":null}},"16":{"start":{"line":148,"column":6},"end":{"line":170,"column":null}},"17":{"start":{"line":149,"column":21},"end":{"line":160,"column":null}},"18":{"start":{"line":161,"column":8},"end":{"line":161,"column":null}},"19":{"start":{"line":164,"column":8},"end":{"line":169,"column":null}},"20":{"start":{"line":165,"column":10},"end":{"line":168,"column":null}},"21":{"start":{"line":175,"column":2},"end":{"line":192,"column":null}},"22":{"start":{"line":176,"column":4},"end":{"line":191,"column":null}},"23":{"start":{"line":177,"column":30},"end":{"line":177,"column":null}},"24":{"start":{"line":178,"column":6},"end":{"line":182,"column":null}},"25":{"start":{"line":179,"column":8},"end":{"line":181,"column":null}},"26":{"start":{"line":185,"column":6},"end":{"line":190,"column":null}},"27":{"start":{"line":194,"column":2},"end":{"line":199,"column":null}},"28":{"start":{"line":214,"column":49},"end":{"line":231,"column":null}},"29":{"start":{"line":240,"column":51},"end":{"line":263,"column":null}},"30":{"start":{"line":272,"column":50},"end":{"line":316,"column":null}}},"fnMap":{"0":{"name":"seedFixture","decl":{"start":{"line":97,"column":22},"end":{"line":97,"column":null}},"loc":{"start":{"line":100,"column":26},"end":{"line":200,"column":null}},"line":100}},"branchMap":{"0":{"loc":{"start":{"line":155,"column":20},"end":{"line":155,"column":null}},"type":"binary-expr","locations":[{"start":{"line":155,"column":20},"end":{"line":155,"column":44}},{"start":{"line":155,"column":44},"end":{"line":155,"column":null}}],"line":155},"1":{"loc":{"start":{"line":157,"column":20},"end":{"line":157,"column":null}},"type":"binary-expr","locations":[{"start":{"line":157,"column":20},"end":{"line":157,"column":44}},{"start":{"line":157,"column":44},"end":{"line":157,"column":null}}],"line":157},"2":{"loc":{"start":{"line":164,"column":8},"end":{"line":169,"column":null}},"type":"if","locations":[{"start":{"line":164,"column":8},"end":{"line":169,"column":null}},{"start":{},"end":{}}],"line":164},"3":{"loc":{"start":{"line":164,"column":12},"end":{"line":164,"column":71}},"type":"binary-expr","locations":[{"start":{"line":164,"column":12},"end":{"line":164,"column":37}},{"start":{"line":164,"column":37},"end":{"line":164,"column":71}}],"line":164},"4":{"loc":{"start":{"line":178,"column":6},"end":{"line":182,"column":null}},"type":"if","locations":[{"start":{"line":178,"column":6},"end":{"line":182,"column":null}},{"start":{},"end":{}}],"line":178}},"s":{"0":48,"1":48,"2":48,"3":48,"4":48,"5":48,"6":48,"7":48,"8":48,"9":53,"10":53,"11":53,"12":53,"13":67,"14":67,"15":67,"16":67,"17":158,"18":158,"19":158,"20":93,"21":48,"22":93,"23":98,"24":98,"25":0,"26":98,"27":48,"28":8,"29":8,"30":8},"f":{"0":48},"b":{"0":[158,158],"1":[158,0],"2":[93,65],"3":[158,93],"4":[0,98]},"meta":{"lastBranch":5,"lastFunction":1,"lastStatement":31,"seen":{"f:97:22:97:Infinity":0,"s:102:25:102:Infinity":0,"s:103:20:103:Infinity":1,"s:104:19:104:Infinity":2,"s:107:20:107:Infinity":3,"s:108:24:108:Infinity":4,"s:109:19:109:Infinity":5,"s:112:83:112:Infinity":6,"s:115:21:118:Infinity":7,"s:121:2:172:Infinity":8,"s:122:18:126:Infinity":9,"s:127:4:127:Infinity":10,"s:130:20:130:Infinity":11,"s:131:4:171:Infinity":12,"s:133:25:143:Infinity":13,"s:144:6:144:Infinity":14,"s:147:23:147:Infinity":15,"s:148:6:170:Infinity":16,"s:149:21:160:Infinity":17,"b:155:20:155:44:155:44:155:Infinity":0,"b:157:20:157:44:157:44:157:Infinity":1,"s:161:8:161:Infinity":18,"b:164:8:169:Infinity:undefined:undefined:undefined:undefined":2,"s:164:8:169:Infinity":19,"b:164:12:164:37:164:37:164:71":3,"s:165:10:168:Infinity":20,"s:175:2:192:Infinity":21,"s:176:4:191:Infinity":22,"s:177:30:177:Infinity":23,"b:178:6:182:Infinity:undefined:undefined:undefined:undefined":4,"s:178:6:182:Infinity":24,"s:179:8:181:Infinity":25,"s:185:6:190:Infinity":26,"s:194:2:199:Infinity":27,"s:214:49:231:Infinity":28,"s:240:51:263:Infinity":29,"s:272:50:316:Infinity":30}}} +,"/Users/lukasmay/development/projects/codewalk-district/src/test/harness.ts": {"path":"/Users/lukasmay/development/projects/codewalk-district/src/test/harness.ts","statementMap":{"0":{"start":{"line":48,"column":45},"end":{"line":48,"column":null}},"1":{"start":{"line":49,"column":51},"end":{"line":49,"column":null}},"2":{"start":{"line":56,"column":4},"end":{"line":56,"column":null}},"3":{"start":{"line":60,"column":31},"end":{"line":65,"column":null}},"4":{"start":{"line":66,"column":4},"end":{"line":66,"column":null}},"5":{"start":{"line":67,"column":4},"end":{"line":67,"column":null}},"6":{"start":{"line":71,"column":4},"end":{"line":73,"column":null}},"7":{"start":{"line":72,"column":6},"end":{"line":72,"column":null}},"8":{"start":{"line":74,"column":4},"end":{"line":74,"column":null}},"9":{"start":{"line":75,"column":4},"end":{"line":75,"column":null}},"10":{"start":{"line":79,"column":4},"end":{"line":79,"column":null}},"11":{"start":{"line":83,"column":4},"end":{"line":83,"column":null}},"12":{"start":{"line":87,"column":4},"end":{"line":89,"column":null}},"13":{"start":{"line":88,"column":6},"end":{"line":88,"column":null}},"14":{"start":{"line":90,"column":4},"end":{"line":93,"column":null}},"15":{"start":{"line":97,"column":4},"end":{"line":99,"column":null}},"16":{"start":{"line":98,"column":6},"end":{"line":98,"column":null}},"17":{"start":{"line":102,"column":25},"end":{"line":102,"column":null}},"18":{"start":{"line":103,"column":4},"end":{"line":105,"column":null}},"19":{"start":{"line":104,"column":6},"end":{"line":104,"column":null}},"20":{"start":{"line":107,"column":4},"end":{"line":110,"column":null}},"21":{"start":{"line":118,"column":4},"end":{"line":118,"column":null}},"22":{"start":{"line":119,"column":4},"end":{"line":119,"column":null}},"23":{"start":{"line":133,"column":33},"end":{"line":133,"column":null}},"24":{"start":{"line":136,"column":4},"end":{"line":136,"column":null}},"25":{"start":{"line":137,"column":4},"end":{"line":137,"column":null}},"26":{"start":{"line":144,"column":4},"end":{"line":144,"column":null}},"27":{"start":{"line":144,"column":44},"end":{"line":144,"column":59}},"28":{"start":{"line":151,"column":4},"end":{"line":151,"column":null}},"29":{"start":{"line":162,"column":6},"end":{"line":162,"column":null}},"30":{"start":{"line":389,"column":8},"end":{"line":389,"column":null}},"31":{"start":{"line":392,"column":19},"end":{"line":392,"column":null}},"32":{"start":{"line":395,"column":23},"end":{"line":395,"column":null}},"33":{"start":{"line":396,"column":26},"end":{"line":396,"column":null}},"34":{"start":{"line":399,"column":8},"end":{"line":399,"column":null}},"35":{"start":{"line":400,"column":104},"end":{"line":400,"column":null}},"36":{"start":{"line":403,"column":26},"end":{"line":408,"column":null}},"37":{"start":{"line":410,"column":31},"end":{"line":415,"column":null}},"38":{"start":{"line":417,"column":30},"end":{"line":423,"column":null}},"39":{"start":{"line":426,"column":8},"end":{"line":438,"column":null}},"40":{"start":{"line":441,"column":17},"end":{"line":441,"column":null}},"41":{"start":{"line":444,"column":31},"end":{"line":617,"column":null}},"42":{"start":{"line":466,"column":18},"end":{"line":466,"column":null}},"43":{"start":{"line":469,"column":6},"end":{"line":469,"column":null}},"44":{"start":{"line":473,"column":6},"end":{"line":473,"column":null}},"45":{"start":{"line":480,"column":6},"end":{"line":480,"column":null}},"46":{"start":{"line":489,"column":6},"end":{"line":492,"column":null}},"47":{"start":{"line":496,"column":6},"end":{"line":496,"column":null}},"48":{"start":{"line":499,"column":46},"end":{"line":499,"column":null}},"49":{"start":{"line":501,"column":39},"end":{"line":501,"column":null}},"50":{"start":{"line":503,"column":40},"end":{"line":503,"column":null}},"51":{"start":{"line":505,"column":23},"end":{"line":505,"column":null}},"52":{"start":{"line":508,"column":6},"end":{"line":508,"column":null}},"53":{"start":{"line":509,"column":6},"end":{"line":509,"column":null}},"54":{"start":{"line":510,"column":6},"end":{"line":510,"column":null}},"55":{"start":{"line":514,"column":25},"end":{"line":514,"column":null}},"56":{"start":{"line":525,"column":6},"end":{"line":529,"column":null}},"57":{"start":{"line":536,"column":6},"end":{"line":540,"column":null}},"58":{"start":{"line":547,"column":6},"end":{"line":551,"column":null}},"59":{"start":{"line":558,"column":6},"end":{"line":562,"column":null}},"60":{"start":{"line":569,"column":6},"end":{"line":573,"column":null}},"61":{"start":{"line":581,"column":6},"end":{"line":585,"column":null}},"62":{"start":{"line":582,"column":8},"end":{"line":582,"column":null}},"63":{"start":{"line":584,"column":8},"end":{"line":584,"column":null}},"64":{"start":{"line":589,"column":6},"end":{"line":589,"column":null}},"65":{"start":{"line":593,"column":6},"end":{"line":593,"column":null}},"66":{"start":{"line":600,"column":6},"end":{"line":600,"column":null}},"67":{"start":{"line":604,"column":6},"end":{"line":611,"column":null}},"68":{"start":{"line":615,"column":6},"end":{"line":615,"column":null}},"69":{"start":{"line":619,"column":2},"end":{"line":619,"column":null}}},"fnMap":{"0":{"name":"(anonymous_0)","decl":{"start":{"line":55,"column":2},"end":{"line":55,"column":17}},"loc":{"start":{"line":55,"column":64},"end":{"line":57,"column":null}},"line":55},"1":{"name":"(anonymous_1)","decl":{"start":{"line":59,"column":8},"end":{"line":59,"column":15}},"loc":{"start":{"line":59,"column":83},"end":{"line":68,"column":null}},"line":59},"2":{"name":"(anonymous_2)","decl":{"start":{"line":70,"column":8},"end":{"line":70,"column":15}},"loc":{"start":{"line":70,"column":42},"end":{"line":76,"column":null}},"line":70},"3":{"name":"(anonymous_3)","decl":{"start":{"line":78,"column":8},"end":{"line":78,"column":36}},"loc":{"start":{"line":78,"column":36},"end":{"line":80,"column":null}},"line":78},"4":{"name":"(anonymous_4)","decl":{"start":{"line":82,"column":8},"end":{"line":82,"column":12}},"loc":{"start":{"line":82,"column":50},"end":{"line":84,"column":null}},"line":82},"5":{"name":"(anonymous_5)","decl":{"start":{"line":86,"column":8},"end":{"line":86,"column":13}},"loc":{"start":{"line":86,"column":48},"end":{"line":94,"column":null}},"line":86},"6":{"name":"(anonymous_6)","decl":{"start":{"line":96,"column":8},"end":{"line":96,"column":14}},"loc":{"start":{"line":96,"column":70},"end":{"line":111,"column":null}},"line":96},"7":{"name":"(anonymous_7)","decl":{"start":{"line":117,"column":2},"end":{"line":117,"column":16}},"loc":{"start":{"line":117,"column":16},"end":{"line":120,"column":null}},"line":117},"8":{"name":"(anonymous_8)","decl":{"start":{"line":135,"column":2},"end":{"line":135,"column":30}},"loc":{"start":{"line":135,"column":46},"end":{"line":138,"column":null}},"line":135},"9":{"name":"(anonymous_9)","decl":{"start":{"line":143,"column":2},"end":{"line":143,"column":18}},"loc":{"start":{"line":143,"column":47},"end":{"line":145,"column":null}},"line":143},"10":{"name":"(anonymous_10)","decl":{"start":{"line":144,"column":37},"end":{"line":144,"column":38}},"loc":{"start":{"line":144,"column":44},"end":{"line":144,"column":59}},"line":144},"11":{"name":"(anonymous_11)","decl":{"start":{"line":150,"column":2},"end":{"line":150,"column":22}},"loc":{"start":{"line":150,"column":22},"end":{"line":152,"column":null}},"line":150},"12":{"name":"createTestHarness","decl":{"start":{"line":387,"column":16},"end":{"line":387,"column":49}},"loc":{"start":{"line":387,"column":49},"end":{"line":620,"column":null}},"line":387},"13":{"name":"(anonymous_13)","decl":{"start":{"line":466,"column":17},"end":{"line":466,"column":18}},"loc":{"start":{"line":466,"column":18},"end":{"line":466,"column":null}},"line":466},"14":{"name":"(anonymous_14)","decl":{"start":{"line":468,"column":22},"end":{"line":468,"column":23}},"loc":{"start":{"line":468,"column":74},"end":{"line":470,"column":null}},"line":468},"15":{"name":"(anonymous_15)","decl":{"start":{"line":472,"column":18},"end":{"line":472,"column":19}},"loc":{"start":{"line":472,"column":58},"end":{"line":474,"column":null}},"line":472},"16":{"name":"(anonymous_16)","decl":{"start":{"line":476,"column":23},"end":{"line":476,"column":null}},"loc":{"start":{"line":479,"column":9},"end":{"line":481,"column":null}},"line":479},"17":{"name":"(anonymous_17)","decl":{"start":{"line":483,"column":22},"end":{"line":483,"column":null}},"loc":{"start":{"line":488,"column":9},"end":{"line":493,"column":null}},"line":488},"18":{"name":"(anonymous_18)","decl":{"start":{"line":495,"column":19},"end":{"line":495,"column":20}},"loc":{"start":{"line":495,"column":57},"end":{"line":497,"column":null}},"line":495},"19":{"name":"(anonymous_19)","decl":{"start":{"line":499,"column":25},"end":{"line":499,"column":26}},"loc":{"start":{"line":499,"column":46},"end":{"line":499,"column":null}},"line":499},"20":{"name":"(anonymous_20)","decl":{"start":{"line":501,"column":21},"end":{"line":501,"column":22}},"loc":{"start":{"line":501,"column":39},"end":{"line":501,"column":null}},"line":501},"21":{"name":"(anonymous_21)","decl":{"start":{"line":503,"column":22},"end":{"line":503,"column":23}},"loc":{"start":{"line":503,"column":40},"end":{"line":503,"column":null}},"line":503},"22":{"name":"(anonymous_22)","decl":{"start":{"line":505,"column":17},"end":{"line":505,"column":23}},"loc":{"start":{"line":505,"column":23},"end":{"line":505,"column":null}},"line":505},"23":{"name":"(anonymous_23)","decl":{"start":{"line":507,"column":13},"end":{"line":507,"column":19}},"loc":{"start":{"line":507,"column":19},"end":{"line":511,"column":null}},"line":507},"24":{"name":"(anonymous_24)","decl":{"start":{"line":514,"column":19},"end":{"line":514,"column":25}},"loc":{"start":{"line":514,"column":25},"end":{"line":514,"column":null}},"line":514},"25":{"name":"(anonymous_25)","decl":{"start":{"line":520,"column":33},"end":{"line":520,"column":null}},"loc":{"start":{"line":524,"column":9},"end":{"line":530,"column":null}},"line":524},"26":{"name":"(anonymous_26)","decl":{"start":{"line":532,"column":34},"end":{"line":532,"column":null}},"loc":{"start":{"line":535,"column":9},"end":{"line":541,"column":null}},"line":535},"27":{"name":"(anonymous_27)","decl":{"start":{"line":543,"column":30},"end":{"line":543,"column":null}},"loc":{"start":{"line":546,"column":9},"end":{"line":552,"column":null}},"line":546},"28":{"name":"(anonymous_28)","decl":{"start":{"line":554,"column":32},"end":{"line":554,"column":null}},"loc":{"start":{"line":557,"column":9},"end":{"line":563,"column":null}},"line":557},"29":{"name":"(anonymous_29)","decl":{"start":{"line":565,"column":33},"end":{"line":565,"column":null}},"loc":{"start":{"line":568,"column":9},"end":{"line":574,"column":null}},"line":568},"30":{"name":"(anonymous_30)","decl":{"start":{"line":580,"column":19},"end":{"line":580,"column":26}},"loc":{"start":{"line":580,"column":41},"end":{"line":586,"column":null}},"line":580},"31":{"name":"(anonymous_31)","decl":{"start":{"line":588,"column":15},"end":{"line":588,"column":16}},"loc":{"start":{"line":588,"column":41},"end":{"line":590,"column":null}},"line":588},"32":{"name":"(anonymous_32)","decl":{"start":{"line":592,"column":22},"end":{"line":592,"column":23}},"loc":{"start":{"line":592,"column":40},"end":{"line":594,"column":null}},"line":592},"33":{"name":"(anonymous_33)","decl":{"start":{"line":596,"column":26},"end":{"line":596,"column":null}},"loc":{"start":{"line":599,"column":9},"end":{"line":601,"column":null}},"line":599},"34":{"name":"(anonymous_34)","decl":{"start":{"line":603,"column":22},"end":{"line":603,"column":29}},"loc":{"start":{"line":603,"column":85},"end":{"line":612,"column":null}},"line":603},"35":{"name":"(anonymous_35)","decl":{"start":{"line":614,"column":19},"end":{"line":614,"column":20}},"loc":{"start":{"line":614,"column":45},"end":{"line":616,"column":null}},"line":614}},"branchMap":{"0":{"loc":{"start":{"line":71,"column":4},"end":{"line":73,"column":null}},"type":"if","locations":[{"start":{"line":71,"column":4},"end":{"line":73,"column":null}},{"start":{},"end":{}}],"line":71},"1":{"loc":{"start":{"line":83,"column":11},"end":{"line":83,"column":null}},"type":"binary-expr","locations":[{"start":{"line":83,"column":11},"end":{"line":83,"column":37}},{"start":{"line":83,"column":37},"end":{"line":83,"column":null}}],"line":83},"2":{"loc":{"start":{"line":87,"column":4},"end":{"line":89,"column":null}},"type":"if","locations":[{"start":{"line":87,"column":4},"end":{"line":89,"column":null}},{"start":{},"end":{}}],"line":87},"3":{"loc":{"start":{"line":97,"column":4},"end":{"line":99,"column":null}},"type":"if","locations":[{"start":{"line":97,"column":4},"end":{"line":99,"column":null}},{"start":{},"end":{}}],"line":97},"4":{"loc":{"start":{"line":103,"column":4},"end":{"line":105,"column":null}},"type":"if","locations":[{"start":{"line":103,"column":4},"end":{"line":105,"column":null}},{"start":{},"end":{}}],"line":103}},"s":{"0":80,"1":80,"2":12,"3":20,"4":20,"5":20,"6":0,"7":0,"8":0,"9":0,"10":0,"11":0,"12":0,"13":0,"14":0,"15":22,"16":0,"17":22,"18":22,"19":12,"20":10,"21":80,"22":80,"23":80,"24":366,"25":366,"26":51,"27":173,"28":124,"29":8,"30":80,"31":80,"32":80,"33":80,"34":80,"35":80,"36":80,"37":80,"38":80,"39":80,"40":80,"41":80,"42":48,"43":13,"44":2,"45":5,"46":1,"47":2,"48":5,"49":46,"50":5,"51":44,"52":80,"53":80,"54":80,"55":14,"56":3,"57":1,"58":5,"59":6,"60":2,"61":0,"62":0,"63":0,"64":2,"65":19,"66":12,"67":7,"68":4,"69":80},"f":{"0":12,"1":20,"2":0,"3":0,"4":0,"5":0,"6":22,"7":80,"8":366,"9":51,"10":173,"11":124,"12":80,"13":48,"14":13,"15":2,"16":5,"17":1,"18":2,"19":5,"20":46,"21":5,"22":44,"23":80,"24":14,"25":3,"26":1,"27":5,"28":6,"29":2,"30":0,"31":2,"32":19,"33":12,"34":7,"35":4},"b":{"0":[0,0],"1":[0,0],"2":[0,0],"3":[0,22],"4":[12,10]},"meta":{"lastBranch":5,"lastFunction":36,"lastStatement":70,"seen":{"s:48:45:48:Infinity":0,"s:49:51:49:Infinity":1,"f:55:2:55:17":0,"s:56:4:56:Infinity":2,"f:59:8:59:15":1,"s:60:31:65:Infinity":3,"s:66:4:66:Infinity":4,"s:67:4:67:Infinity":5,"f:70:8:70:15":2,"b:71:4:73:Infinity:undefined:undefined:undefined:undefined":0,"s:71:4:73:Infinity":6,"s:72:6:72:Infinity":7,"s:74:4:74:Infinity":8,"s:75:4:75:Infinity":9,"f:78:8:78:36":3,"s:79:4:79:Infinity":10,"f:82:8:82:12":4,"s:83:4:83:Infinity":11,"b:83:11:83:37:83:37:83:Infinity":1,"f:86:8:86:13":5,"b:87:4:89:Infinity:undefined:undefined:undefined:undefined":2,"s:87:4:89:Infinity":12,"s:88:6:88:Infinity":13,"s:90:4:93:Infinity":14,"f:96:8:96:14":6,"b:97:4:99:Infinity:undefined:undefined:undefined:undefined":3,"s:97:4:99:Infinity":15,"s:98:6:98:Infinity":16,"s:102:25:102:Infinity":17,"b:103:4:105:Infinity:undefined:undefined:undefined:undefined":4,"s:103:4:105:Infinity":18,"s:104:6:104:Infinity":19,"s:107:4:110:Infinity":20,"f:117:2:117:16":7,"s:118:4:118:Infinity":21,"s:119:4:119:Infinity":22,"s:133:33:133:Infinity":23,"f:135:2:135:30":8,"s:136:4:136:Infinity":24,"s:137:4:137:Infinity":25,"f:143:2:143:18":9,"s:144:4:144:Infinity":26,"f:144:37:144:38":10,"s:144:44:144:59":27,"f:150:2:150:22":11,"s:151:4:151:Infinity":28,"s:162:6:162:Infinity":29,"f:387:16:387:49":12,"s:389:8:389:Infinity":30,"s:392:19:392:Infinity":31,"s:395:23:395:Infinity":32,"s:396:26:396:Infinity":33,"s:399:8:399:Infinity":34,"s:400:104:400:Infinity":35,"s:403:26:408:Infinity":36,"s:410:31:415:Infinity":37,"s:417:30:423:Infinity":38,"s:426:8:438:Infinity":39,"s:441:17:441:Infinity":40,"s:444:31:617:Infinity":41,"f:466:17:466:18":13,"s:466:18:466:Infinity":42,"f:468:22:468:23":14,"s:469:6:469:Infinity":43,"f:472:18:472:19":15,"s:473:6:473:Infinity":44,"f:476:23:476:Infinity":16,"s:480:6:480:Infinity":45,"f:483:22:483:Infinity":17,"s:489:6:492:Infinity":46,"f:495:19:495:20":18,"s:496:6:496:Infinity":47,"f:499:25:499:26":19,"s:499:46:499:Infinity":48,"f:501:21:501:22":20,"s:501:39:501:Infinity":49,"f:503:22:503:23":21,"s:503:40:503:Infinity":50,"f:505:17:505:23":22,"s:505:23:505:Infinity":51,"f:507:13:507:19":23,"s:508:6:508:Infinity":52,"s:509:6:509:Infinity":53,"s:510:6:510:Infinity":54,"f:514:19:514:25":24,"s:514:25:514:Infinity":55,"f:520:33:520:Infinity":25,"s:525:6:529:Infinity":56,"f:532:34:532:Infinity":26,"s:536:6:540:Infinity":57,"f:543:30:543:Infinity":27,"s:547:6:551:Infinity":58,"f:554:32:554:Infinity":28,"s:558:6:562:Infinity":59,"f:565:33:565:Infinity":29,"s:569:6:573:Infinity":60,"f:580:19:580:26":30,"s:581:6:585:Infinity":61,"s:582:8:582:Infinity":62,"s:584:8:584:Infinity":63,"f:588:15:588:16":31,"s:589:6:589:Infinity":64,"f:592:22:592:23":32,"s:593:6:593:Infinity":65,"f:596:26:596:Infinity":33,"s:600:6:600:Infinity":66,"f:603:22:603:29":34,"s:604:6:611:Infinity":67,"f:614:19:614:20":35,"s:615:6:615:Infinity":68,"s:619:2:619:Infinity":69}}} +,"/Users/lukasmay/development/projects/codewalk-district/src/test/index.ts": {"path":"/Users/lukasmay/development/projects/codewalk-district/src/test/index.ts","statementMap":{},"fnMap":{},"branchMap":{},"s":{},"f":{},"b":{},"meta":{"lastBranch":0,"lastFunction":0,"lastStatement":0,"seen":{}}} +,"/Users/lukasmay/development/projects/codewalk-district/src/test/integration/real-providers/harness.ts": {"path":"/Users/lukasmay/development/projects/codewalk-district/src/test/integration/real-providers/harness.ts","statementMap":{"0":{"start":{"line":39,"column":2},"end":{"line":39,"column":null}},"1":{"start":{"line":39,"column":34},"end":{"line":39,"column":57}},"2":{"start":{"line":46,"column":33},"end":{"line":46,"column":null}},"3":{"start":{"line":49,"column":4},"end":{"line":49,"column":null}},"4":{"start":{"line":50,"column":4},"end":{"line":50,"column":null}},"5":{"start":{"line":54,"column":4},"end":{"line":54,"column":null}},"6":{"start":{"line":54,"column":44},"end":{"line":54,"column":59}},"7":{"start":{"line":58,"column":4},"end":{"line":58,"column":null}},"8":{"start":{"line":152,"column":25},"end":{"line":152,"column":null}},"9":{"start":{"line":186,"column":24},"end":{"line":186,"column":null}},"10":{"start":{"line":187,"column":25},"end":{"line":187,"column":null}},"11":{"start":{"line":190,"column":2},"end":{"line":197,"column":null}},"12":{"start":{"line":191,"column":25},"end":{"line":191,"column":null}},"13":{"start":{"line":192,"column":4},"end":{"line":192,"column":null}},"14":{"start":{"line":193,"column":4},"end":{"line":193,"column":null}},"15":{"start":{"line":194,"column":4},"end":{"line":194,"column":null}},"16":{"start":{"line":196,"column":4},"end":{"line":196,"column":null}},"17":{"start":{"line":200,"column":8},"end":{"line":200,"column":null}},"18":{"start":{"line":203,"column":26},"end":{"line":203,"column":null}},"19":{"start":{"line":204,"column":28},"end":{"line":204,"column":null}},"20":{"start":{"line":205,"column":28},"end":{"line":205,"column":null}},"21":{"start":{"line":206,"column":31},"end":{"line":206,"column":null}},"22":{"start":{"line":209,"column":19},"end":{"line":209,"column":null}},"23":{"start":{"line":212,"column":23},"end":{"line":218,"column":null}},"24":{"start":{"line":221,"column":39},"end":{"line":341,"column":null}},"25":{"start":{"line":232,"column":23},"end":{"line":232,"column":null}},"26":{"start":{"line":234,"column":6},"end":{"line":255,"column":null}},"27":{"start":{"line":235,"column":22},"end":{"line":235,"column":null}},"28":{"start":{"line":236,"column":8},"end":{"line":236,"column":null}},"29":{"start":{"line":236,"column":20},"end":{"line":236,"column":null}},"30":{"start":{"line":238,"column":8},"end":{"line":241,"column":null}},"31":{"start":{"line":240,"column":10},"end":{"line":240,"column":null}},"32":{"start":{"line":243,"column":8},"end":{"line":246,"column":null}},"33":{"start":{"line":245,"column":10},"end":{"line":245,"column":null}},"34":{"start":{"line":248,"column":8},"end":{"line":251,"column":null}},"35":{"start":{"line":250,"column":10},"end":{"line":250,"column":null}},"36":{"start":{"line":254,"column":8},"end":{"line":254,"column":null}},"37":{"start":{"line":257,"column":6},"end":{"line":257,"column":null}},"38":{"start":{"line":261,"column":23},"end":{"line":261,"column":null}},"39":{"start":{"line":263,"column":6},"end":{"line":278,"column":null}},"40":{"start":{"line":264,"column":22},"end":{"line":264,"column":null}},"41":{"start":{"line":265,"column":8},"end":{"line":265,"column":null}},"42":{"start":{"line":265,"column":20},"end":{"line":265,"column":null}},"43":{"start":{"line":267,"column":8},"end":{"line":269,"column":null}},"44":{"start":{"line":268,"column":10},"end":{"line":268,"column":null}},"45":{"start":{"line":271,"column":8},"end":{"line":274,"column":null}},"46":{"start":{"line":273,"column":10},"end":{"line":273,"column":null}},"47":{"start":{"line":277,"column":8},"end":{"line":277,"column":null}},"48":{"start":{"line":280,"column":6},"end":{"line":280,"column":null}},"49":{"start":{"line":284,"column":23},"end":{"line":284,"column":null}},"50":{"start":{"line":286,"column":6},"end":{"line":302,"column":null}},"51":{"start":{"line":287,"column":22},"end":{"line":287,"column":null}},"52":{"start":{"line":288,"column":8},"end":{"line":290,"column":null}},"53":{"start":{"line":289,"column":10},"end":{"line":289,"column":null}},"54":{"start":{"line":292,"column":8},"end":{"line":294,"column":null}},"55":{"start":{"line":293,"column":10},"end":{"line":293,"column":null}},"56":{"start":{"line":297,"column":8},"end":{"line":299,"column":null}},"57":{"start":{"line":298,"column":10},"end":{"line":298,"column":null}},"58":{"start":{"line":301,"column":8},"end":{"line":301,"column":null}},"59":{"start":{"line":304,"column":6},"end":{"line":304,"column":null}},"60":{"start":{"line":308,"column":6},"end":{"line":308,"column":null}},"61":{"start":{"line":312,"column":6},"end":{"line":312,"column":null}},"62":{"start":{"line":316,"column":21},"end":{"line":316,"column":null}},"63":{"start":{"line":317,"column":6},"end":{"line":325,"column":null}},"64":{"start":{"line":318,"column":8},"end":{"line":324,"column":null}},"65":{"start":{"line":319,"column":10},"end":{"line":323,"column":null}},"66":{"start":{"line":320,"column":12},"end":{"line":320,"column":null}},"67":{"start":{"line":330,"column":6},"end":{"line":330,"column":null}},"68":{"start":{"line":333,"column":6},"end":{"line":339,"column":null}},"69":{"start":{"line":334,"column":8},"end":{"line":338,"column":null}},"70":{"start":{"line":335,"column":10},"end":{"line":335,"column":null}},"71":{"start":{"line":343,"column":2},"end":{"line":343,"column":null}},"72":{"start":{"line":350,"column":40},"end":{"line":350,"column":null}},"73":{"start":{"line":356,"column":39},"end":{"line":356,"column":null}},"74":{"start":{"line":361,"column":51},"end":{"line":361,"column":null}},"75":{"start":{"line":366,"column":50},"end":{"line":366,"column":null}},"76":{"start":{"line":372,"column":33},"end":{"line":372,"column":null}},"77":{"start":{"line":378,"column":37},"end":{"line":378,"column":null}}},"fnMap":{"0":{"name":"sleep","decl":{"start":{"line":38,"column":16},"end":{"line":38,"column":22}},"loc":{"start":{"line":38,"column":49},"end":{"line":40,"column":null}},"line":38},"1":{"name":"(anonymous_1)","decl":{"start":{"line":39,"column":21},"end":{"line":39,"column":22}},"loc":{"start":{"line":39,"column":34},"end":{"line":39,"column":57}},"line":39},"2":{"name":"(anonymous_2)","decl":{"start":{"line":48,"column":2},"end":{"line":48,"column":30}},"loc":{"start":{"line":48,"column":46},"end":{"line":51,"column":null}},"line":48},"3":{"name":"(anonymous_3)","decl":{"start":{"line":53,"column":2},"end":{"line":53,"column":41}},"loc":{"start":{"line":53,"column":63},"end":{"line":55,"column":null}},"line":53},"4":{"name":"(anonymous_4)","decl":{"start":{"line":54,"column":37},"end":{"line":54,"column":38}},"loc":{"start":{"line":54,"column":44},"end":{"line":54,"column":59}},"line":54},"5":{"name":"(anonymous_5)","decl":{"start":{"line":57,"column":2},"end":{"line":57,"column":22}},"loc":{"start":{"line":57,"column":22},"end":{"line":59,"column":null}},"line":57},"6":{"name":"createRealProviderHarness","decl":{"start":{"line":182,"column":22},"end":{"line":182,"column":null}},"loc":{"start":{"line":184,"column":32},"end":{"line":344,"column":null}},"line":184},"7":{"name":"(anonymous_7)","decl":{"start":{"line":231,"column":10},"end":{"line":231,"column":33}},"loc":{"start":{"line":231,"column":99},"end":{"line":258,"column":null}},"line":231},"8":{"name":"(anonymous_8)","decl":{"start":{"line":260,"column":10},"end":{"line":260,"column":30}},"loc":{"start":{"line":260,"column":101},"end":{"line":281,"column":null}},"line":260},"9":{"name":"(anonymous_9)","decl":{"start":{"line":283,"column":10},"end":{"line":283,"column":29}},"loc":{"start":{"line":283,"column":102},"end":{"line":305,"column":null}},"line":283},"10":{"name":"(anonymous_10)","decl":{"start":{"line":307,"column":4},"end":{"line":307,"column":43}},"loc":{"start":{"line":307,"column":65},"end":{"line":309,"column":null}},"line":307},"11":{"name":"(anonymous_11)","decl":{"start":{"line":311,"column":4},"end":{"line":311,"column":24}},"loc":{"start":{"line":311,"column":24},"end":{"line":313,"column":null}},"line":311},"12":{"name":"(anonymous_12)","decl":{"start":{"line":315,"column":10},"end":{"line":315,"column":41}},"loc":{"start":{"line":315,"column":41},"end":{"line":326,"column":null}},"line":315},"13":{"name":"(anonymous_13)","decl":{"start":{"line":328,"column":10},"end":{"line":328,"column":35}},"loc":{"start":{"line":328,"column":35},"end":{"line":340,"column":null}},"line":328}},"branchMap":{"0":{"loc":{"start":{"line":183,"column":2},"end":{"line":183,"column":null}},"type":"default-arg","locations":[{"start":{"line":183,"column":40},"end":{"line":183,"column":null}}],"line":183},"1":{"loc":{"start":{"line":186,"column":24},"end":{"line":186,"column":null}},"type":"binary-expr","locations":[{"start":{"line":186,"column":24},"end":{"line":186,"column":50}},{"start":{"line":186,"column":50},"end":{"line":186,"column":null}}],"line":186},"2":{"loc":{"start":{"line":190,"column":2},"end":{"line":197,"column":null}},"type":"if","locations":[{"start":{"line":190,"column":2},"end":{"line":197,"column":null}},{"start":{},"end":{}}],"line":190},"3":{"loc":{"start":{"line":231,"column":50},"end":{"line":231,"column":99}},"type":"default-arg","locations":[{"start":{"line":231,"column":62},"end":{"line":231,"column":99}}],"line":231},"4":{"loc":{"start":{"line":236,"column":8},"end":{"line":236,"column":null}},"type":"if","locations":[{"start":{"line":236,"column":8},"end":{"line":236,"column":null}},{"start":{},"end":{}}],"line":236},"5":{"loc":{"start":{"line":238,"column":8},"end":{"line":241,"column":null}},"type":"if","locations":[{"start":{"line":238,"column":8},"end":{"line":241,"column":null}},{"start":{},"end":{}}],"line":238},"6":{"loc":{"start":{"line":238,"column":12},"end":{"line":238,"column":67}},"type":"binary-expr","locations":[{"start":{"line":238,"column":12},"end":{"line":238,"column":39}},{"start":{"line":238,"column":39},"end":{"line":238,"column":67}}],"line":238},"7":{"loc":{"start":{"line":243,"column":8},"end":{"line":246,"column":null}},"type":"if","locations":[{"start":{"line":243,"column":8},"end":{"line":246,"column":null}},{"start":{},"end":{}}],"line":243},"8":{"loc":{"start":{"line":248,"column":8},"end":{"line":251,"column":null}},"type":"if","locations":[{"start":{"line":248,"column":8},"end":{"line":251,"column":null}},{"start":{},"end":{}}],"line":248},"9":{"loc":{"start":{"line":260,"column":47},"end":{"line":260,"column":101}},"type":"default-arg","locations":[{"start":{"line":260,"column":59},"end":{"line":260,"column":101}}],"line":260},"10":{"loc":{"start":{"line":265,"column":8},"end":{"line":265,"column":null}},"type":"if","locations":[{"start":{"line":265,"column":8},"end":{"line":265,"column":null}},{"start":{},"end":{}}],"line":265},"11":{"loc":{"start":{"line":267,"column":8},"end":{"line":269,"column":null}},"type":"if","locations":[{"start":{"line":267,"column":8},"end":{"line":269,"column":null}},{"start":{},"end":{}}],"line":267},"12":{"loc":{"start":{"line":271,"column":8},"end":{"line":274,"column":null}},"type":"if","locations":[{"start":{"line":271,"column":8},"end":{"line":274,"column":null}},{"start":{},"end":{}}],"line":271},"13":{"loc":{"start":{"line":271,"column":12},"end":{"line":271,"column":97}},"type":"binary-expr","locations":[{"start":{"line":271,"column":12},"end":{"line":271,"column":39}},{"start":{"line":271,"column":39},"end":{"line":271,"column":69}},{"start":{"line":271,"column":69},"end":{"line":271,"column":97}}],"line":271},"14":{"loc":{"start":{"line":283,"column":67},"end":{"line":283,"column":102}},"type":"default-arg","locations":[{"start":{"line":283,"column":79},"end":{"line":283,"column":102}}],"line":283},"15":{"loc":{"start":{"line":288,"column":8},"end":{"line":290,"column":null}},"type":"if","locations":[{"start":{"line":288,"column":8},"end":{"line":290,"column":null}},{"start":{},"end":{}}],"line":288},"16":{"loc":{"start":{"line":292,"column":8},"end":{"line":294,"column":null}},"type":"if","locations":[{"start":{"line":292,"column":8},"end":{"line":294,"column":null}},{"start":{},"end":{}}],"line":292},"17":{"loc":{"start":{"line":297,"column":8},"end":{"line":299,"column":null}},"type":"if","locations":[{"start":{"line":297,"column":8},"end":{"line":299,"column":null}},{"start":{},"end":{}}],"line":297},"18":{"loc":{"start":{"line":297,"column":12},"end":{"line":297,"column":112}},"type":"binary-expr","locations":[{"start":{"line":297,"column":12},"end":{"line":297,"column":36}},{"start":{"line":297,"column":36},"end":{"line":297,"column":112}}],"line":297},"19":{"loc":{"start":{"line":318,"column":8},"end":{"line":324,"column":null}},"type":"if","locations":[{"start":{"line":318,"column":8},"end":{"line":324,"column":null}},{"start":{},"end":{}}],"line":318},"20":{"loc":{"start":{"line":333,"column":6},"end":{"line":339,"column":null}},"type":"if","locations":[{"start":{"line":333,"column":6},"end":{"line":339,"column":null}},{"start":{},"end":{}}],"line":333},"21":{"loc":{"start":{"line":361,"column":51},"end":{"line":361,"column":null}},"type":"cond-expr","locations":[{"start":{"line":361,"column":78},"end":{"line":361,"column":90}},{"start":{"line":361,"column":90},"end":{"line":361,"column":null}}],"line":361},"22":{"loc":{"start":{"line":366,"column":50},"end":{"line":366,"column":null}},"type":"cond-expr","locations":[{"start":{"line":366,"column":76},"end":{"line":366,"column":88}},{"start":{"line":366,"column":88},"end":{"line":366,"column":null}}],"line":366}},"s":{"0":0,"1":0,"2":0,"3":0,"4":0,"5":0,"6":0,"7":0,"8":5,"9":0,"10":0,"11":0,"12":0,"13":0,"14":0,"15":0,"16":0,"17":0,"18":0,"19":0,"20":0,"21":0,"22":0,"23":0,"24":0,"25":0,"26":0,"27":0,"28":0,"29":0,"30":0,"31":0,"32":0,"33":0,"34":0,"35":0,"36":0,"37":0,"38":0,"39":0,"40":0,"41":0,"42":0,"43":0,"44":0,"45":0,"46":0,"47":0,"48":0,"49":0,"50":0,"51":0,"52":0,"53":0,"54":0,"55":0,"56":0,"57":0,"58":0,"59":0,"60":0,"61":0,"62":0,"63":0,"64":0,"65":0,"66":0,"67":0,"68":0,"69":0,"70":0,"71":0,"72":5,"73":5,"74":5,"75":5,"76":5,"77":5},"f":{"0":0,"1":0,"2":0,"3":0,"4":0,"5":0,"6":0,"7":0,"8":0,"9":0,"10":0,"11":0,"12":0,"13":0},"b":{"0":[0],"1":[0,0],"2":[0,0],"3":[0],"4":[0,0],"5":[0,0],"6":[0,0],"7":[0,0],"8":[0,0],"9":[0],"10":[0,0],"11":[0,0],"12":[0,0],"13":[0,0,0],"14":[0],"15":[0,0],"16":[0,0],"17":[0,0],"18":[0,0],"19":[0,0],"20":[0,0],"21":[0,5],"22":[0,5]},"meta":{"lastBranch":23,"lastFunction":14,"lastStatement":78,"seen":{"f:38:16:38:22":0,"s:39:2:39:Infinity":0,"f:39:21:39:22":1,"s:39:34:39:57":1,"s:46:33:46:Infinity":2,"f:48:2:48:30":2,"s:49:4:49:Infinity":3,"s:50:4:50:Infinity":4,"f:53:2:53:41":3,"s:54:4:54:Infinity":5,"f:54:37:54:38":4,"s:54:44:54:59":6,"f:57:2:57:22":5,"s:58:4:58:Infinity":7,"s:152:25:152:Infinity":8,"f:182:22:182:Infinity":6,"b:183:40:183:Infinity":0,"s:186:24:186:Infinity":9,"b:186:24:186:50:186:50:186:Infinity":1,"s:187:25:187:Infinity":10,"b:190:2:197:Infinity:undefined:undefined:undefined:undefined":2,"s:190:2:197:Infinity":11,"s:191:25:191:Infinity":12,"s:192:4:192:Infinity":13,"s:193:4:193:Infinity":14,"s:194:4:194:Infinity":15,"s:196:4:196:Infinity":16,"s:200:8:200:Infinity":17,"s:203:26:203:Infinity":18,"s:204:28:204:Infinity":19,"s:205:28:205:Infinity":20,"s:206:31:206:Infinity":21,"s:209:19:209:Infinity":22,"s:212:23:218:Infinity":23,"s:221:39:341:Infinity":24,"f:231:10:231:33":7,"b:231:62:231:99":3,"s:232:23:232:Infinity":25,"s:234:6:255:Infinity":26,"s:235:22:235:Infinity":27,"b:236:8:236:Infinity:undefined:undefined:undefined:undefined":4,"s:236:8:236:Infinity":28,"s:236:20:236:Infinity":29,"b:238:8:241:Infinity:undefined:undefined:undefined:undefined":5,"s:238:8:241:Infinity":30,"b:238:12:238:39:238:39:238:67":6,"s:240:10:240:Infinity":31,"b:243:8:246:Infinity:undefined:undefined:undefined:undefined":7,"s:243:8:246:Infinity":32,"s:245:10:245:Infinity":33,"b:248:8:251:Infinity:undefined:undefined:undefined:undefined":8,"s:248:8:251:Infinity":34,"s:250:10:250:Infinity":35,"s:254:8:254:Infinity":36,"s:257:6:257:Infinity":37,"f:260:10:260:30":8,"b:260:59:260:101":9,"s:261:23:261:Infinity":38,"s:263:6:278:Infinity":39,"s:264:22:264:Infinity":40,"b:265:8:265:Infinity:undefined:undefined:undefined:undefined":10,"s:265:8:265:Infinity":41,"s:265:20:265:Infinity":42,"b:267:8:269:Infinity:undefined:undefined:undefined:undefined":11,"s:267:8:269:Infinity":43,"s:268:10:268:Infinity":44,"b:271:8:274:Infinity:undefined:undefined:undefined:undefined":12,"s:271:8:274:Infinity":45,"b:271:12:271:39:271:39:271:69:271:69:271:97":13,"s:273:10:273:Infinity":46,"s:277:8:277:Infinity":47,"s:280:6:280:Infinity":48,"f:283:10:283:29":9,"b:283:79:283:102":14,"s:284:23:284:Infinity":49,"s:286:6:302:Infinity":50,"s:287:22:287:Infinity":51,"b:288:8:290:Infinity:undefined:undefined:undefined:undefined":15,"s:288:8:290:Infinity":52,"s:289:10:289:Infinity":53,"b:292:8:294:Infinity:undefined:undefined:undefined:undefined":16,"s:292:8:294:Infinity":54,"s:293:10:293:Infinity":55,"b:297:8:299:Infinity:undefined:undefined:undefined:undefined":17,"s:297:8:299:Infinity":56,"b:297:12:297:36:297:36:297:112":18,"s:298:10:298:Infinity":57,"s:301:8:301:Infinity":58,"s:304:6:304:Infinity":59,"f:307:4:307:43":10,"s:308:6:308:Infinity":60,"f:311:4:311:24":11,"s:312:6:312:Infinity":61,"f:315:10:315:41":12,"s:316:21:316:Infinity":62,"s:317:6:325:Infinity":63,"b:318:8:324:Infinity:undefined:undefined:undefined:undefined":19,"s:318:8:324:Infinity":64,"s:319:10:323:Infinity":65,"s:320:12:320:Infinity":66,"f:328:10:328:35":13,"s:330:6:330:Infinity":67,"b:333:6:339:Infinity:undefined:undefined:undefined:undefined":20,"s:333:6:339:Infinity":68,"s:334:8:338:Infinity":69,"s:335:10:335:Infinity":70,"s:343:2:343:Infinity":71,"s:350:40:350:Infinity":72,"s:356:39:356:Infinity":73,"s:361:51:361:Infinity":74,"b:361:78:361:90:361:90:361:Infinity":21,"s:366:50:366:Infinity":75,"b:366:76:366:88:366:88:366:Infinity":22,"s:372:33:372:Infinity":76,"s:378:37:378:Infinity":77}}} +,"/Users/lukasmay/development/projects/codewalk-district/src/test/integration/real-providers/prompts.ts": {"path":"/Users/lukasmay/development/projects/codewalk-district/src/test/integration/real-providers/prompts.ts","statementMap":{"0":{"start":{"line":11,"column":31},"end":{"line":97,"column":null}},"1":{"start":{"line":67,"column":24},"end":{"line":69,"column":null}},"2":{"start":{"line":68,"column":29},"end":{"line":68,"column":47}},"3":{"start":{"line":70,"column":4},"end":{"line":71,"column":null}},"4":{"start":{"line":103,"column":29},"end":{"line":113,"column":null}}},"fnMap":{"0":{"name":"(anonymous_0)","decl":{"start":{"line":66,"column":22},"end":{"line":66,"column":23}},"loc":{"start":{"line":66,"column":67},"end":{"line":75,"column":null}},"line":66},"1":{"name":"(anonymous_1)","decl":{"start":{"line":68,"column":11},"end":{"line":68,"column":12}},"loc":{"start":{"line":68,"column":29},"end":{"line":68,"column":47}},"line":68}},"branchMap":{},"s":{"0":4,"1":0,"2":0,"3":0,"4":4},"f":{"0":0,"1":0},"b":{},"meta":{"lastBranch":0,"lastFunction":2,"lastStatement":5,"seen":{"s:11:31:97:Infinity":0,"f:66:22:66:23":0,"s:67:24:69:Infinity":1,"f:68:11:68:12":1,"s:68:29:68:47":2,"s:70:4:71:Infinity":3,"s:103:29:113:Infinity":4}}} +,"/Users/lukasmay/development/projects/codewalk-district/src/trpc/context.ts": {"path":"/Users/lukasmay/development/projects/codewalk-district/src/trpc/context.ts","statementMap":{"0":{"start":{"line":115,"column":2},"end":{"line":138,"column":null}}},"fnMap":{"0":{"name":"createContext","decl":{"start":{"line":114,"column":16},"end":{"line":114,"column":30}},"loc":{"start":{"line":114,"column":74},"end":{"line":139,"column":null}},"line":114}},"branchMap":{},"s":{"0":87},"f":{"0":87},"b":{},"meta":{"lastBranch":0,"lastFunction":1,"lastStatement":1,"seen":{"f:114:16:114:30":0,"s:115:2:138:Infinity":0}}} +,"/Users/lukasmay/development/projects/codewalk-district/src/trpc/index.ts": {"path":"/Users/lukasmay/development/projects/codewalk-district/src/trpc/index.ts","statementMap":{},"fnMap":{},"branchMap":{},"s":{},"f":{},"b":{},"meta":{"lastBranch":0,"lastFunction":0,"lastStatement":0,"seen":{}}} +,"/Users/lukasmay/development/projects/codewalk-district/src/trpc/router.ts": {"path":"/Users/lukasmay/development/projects/codewalk-district/src/trpc/router.ts","statementMap":{"0":{"start":{"line":46,"column":13},"end":{"line":64,"column":null}}},"fnMap":{},"branchMap":{},"s":{"0":11},"f":{},"b":{},"meta":{"lastBranch":0,"lastFunction":0,"lastStatement":1,"seen":{"s:46:13:64:Infinity":0}}} +,"/Users/lukasmay/development/projects/codewalk-district/src/trpc/subscriptions.ts": {"path":"/Users/lukasmay/development/projects/codewalk-district/src/trpc/subscriptions.ts","statementMap":{"0":{"start":{"line":25,"column":50},"end":{"line":66,"column":null}},"1":{"start":{"line":71,"column":52},"end":{"line":80,"column":null}},"2":{"start":{"line":85,"column":51},"end":{"line":97,"column":null}},"3":{"start":{"line":102,"column":51},"end":{"line":106,"column":null}},"4":{"start":{"line":109,"column":19},"end":{"line":109,"column":null}},"5":{"start":{"line":112,"column":23},"end":{"line":112,"column":null}},"6":{"start":{"line":115,"column":30},"end":{"line":115,"column":null}},"7":{"start":{"line":141,"column":31},"end":{"line":141,"column":null}},"8":{"start":{"line":142,"column":37},"end":{"line":142,"column":null}},"9":{"start":{"line":145,"column":18},"end":{"line":156,"column":null}},"10":{"start":{"line":146,"column":4},"end":{"line":146,"column":null}},"11":{"start":{"line":148,"column":4},"end":{"line":150,"column":null}},"12":{"start":{"line":149,"column":6},"end":{"line":149,"column":null}},"13":{"start":{"line":151,"column":4},"end":{"line":155,"column":null}},"14":{"start":{"line":152,"column":16},"end":{"line":152,"column":null}},"15":{"start":{"line":153,"column":6},"end":{"line":153,"column":null}},"16":{"start":{"line":154,"column":6},"end":{"line":154,"column":null}},"17":{"start":{"line":159,"column":2},"end":{"line":161,"column":null}},"18":{"start":{"line":160,"column":4},"end":{"line":160,"column":null}},"19":{"start":{"line":164,"column":18},"end":{"line":174,"column":null}},"20":{"start":{"line":165,"column":4},"end":{"line":167,"column":null}},"21":{"start":{"line":166,"column":6},"end":{"line":166,"column":null}},"22":{"start":{"line":169,"column":4},"end":{"line":173,"column":null}},"23":{"start":{"line":170,"column":16},"end":{"line":170,"column":null}},"24":{"start":{"line":171,"column":6},"end":{"line":171,"column":null}},"25":{"start":{"line":172,"column":6},"end":{"line":172,"column":null}},"26":{"start":{"line":177,"column":2},"end":{"line":177,"column":null}},"27":{"start":{"line":179,"column":2},"end":{"line":217,"column":null}},"28":{"start":{"line":180,"column":4},"end":{"line":214,"column":null}},"29":{"start":{"line":182,"column":6},"end":{"line":192,"column":null}},"30":{"start":{"line":183,"column":22},"end":{"line":183,"column":null}},"31":{"start":{"line":184,"column":19},"end":{"line":184,"column":null}},"32":{"start":{"line":185,"column":44},"end":{"line":190,"column":null}},"33":{"start":{"line":191,"column":8},"end":{"line":191,"column":null}},"34":{"start":{"line":195,"column":6},"end":{"line":213,"column":null}},"35":{"start":{"line":196,"column":25},"end":{"line":201,"column":null}},"36":{"start":{"line":198,"column":12},"end":{"line":198,"column":null}},"37":{"start":{"line":198,"column":28},"end":{"line":198,"column":null}},"38":{"start":{"line":200,"column":36},"end":{"line":200,"column":85}},"39":{"start":{"line":200,"column":53},"end":{"line":200,"column":63}},"40":{"start":{"line":203,"column":8},"end":{"line":212,"column":null}},"41":{"start":{"line":205,"column":21},"end":{"line":205,"column":null}},"42":{"start":{"line":206,"column":10},"end":{"line":211,"column":null}},"43":{"start":{"line":216,"column":4},"end":{"line":216,"column":null}}},"fnMap":{"0":{"name":"eventBusIterable","decl":{"start":{"line":136,"column":23},"end":{"line":136,"column":null}},"loc":{"start":{"line":140,"column":58},"end":{"line":218,"column":null}},"line":140},"1":{"name":"(anonymous_1)","decl":{"start":{"line":145,"column":18},"end":{"line":145,"column":19}},"loc":{"start":{"line":145,"column":42},"end":{"line":156,"column":null}},"line":145},"2":{"name":"(anonymous_2)","decl":{"start":{"line":164,"column":18},"end":{"line":164,"column":24}},"loc":{"start":{"line":164,"column":24},"end":{"line":174,"column":null}},"line":164},"3":{"name":"(anonymous_3)","decl":{"start":{"line":197,"column":28},"end":{"line":197,"column":29}},"loc":{"start":{"line":197,"column":35},"end":{"line":199,"column":11}},"line":197},"4":{"name":"(anonymous_4)","decl":{"start":{"line":198,"column":22},"end":{"line":198,"column":28}},"loc":{"start":{"line":198,"column":28},"end":{"line":198,"column":null}},"line":198},"5":{"name":"(anonymous_5)","decl":{"start":{"line":200,"column":29},"end":{"line":200,"column":30}},"loc":{"start":{"line":200,"column":36},"end":{"line":200,"column":85}},"line":200},"6":{"name":"(anonymous_6)","decl":{"start":{"line":200,"column":47},"end":{"line":200,"column":53}},"loc":{"start":{"line":200,"column":53},"end":{"line":200,"column":63}},"line":200}},"branchMap":{"0":{"loc":{"start":{"line":151,"column":4},"end":{"line":155,"column":null}},"type":"if","locations":[{"start":{"line":151,"column":4},"end":{"line":155,"column":null}},{"start":{},"end":{}}],"line":151},"1":{"loc":{"start":{"line":169,"column":4},"end":{"line":173,"column":null}},"type":"if","locations":[{"start":{"line":169,"column":4},"end":{"line":173,"column":null}},{"start":{},"end":{}}],"line":169},"2":{"loc":{"start":{"line":195,"column":6},"end":{"line":213,"column":null}},"type":"if","locations":[{"start":{"line":195,"column":6},"end":{"line":213,"column":null}},{"start":{},"end":{}}],"line":195},"3":{"loc":{"start":{"line":203,"column":8},"end":{"line":212,"column":null}},"type":"if","locations":[{"start":{"line":203,"column":8},"end":{"line":212,"column":null}},{"start":{},"end":{}}],"line":203},"4":{"loc":{"start":{"line":203,"column":12},"end":{"line":203,"column":42}},"type":"binary-expr","locations":[{"start":{"line":203,"column":12},"end":{"line":203,"column":25}},{"start":{"line":203,"column":25},"end":{"line":203,"column":42}}],"line":203}},"s":{"0":11,"1":11,"2":11,"3":11,"4":11,"5":11,"6":11,"7":0,"8":0,"9":0,"10":0,"11":0,"12":0,"13":0,"14":0,"15":0,"16":0,"17":0,"18":0,"19":0,"20":0,"21":0,"22":0,"23":0,"24":0,"25":0,"26":0,"27":0,"28":0,"29":0,"30":0,"31":0,"32":0,"33":0,"34":0,"35":0,"36":0,"37":0,"38":0,"39":0,"40":0,"41":0,"42":0,"43":0},"f":{"0":0,"1":0,"2":0,"3":0,"4":0,"5":0,"6":0},"b":{"0":[0,0],"1":[0,0],"2":[0,0],"3":[0,0],"4":[0,0]},"meta":{"lastBranch":5,"lastFunction":7,"lastStatement":44,"seen":{"s:25:50:66:Infinity":0,"s:71:52:80:Infinity":1,"s:85:51:97:Infinity":2,"s:102:51:106:Infinity":3,"s:109:19:109:Infinity":4,"s:112:23:112:Infinity":5,"s:115:30:115:Infinity":6,"f:136:23:136:Infinity":0,"s:141:31:141:Infinity":7,"s:142:37:142:Infinity":8,"s:145:18:156:Infinity":9,"f:145:18:145:19":1,"s:146:4:146:Infinity":10,"s:148:4:150:Infinity":11,"s:149:6:149:Infinity":12,"b:151:4:155:Infinity:undefined:undefined:undefined:undefined":0,"s:151:4:155:Infinity":13,"s:152:16:152:Infinity":14,"s:153:6:153:Infinity":15,"s:154:6:154:Infinity":16,"s:159:2:161:Infinity":17,"s:160:4:160:Infinity":18,"s:164:18:174:Infinity":19,"f:164:18:164:24":2,"s:165:4:167:Infinity":20,"s:166:6:166:Infinity":21,"b:169:4:173:Infinity:undefined:undefined:undefined:undefined":1,"s:169:4:173:Infinity":22,"s:170:16:170:Infinity":23,"s:171:6:171:Infinity":24,"s:172:6:172:Infinity":25,"s:177:2:177:Infinity":26,"s:179:2:217:Infinity":27,"s:180:4:214:Infinity":28,"s:182:6:192:Infinity":29,"s:183:22:183:Infinity":30,"s:184:19:184:Infinity":31,"s:185:44:190:Infinity":32,"s:191:8:191:Infinity":33,"b:195:6:213:Infinity:undefined:undefined:undefined:undefined":2,"s:195:6:213:Infinity":34,"s:196:25:201:Infinity":35,"f:197:28:197:29":3,"s:198:12:198:Infinity":36,"f:198:22:198:28":4,"s:198:28:198:Infinity":37,"f:200:29:200:30":5,"s:200:36:200:85":38,"f:200:47:200:53":6,"s:200:53:200:63":39,"b:203:8:212:Infinity:undefined:undefined:undefined:undefined":3,"s:203:8:212:Infinity":40,"b:203:12:203:25:203:25:203:42":4,"s:205:21:205:Infinity":41,"s:206:10:211:Infinity":42,"s:216:4:216:Infinity":43}}} +,"/Users/lukasmay/development/projects/codewalk-district/src/trpc/trpc.ts": {"path":"/Users/lukasmay/development/projects/codewalk-district/src/trpc/trpc.ts","statementMap":{"0":{"start":{"line":11,"column":10},"end":{"line":11,"column":null}},"1":{"start":{"line":13,"column":22},"end":{"line":13,"column":null}},"2":{"start":{"line":14,"column":31},"end":{"line":14,"column":null}},"3":{"start":{"line":15,"column":26},"end":{"line":15,"column":null}},"4":{"start":{"line":16,"column":35},"end":{"line":16,"column":null}}},"fnMap":{},"branchMap":{},"s":{"0":12,"1":12,"2":12,"3":12,"4":12},"f":{},"b":{},"meta":{"lastBranch":0,"lastFunction":0,"lastStatement":5,"seen":{"s:11:10:11:Infinity":0,"s:13:22:13:Infinity":1,"s:14:31:14:Infinity":2,"s:15:26:15:Infinity":3,"s:16:35:16:Infinity":4}}} +,"/Users/lukasmay/development/projects/codewalk-district/src/trpc/routers/_helpers.ts": {"path":"/Users/lukasmay/development/projects/codewalk-district/src/trpc/routers/_helpers.ts","statementMap":{"0":{"start":{"line":27,"column":2},"end":{"line":32,"column":null}},"1":{"start":{"line":28,"column":4},"end":{"line":31,"column":null}},"2":{"start":{"line":33,"column":2},"end":{"line":33,"column":null}},"3":{"start":{"line":37,"column":2},"end":{"line":42,"column":null}},"4":{"start":{"line":38,"column":4},"end":{"line":41,"column":null}},"5":{"start":{"line":43,"column":2},"end":{"line":43,"column":null}},"6":{"start":{"line":47,"column":2},"end":{"line":52,"column":null}},"7":{"start":{"line":48,"column":4},"end":{"line":51,"column":null}},"8":{"start":{"line":53,"column":2},"end":{"line":53,"column":null}},"9":{"start":{"line":57,"column":2},"end":{"line":62,"column":null}},"10":{"start":{"line":58,"column":4},"end":{"line":61,"column":null}},"11":{"start":{"line":63,"column":2},"end":{"line":63,"column":null}},"12":{"start":{"line":67,"column":2},"end":{"line":72,"column":null}},"13":{"start":{"line":68,"column":4},"end":{"line":71,"column":null}},"14":{"start":{"line":73,"column":2},"end":{"line":73,"column":null}},"15":{"start":{"line":77,"column":2},"end":{"line":82,"column":null}},"16":{"start":{"line":78,"column":4},"end":{"line":81,"column":null}},"17":{"start":{"line":83,"column":2},"end":{"line":83,"column":null}},"18":{"start":{"line":87,"column":2},"end":{"line":92,"column":null}},"19":{"start":{"line":88,"column":4},"end":{"line":91,"column":null}},"20":{"start":{"line":93,"column":2},"end":{"line":93,"column":null}},"21":{"start":{"line":97,"column":2},"end":{"line":102,"column":null}},"22":{"start":{"line":98,"column":4},"end":{"line":101,"column":null}},"23":{"start":{"line":103,"column":2},"end":{"line":103,"column":null}},"24":{"start":{"line":107,"column":2},"end":{"line":112,"column":null}},"25":{"start":{"line":108,"column":4},"end":{"line":111,"column":null}},"26":{"start":{"line":113,"column":2},"end":{"line":113,"column":null}},"27":{"start":{"line":117,"column":2},"end":{"line":122,"column":null}},"28":{"start":{"line":118,"column":4},"end":{"line":121,"column":null}},"29":{"start":{"line":123,"column":2},"end":{"line":123,"column":null}},"30":{"start":{"line":127,"column":2},"end":{"line":132,"column":null}},"31":{"start":{"line":128,"column":4},"end":{"line":131,"column":null}},"32":{"start":{"line":133,"column":2},"end":{"line":133,"column":null}},"33":{"start":{"line":137,"column":2},"end":{"line":142,"column":null}},"34":{"start":{"line":138,"column":4},"end":{"line":141,"column":null}},"35":{"start":{"line":143,"column":2},"end":{"line":143,"column":null}},"36":{"start":{"line":147,"column":2},"end":{"line":152,"column":null}},"37":{"start":{"line":148,"column":4},"end":{"line":151,"column":null}},"38":{"start":{"line":153,"column":2},"end":{"line":153,"column":null}},"39":{"start":{"line":157,"column":2},"end":{"line":162,"column":null}},"40":{"start":{"line":158,"column":4},"end":{"line":161,"column":null}},"41":{"start":{"line":163,"column":2},"end":{"line":163,"column":null}},"42":{"start":{"line":167,"column":2},"end":{"line":172,"column":null}},"43":{"start":{"line":168,"column":4},"end":{"line":171,"column":null}},"44":{"start":{"line":173,"column":2},"end":{"line":173,"column":null}},"45":{"start":{"line":177,"column":2},"end":{"line":182,"column":null}},"46":{"start":{"line":178,"column":4},"end":{"line":181,"column":null}},"47":{"start":{"line":183,"column":2},"end":{"line":183,"column":null}},"48":{"start":{"line":187,"column":2},"end":{"line":192,"column":null}},"49":{"start":{"line":188,"column":4},"end":{"line":191,"column":null}},"50":{"start":{"line":193,"column":2},"end":{"line":193,"column":null}}},"fnMap":{"0":{"name":"requireAgentManager","decl":{"start":{"line":26,"column":16},"end":{"line":26,"column":36}},"loc":{"start":{"line":26,"column":54},"end":{"line":34,"column":null}},"line":26},"1":{"name":"requireTaskRepository","decl":{"start":{"line":36,"column":16},"end":{"line":36,"column":38}},"loc":{"start":{"line":36,"column":72},"end":{"line":44,"column":null}},"line":36},"2":{"name":"requireMessageRepository","decl":{"start":{"line":46,"column":16},"end":{"line":46,"column":41}},"loc":{"start":{"line":46,"column":78},"end":{"line":54,"column":null}},"line":46},"3":{"name":"requireDispatchManager","decl":{"start":{"line":56,"column":16},"end":{"line":56,"column":39}},"loc":{"start":{"line":56,"column":74},"end":{"line":64,"column":null}},"line":56},"4":{"name":"requireCoordinationManager","decl":{"start":{"line":66,"column":16},"end":{"line":66,"column":43}},"loc":{"start":{"line":66,"column":82},"end":{"line":74,"column":null}},"line":66},"5":{"name":"requireInitiativeRepository","decl":{"start":{"line":76,"column":16},"end":{"line":76,"column":44}},"loc":{"start":{"line":76,"column":84},"end":{"line":84,"column":null}},"line":76},"6":{"name":"requirePhaseRepository","decl":{"start":{"line":86,"column":16},"end":{"line":86,"column":39}},"loc":{"start":{"line":86,"column":74},"end":{"line":94,"column":null}},"line":86},"7":{"name":"requirePhaseDispatchManager","decl":{"start":{"line":96,"column":16},"end":{"line":96,"column":44}},"loc":{"start":{"line":96,"column":84},"end":{"line":104,"column":null}},"line":96},"8":{"name":"requirePageRepository","decl":{"start":{"line":106,"column":16},"end":{"line":106,"column":38}},"loc":{"start":{"line":106,"column":72},"end":{"line":114,"column":null}},"line":106},"9":{"name":"requireProjectRepository","decl":{"start":{"line":116,"column":16},"end":{"line":116,"column":41}},"loc":{"start":{"line":116,"column":78},"end":{"line":124,"column":null}},"line":116},"10":{"name":"requireAccountRepository","decl":{"start":{"line":126,"column":16},"end":{"line":126,"column":41}},"loc":{"start":{"line":126,"column":78},"end":{"line":134,"column":null}},"line":126},"11":{"name":"requireChangeSetRepository","decl":{"start":{"line":136,"column":16},"end":{"line":136,"column":43}},"loc":{"start":{"line":136,"column":82},"end":{"line":144,"column":null}},"line":136},"12":{"name":"requireLogChunkRepository","decl":{"start":{"line":146,"column":16},"end":{"line":146,"column":42}},"loc":{"start":{"line":146,"column":80},"end":{"line":154,"column":null}},"line":146},"13":{"name":"requireBranchManager","decl":{"start":{"line":156,"column":16},"end":{"line":156,"column":37}},"loc":{"start":{"line":156,"column":70},"end":{"line":164,"column":null}},"line":156},"14":{"name":"requireExecutionOrchestrator","decl":{"start":{"line":166,"column":16},"end":{"line":166,"column":45}},"loc":{"start":{"line":166,"column":86},"end":{"line":174,"column":null}},"line":166},"15":{"name":"requirePreviewManager","decl":{"start":{"line":176,"column":16},"end":{"line":176,"column":38}},"loc":{"start":{"line":176,"column":72},"end":{"line":184,"column":null}},"line":176},"16":{"name":"requireConversationRepository","decl":{"start":{"line":186,"column":16},"end":{"line":186,"column":46}},"loc":{"start":{"line":186,"column":88},"end":{"line":194,"column":null}},"line":186}},"branchMap":{"0":{"loc":{"start":{"line":27,"column":2},"end":{"line":32,"column":null}},"type":"if","locations":[{"start":{"line":27,"column":2},"end":{"line":32,"column":null}},{"start":{},"end":{}}],"line":27},"1":{"loc":{"start":{"line":37,"column":2},"end":{"line":42,"column":null}},"type":"if","locations":[{"start":{"line":37,"column":2},"end":{"line":42,"column":null}},{"start":{},"end":{}}],"line":37},"2":{"loc":{"start":{"line":47,"column":2},"end":{"line":52,"column":null}},"type":"if","locations":[{"start":{"line":47,"column":2},"end":{"line":52,"column":null}},{"start":{},"end":{}}],"line":47},"3":{"loc":{"start":{"line":57,"column":2},"end":{"line":62,"column":null}},"type":"if","locations":[{"start":{"line":57,"column":2},"end":{"line":62,"column":null}},{"start":{},"end":{}}],"line":57},"4":{"loc":{"start":{"line":67,"column":2},"end":{"line":72,"column":null}},"type":"if","locations":[{"start":{"line":67,"column":2},"end":{"line":72,"column":null}},{"start":{},"end":{}}],"line":67},"5":{"loc":{"start":{"line":77,"column":2},"end":{"line":82,"column":null}},"type":"if","locations":[{"start":{"line":77,"column":2},"end":{"line":82,"column":null}},{"start":{},"end":{}}],"line":77},"6":{"loc":{"start":{"line":87,"column":2},"end":{"line":92,"column":null}},"type":"if","locations":[{"start":{"line":87,"column":2},"end":{"line":92,"column":null}},{"start":{},"end":{}}],"line":87},"7":{"loc":{"start":{"line":97,"column":2},"end":{"line":102,"column":null}},"type":"if","locations":[{"start":{"line":97,"column":2},"end":{"line":102,"column":null}},{"start":{},"end":{}}],"line":97},"8":{"loc":{"start":{"line":107,"column":2},"end":{"line":112,"column":null}},"type":"if","locations":[{"start":{"line":107,"column":2},"end":{"line":112,"column":null}},{"start":{},"end":{}}],"line":107},"9":{"loc":{"start":{"line":117,"column":2},"end":{"line":122,"column":null}},"type":"if","locations":[{"start":{"line":117,"column":2},"end":{"line":122,"column":null}},{"start":{},"end":{}}],"line":117},"10":{"loc":{"start":{"line":127,"column":2},"end":{"line":132,"column":null}},"type":"if","locations":[{"start":{"line":127,"column":2},"end":{"line":132,"column":null}},{"start":{},"end":{}}],"line":127},"11":{"loc":{"start":{"line":137,"column":2},"end":{"line":142,"column":null}},"type":"if","locations":[{"start":{"line":137,"column":2},"end":{"line":142,"column":null}},{"start":{},"end":{}}],"line":137},"12":{"loc":{"start":{"line":147,"column":2},"end":{"line":152,"column":null}},"type":"if","locations":[{"start":{"line":147,"column":2},"end":{"line":152,"column":null}},{"start":{},"end":{}}],"line":147},"13":{"loc":{"start":{"line":157,"column":2},"end":{"line":162,"column":null}},"type":"if","locations":[{"start":{"line":157,"column":2},"end":{"line":162,"column":null}},{"start":{},"end":{}}],"line":157},"14":{"loc":{"start":{"line":167,"column":2},"end":{"line":172,"column":null}},"type":"if","locations":[{"start":{"line":167,"column":2},"end":{"line":172,"column":null}},{"start":{},"end":{}}],"line":167},"15":{"loc":{"start":{"line":177,"column":2},"end":{"line":182,"column":null}},"type":"if","locations":[{"start":{"line":177,"column":2},"end":{"line":182,"column":null}},{"start":{},"end":{}}],"line":177},"16":{"loc":{"start":{"line":187,"column":2},"end":{"line":192,"column":null}},"type":"if","locations":[{"start":{"line":187,"column":2},"end":{"line":192,"column":null}},{"start":{},"end":{}}],"line":187}},"s":{"0":27,"1":0,"2":27,"3":36,"4":0,"5":36,"6":0,"7":0,"8":0,"9":0,"10":0,"11":0,"12":0,"13":0,"14":0,"15":40,"16":0,"17":40,"18":31,"19":0,"20":31,"21":0,"22":0,"23":0,"24":0,"25":0,"26":0,"27":0,"28":0,"29":0,"30":0,"31":0,"32":0,"33":0,"34":0,"35":0,"36":0,"37":0,"38":0,"39":0,"40":0,"41":0,"42":0,"43":0,"44":0,"45":0,"46":0,"47":0,"48":0,"49":0,"50":0},"f":{"0":27,"1":36,"2":0,"3":0,"4":0,"5":40,"6":31,"7":0,"8":0,"9":0,"10":0,"11":0,"12":0,"13":0,"14":0,"15":0,"16":0},"b":{"0":[0,27],"1":[0,36],"2":[0,0],"3":[0,0],"4":[0,0],"5":[0,40],"6":[0,31],"7":[0,0],"8":[0,0],"9":[0,0],"10":[0,0],"11":[0,0],"12":[0,0],"13":[0,0],"14":[0,0],"15":[0,0],"16":[0,0]},"meta":{"lastBranch":17,"lastFunction":17,"lastStatement":51,"seen":{"f:26:16:26:36":0,"b:27:2:32:Infinity:undefined:undefined:undefined:undefined":0,"s:27:2:32:Infinity":0,"s:28:4:31:Infinity":1,"s:33:2:33:Infinity":2,"f:36:16:36:38":1,"b:37:2:42:Infinity:undefined:undefined:undefined:undefined":1,"s:37:2:42:Infinity":3,"s:38:4:41:Infinity":4,"s:43:2:43:Infinity":5,"f:46:16:46:41":2,"b:47:2:52:Infinity:undefined:undefined:undefined:undefined":2,"s:47:2:52:Infinity":6,"s:48:4:51:Infinity":7,"s:53:2:53:Infinity":8,"f:56:16:56:39":3,"b:57:2:62:Infinity:undefined:undefined:undefined:undefined":3,"s:57:2:62:Infinity":9,"s:58:4:61:Infinity":10,"s:63:2:63:Infinity":11,"f:66:16:66:43":4,"b:67:2:72:Infinity:undefined:undefined:undefined:undefined":4,"s:67:2:72:Infinity":12,"s:68:4:71:Infinity":13,"s:73:2:73:Infinity":14,"f:76:16:76:44":5,"b:77:2:82:Infinity:undefined:undefined:undefined:undefined":5,"s:77:2:82:Infinity":15,"s:78:4:81:Infinity":16,"s:83:2:83:Infinity":17,"f:86:16:86:39":6,"b:87:2:92:Infinity:undefined:undefined:undefined:undefined":6,"s:87:2:92:Infinity":18,"s:88:4:91:Infinity":19,"s:93:2:93:Infinity":20,"f:96:16:96:44":7,"b:97:2:102:Infinity:undefined:undefined:undefined:undefined":7,"s:97:2:102:Infinity":21,"s:98:4:101:Infinity":22,"s:103:2:103:Infinity":23,"f:106:16:106:38":8,"b:107:2:112:Infinity:undefined:undefined:undefined:undefined":8,"s:107:2:112:Infinity":24,"s:108:4:111:Infinity":25,"s:113:2:113:Infinity":26,"f:116:16:116:41":9,"b:117:2:122:Infinity:undefined:undefined:undefined:undefined":9,"s:117:2:122:Infinity":27,"s:118:4:121:Infinity":28,"s:123:2:123:Infinity":29,"f:126:16:126:41":10,"b:127:2:132:Infinity:undefined:undefined:undefined:undefined":10,"s:127:2:132:Infinity":30,"s:128:4:131:Infinity":31,"s:133:2:133:Infinity":32,"f:136:16:136:43":11,"b:137:2:142:Infinity:undefined:undefined:undefined:undefined":11,"s:137:2:142:Infinity":33,"s:138:4:141:Infinity":34,"s:143:2:143:Infinity":35,"f:146:16:146:42":12,"b:147:2:152:Infinity:undefined:undefined:undefined:undefined":12,"s:147:2:152:Infinity":36,"s:148:4:151:Infinity":37,"s:153:2:153:Infinity":38,"f:156:16:156:37":13,"b:157:2:162:Infinity:undefined:undefined:undefined:undefined":13,"s:157:2:162:Infinity":39,"s:158:4:161:Infinity":40,"s:163:2:163:Infinity":41,"f:166:16:166:45":14,"b:167:2:172:Infinity:undefined:undefined:undefined:undefined":14,"s:167:2:172:Infinity":42,"s:168:4:171:Infinity":43,"s:173:2:173:Infinity":44,"f:176:16:176:38":15,"b:177:2:182:Infinity:undefined:undefined:undefined:undefined":15,"s:177:2:182:Infinity":45,"s:178:4:181:Infinity":46,"s:183:2:183:Infinity":47,"f:186:16:186:46":16,"b:187:2:192:Infinity:undefined:undefined:undefined:undefined":16,"s:187:2:192:Infinity":48,"s:188:4:191:Infinity":49,"s:193:2:193:Infinity":50}}} +,"/Users/lukasmay/development/projects/codewalk-district/src/trpc/routers/account.ts": {"path":"/Users/lukasmay/development/projects/codewalk-district/src/trpc/routers/account.ts","statementMap":{"0":{"start":{"line":11,"column":2},"end":{"line":75,"column":null}},"1":{"start":{"line":14,"column":14},"end":{"line":14,"column":null}},"2":{"start":{"line":15,"column":8},"end":{"line":15,"column":null}},"3":{"start":{"line":26,"column":14},"end":{"line":26,"column":null}},"4":{"start":{"line":27,"column":8},"end":{"line":32,"column":null}},"5":{"start":{"line":38,"column":14},"end":{"line":38,"column":null}},"6":{"start":{"line":39,"column":8},"end":{"line":39,"column":null}},"7":{"start":{"line":40,"column":8},"end":{"line":40,"column":null}},"8":{"start":{"line":45,"column":14},"end":{"line":45,"column":null}},"9":{"start":{"line":46,"column":24},"end":{"line":46,"column":null}},"10":{"start":{"line":47,"column":8},"end":{"line":47,"column":null}},"11":{"start":{"line":57,"column":14},"end":{"line":57,"column":null}},"12":{"start":{"line":58,"column":8},"end":{"line":58,"column":null}},"13":{"start":{"line":67,"column":14},"end":{"line":67,"column":null}},"14":{"start":{"line":68,"column":8},"end":{"line":68,"column":null}},"15":{"start":{"line":73,"column":8},"end":{"line":73,"column":null}}},"fnMap":{"0":{"name":"accountProcedures","decl":{"start":{"line":10,"column":16},"end":{"line":10,"column":34}},"loc":{"start":{"line":10,"column":69},"end":{"line":76,"column":null}},"line":10},"1":{"name":"(anonymous_1)","decl":{"start":{"line":13,"column":13},"end":{"line":13,"column":20}},"loc":{"start":{"line":13,"column":32},"end":{"line":16,"column":7}},"line":13},"2":{"name":"(anonymous_2)","decl":{"start":{"line":25,"column":16},"end":{"line":25,"column":23}},"loc":{"start":{"line":25,"column":42},"end":{"line":33,"column":7}},"line":25},"3":{"name":"(anonymous_3)","decl":{"start":{"line":37,"column":16},"end":{"line":37,"column":23}},"loc":{"start":{"line":37,"column":42},"end":{"line":41,"column":7}},"line":37},"4":{"name":"(anonymous_4)","decl":{"start":{"line":44,"column":16},"end":{"line":44,"column":23}},"loc":{"start":{"line":44,"column":35},"end":{"line":48,"column":7}},"line":44},"5":{"name":"(anonymous_5)","decl":{"start":{"line":56,"column":16},"end":{"line":56,"column":23}},"loc":{"start":{"line":56,"column":42},"end":{"line":59,"column":7}},"line":56},"6":{"name":"(anonymous_6)","decl":{"start":{"line":66,"column":16},"end":{"line":66,"column":23}},"loc":{"start":{"line":66,"column":42},"end":{"line":69,"column":7}},"line":66},"7":{"name":"(anonymous_7)","decl":{"start":{"line":72,"column":13},"end":{"line":72,"column":19}},"loc":{"start":{"line":72,"column":19},"end":{"line":74,"column":7}},"line":72}},"branchMap":{},"s":{"0":11,"1":0,"2":0,"3":0,"4":0,"5":0,"6":0,"7":0,"8":0,"9":0,"10":0,"11":0,"12":0,"13":0,"14":0,"15":0},"f":{"0":11,"1":0,"2":0,"3":0,"4":0,"5":0,"6":0,"7":0},"b":{},"meta":{"lastBranch":0,"lastFunction":8,"lastStatement":16,"seen":{"f:10:16:10:34":0,"s:11:2:75:Infinity":0,"f:13:13:13:20":1,"s:14:14:14:Infinity":1,"s:15:8:15:Infinity":2,"f:25:16:25:23":2,"s:26:14:26:Infinity":3,"s:27:8:32:Infinity":4,"f:37:16:37:23":3,"s:38:14:38:Infinity":5,"s:39:8:39:Infinity":6,"s:40:8:40:Infinity":7,"f:44:16:44:23":4,"s:45:14:45:Infinity":8,"s:46:24:46:Infinity":9,"s:47:8:47:Infinity":10,"f:56:16:56:23":5,"s:57:14:57:Infinity":11,"s:58:8:58:Infinity":12,"f:66:16:66:23":6,"s:67:14:67:Infinity":13,"s:68:8:68:Infinity":14,"f:72:13:72:19":7,"s:73:8:73:Infinity":15}}} +,"/Users/lukasmay/development/projects/codewalk-district/src/trpc/routers/agent.ts": {"path":"/Users/lukasmay/development/projects/codewalk-district/src/trpc/routers/agent.ts","statementMap":{"0":{"start":{"line":14,"column":37},"end":{"line":22,"column":null}},"1":{"start":{"line":26,"column":37},"end":{"line":31,"column":null}},"2":{"start":{"line":29,"column":18},"end":{"line":29,"column":40}},"3":{"start":{"line":35,"column":38},"end":{"line":41,"column":null}},"4":{"start":{"line":39,"column":18},"end":{"line":39,"column":40}},"5":{"start":{"line":49,"column":2},"end":{"line":54,"column":null}},"6":{"start":{"line":50,"column":4},"end":{"line":53,"column":null}},"7":{"start":{"line":56,"column":16},"end":{"line":58,"column":null}},"8":{"start":{"line":60,"column":2},"end":{"line":65,"column":null}},"9":{"start":{"line":61,"column":4},"end":{"line":64,"column":null}},"10":{"start":{"line":67,"column":2},"end":{"line":67,"column":null}},"11":{"start":{"line":71,"column":2},"end":{"line":247,"column":null}},"12":{"start":{"line":75,"column":14},"end":{"line":75,"column":null}},"13":{"start":{"line":76,"column":8},"end":{"line":84,"column":null}},"14":{"start":{"line":90,"column":14},"end":{"line":90,"column":null}},"15":{"start":{"line":91,"column":22},"end":{"line":91,"column":null}},"16":{"start":{"line":92,"column":8},"end":{"line":92,"column":null}},"17":{"start":{"line":93,"column":8},"end":{"line":93,"column":null}},"18":{"start":{"line":99,"column":14},"end":{"line":99,"column":null}},"19":{"start":{"line":100,"column":22},"end":{"line":100,"column":null}},"20":{"start":{"line":101,"column":8},"end":{"line":101,"column":null}},"21":{"start":{"line":102,"column":8},"end":{"line":102,"column":null}},"22":{"start":{"line":108,"column":14},"end":{"line":108,"column":null}},"23":{"start":{"line":109,"column":22},"end":{"line":109,"column":null}},"24":{"start":{"line":110,"column":8},"end":{"line":110,"column":null}},"25":{"start":{"line":111,"column":8},"end":{"line":111,"column":null}},"26":{"start":{"line":116,"column":14},"end":{"line":116,"column":null}},"27":{"start":{"line":117,"column":8},"end":{"line":117,"column":null}},"28":{"start":{"line":123,"column":8},"end":{"line":123,"column":null}},"29":{"start":{"line":129,"column":14},"end":{"line":129,"column":null}},"30":{"start":{"line":130,"column":8},"end":{"line":130,"column":null}},"31":{"start":{"line":136,"column":14},"end":{"line":136,"column":null}},"32":{"start":{"line":137,"column":22},"end":{"line":137,"column":null}},"33":{"start":{"line":138,"column":8},"end":{"line":138,"column":null}},"34":{"start":{"line":139,"column":8},"end":{"line":139,"column":null}},"35":{"start":{"line":145,"column":14},"end":{"line":145,"column":null}},"36":{"start":{"line":146,"column":22},"end":{"line":146,"column":null}},"37":{"start":{"line":147,"column":8},"end":{"line":147,"column":null}},"38":{"start":{"line":153,"column":14},"end":{"line":153,"column":null}},"39":{"start":{"line":154,"column":22},"end":{"line":154,"column":null}},"40":{"start":{"line":155,"column":8},"end":{"line":155,"column":null}},"41":{"start":{"line":160,"column":14},"end":{"line":160,"column":null}},"42":{"start":{"line":161,"column":26},"end":{"line":161,"column":null}},"43":{"start":{"line":162,"column":8},"end":{"line":162,"column":null}},"44":{"start":{"line":162,"column":41},"end":{"line":162,"column":77}},"45":{"start":{"line":168,"column":14},"end":{"line":168,"column":null}},"46":{"start":{"line":169,"column":26},"end":{"line":169,"column":null}},"47":{"start":{"line":170,"column":27},"end":{"line":181,"column":null}},"48":{"start":{"line":173,"column":14},"end":{"line":176,"column":null}},"49":{"start":{"line":180,"column":14},"end":{"line":180,"column":null}},"50":{"start":{"line":182,"column":8},"end":{"line":182,"column":null}},"51":{"start":{"line":188,"column":22},"end":{"line":188,"column":null}},"52":{"start":{"line":189,"column":14},"end":{"line":189,"column":null}},"53":{"start":{"line":191,"column":23},"end":{"line":191,"column":null}},"54":{"start":{"line":192,"column":8},"end":{"line":192,"column":null}},"55":{"start":{"line":192,"column":31},"end":{"line":192,"column":40}},"56":{"start":{"line":198,"column":28},"end":{"line":198,"column":null}},"57":{"start":{"line":199,"column":23},"end":{"line":199,"column":null}},"58":{"start":{"line":200,"column":25},"end":{"line":200,"column":null}},"59":{"start":{"line":202,"column":27},"end":{"line":202,"column":null}},"60":{"start":{"line":203,"column":32},"end":{"line":203,"column":null}},"61":{"start":{"line":204,"column":43},"end":{"line":204,"column":null}},"62":{"start":{"line":206,"column":24},"end":{"line":214,"column":null}},"63":{"start":{"line":207,"column":10},"end":{"line":207,"column":null}},"64":{"start":{"line":207,"column":49},"end":{"line":207,"column":null}},"65":{"start":{"line":208,"column":10},"end":{"line":208,"column":null}},"66":{"start":{"line":209,"column":10},"end":{"line":213,"column":null}},"67":{"start":{"line":210,"column":22},"end":{"line":210,"column":null}},"68":{"start":{"line":211,"column":12},"end":{"line":211,"column":null}},"69":{"start":{"line":212,"column":12},"end":{"line":212,"column":null}},"70":{"start":{"line":216,"column":8},"end":{"line":216,"column":null}},"71":{"start":{"line":218,"column":24},"end":{"line":225,"column":null}},"72":{"start":{"line":219,"column":10},"end":{"line":219,"column":null}},"73":{"start":{"line":220,"column":10},"end":{"line":224,"column":null}},"74":{"start":{"line":221,"column":22},"end":{"line":221,"column":null}},"75":{"start":{"line":222,"column":12},"end":{"line":222,"column":null}},"76":{"start":{"line":223,"column":12},"end":{"line":223,"column":null}},"77":{"start":{"line":227,"column":8},"end":{"line":227,"column":null}},"78":{"start":{"line":229,"column":8},"end":{"line":245,"column":null}},"79":{"start":{"line":230,"column":10},"end":{"line":242,"column":null}},"80":{"start":{"line":231,"column":12},"end":{"line":235,"column":null}},"81":{"start":{"line":232,"column":27},"end":{"line":232,"column":null}},"82":{"start":{"line":233,"column":25},"end":{"line":233,"column":null}},"83":{"start":{"line":234,"column":14},"end":{"line":234,"column":null}},"84":{"start":{"line":237,"column":12},"end":{"line":241,"column":null}},"85":{"start":{"line":238,"column":14},"end":{"line":240,"column":null}},"86":{"start":{"line":239,"column":16},"end":{"line":239,"column":null}},"87":{"start":{"line":244,"column":10},"end":{"line":244,"column":null}}},"fnMap":{"0":{"name":"(anonymous_0)","decl":{"start":{"line":29,"column":10},"end":{"line":29,"column":18}},"loc":{"start":{"line":29,"column":18},"end":{"line":29,"column":40}},"line":29},"1":{"name":"(anonymous_1)","decl":{"start":{"line":39,"column":10},"end":{"line":39,"column":18}},"loc":{"start":{"line":39,"column":18},"end":{"line":39,"column":40}},"line":39},"2":{"name":"resolveAgent","decl":{"start":{"line":45,"column":15},"end":{"line":45,"column":null}},"loc":{"start":{"line":48,"column":22},"end":{"line":68,"column":null}},"line":48},"3":{"name":"agentProcedures","decl":{"start":{"line":70,"column":16},"end":{"line":70,"column":32}},"loc":{"start":{"line":70,"column":67},"end":{"line":248,"column":null}},"line":70},"4":{"name":"(anonymous_4)","decl":{"start":{"line":74,"column":16},"end":{"line":74,"column":23}},"loc":{"start":{"line":74,"column":42},"end":{"line":85,"column":7}},"line":74},"5":{"name":"(anonymous_5)","decl":{"start":{"line":89,"column":16},"end":{"line":89,"column":23}},"loc":{"start":{"line":89,"column":42},"end":{"line":94,"column":7}},"line":89},"6":{"name":"(anonymous_6)","decl":{"start":{"line":98,"column":16},"end":{"line":98,"column":23}},"loc":{"start":{"line":98,"column":42},"end":{"line":103,"column":7}},"line":98},"7":{"name":"(anonymous_7)","decl":{"start":{"line":107,"column":16},"end":{"line":107,"column":23}},"loc":{"start":{"line":107,"column":42},"end":{"line":112,"column":7}},"line":107},"8":{"name":"(anonymous_8)","decl":{"start":{"line":115,"column":13},"end":{"line":115,"column":20}},"loc":{"start":{"line":115,"column":32},"end":{"line":118,"column":7}},"line":115},"9":{"name":"(anonymous_9)","decl":{"start":{"line":122,"column":13},"end":{"line":122,"column":20}},"loc":{"start":{"line":122,"column":39},"end":{"line":124,"column":7}},"line":122},"10":{"name":"(anonymous_10)","decl":{"start":{"line":128,"column":13},"end":{"line":128,"column":20}},"loc":{"start":{"line":128,"column":39},"end":{"line":131,"column":7}},"line":128},"11":{"name":"(anonymous_11)","decl":{"start":{"line":135,"column":16},"end":{"line":135,"column":23}},"loc":{"start":{"line":135,"column":42},"end":{"line":140,"column":7}},"line":135},"12":{"name":"(anonymous_12)","decl":{"start":{"line":144,"column":13},"end":{"line":144,"column":20}},"loc":{"start":{"line":144,"column":68},"end":{"line":148,"column":7}},"line":144},"13":{"name":"(anonymous_13)","decl":{"start":{"line":152,"column":13},"end":{"line":152,"column":20}},"loc":{"start":{"line":152,"column":73},"end":{"line":156,"column":7}},"line":152},"14":{"name":"(anonymous_14)","decl":{"start":{"line":159,"column":13},"end":{"line":159,"column":20}},"loc":{"start":{"line":159,"column":32},"end":{"line":163,"column":7}},"line":159},"15":{"name":"(anonymous_15)","decl":{"start":{"line":162,"column":32},"end":{"line":162,"column":41}},"loc":{"start":{"line":162,"column":41},"end":{"line":162,"column":77}},"line":162},"16":{"name":"(anonymous_16)","decl":{"start":{"line":167,"column":13},"end":{"line":167,"column":20}},"loc":{"start":{"line":167,"column":66},"end":{"line":183,"column":7}},"line":167},"17":{"name":"(anonymous_17)","decl":{"start":{"line":172,"column":12},"end":{"line":172,"column":13}},"loc":{"start":{"line":173,"column":14},"end":{"line":176,"column":null}},"line":173},"18":{"name":"(anonymous_18)","decl":{"start":{"line":179,"column":12},"end":{"line":179,"column":13}},"loc":{"start":{"line":180,"column":14},"end":{"line":180,"column":null}},"line":180},"19":{"name":"(anonymous_19)","decl":{"start":{"line":187,"column":13},"end":{"line":187,"column":20}},"loc":{"start":{"line":187,"column":56},"end":{"line":193,"column":7}},"line":187},"20":{"name":"(anonymous_20)","decl":{"start":{"line":192,"column":26},"end":{"line":192,"column":31}},"loc":{"start":{"line":192,"column":31},"end":{"line":192,"column":40}},"line":192},"21":{"name":"(anonymous_21)","decl":{"start":{"line":197,"column":20},"end":{"line":197,"column":37}},"loc":{"start":{"line":197,"column":111},"end":{"line":246,"column":7}},"line":197},"22":{"name":"(anonymous_22)","decl":{"start":{"line":206,"column":24},"end":{"line":206,"column":25}},"loc":{"start":{"line":206,"column":53},"end":{"line":214,"column":null}},"line":206},"23":{"name":"(anonymous_23)","decl":{"start":{"line":218,"column":24},"end":{"line":218,"column":30}},"loc":{"start":{"line":218,"column":30},"end":{"line":225,"column":null}},"line":218},"24":{"name":"(anonymous_24)","decl":{"start":{"line":238,"column":38},"end":{"line":238,"column":39}},"loc":{"start":{"line":238,"column":45},"end":{"line":240,"column":15}},"line":238}},"branchMap":{"0":{"loc":{"start":{"line":29,"column":18},"end":{"line":29,"column":40}},"type":"binary-expr","locations":[{"start":{"line":29,"column":18},"end":{"line":29,"column":31}},{"start":{"line":29,"column":31},"end":{"line":29,"column":40}}],"line":29},"1":{"loc":{"start":{"line":39,"column":18},"end":{"line":39,"column":40}},"type":"binary-expr","locations":[{"start":{"line":39,"column":18},"end":{"line":39,"column":31}},{"start":{"line":39,"column":31},"end":{"line":39,"column":40}}],"line":39},"2":{"loc":{"start":{"line":49,"column":2},"end":{"line":54,"column":null}},"type":"if","locations":[{"start":{"line":49,"column":2},"end":{"line":54,"column":null}},{"start":{},"end":{}}],"line":49},"3":{"loc":{"start":{"line":56,"column":16},"end":{"line":58,"column":null}},"type":"cond-expr","locations":[{"start":{"line":57,"column":6},"end":{"line":57,"column":null}},{"start":{"line":58,"column":6},"end":{"line":58,"column":null}}],"line":56},"4":{"loc":{"start":{"line":60,"column":2},"end":{"line":65,"column":null}},"type":"if","locations":[{"start":{"line":60,"column":2},"end":{"line":65,"column":null}},{"start":{},"end":{}}],"line":60},"5":{"loc":{"start":{"line":63,"column":25},"end":{"line":63,"column":47}},"type":"binary-expr","locations":[{"start":{"line":63,"column":25},"end":{"line":63,"column":39}},{"start":{"line":63,"column":39},"end":{"line":63,"column":47}}],"line":63},"6":{"loc":{"start":{"line":173,"column":14},"end":{"line":176,"column":null}},"type":"binary-expr","locations":[{"start":{"line":173,"column":14},"end":{"line":173,"column":null}},{"start":{"line":174,"column":14},"end":{"line":174,"column":null}},{"start":{"line":175,"column":14},"end":{"line":175,"column":null}},{"start":{"line":176,"column":14},"end":{"line":176,"column":null}}],"line":173},"7":{"loc":{"start":{"line":182,"column":15},"end":{"line":182,"column":null}},"type":"binary-expr","locations":[{"start":{"line":182,"column":15},"end":{"line":182,"column":32}},{"start":{"line":182,"column":32},"end":{"line":182,"column":null}}],"line":182},"8":{"loc":{"start":{"line":199,"column":23},"end":{"line":199,"column":null}},"type":"binary-expr","locations":[{"start":{"line":199,"column":23},"end":{"line":199,"column":38}},{"start":{"line":199,"column":38},"end":{"line":199,"column":null}}],"line":199},"9":{"loc":{"start":{"line":207,"column":10},"end":{"line":207,"column":null}},"type":"if","locations":[{"start":{"line":207,"column":10},"end":{"line":207,"column":null}},{"start":{},"end":{}}],"line":207},"10":{"loc":{"start":{"line":209,"column":10},"end":{"line":213,"column":null}},"type":"if","locations":[{"start":{"line":209,"column":10},"end":{"line":213,"column":null}},{"start":{},"end":{}}],"line":209},"11":{"loc":{"start":{"line":220,"column":10},"end":{"line":224,"column":null}},"type":"if","locations":[{"start":{"line":220,"column":10},"end":{"line":224,"column":null}},{"start":{},"end":{}}],"line":220},"12":{"loc":{"start":{"line":237,"column":12},"end":{"line":241,"column":null}},"type":"if","locations":[{"start":{"line":237,"column":12},"end":{"line":241,"column":null}},{"start":{},"end":{}}],"line":237}},"s":{"0":11,"1":11,"2":6,"3":11,"4":3,"5":9,"6":0,"7":9,"8":0,"9":0,"10":9,"11":11,"12":0,"13":0,"14":0,"15":0,"16":0,"17":0,"18":0,"19":0,"20":0,"21":0,"22":0,"23":0,"24":0,"25":0,"26":3,"27":3,"28":6,"29":0,"30":0,"31":3,"32":3,"33":3,"34":3,"35":0,"36":0,"37":0,"38":0,"39":0,"40":0,"41":0,"42":0,"43":0,"44":0,"45":0,"46":0,"47":0,"48":0,"49":0,"50":0,"51":0,"52":0,"53":0,"54":0,"55":0,"56":0,"57":0,"58":0,"59":0,"60":0,"61":0,"62":0,"63":0,"64":0,"65":0,"66":0,"67":0,"68":0,"69":0,"70":0,"71":0,"72":0,"73":0,"74":0,"75":0,"76":0,"77":0,"78":0,"79":0,"80":0,"81":0,"82":0,"83":0,"84":0,"85":0,"86":0,"87":0},"f":{"0":6,"1":3,"2":9,"3":11,"4":0,"5":0,"6":0,"7":0,"8":3,"9":6,"10":0,"11":3,"12":0,"13":0,"14":0,"15":0,"16":0,"17":0,"18":0,"19":0,"20":0,"21":0,"22":0,"23":0,"24":0},"b":{"0":[6,0],"1":[3,0],"2":[0,9],"3":[9,0],"4":[0,0],"5":[0,0],"6":[0,0,0,0],"7":[0,0],"8":[0,0],"9":[0,0],"10":[0,0],"11":[0,0],"12":[0,0]},"meta":{"lastBranch":13,"lastFunction":25,"lastStatement":88,"seen":{"s:14:37:22:Infinity":0,"s:26:37:31:Infinity":1,"f:29:10:29:18":0,"s:29:18:29:40":2,"b:29:18:29:31:29:31:29:40":0,"s:35:38:41:Infinity":3,"f:39:10:39:18":1,"s:39:18:39:40":4,"b:39:18:39:31:39:31:39:40":1,"f:45:15:45:Infinity":2,"b:49:2:54:Infinity:undefined:undefined:undefined:undefined":2,"s:49:2:54:Infinity":5,"s:50:4:53:Infinity":6,"s:56:16:58:Infinity":7,"b:57:6:57:Infinity:58:6:58:Infinity":3,"b:60:2:65:Infinity:undefined:undefined:undefined:undefined":4,"s:60:2:65:Infinity":8,"s:61:4:64:Infinity":9,"b:63:25:63:39:63:39:63:47":5,"s:67:2:67:Infinity":10,"f:70:16:70:32":3,"s:71:2:247:Infinity":11,"f:74:16:74:23":4,"s:75:14:75:Infinity":12,"s:76:8:84:Infinity":13,"f:89:16:89:23":5,"s:90:14:90:Infinity":14,"s:91:22:91:Infinity":15,"s:92:8:92:Infinity":16,"s:93:8:93:Infinity":17,"f:98:16:98:23":6,"s:99:14:99:Infinity":18,"s:100:22:100:Infinity":19,"s:101:8:101:Infinity":20,"s:102:8:102:Infinity":21,"f:107:16:107:23":7,"s:108:14:108:Infinity":22,"s:109:22:109:Infinity":23,"s:110:8:110:Infinity":24,"s:111:8:111:Infinity":25,"f:115:13:115:20":8,"s:116:14:116:Infinity":26,"s:117:8:117:Infinity":27,"f:122:13:122:20":9,"s:123:8:123:Infinity":28,"f:128:13:128:20":10,"s:129:14:129:Infinity":29,"s:130:8:130:Infinity":30,"f:135:16:135:23":11,"s:136:14:136:Infinity":31,"s:137:22:137:Infinity":32,"s:138:8:138:Infinity":33,"s:139:8:139:Infinity":34,"f:144:13:144:20":12,"s:145:14:145:Infinity":35,"s:146:22:146:Infinity":36,"s:147:8:147:Infinity":37,"f:152:13:152:20":13,"s:153:14:153:Infinity":38,"s:154:22:154:Infinity":39,"s:155:8:155:Infinity":40,"f:159:13:159:20":14,"s:160:14:160:Infinity":41,"s:161:26:161:Infinity":42,"s:162:8:162:Infinity":43,"f:162:32:162:41":15,"s:162:41:162:77":44,"f:167:13:167:20":16,"s:168:14:168:Infinity":45,"s:169:26:169:Infinity":46,"s:170:27:181:Infinity":47,"f:172:12:172:13":17,"s:173:14:176:Infinity":48,"b:173:14:173:Infinity:174:14:174:Infinity:175:14:175:Infinity:176:14:176:Infinity":6,"f:179:12:179:13":18,"s:180:14:180:Infinity":49,"s:182:8:182:Infinity":50,"b:182:15:182:32:182:32:182:Infinity":7,"f:187:13:187:20":19,"s:188:22:188:Infinity":51,"s:189:14:189:Infinity":52,"s:191:23:191:Infinity":53,"s:192:8:192:Infinity":54,"f:192:26:192:31":20,"s:192:31:192:40":55,"f:197:20:197:37":21,"s:198:28:198:Infinity":56,"s:199:23:199:Infinity":57,"b:199:23:199:38:199:38:199:Infinity":8,"s:200:25:200:Infinity":58,"s:202:27:202:Infinity":59,"s:203:32:203:Infinity":60,"s:204:43:204:Infinity":61,"s:206:24:214:Infinity":62,"f:206:24:206:25":22,"b:207:10:207:Infinity:undefined:undefined:undefined:undefined":9,"s:207:10:207:Infinity":63,"s:207:49:207:Infinity":64,"s:208:10:208:Infinity":65,"b:209:10:213:Infinity:undefined:undefined:undefined:undefined":10,"s:209:10:213:Infinity":66,"s:210:22:210:Infinity":67,"s:211:12:211:Infinity":68,"s:212:12:212:Infinity":69,"s:216:8:216:Infinity":70,"s:218:24:225:Infinity":71,"f:218:24:218:30":23,"s:219:10:219:Infinity":72,"b:220:10:224:Infinity:undefined:undefined:undefined:undefined":11,"s:220:10:224:Infinity":73,"s:221:22:221:Infinity":74,"s:222:12:222:Infinity":75,"s:223:12:223:Infinity":76,"s:227:8:227:Infinity":77,"s:229:8:245:Infinity":78,"s:230:10:242:Infinity":79,"s:231:12:235:Infinity":80,"s:232:27:232:Infinity":81,"s:233:25:233:Infinity":82,"s:234:14:234:Infinity":83,"b:237:12:241:Infinity:undefined:undefined:undefined:undefined":12,"s:237:12:241:Infinity":84,"s:238:14:240:Infinity":85,"f:238:38:238:39":24,"s:239:16:239:Infinity":86,"s:244:10:244:Infinity":87}}} +,"/Users/lukasmay/development/projects/codewalk-district/src/trpc/routers/architect.ts": {"path":"/Users/lukasmay/development/projects/codewalk-district/src/trpc/routers/architect.ts","statementMap":{"0":{"start":{"line":38,"column":52},"end":{"line":43,"column":null}},"1":{"start":{"line":46,"column":22},"end":{"line":46,"column":null}},"2":{"start":{"line":47,"column":2},"end":{"line":51,"column":null}},"3":{"start":{"line":48,"column":16},"end":{"line":48,"column":null}},"4":{"start":{"line":49,"column":4},"end":{"line":49,"column":null}},"5":{"start":{"line":50,"column":4},"end":{"line":50,"column":null}},"6":{"start":{"line":52,"column":17},"end":{"line":55,"column":null}},"7":{"start":{"line":52,"column":40},"end":{"line":55,"column":4}},"8":{"start":{"line":58,"column":18},"end":{"line":58,"column":null}},"9":{"start":{"line":58,"column":53},"end":{"line":58,"column":57}},"10":{"start":{"line":59,"column":19},"end":{"line":59,"column":null}},"11":{"start":{"line":60,"column":2},"end":{"line":70,"column":null}},"12":{"start":{"line":61,"column":4},"end":{"line":69,"column":null}},"13":{"start":{"line":62,"column":25},"end":{"line":62,"column":null}},"14":{"start":{"line":63,"column":6},"end":{"line":68,"column":null}},"15":{"start":{"line":64,"column":8},"end":{"line":67,"column":null}},"16":{"start":{"line":65,"column":10},"end":{"line":65,"column":null}},"17":{"start":{"line":66,"column":10},"end":{"line":66,"column":null}},"18":{"start":{"line":73,"column":30},"end":{"line":73,"column":null}},"19":{"start":{"line":73,"column":51},"end":{"line":73,"column":82}},"20":{"start":{"line":75,"column":2},"end":{"line":75,"column":null}},"21":{"start":{"line":79,"column":2},"end":{"line":364,"column":null}},"22":{"start":{"line":88,"column":14},"end":{"line":88,"column":null}},"23":{"start":{"line":89,"column":14},"end":{"line":89,"column":null}},"24":{"start":{"line":90,"column":14},"end":{"line":90,"column":null}},"25":{"start":{"line":92,"column":27},"end":{"line":92,"column":null}},"26":{"start":{"line":93,"column":8},"end":{"line":98,"column":null}},"27":{"start":{"line":94,"column":10},"end":{"line":97,"column":null}},"28":{"start":{"line":100,"column":21},"end":{"line":106,"column":null}},"29":{"start":{"line":108,"column":14},"end":{"line":108,"column":null}},"30":{"start":{"line":110,"column":8},"end":{"line":118,"column":null}},"31":{"start":{"line":129,"column":14},"end":{"line":129,"column":null}},"32":{"start":{"line":130,"column":14},"end":{"line":130,"column":null}},"33":{"start":{"line":131,"column":14},"end":{"line":131,"column":null}},"34":{"start":{"line":133,"column":27},"end":{"line":133,"column":null}},"35":{"start":{"line":134,"column":8},"end":{"line":139,"column":null}},"36":{"start":{"line":135,"column":10},"end":{"line":138,"column":null}},"37":{"start":{"line":142,"column":26},"end":{"line":142,"column":null}},"38":{"start":{"line":143,"column":28},"end":{"line":149,"column":null}},"39":{"start":{"line":145,"column":12},"end":{"line":148,"column":null}},"40":{"start":{"line":150,"column":8},"end":{"line":152,"column":null}},"41":{"start":{"line":151,"column":10},"end":{"line":151,"column":null}},"42":{"start":{"line":155,"column":33},"end":{"line":160,"column":null}},"43":{"start":{"line":157,"column":12},"end":{"line":159,"column":null}},"44":{"start":{"line":161,"column":8},"end":{"line":166,"column":null}},"45":{"start":{"line":162,"column":10},"end":{"line":165,"column":null}},"46":{"start":{"line":168,"column":21},"end":{"line":174,"column":null}},"47":{"start":{"line":176,"column":24},"end":{"line":176,"column":null}},"48":{"start":{"line":178,"column":14},"end":{"line":178,"column":null}},"49":{"start":{"line":180,"column":8},"end":{"line":193,"column":null}},"50":{"start":{"line":204,"column":14},"end":{"line":204,"column":null}},"51":{"start":{"line":205,"column":14},"end":{"line":205,"column":null}},"52":{"start":{"line":206,"column":14},"end":{"line":206,"column":null}},"53":{"start":{"line":207,"column":14},"end":{"line":207,"column":null}},"54":{"start":{"line":209,"column":27},"end":{"line":209,"column":null}},"55":{"start":{"line":210,"column":8},"end":{"line":215,"column":null}},"56":{"start":{"line":211,"column":10},"end":{"line":214,"column":null}},"57":{"start":{"line":218,"column":26},"end":{"line":218,"column":null}},"58":{"start":{"line":219,"column":28},"end":{"line":225,"column":null}},"59":{"start":{"line":221,"column":12},"end":{"line":224,"column":null}},"60":{"start":{"line":226,"column":8},"end":{"line":228,"column":null}},"61":{"start":{"line":227,"column":10},"end":{"line":227,"column":null}},"62":{"start":{"line":231,"column":35},"end":{"line":236,"column":null}},"63":{"start":{"line":233,"column":12},"end":{"line":235,"column":null}},"64":{"start":{"line":237,"column":8},"end":{"line":242,"column":null}},"65":{"start":{"line":238,"column":10},"end":{"line":241,"column":null}},"66":{"start":{"line":244,"column":22},"end":{"line":244,"column":null}},"67":{"start":{"line":246,"column":8},"end":{"line":251,"column":null}},"68":{"start":{"line":247,"column":10},"end":{"line":250,"column":null}},"69":{"start":{"line":253,"column":21},"end":{"line":259,"column":null}},"70":{"start":{"line":261,"column":14},"end":{"line":261,"column":null}},"71":{"start":{"line":263,"column":8},"end":{"line":271,"column":null}},"72":{"start":{"line":283,"column":14},"end":{"line":283,"column":null}},"73":{"start":{"line":284,"column":14},"end":{"line":284,"column":null}},"74":{"start":{"line":285,"column":14},"end":{"line":285,"column":null}},"75":{"start":{"line":286,"column":14},"end":{"line":286,"column":null}},"76":{"start":{"line":288,"column":22},"end":{"line":288,"column":null}},"77":{"start":{"line":289,"column":8},"end":{"line":294,"column":null}},"78":{"start":{"line":290,"column":10},"end":{"line":293,"column":null}},"79":{"start":{"line":295,"column":27},"end":{"line":295,"column":null}},"80":{"start":{"line":296,"column":8},"end":{"line":301,"column":null}},"81":{"start":{"line":297,"column":10},"end":{"line":300,"column":null}},"82":{"start":{"line":304,"column":26},"end":{"line":304,"column":null}},"83":{"start":{"line":305,"column":29},"end":{"line":307,"column":null}},"84":{"start":{"line":306,"column":17},"end":{"line":306,"column":null}},"85":{"start":{"line":310,"column":52},"end":{"line":310,"column":null}},"86":{"start":{"line":311,"column":51},"end":{"line":311,"column":null}},"87":{"start":{"line":312,"column":8},"end":{"line":322,"column":null}},"88":{"start":{"line":313,"column":10},"end":{"line":313,"column":null}},"89":{"start":{"line":313,"column":29},"end":{"line":313,"column":null}},"90":{"start":{"line":314,"column":28},"end":{"line":314,"column":null}},"91":{"start":{"line":315,"column":10},"end":{"line":315,"column":null}},"92":{"start":{"line":315,"column":52},"end":{"line":315,"column":null}},"93":{"start":{"line":317,"column":10},"end":{"line":321,"column":null}},"94":{"start":{"line":318,"column":12},"end":{"line":318,"column":null}},"95":{"start":{"line":319,"column":10},"end":{"line":321,"column":null}},"96":{"start":{"line":320,"column":12},"end":{"line":320,"column":null}},"97":{"start":{"line":323,"column":8},"end":{"line":325,"column":null}},"98":{"start":{"line":324,"column":10},"end":{"line":324,"column":null}},"99":{"start":{"line":326,"column":8},"end":{"line":331,"column":null}},"100":{"start":{"line":327,"column":10},"end":{"line":330,"column":null}},"101":{"start":{"line":333,"column":31},"end":{"line":333,"column":null}},"102":{"start":{"line":334,"column":21},"end":{"line":341,"column":null}},"103":{"start":{"line":343,"column":24},"end":{"line":343,"column":null}},"104":{"start":{"line":345,"column":14},"end":{"line":345,"column":null}},"105":{"start":{"line":347,"column":8},"end":{"line":362,"column":null}}},"fnMap":{"0":{"name":"gatherInitiativeContext","decl":{"start":{"line":28,"column":15},"end":{"line":28,"column":null}},"loc":{"start":{"line":37,"column":3},"end":{"line":76,"column":null}},"line":37},"1":{"name":"(anonymous_1)","decl":{"start":{"line":52,"column":31},"end":{"line":52,"column":32}},"loc":{"start":{"line":52,"column":40},"end":{"line":55,"column":4}},"line":52},"2":{"name":"(anonymous_2)","decl":{"start":{"line":58,"column":46},"end":{"line":58,"column":47}},"loc":{"start":{"line":58,"column":53},"end":{"line":58,"column":57}},"line":58},"3":{"name":"(anonymous_3)","decl":{"start":{"line":73,"column":46},"end":{"line":73,"column":51}},"loc":{"start":{"line":73,"column":51},"end":{"line":73,"column":82}},"line":73},"4":{"name":"architectProcedures","decl":{"start":{"line":78,"column":16},"end":{"line":78,"column":36}},"loc":{"start":{"line":78,"column":71},"end":{"line":365,"column":null}},"line":78},"5":{"name":"(anonymous_5)","decl":{"start":{"line":87,"column":16},"end":{"line":87,"column":23}},"loc":{"start":{"line":87,"column":42},"end":{"line":119,"column":7}},"line":87},"6":{"name":"(anonymous_6)","decl":{"start":{"line":128,"column":16},"end":{"line":128,"column":23}},"loc":{"start":{"line":128,"column":42},"end":{"line":194,"column":7}},"line":128},"7":{"name":"(anonymous_7)","decl":{"start":{"line":144,"column":10},"end":{"line":144,"column":11}},"loc":{"start":{"line":145,"column":12},"end":{"line":148,"column":null}},"line":145},"8":{"name":"(anonymous_8)","decl":{"start":{"line":156,"column":10},"end":{"line":156,"column":11}},"loc":{"start":{"line":157,"column":12},"end":{"line":159,"column":null}},"line":157},"9":{"name":"(anonymous_9)","decl":{"start":{"line":203,"column":16},"end":{"line":203,"column":23}},"loc":{"start":{"line":203,"column":42},"end":{"line":272,"column":7}},"line":203},"10":{"name":"(anonymous_10)","decl":{"start":{"line":220,"column":10},"end":{"line":220,"column":11}},"loc":{"start":{"line":221,"column":12},"end":{"line":224,"column":null}},"line":221},"11":{"name":"(anonymous_11)","decl":{"start":{"line":232,"column":10},"end":{"line":232,"column":11}},"loc":{"start":{"line":233,"column":12},"end":{"line":235,"column":null}},"line":233},"12":{"name":"(anonymous_12)","decl":{"start":{"line":282,"column":16},"end":{"line":282,"column":23}},"loc":{"start":{"line":282,"column":42},"end":{"line":363,"column":7}},"line":282},"13":{"name":"(anonymous_13)","decl":{"start":{"line":306,"column":10},"end":{"line":306,"column":11}},"loc":{"start":{"line":306,"column":17},"end":{"line":306,"column":null}},"line":306}},"branchMap":{"0":{"loc":{"start":{"line":39,"column":4},"end":{"line":39,"column":null}},"type":"binary-expr","locations":[{"start":{"line":39,"column":4},"end":{"line":39,"column":51}},{"start":{"line":39,"column":51},"end":{"line":39,"column":null}}],"line":39},"1":{"loc":{"start":{"line":40,"column":4},"end":{"line":40,"column":null}},"type":"binary-expr","locations":[{"start":{"line":40,"column":4},"end":{"line":40,"column":63}},{"start":{"line":40,"column":63},"end":{"line":40,"column":null}}],"line":40},"2":{"loc":{"start":{"line":41,"column":4},"end":{"line":41,"column":null}},"type":"binary-expr","locations":[{"start":{"line":41,"column":4},"end":{"line":41,"column":50}},{"start":{"line":41,"column":50},"end":{"line":41,"column":null}}],"line":41},"3":{"loc":{"start":{"line":42,"column":4},"end":{"line":42,"column":null}},"type":"binary-expr","locations":[{"start":{"line":42,"column":4},"end":{"line":42,"column":50}},{"start":{"line":42,"column":50},"end":{"line":42,"column":null}}],"line":42},"4":{"loc":{"start":{"line":48,"column":16},"end":{"line":48,"column":null}},"type":"binary-expr","locations":[{"start":{"line":48,"column":16},"end":{"line":48,"column":48}},{"start":{"line":48,"column":48},"end":{"line":48,"column":null}}],"line":48},"5":{"loc":{"start":{"line":54,"column":15},"end":{"line":54,"column":null}},"type":"binary-expr","locations":[{"start":{"line":54,"column":15},"end":{"line":54,"column":41}},{"start":{"line":54,"column":41},"end":{"line":54,"column":null}}],"line":54},"6":{"loc":{"start":{"line":60,"column":2},"end":{"line":70,"column":null}},"type":"if","locations":[{"start":{"line":60,"column":2},"end":{"line":70,"column":null}},{"start":{},"end":{}}],"line":60},"7":{"loc":{"start":{"line":64,"column":8},"end":{"line":67,"column":null}},"type":"if","locations":[{"start":{"line":64,"column":8},"end":{"line":67,"column":null}},{"start":{},"end":{}}],"line":64},"8":{"loc":{"start":{"line":93,"column":8},"end":{"line":98,"column":null}},"type":"if","locations":[{"start":{"line":93,"column":8},"end":{"line":98,"column":null}},{"start":{},"end":{}}],"line":93},"9":{"loc":{"start":{"line":103,"column":23},"end":{"line":103,"column":null}},"type":"binary-expr","locations":[{"start":{"line":103,"column":23},"end":{"line":103,"column":40}},{"start":{"line":103,"column":40},"end":{"line":103,"column":null}}],"line":103},"10":{"loc":{"start":{"line":134,"column":8},"end":{"line":139,"column":null}},"type":"if","locations":[{"start":{"line":134,"column":8},"end":{"line":139,"column":null}},{"start":{},"end":{}}],"line":134},"11":{"loc":{"start":{"line":145,"column":12},"end":{"line":148,"column":null}},"type":"binary-expr","locations":[{"start":{"line":145,"column":12},"end":{"line":145,"column":null}},{"start":{"line":146,"column":12},"end":{"line":146,"column":null}},{"start":{"line":147,"column":12},"end":{"line":147,"column":null}},{"start":{"line":148,"column":12},"end":{"line":148,"column":null}}],"line":145},"12":{"loc":{"start":{"line":157,"column":12},"end":{"line":159,"column":null}},"type":"binary-expr","locations":[{"start":{"line":157,"column":12},"end":{"line":157,"column":null}},{"start":{"line":158,"column":12},"end":{"line":158,"column":null}},{"start":{"line":159,"column":12},"end":{"line":159,"column":null}}],"line":157},"13":{"loc":{"start":{"line":161,"column":8},"end":{"line":166,"column":null}},"type":"if","locations":[{"start":{"line":161,"column":8},"end":{"line":166,"column":null}},{"start":{},"end":{}}],"line":161},"14":{"loc":{"start":{"line":189,"column":19},"end":{"line":189,"column":null}},"type":"cond-expr","locations":[{"start":{"line":189,"column":46},"end":{"line":189,"column":62}},{"start":{"line":189,"column":62},"end":{"line":189,"column":null}}],"line":189},"15":{"loc":{"start":{"line":190,"column":20},"end":{"line":190,"column":null}},"type":"cond-expr","locations":[{"start":{"line":190,"column":48},"end":{"line":190,"column":65}},{"start":{"line":190,"column":65},"end":{"line":190,"column":null}}],"line":190},"16":{"loc":{"start":{"line":191,"column":19},"end":{"line":191,"column":null}},"type":"cond-expr","locations":[{"start":{"line":191,"column":46},"end":{"line":191,"column":62}},{"start":{"line":191,"column":62},"end":{"line":191,"column":null}}],"line":191},"17":{"loc":{"start":{"line":210,"column":8},"end":{"line":215,"column":null}},"type":"if","locations":[{"start":{"line":210,"column":8},"end":{"line":215,"column":null}},{"start":{},"end":{}}],"line":210},"18":{"loc":{"start":{"line":221,"column":12},"end":{"line":224,"column":null}},"type":"binary-expr","locations":[{"start":{"line":221,"column":12},"end":{"line":221,"column":null}},{"start":{"line":222,"column":12},"end":{"line":222,"column":null}},{"start":{"line":223,"column":12},"end":{"line":223,"column":null}},{"start":{"line":224,"column":12},"end":{"line":224,"column":null}}],"line":221},"19":{"loc":{"start":{"line":233,"column":12},"end":{"line":235,"column":null}},"type":"binary-expr","locations":[{"start":{"line":233,"column":12},"end":{"line":233,"column":null}},{"start":{"line":234,"column":12},"end":{"line":234,"column":null}},{"start":{"line":235,"column":12},"end":{"line":235,"column":null}}],"line":233},"20":{"loc":{"start":{"line":237,"column":8},"end":{"line":242,"column":null}},"type":"if","locations":[{"start":{"line":237,"column":8},"end":{"line":242,"column":null}},{"start":{},"end":{}}],"line":237},"21":{"loc":{"start":{"line":246,"column":8},"end":{"line":251,"column":null}},"type":"if","locations":[{"start":{"line":246,"column":8},"end":{"line":251,"column":null}},{"start":{},"end":{}}],"line":246},"22":{"loc":{"start":{"line":256,"column":23},"end":{"line":256,"column":null}},"type":"binary-expr","locations":[{"start":{"line":256,"column":23},"end":{"line":256,"column":44}},{"start":{"line":256,"column":44},"end":{"line":256,"column":null}}],"line":256},"23":{"loc":{"start":{"line":289,"column":8},"end":{"line":294,"column":null}},"type":"if","locations":[{"start":{"line":289,"column":8},"end":{"line":294,"column":null}},{"start":{},"end":{}}],"line":289},"24":{"loc":{"start":{"line":296,"column":8},"end":{"line":301,"column":null}},"type":"if","locations":[{"start":{"line":296,"column":8},"end":{"line":301,"column":null}},{"start":{},"end":{}}],"line":296},"25":{"loc":{"start":{"line":306,"column":17},"end":{"line":306,"column":null}},"type":"binary-expr","locations":[{"start":{"line":306,"column":17},"end":{"line":306,"column":40}},{"start":{"line":306,"column":40},"end":{"line":306,"column":null}}],"line":306},"26":{"loc":{"start":{"line":313,"column":10},"end":{"line":313,"column":null}},"type":"if","locations":[{"start":{"line":313,"column":10},"end":{"line":313,"column":null}},{"start":{},"end":{}}],"line":313},"27":{"loc":{"start":{"line":315,"column":10},"end":{"line":315,"column":null}},"type":"if","locations":[{"start":{"line":315,"column":10},"end":{"line":315,"column":null}},{"start":{},"end":{}}],"line":315},"28":{"loc":{"start":{"line":317,"column":10},"end":{"line":321,"column":null}},"type":"if","locations":[{"start":{"line":317,"column":10},"end":{"line":321,"column":null}},{"start":{"line":319,"column":10},"end":{"line":321,"column":null}}],"line":317},"29":{"loc":{"start":{"line":319,"column":10},"end":{"line":321,"column":null}},"type":"if","locations":[{"start":{"line":319,"column":10},"end":{"line":321,"column":null}},{"start":{},"end":{}}],"line":319},"30":{"loc":{"start":{"line":326,"column":8},"end":{"line":331,"column":null}},"type":"if","locations":[{"start":{"line":326,"column":8},"end":{"line":331,"column":null}},{"start":{},"end":{}}],"line":326},"31":{"loc":{"start":{"line":333,"column":31},"end":{"line":333,"column":null}},"type":"binary-expr","locations":[{"start":{"line":333,"column":31},"end":{"line":333,"column":49}},{"start":{"line":333,"column":49},"end":{"line":333,"column":null}}],"line":333},"32":{"loc":{"start":{"line":338,"column":23},"end":{"line":338,"column":null}},"type":"binary-expr","locations":[{"start":{"line":338,"column":23},"end":{"line":338,"column":40}},{"start":{"line":338,"column":40},"end":{"line":338,"column":null}}],"line":338},"33":{"loc":{"start":{"line":358,"column":19},"end":{"line":358,"column":null}},"type":"cond-expr","locations":[{"start":{"line":358,"column":46},"end":{"line":358,"column":62}},{"start":{"line":358,"column":62},"end":{"line":358,"column":null}}],"line":358},"34":{"loc":{"start":{"line":359,"column":20},"end":{"line":359,"column":null}},"type":"cond-expr","locations":[{"start":{"line":359,"column":48},"end":{"line":359,"column":65}},{"start":{"line":359,"column":65},"end":{"line":359,"column":null}}],"line":359},"35":{"loc":{"start":{"line":360,"column":19},"end":{"line":360,"column":null}},"type":"cond-expr","locations":[{"start":{"line":360,"column":46},"end":{"line":360,"column":62}},{"start":{"line":360,"column":62},"end":{"line":360,"column":null}}],"line":360}},"s":{"0":16,"1":16,"2":16,"3":0,"4":0,"5":0,"6":16,"7":11,"8":16,"9":20,"10":16,"11":16,"12":16,"13":11,"14":11,"15":15,"16":4,"17":4,"18":16,"19":24,"20":16,"21":11,"22":3,"23":3,"24":3,"25":3,"26":3,"27":0,"28":3,"29":3,"30":3,"31":8,"32":8,"33":8,"34":8,"35":8,"36":0,"37":8,"38":8,"39":4,"40":8,"41":1,"42":8,"43":4,"44":8,"45":1,"46":7,"47":7,"48":7,"49":7,"50":0,"51":0,"52":0,"53":0,"54":0,"55":0,"56":0,"57":0,"58":0,"59":0,"60":0,"61":0,"62":0,"63":0,"64":0,"65":0,"66":0,"67":0,"68":0,"69":0,"70":0,"71":0,"72":10,"73":10,"74":10,"75":10,"76":10,"77":10,"78":0,"79":10,"80":10,"81":0,"82":10,"83":10,"84":3,"85":10,"86":10,"87":10,"88":3,"89":0,"90":3,"91":3,"92":1,"93":2,"94":1,"95":1,"96":1,"97":10,"98":1,"99":10,"100":1,"101":9,"102":10,"103":9,"104":9,"105":9},"f":{"0":16,"1":11,"2":20,"3":24,"4":11,"5":3,"6":8,"7":4,"8":4,"9":0,"10":0,"11":0,"12":10,"13":3},"b":{"0":[16,0],"1":[16,0],"2":[16,0],"3":[16,16],"4":[0,0],"5":[11,11],"6":[16,0],"7":[4,11],"8":[0,3],"9":[3,3],"10":[0,8],"11":[4,3,2,1],"12":[4,3,2],"13":[1,7],"14":[0,7],"15":[0,7],"16":[0,7],"17":[0,0],"18":[0,0,0,0],"19":[0,0,0],"20":[0,0],"21":[0,0],"22":[0,0],"23":[0,10],"24":[0,10],"25":[3,3],"26":[0,3],"27":[1,2],"28":[1,1],"29":[1,0],"30":[1,9],"31":[9,9],"32":[10,9],"33":[0,9],"34":[9,0],"35":[0,9]},"meta":{"lastBranch":36,"lastFunction":14,"lastStatement":106,"seen":{"f:28:15:28:Infinity":0,"s:38:52:43:Infinity":0,"b:39:4:39:51:39:51:39:Infinity":0,"b:40:4:40:63:40:63:40:Infinity":1,"b:41:4:41:50:41:50:41:Infinity":2,"b:42:4:42:50:42:50:42:Infinity":3,"s:46:22:46:Infinity":1,"s:47:2:51:Infinity":2,"s:48:16:48:Infinity":3,"b:48:16:48:48:48:48:48:Infinity":4,"s:49:4:49:Infinity":4,"s:50:4:50:Infinity":5,"s:52:17:55:Infinity":6,"f:52:31:52:32":1,"s:52:40:55:4":7,"b:54:15:54:41:54:41:54:Infinity":5,"s:58:18:58:Infinity":8,"f:58:46:58:47":2,"s:58:53:58:57":9,"s:59:19:59:Infinity":10,"b:60:2:70:Infinity:undefined:undefined:undefined:undefined":6,"s:60:2:70:Infinity":11,"s:61:4:69:Infinity":12,"s:62:25:62:Infinity":13,"s:63:6:68:Infinity":14,"b:64:8:67:Infinity:undefined:undefined:undefined:undefined":7,"s:64:8:67:Infinity":15,"s:65:10:65:Infinity":16,"s:66:10:66:Infinity":17,"s:73:30:73:Infinity":18,"f:73:46:73:51":3,"s:73:51:73:82":19,"s:75:2:75:Infinity":20,"f:78:16:78:36":4,"s:79:2:364:Infinity":21,"f:87:16:87:23":5,"s:88:14:88:Infinity":22,"s:89:14:89:Infinity":23,"s:90:14:90:Infinity":24,"s:92:27:92:Infinity":25,"b:93:8:98:Infinity:undefined:undefined:undefined:undefined":8,"s:93:8:98:Infinity":26,"s:94:10:97:Infinity":27,"s:100:21:106:Infinity":28,"b:103:23:103:40:103:40:103:Infinity":9,"s:108:14:108:Infinity":29,"s:110:8:118:Infinity":30,"f:128:16:128:23":6,"s:129:14:129:Infinity":31,"s:130:14:130:Infinity":32,"s:131:14:131:Infinity":33,"s:133:27:133:Infinity":34,"b:134:8:139:Infinity:undefined:undefined:undefined:undefined":10,"s:134:8:139:Infinity":35,"s:135:10:138:Infinity":36,"s:142:26:142:Infinity":37,"s:143:28:149:Infinity":38,"f:144:10:144:11":7,"s:145:12:148:Infinity":39,"b:145:12:145:Infinity:146:12:146:Infinity:147:12:147:Infinity:148:12:148:Infinity":11,"s:150:8:152:Infinity":40,"s:151:10:151:Infinity":41,"s:155:33:160:Infinity":42,"f:156:10:156:11":8,"s:157:12:159:Infinity":43,"b:157:12:157:Infinity:158:12:158:Infinity:159:12:159:Infinity":12,"b:161:8:166:Infinity:undefined:undefined:undefined:undefined":13,"s:161:8:166:Infinity":44,"s:162:10:165:Infinity":45,"s:168:21:174:Infinity":46,"s:176:24:176:Infinity":47,"s:178:14:178:Infinity":48,"s:180:8:193:Infinity":49,"b:189:46:189:62:189:62:189:Infinity":14,"b:190:48:190:65:190:65:190:Infinity":15,"b:191:46:191:62:191:62:191:Infinity":16,"f:203:16:203:23":9,"s:204:14:204:Infinity":50,"s:205:14:205:Infinity":51,"s:206:14:206:Infinity":52,"s:207:14:207:Infinity":53,"s:209:27:209:Infinity":54,"b:210:8:215:Infinity:undefined:undefined:undefined:undefined":17,"s:210:8:215:Infinity":55,"s:211:10:214:Infinity":56,"s:218:26:218:Infinity":57,"s:219:28:225:Infinity":58,"f:220:10:220:11":10,"s:221:12:224:Infinity":59,"b:221:12:221:Infinity:222:12:222:Infinity:223:12:223:Infinity:224:12:224:Infinity":18,"s:226:8:228:Infinity":60,"s:227:10:227:Infinity":61,"s:231:35:236:Infinity":62,"f:232:10:232:11":11,"s:233:12:235:Infinity":63,"b:233:12:233:Infinity:234:12:234:Infinity:235:12:235:Infinity":19,"b:237:8:242:Infinity:undefined:undefined:undefined:undefined":20,"s:237:8:242:Infinity":64,"s:238:10:241:Infinity":65,"s:244:22:244:Infinity":66,"b:246:8:251:Infinity:undefined:undefined:undefined:undefined":21,"s:246:8:251:Infinity":67,"s:247:10:250:Infinity":68,"s:253:21:259:Infinity":69,"b:256:23:256:44:256:44:256:Infinity":22,"s:261:14:261:Infinity":70,"s:263:8:271:Infinity":71,"f:282:16:282:23":12,"s:283:14:283:Infinity":72,"s:284:14:284:Infinity":73,"s:285:14:285:Infinity":74,"s:286:14:286:Infinity":75,"s:288:22:288:Infinity":76,"b:289:8:294:Infinity:undefined:undefined:undefined:undefined":23,"s:289:8:294:Infinity":77,"s:290:10:293:Infinity":78,"s:295:27:295:Infinity":79,"b:296:8:301:Infinity:undefined:undefined:undefined:undefined":24,"s:296:8:301:Infinity":80,"s:297:10:300:Infinity":81,"s:304:26:304:Infinity":82,"s:305:29:307:Infinity":83,"f:306:10:306:11":13,"s:306:17:306:Infinity":84,"b:306:17:306:40:306:40:306:Infinity":25,"s:310:52:310:Infinity":85,"s:311:51:311:Infinity":86,"s:312:8:322:Infinity":87,"b:313:10:313:Infinity:undefined:undefined:undefined:undefined":26,"s:313:10:313:Infinity":88,"s:313:29:313:Infinity":89,"s:314:28:314:Infinity":90,"b:315:10:315:Infinity:undefined:undefined:undefined:undefined":27,"s:315:10:315:Infinity":91,"s:315:52:315:Infinity":92,"b:317:10:321:Infinity:319:10:321:Infinity":28,"s:317:10:321:Infinity":93,"s:318:12:318:Infinity":94,"b:319:10:321:Infinity:undefined:undefined:undefined:undefined":29,"s:319:10:321:Infinity":95,"s:320:12:320:Infinity":96,"s:323:8:325:Infinity":97,"s:324:10:324:Infinity":98,"b:326:8:331:Infinity:undefined:undefined:undefined:undefined":30,"s:326:8:331:Infinity":99,"s:327:10:330:Infinity":100,"s:333:31:333:Infinity":101,"b:333:31:333:49:333:49:333:Infinity":31,"s:334:21:341:Infinity":102,"b:338:23:338:40:338:40:338:Infinity":32,"s:343:24:343:Infinity":103,"s:345:14:345:Infinity":104,"s:347:8:362:Infinity":105,"b:358:46:358:62:358:62:358:Infinity":33,"b:359:48:359:65:359:65:359:Infinity":34,"b:360:46:360:62:360:62:360:Infinity":35}}} +,"/Users/lukasmay/development/projects/codewalk-district/src/trpc/routers/change-set.ts": {"path":"/Users/lukasmay/development/projects/codewalk-district/src/trpc/routers/change-set.ts","statementMap":{"0":{"start":{"line":16,"column":2},"end":{"line":145,"column":null}},"1":{"start":{"line":23,"column":14},"end":{"line":23,"column":null}},"2":{"start":{"line":24,"column":8},"end":{"line":26,"column":null}},"3":{"start":{"line":25,"column":10},"end":{"line":25,"column":null}},"4":{"start":{"line":27,"column":8},"end":{"line":29,"column":null}},"5":{"start":{"line":28,"column":10},"end":{"line":28,"column":null}},"6":{"start":{"line":30,"column":8},"end":{"line":33,"column":null}},"7":{"start":{"line":39,"column":14},"end":{"line":39,"column":null}},"8":{"start":{"line":40,"column":19},"end":{"line":40,"column":null}},"9":{"start":{"line":41,"column":8},"end":{"line":43,"column":null}},"10":{"start":{"line":42,"column":10},"end":{"line":42,"column":null}},"11":{"start":{"line":44,"column":8},"end":{"line":44,"column":null}},"12":{"start":{"line":50,"column":14},"end":{"line":50,"column":null}},"13":{"start":{"line":51,"column":19},"end":{"line":51,"column":null}},"14":{"start":{"line":52,"column":8},"end":{"line":54,"column":null}},"15":{"start":{"line":53,"column":10},"end":{"line":53,"column":null}},"16":{"start":{"line":55,"column":8},"end":{"line":57,"column":null}},"17":{"start":{"line":56,"column":10},"end":{"line":56,"column":null}},"18":{"start":{"line":59,"column":14},"end":{"line":59,"column":null}},"19":{"start":{"line":60,"column":14},"end":{"line":60,"column":null}},"20":{"start":{"line":61,"column":14},"end":{"line":61,"column":null}},"21":{"start":{"line":64,"column":8},"end":{"line":92,"column":null}},"22":{"start":{"line":65,"column":38},"end":{"line":65,"column":null}},"23":{"start":{"line":66,"column":10},"end":{"line":88,"column":null}},"24":{"start":{"line":67,"column":12},"end":{"line":87,"column":null}},"25":{"start":{"line":68,"column":14},"end":{"line":78,"column":null}},"26":{"start":{"line":69,"column":30},"end":{"line":69,"column":null}},"27":{"start":{"line":70,"column":16},"end":{"line":72,"column":null}},"28":{"start":{"line":71,"column":18},"end":{"line":71,"column":null}},"29":{"start":{"line":73,"column":14},"end":{"line":78,"column":null}},"30":{"start":{"line":74,"column":29},"end":{"line":74,"column":null}},"31":{"start":{"line":75,"column":16},"end":{"line":77,"column":null}},"32":{"start":{"line":76,"column":18},"end":{"line":76,"column":null}},"33":{"start":{"line":79,"column":12},"end":{"line":87,"column":null}},"34":{"start":{"line":80,"column":27},"end":{"line":80,"column":null}},"35":{"start":{"line":81,"column":14},"end":{"line":86,"column":null}},"36":{"start":{"line":82,"column":40},"end":{"line":82,"column":null}},"37":{"start":{"line":83,"column":16},"end":{"line":85,"column":null}},"38":{"start":{"line":84,"column":18},"end":{"line":84,"column":null}},"39":{"start":{"line":89,"column":10},"end":{"line":91,"column":null}},"40":{"start":{"line":90,"column":12},"end":{"line":90,"column":null}},"41":{"start":{"line":95,"column":32},"end":{"line":95,"column":null}},"42":{"start":{"line":96,"column":8},"end":{"line":133,"column":null}},"43":{"start":{"line":97,"column":10},"end":{"line":132,"column":null}},"44":{"start":{"line":98,"column":12},"end":{"line":129,"column":null}},"45":{"start":{"line":99,"column":14},"end":{"line":113,"column":null}},"46":{"start":{"line":101,"column":18},"end":{"line":101,"column":null}},"47":{"start":{"line":101,"column":24},"end":{"line":101,"column":64}},"48":{"start":{"line":102,"column":18},"end":{"line":102,"column":null}},"49":{"start":{"line":104,"column":18},"end":{"line":104,"column":null}},"50":{"start":{"line":104,"column":24},"end":{"line":104,"column":63}},"51":{"start":{"line":105,"column":18},"end":{"line":105,"column":null}},"52":{"start":{"line":107,"column":34},"end":{"line":107,"column":null}},"53":{"start":{"line":108,"column":18},"end":{"line":110,"column":null}},"54":{"start":{"line":109,"column":20},"end":{"line":109,"column":null}},"55":{"start":{"line":109,"column":26},"end":{"line":109,"column":103}},"56":{"start":{"line":111,"column":18},"end":{"line":111,"column":null}},"57":{"start":{"line":114,"column":12},"end":{"line":129,"column":null}},"58":{"start":{"line":115,"column":27},"end":{"line":115,"column":null}},"59":{"start":{"line":116,"column":14},"end":{"line":128,"column":null}},"60":{"start":{"line":118,"column":18},"end":{"line":121,"column":null}},"61":{"start":{"line":122,"column":18},"end":{"line":126,"column":null}},"62":{"start":{"line":127,"column":18},"end":{"line":127,"column":null}},"63":{"start":{"line":135,"column":8},"end":{"line":135,"column":null}},"64":{"start":{"line":137,"column":8},"end":{"line":141,"column":null}},"65":{"start":{"line":143,"column":8},"end":{"line":143,"column":null}}},"fnMap":{"0":{"name":"changeSetProcedures","decl":{"start":{"line":15,"column":16},"end":{"line":15,"column":36}},"loc":{"start":{"line":15,"column":71},"end":{"line":146,"column":null}},"line":15},"1":{"name":"(anonymous_1)","decl":{"start":{"line":22,"column":13},"end":{"line":22,"column":20}},"loc":{"start":{"line":22,"column":39},"end":{"line":34,"column":7}},"line":22},"2":{"name":"(anonymous_2)","decl":{"start":{"line":38,"column":13},"end":{"line":38,"column":20}},"loc":{"start":{"line":38,"column":39},"end":{"line":45,"column":7}},"line":38},"3":{"name":"(anonymous_3)","decl":{"start":{"line":49,"column":16},"end":{"line":49,"column":23}},"loc":{"start":{"line":49,"column":42},"end":{"line":144,"column":7}},"line":49}},"branchMap":{"0":{"loc":{"start":{"line":24,"column":8},"end":{"line":26,"column":null}},"type":"if","locations":[{"start":{"line":24,"column":8},"end":{"line":26,"column":null}},{"start":{},"end":{}}],"line":24},"1":{"loc":{"start":{"line":27,"column":8},"end":{"line":29,"column":null}},"type":"if","locations":[{"start":{"line":27,"column":8},"end":{"line":29,"column":null}},{"start":{},"end":{}}],"line":27},"2":{"loc":{"start":{"line":41,"column":8},"end":{"line":43,"column":null}},"type":"if","locations":[{"start":{"line":41,"column":8},"end":{"line":43,"column":null}},{"start":{},"end":{}}],"line":41},"3":{"loc":{"start":{"line":52,"column":8},"end":{"line":54,"column":null}},"type":"if","locations":[{"start":{"line":52,"column":8},"end":{"line":54,"column":null}},{"start":{},"end":{}}],"line":52},"4":{"loc":{"start":{"line":55,"column":8},"end":{"line":57,"column":null}},"type":"if","locations":[{"start":{"line":55,"column":8},"end":{"line":57,"column":null}},{"start":{},"end":{}}],"line":55},"5":{"loc":{"start":{"line":64,"column":8},"end":{"line":92,"column":null}},"type":"if","locations":[{"start":{"line":64,"column":8},"end":{"line":92,"column":null}},{"start":{},"end":{}}],"line":64},"6":{"loc":{"start":{"line":67,"column":12},"end":{"line":87,"column":null}},"type":"if","locations":[{"start":{"line":67,"column":12},"end":{"line":87,"column":null}},{"start":{"line":79,"column":12},"end":{"line":87,"column":null}}],"line":67},"7":{"loc":{"start":{"line":68,"column":14},"end":{"line":78,"column":null}},"type":"if","locations":[{"start":{"line":68,"column":14},"end":{"line":78,"column":null}},{"start":{"line":73,"column":14},"end":{"line":78,"column":null}}],"line":68},"8":{"loc":{"start":{"line":70,"column":16},"end":{"line":72,"column":null}},"type":"if","locations":[{"start":{"line":70,"column":16},"end":{"line":72,"column":null}},{"start":{},"end":{}}],"line":70},"9":{"loc":{"start":{"line":70,"column":20},"end":{"line":70,"column":61}},"type":"binary-expr","locations":[{"start":{"line":70,"column":20},"end":{"line":70,"column":29}},{"start":{"line":70,"column":29},"end":{"line":70,"column":61}}],"line":70},"10":{"loc":{"start":{"line":73,"column":14},"end":{"line":78,"column":null}},"type":"if","locations":[{"start":{"line":73,"column":14},"end":{"line":78,"column":null}},{"start":{},"end":{}}],"line":73},"11":{"loc":{"start":{"line":75,"column":16},"end":{"line":77,"column":null}},"type":"if","locations":[{"start":{"line":75,"column":16},"end":{"line":77,"column":null}},{"start":{},"end":{}}],"line":75},"12":{"loc":{"start":{"line":75,"column":20},"end":{"line":75,"column":59}},"type":"binary-expr","locations":[{"start":{"line":75,"column":20},"end":{"line":75,"column":28}},{"start":{"line":75,"column":28},"end":{"line":75,"column":59}}],"line":75},"13":{"loc":{"start":{"line":79,"column":12},"end":{"line":87,"column":null}},"type":"if","locations":[{"start":{"line":79,"column":12},"end":{"line":87,"column":null}},{"start":{},"end":{}}],"line":79},"14":{"loc":{"start":{"line":79,"column":23},"end":{"line":79,"column":99}},"type":"binary-expr","locations":[{"start":{"line":79,"column":23},"end":{"line":79,"column":52}},{"start":{"line":79,"column":52},"end":{"line":79,"column":83}},{"start":{"line":79,"column":83},"end":{"line":79,"column":99}}],"line":79},"15":{"loc":{"start":{"line":81,"column":14},"end":{"line":86,"column":null}},"type":"if","locations":[{"start":{"line":81,"column":14},"end":{"line":86,"column":null}},{"start":{},"end":{}}],"line":81},"16":{"loc":{"start":{"line":83,"column":16},"end":{"line":85,"column":null}},"type":"if","locations":[{"start":{"line":83,"column":16},"end":{"line":85,"column":null}},{"start":{},"end":{}}],"line":83},"17":{"loc":{"start":{"line":89,"column":10},"end":{"line":91,"column":null}},"type":"if","locations":[{"start":{"line":89,"column":10},"end":{"line":91,"column":null}},{"start":{},"end":{}}],"line":89},"18":{"loc":{"start":{"line":98,"column":12},"end":{"line":129,"column":null}},"type":"if","locations":[{"start":{"line":98,"column":12},"end":{"line":129,"column":null}},{"start":{"line":114,"column":12},"end":{"line":129,"column":null}}],"line":98},"19":{"loc":{"start":{"line":99,"column":14},"end":{"line":113,"column":null}},"type":"switch","locations":[{"start":{"line":100,"column":16},"end":{"line":102,"column":null}},{"start":{"line":103,"column":16},"end":{"line":105,"column":null}},{"start":{"line":106,"column":16},"end":{"line":112,"column":null}}],"line":99},"20":{"loc":{"start":{"line":107,"column":45},"end":{"line":107,"column":67}},"type":"binary-expr","locations":[{"start":{"line":107,"column":45},"end":{"line":107,"column":63}},{"start":{"line":107,"column":63},"end":{"line":107,"column":67}}],"line":107},"21":{"loc":{"start":{"line":108,"column":18},"end":{"line":110,"column":null}},"type":"if","locations":[{"start":{"line":108,"column":18},"end":{"line":110,"column":null}},{"start":{},"end":{}}],"line":108},"22":{"loc":{"start":{"line":108,"column":22},"end":{"line":108,"column":67}},"type":"binary-expr","locations":[{"start":{"line":108,"column":22},"end":{"line":108,"column":41}},{"start":{"line":108,"column":41},"end":{"line":108,"column":67}}],"line":108},"23":{"loc":{"start":{"line":114,"column":12},"end":{"line":129,"column":null}},"type":"if","locations":[{"start":{"line":114,"column":12},"end":{"line":129,"column":null}},{"start":{},"end":{}}],"line":114},"24":{"loc":{"start":{"line":114,"column":23},"end":{"line":114,"column":73}},"type":"binary-expr","locations":[{"start":{"line":114,"column":23},"end":{"line":114,"column":52}},{"start":{"line":114,"column":52},"end":{"line":114,"column":73}}],"line":114},"25":{"loc":{"start":{"line":116,"column":14},"end":{"line":128,"column":null}},"type":"switch","locations":[{"start":{"line":117,"column":16},"end":{"line":127,"column":null}}],"line":116}},"s":{"0":11,"1":0,"2":0,"3":0,"4":0,"5":0,"6":0,"7":0,"8":0,"9":0,"10":0,"11":0,"12":0,"13":0,"14":0,"15":0,"16":0,"17":0,"18":0,"19":0,"20":0,"21":0,"22":0,"23":0,"24":0,"25":0,"26":0,"27":0,"28":0,"29":0,"30":0,"31":0,"32":0,"33":0,"34":0,"35":0,"36":0,"37":0,"38":0,"39":0,"40":0,"41":0,"42":0,"43":0,"44":0,"45":0,"46":0,"47":0,"48":0,"49":0,"50":0,"51":0,"52":0,"53":0,"54":0,"55":0,"56":0,"57":0,"58":0,"59":0,"60":0,"61":0,"62":0,"63":0,"64":0,"65":0},"f":{"0":11,"1":0,"2":0,"3":0},"b":{"0":[0,0],"1":[0,0],"2":[0,0],"3":[0,0],"4":[0,0],"5":[0,0],"6":[0,0],"7":[0,0],"8":[0,0],"9":[0,0],"10":[0,0],"11":[0,0],"12":[0,0],"13":[0,0],"14":[0,0,0],"15":[0,0],"16":[0,0],"17":[0,0],"18":[0,0],"19":[0,0,0],"20":[0,0],"21":[0,0],"22":[0,0],"23":[0,0],"24":[0,0],"25":[0]},"meta":{"lastBranch":26,"lastFunction":4,"lastStatement":66,"seen":{"f:15:16:15:36":0,"s:16:2:145:Infinity":0,"f:22:13:22:20":1,"s:23:14:23:Infinity":1,"b:24:8:26:Infinity:undefined:undefined:undefined:undefined":0,"s:24:8:26:Infinity":2,"s:25:10:25:Infinity":3,"b:27:8:29:Infinity:undefined:undefined:undefined:undefined":1,"s:27:8:29:Infinity":4,"s:28:10:28:Infinity":5,"s:30:8:33:Infinity":6,"f:38:13:38:20":2,"s:39:14:39:Infinity":7,"s:40:19:40:Infinity":8,"b:41:8:43:Infinity:undefined:undefined:undefined:undefined":2,"s:41:8:43:Infinity":9,"s:42:10:42:Infinity":10,"s:44:8:44:Infinity":11,"f:49:16:49:23":3,"s:50:14:50:Infinity":12,"s:51:19:51:Infinity":13,"b:52:8:54:Infinity:undefined:undefined:undefined:undefined":3,"s:52:8:54:Infinity":14,"s:53:10:53:Infinity":15,"b:55:8:57:Infinity:undefined:undefined:undefined:undefined":4,"s:55:8:57:Infinity":16,"s:56:10:56:Infinity":17,"s:59:14:59:Infinity":18,"s:60:14:60:Infinity":19,"s:61:14:61:Infinity":20,"b:64:8:92:Infinity:undefined:undefined:undefined:undefined":5,"s:64:8:92:Infinity":21,"s:65:38:65:Infinity":22,"s:66:10:88:Infinity":23,"b:67:12:87:Infinity:79:12:87:Infinity":6,"s:67:12:87:Infinity":24,"b:68:14:78:Infinity:73:14:78:Infinity":7,"s:68:14:78:Infinity":25,"s:69:30:69:Infinity":26,"b:70:16:72:Infinity:undefined:undefined:undefined:undefined":8,"s:70:16:72:Infinity":27,"b:70:20:70:29:70:29:70:61":9,"s:71:18:71:Infinity":28,"b:73:14:78:Infinity:undefined:undefined:undefined:undefined":10,"s:73:14:78:Infinity":29,"s:74:29:74:Infinity":30,"b:75:16:77:Infinity:undefined:undefined:undefined:undefined":11,"s:75:16:77:Infinity":31,"b:75:20:75:28:75:28:75:59":12,"s:76:18:76:Infinity":32,"b:79:12:87:Infinity:undefined:undefined:undefined:undefined":13,"s:79:12:87:Infinity":33,"b:79:23:79:52:79:52:79:83:79:83:79:99":14,"s:80:27:80:Infinity":34,"b:81:14:86:Infinity:undefined:undefined:undefined:undefined":15,"s:81:14:86:Infinity":35,"s:82:40:82:Infinity":36,"b:83:16:85:Infinity:undefined:undefined:undefined:undefined":16,"s:83:16:85:Infinity":37,"s:84:18:84:Infinity":38,"b:89:10:91:Infinity:undefined:undefined:undefined:undefined":17,"s:89:10:91:Infinity":39,"s:90:12:90:Infinity":40,"s:95:32:95:Infinity":41,"s:96:8:133:Infinity":42,"s:97:10:132:Infinity":43,"b:98:12:129:Infinity:114:12:129:Infinity":18,"s:98:12:129:Infinity":44,"b:100:16:102:Infinity:103:16:105:Infinity:106:16:112:Infinity":19,"s:99:14:113:Infinity":45,"s:101:18:101:Infinity":46,"s:101:24:101:64":47,"s:102:18:102:Infinity":48,"s:104:18:104:Infinity":49,"s:104:24:104:63":50,"s:105:18:105:Infinity":51,"s:107:34:107:Infinity":52,"b:107:45:107:63:107:63:107:67":20,"b:108:18:110:Infinity:undefined:undefined:undefined:undefined":21,"s:108:18:110:Infinity":53,"b:108:22:108:41:108:41:108:67":22,"s:109:20:109:Infinity":54,"s:109:26:109:103":55,"s:111:18:111:Infinity":56,"b:114:12:129:Infinity:undefined:undefined:undefined:undefined":23,"s:114:12:129:Infinity":57,"b:114:23:114:52:114:52:114:73":24,"s:115:27:115:Infinity":58,"b:117:16:127:Infinity":25,"s:116:14:128:Infinity":59,"s:118:18:121:Infinity":60,"s:122:18:126:Infinity":61,"s:127:18:127:Infinity":62,"s:135:8:135:Infinity":63,"s:137:8:141:Infinity":64,"s:143:8:143:Infinity":65}}} +,"/Users/lukasmay/development/projects/codewalk-district/src/trpc/routers/conversation.ts": {"path":"/Users/lukasmay/development/projects/codewalk-district/src/trpc/routers/conversation.ts","statementMap":{"0":{"start":{"line":13,"column":2},"end":{"line":280,"column":null}},"1":{"start":{"line":23,"column":14},"end":{"line":23,"column":null}},"2":{"start":{"line":24,"column":14},"end":{"line":24,"column":null}},"3":{"start":{"line":26,"column":24},"end":{"line":26,"column":null}},"4":{"start":{"line":29,"column":8},"end":{"line":39,"column":null}},"5":{"start":{"line":30,"column":25},"end":{"line":30,"column":null}},"6":{"start":{"line":31,"column":24},"end":{"line":31,"column":null}},"7":{"start":{"line":31,"column":41},"end":{"line":31,"column":92}},"8":{"start":{"line":32,"column":10},"end":{"line":37,"column":null}},"9":{"start":{"line":33,"column":12},"end":{"line":36,"column":null}},"10":{"start":{"line":38,"column":10},"end":{"line":38,"column":null}},"11":{"start":{"line":42,"column":8},"end":{"line":55,"column":null}},"12":{"start":{"line":43,"column":16},"end":{"line":43,"column":null}},"13":{"start":{"line":44,"column":24},"end":{"line":44,"column":null}},"14":{"start":{"line":45,"column":26},"end":{"line":45,"column":null}},"15":{"start":{"line":45,"column":49},"end":{"line":45,"column":53}},"16":{"start":{"line":46,"column":25},"end":{"line":46,"column":null}},"17":{"start":{"line":47,"column":24},"end":{"line":47,"column":null}},"18":{"start":{"line":47,"column":41},"end":{"line":47,"column":100}},"19":{"start":{"line":48,"column":10},"end":{"line":53,"column":null}},"20":{"start":{"line":49,"column":12},"end":{"line":52,"column":null}},"21":{"start":{"line":54,"column":10},"end":{"line":54,"column":null}},"22":{"start":{"line":57,"column":8},"end":{"line":62,"column":null}},"23":{"start":{"line":58,"column":10},"end":{"line":61,"column":null}},"24":{"start":{"line":64,"column":29},"end":{"line":71,"column":null}},"25":{"start":{"line":73,"column":8},"end":{"line":81,"column":null}},"26":{"start":{"line":83,"column":8},"end":{"line":83,"column":null}},"27":{"start":{"line":91,"column":14},"end":{"line":91,"column":null}},"28":{"start":{"line":92,"column":8},"end":{"line":92,"column":null}},"29":{"start":{"line":100,"column":14},"end":{"line":100,"column":null}},"30":{"start":{"line":101,"column":8},"end":{"line":101,"column":null}},"31":{"start":{"line":110,"column":14},"end":{"line":110,"column":null}},"32":{"start":{"line":111,"column":25},"end":{"line":111,"column":null}},"33":{"start":{"line":112,"column":8},"end":{"line":117,"column":null}},"34":{"start":{"line":113,"column":10},"end":{"line":116,"column":null}},"35":{"start":{"line":118,"column":8},"end":{"line":123,"column":null}},"36":{"start":{"line":119,"column":10},"end":{"line":122,"column":null}},"37":{"start":{"line":125,"column":24},"end":{"line":125,"column":null}},"38":{"start":{"line":127,"column":8},"end":{"line":135,"column":null}},"39":{"start":{"line":137,"column":8},"end":{"line":137,"column":null}},"40":{"start":{"line":149,"column":28},"end":{"line":149,"column":null}},"41":{"start":{"line":150,"column":23},"end":{"line":150,"column":null}},"42":{"start":{"line":151,"column":25},"end":{"line":151,"column":null}},"43":{"start":{"line":152,"column":14},"end":{"line":152,"column":null}},"44":{"start":{"line":155,"column":25},"end":{"line":155,"column":null}},"45":{"start":{"line":156,"column":27},"end":{"line":156,"column":null}},"46":{"start":{"line":157,"column":8},"end":{"line":165,"column":null}},"47":{"start":{"line":158,"column":10},"end":{"line":164,"column":null}},"48":{"start":{"line":168,"column":32},"end":{"line":168,"column":null}},"49":{"start":{"line":169,"column":43},"end":{"line":169,"column":null}},"50":{"start":{"line":171,"column":24},"end":{"line":179,"column":null}},"51":{"start":{"line":172,"column":10},"end":{"line":172,"column":null}},"52":{"start":{"line":172,"column":51},"end":{"line":172,"column":null}},"53":{"start":{"line":173,"column":10},"end":{"line":173,"column":null}},"54":{"start":{"line":174,"column":10},"end":{"line":178,"column":null}},"55":{"start":{"line":175,"column":22},"end":{"line":175,"column":null}},"56":{"start":{"line":176,"column":12},"end":{"line":176,"column":null}},"57":{"start":{"line":177,"column":12},"end":{"line":177,"column":null}},"58":{"start":{"line":181,"column":8},"end":{"line":181,"column":null}},"59":{"start":{"line":183,"column":24},"end":{"line":190,"column":null}},"60":{"start":{"line":184,"column":10},"end":{"line":184,"column":null}},"61":{"start":{"line":185,"column":10},"end":{"line":189,"column":null}},"62":{"start":{"line":186,"column":22},"end":{"line":186,"column":null}},"63":{"start":{"line":187,"column":12},"end":{"line":187,"column":null}},"64":{"start":{"line":188,"column":12},"end":{"line":188,"column":null}},"65":{"start":{"line":192,"column":8},"end":{"line":192,"column":null}},"66":{"start":{"line":194,"column":8},"end":{"line":218,"column":null}},"67":{"start":{"line":195,"column":10},"end":{"line":215,"column":null}},"68":{"start":{"line":196,"column":12},"end":{"line":208,"column":null}},"69":{"start":{"line":197,"column":29},"end":{"line":197,"column":null}},"70":{"start":{"line":198,"column":27},"end":{"line":198,"column":null}},"71":{"start":{"line":199,"column":14},"end":{"line":207,"column":null}},"72":{"start":{"line":200,"column":16},"end":{"line":206,"column":null}},"73":{"start":{"line":210,"column":12},"end":{"line":214,"column":null}},"74":{"start":{"line":211,"column":14},"end":{"line":213,"column":null}},"75":{"start":{"line":212,"column":16},"end":{"line":212,"column":null}},"76":{"start":{"line":217,"column":10},"end":{"line":217,"column":null}},"77":{"start":{"line":224,"column":35},"end":{"line":224,"column":null}},"78":{"start":{"line":225,"column":23},"end":{"line":225,"column":null}},"79":{"start":{"line":226,"column":25},"end":{"line":226,"column":null}},"80":{"start":{"line":227,"column":14},"end":{"line":227,"column":null}},"81":{"start":{"line":230,"column":25},"end":{"line":230,"column":null}},"82":{"start":{"line":231,"column":8},"end":{"line":234,"column":null}},"83":{"start":{"line":232,"column":10},"end":{"line":232,"column":null}},"84":{"start":{"line":233,"column":10},"end":{"line":233,"column":null}},"85":{"start":{"line":237,"column":23},"end":{"line":237,"column":null}},"86":{"start":{"line":238,"column":43},"end":{"line":238,"column":null}},"87":{"start":{"line":240,"column":24},"end":{"line":248,"column":null}},"88":{"start":{"line":241,"column":10},"end":{"line":241,"column":null}},"89":{"start":{"line":241,"column":63},"end":{"line":241,"column":null}},"90":{"start":{"line":242,"column":10},"end":{"line":242,"column":null}},"91":{"start":{"line":243,"column":10},"end":{"line":247,"column":null}},"92":{"start":{"line":244,"column":22},"end":{"line":244,"column":null}},"93":{"start":{"line":245,"column":12},"end":{"line":245,"column":null}},"94":{"start":{"line":246,"column":12},"end":{"line":246,"column":null}},"95":{"start":{"line":250,"column":8},"end":{"line":250,"column":null}},"96":{"start":{"line":252,"column":24},"end":{"line":259,"column":null}},"97":{"start":{"line":253,"column":10},"end":{"line":253,"column":null}},"98":{"start":{"line":254,"column":10},"end":{"line":258,"column":null}},"99":{"start":{"line":255,"column":22},"end":{"line":255,"column":null}},"100":{"start":{"line":256,"column":12},"end":{"line":256,"column":null}},"101":{"start":{"line":257,"column":12},"end":{"line":257,"column":null}},"102":{"start":{"line":261,"column":8},"end":{"line":261,"column":null}},"103":{"start":{"line":263,"column":8},"end":{"line":278,"column":null}},"104":{"start":{"line":264,"column":10},"end":{"line":268,"column":null}},"105":{"start":{"line":265,"column":12},"end":{"line":267,"column":null}},"106":{"start":{"line":266,"column":14},"end":{"line":266,"column":null}},"107":{"start":{"line":270,"column":10},"end":{"line":275,"column":null}},"108":{"start":{"line":271,"column":25},"end":{"line":271,"column":null}},"109":{"start":{"line":272,"column":12},"end":{"line":274,"column":null}},"110":{"start":{"line":273,"column":14},"end":{"line":273,"column":null}},"111":{"start":{"line":277,"column":10},"end":{"line":277,"column":null}}},"fnMap":{"0":{"name":"conversationProcedures","decl":{"start":{"line":12,"column":16},"end":{"line":12,"column":39}},"loc":{"start":{"line":12,"column":74},"end":{"line":281,"column":null}},"line":12},"1":{"name":"(anonymous_1)","decl":{"start":{"line":22,"column":16},"end":{"line":22,"column":23}},"loc":{"start":{"line":22,"column":42},"end":{"line":84,"column":7}},"line":22},"2":{"name":"(anonymous_2)","decl":{"start":{"line":31,"column":36},"end":{"line":31,"column":41}},"loc":{"start":{"line":31,"column":41},"end":{"line":31,"column":92}},"line":31},"3":{"name":"(anonymous_3)","decl":{"start":{"line":45,"column":44},"end":{"line":45,"column":49}},"loc":{"start":{"line":45,"column":49},"end":{"line":45,"column":53}},"line":45},"4":{"name":"(anonymous_4)","decl":{"start":{"line":47,"column":36},"end":{"line":47,"column":41}},"loc":{"start":{"line":47,"column":41},"end":{"line":47,"column":100}},"line":47},"5":{"name":"(anonymous_5)","decl":{"start":{"line":90,"column":13},"end":{"line":90,"column":20}},"loc":{"start":{"line":90,"column":39},"end":{"line":93,"column":7}},"line":90},"6":{"name":"(anonymous_6)","decl":{"start":{"line":99,"column":13},"end":{"line":99,"column":20}},"loc":{"start":{"line":99,"column":39},"end":{"line":102,"column":7}},"line":99},"7":{"name":"(anonymous_7)","decl":{"start":{"line":109,"column":16},"end":{"line":109,"column":23}},"loc":{"start":{"line":109,"column":42},"end":{"line":138,"column":7}},"line":109},"8":{"name":"(anonymous_8)","decl":{"start":{"line":142,"column":20},"end":{"line":142,"column":37}},"loc":{"start":{"line":148,"column":10},"end":{"line":219,"column":7}},"line":148},"9":{"name":"(anonymous_9)","decl":{"start":{"line":171,"column":24},"end":{"line":171,"column":25}},"loc":{"start":{"line":171,"column":61},"end":{"line":179,"column":null}},"line":171},"10":{"name":"(anonymous_10)","decl":{"start":{"line":183,"column":24},"end":{"line":183,"column":30}},"loc":{"start":{"line":183,"column":30},"end":{"line":190,"column":null}},"line":183},"11":{"name":"(anonymous_11)","decl":{"start":{"line":211,"column":38},"end":{"line":211,"column":39}},"loc":{"start":{"line":211,"column":45},"end":{"line":213,"column":15}},"line":211},"12":{"name":"(anonymous_12)","decl":{"start":{"line":223,"column":20},"end":{"line":223,"column":37}},"loc":{"start":{"line":223,"column":96},"end":{"line":279,"column":7}},"line":223},"13":{"name":"(anonymous_13)","decl":{"start":{"line":240,"column":24},"end":{"line":240,"column":25}},"loc":{"start":{"line":240,"column":62},"end":{"line":248,"column":null}},"line":240},"14":{"name":"(anonymous_14)","decl":{"start":{"line":252,"column":24},"end":{"line":252,"column":30}},"loc":{"start":{"line":252,"column":30},"end":{"line":259,"column":null}},"line":252},"15":{"name":"(anonymous_15)","decl":{"start":{"line":265,"column":36},"end":{"line":265,"column":37}},"loc":{"start":{"line":265,"column":43},"end":{"line":267,"column":13}},"line":265}},"branchMap":{"0":{"loc":{"start":{"line":29,"column":8},"end":{"line":39,"column":null}},"type":"if","locations":[{"start":{"line":29,"column":8},"end":{"line":39,"column":null}},{"start":{},"end":{}}],"line":29},"1":{"loc":{"start":{"line":29,"column":12},"end":{"line":29,"column":40}},"type":"binary-expr","locations":[{"start":{"line":29,"column":12},"end":{"line":29,"column":26}},{"start":{"line":29,"column":26},"end":{"line":29,"column":40}}],"line":29},"2":{"loc":{"start":{"line":31,"column":41},"end":{"line":31,"column":92}},"type":"binary-expr","locations":[{"start":{"line":31,"column":41},"end":{"line":31,"column":70}},{"start":{"line":31,"column":70},"end":{"line":31,"column":92}}],"line":31},"3":{"loc":{"start":{"line":32,"column":10},"end":{"line":37,"column":null}},"type":"if","locations":[{"start":{"line":32,"column":10},"end":{"line":37,"column":null}},{"start":{},"end":{}}],"line":32},"4":{"loc":{"start":{"line":42,"column":8},"end":{"line":55,"column":null}},"type":"if","locations":[{"start":{"line":42,"column":8},"end":{"line":55,"column":null}},{"start":{},"end":{}}],"line":42},"5":{"loc":{"start":{"line":42,"column":12},"end":{"line":42,"column":41}},"type":"binary-expr","locations":[{"start":{"line":42,"column":12},"end":{"line":42,"column":26}},{"start":{"line":42,"column":26},"end":{"line":42,"column":41}}],"line":42},"6":{"loc":{"start":{"line":47,"column":41},"end":{"line":47,"column":100}},"type":"binary-expr","locations":[{"start":{"line":47,"column":41},"end":{"line":47,"column":53}},{"start":{"line":47,"column":53},"end":{"line":47,"column":78}},{"start":{"line":47,"column":78},"end":{"line":47,"column":100}}],"line":47},"7":{"loc":{"start":{"line":48,"column":10},"end":{"line":53,"column":null}},"type":"if","locations":[{"start":{"line":48,"column":10},"end":{"line":53,"column":null}},{"start":{},"end":{}}],"line":48},"8":{"loc":{"start":{"line":57,"column":8},"end":{"line":62,"column":null}},"type":"if","locations":[{"start":{"line":57,"column":8},"end":{"line":62,"column":null}},{"start":{},"end":{}}],"line":57},"9":{"loc":{"start":{"line":68,"column":19},"end":{"line":68,"column":null}},"type":"binary-expr","locations":[{"start":{"line":68,"column":19},"end":{"line":68,"column":36}},{"start":{"line":68,"column":36},"end":{"line":68,"column":null}}],"line":68},"10":{"loc":{"start":{"line":69,"column":18},"end":{"line":69,"column":null}},"type":"binary-expr","locations":[{"start":{"line":69,"column":18},"end":{"line":69,"column":34}},{"start":{"line":69,"column":34},"end":{"line":69,"column":null}}],"line":69},"11":{"loc":{"start":{"line":112,"column":8},"end":{"line":117,"column":null}},"type":"if","locations":[{"start":{"line":112,"column":8},"end":{"line":117,"column":null}},{"start":{},"end":{}}],"line":112},"12":{"loc":{"start":{"line":118,"column":8},"end":{"line":123,"column":null}},"type":"if","locations":[{"start":{"line":118,"column":8},"end":{"line":123,"column":null}},{"start":{},"end":{}}],"line":118},"13":{"loc":{"start":{"line":150,"column":23},"end":{"line":150,"column":null}},"type":"binary-expr","locations":[{"start":{"line":150,"column":23},"end":{"line":150,"column":38}},{"start":{"line":150,"column":38},"end":{"line":150,"column":null}}],"line":150},"14":{"loc":{"start":{"line":172,"column":10},"end":{"line":172,"column":null}},"type":"if","locations":[{"start":{"line":172,"column":10},"end":{"line":172,"column":null}},{"start":{},"end":{}}],"line":172},"15":{"loc":{"start":{"line":174,"column":10},"end":{"line":178,"column":null}},"type":"if","locations":[{"start":{"line":174,"column":10},"end":{"line":178,"column":null}},{"start":{},"end":{}}],"line":174},"16":{"loc":{"start":{"line":185,"column":10},"end":{"line":189,"column":null}},"type":"if","locations":[{"start":{"line":185,"column":10},"end":{"line":189,"column":null}},{"start":{},"end":{}}],"line":185},"17":{"loc":{"start":{"line":199,"column":14},"end":{"line":207,"column":null}},"type":"if","locations":[{"start":{"line":199,"column":14},"end":{"line":207,"column":null}},{"start":{},"end":{}}],"line":199},"18":{"loc":{"start":{"line":199,"column":18},"end":{"line":199,"column":53}},"type":"binary-expr","locations":[{"start":{"line":199,"column":18},"end":{"line":199,"column":26}},{"start":{"line":199,"column":26},"end":{"line":199,"column":53}}],"line":199},"19":{"loc":{"start":{"line":210,"column":12},"end":{"line":214,"column":null}},"type":"if","locations":[{"start":{"line":210,"column":12},"end":{"line":214,"column":null}},{"start":{},"end":{}}],"line":210},"20":{"loc":{"start":{"line":225,"column":23},"end":{"line":225,"column":null}},"type":"binary-expr","locations":[{"start":{"line":225,"column":23},"end":{"line":225,"column":38}},{"start":{"line":225,"column":38},"end":{"line":225,"column":null}}],"line":225},"21":{"loc":{"start":{"line":231,"column":8},"end":{"line":234,"column":null}},"type":"if","locations":[{"start":{"line":231,"column":8},"end":{"line":234,"column":null}},{"start":{},"end":{}}],"line":231},"22":{"loc":{"start":{"line":231,"column":12},"end":{"line":231,"column":75}},"type":"binary-expr","locations":[{"start":{"line":231,"column":12},"end":{"line":231,"column":24}},{"start":{"line":231,"column":24},"end":{"line":231,"column":58}},{"start":{"line":231,"column":58},"end":{"line":231,"column":75}}],"line":231},"23":{"loc":{"start":{"line":241,"column":10},"end":{"line":241,"column":null}},"type":"if","locations":[{"start":{"line":241,"column":10},"end":{"line":241,"column":null}},{"start":{},"end":{}}],"line":241},"24":{"loc":{"start":{"line":243,"column":10},"end":{"line":247,"column":null}},"type":"if","locations":[{"start":{"line":243,"column":10},"end":{"line":247,"column":null}},{"start":{},"end":{}}],"line":243},"25":{"loc":{"start":{"line":254,"column":10},"end":{"line":258,"column":null}},"type":"if","locations":[{"start":{"line":254,"column":10},"end":{"line":258,"column":null}},{"start":{},"end":{}}],"line":254},"26":{"loc":{"start":{"line":264,"column":17},"end":{"line":264,"column":47}},"type":"binary-expr","locations":[{"start":{"line":264,"column":17},"end":{"line":264,"column":36}},{"start":{"line":264,"column":36},"end":{"line":264,"column":47}}],"line":264},"27":{"loc":{"start":{"line":270,"column":10},"end":{"line":275,"column":null}},"type":"if","locations":[{"start":{"line":270,"column":10},"end":{"line":275,"column":null}},{"start":{},"end":{}}],"line":270},"28":{"loc":{"start":{"line":272,"column":12},"end":{"line":274,"column":null}},"type":"if","locations":[{"start":{"line":272,"column":12},"end":{"line":274,"column":null}},{"start":{},"end":{}}],"line":272},"29":{"loc":{"start":{"line":272,"column":16},"end":{"line":272,"column":37}},"type":"binary-expr","locations":[{"start":{"line":272,"column":16},"end":{"line":272,"column":24}},{"start":{"line":272,"column":24},"end":{"line":272,"column":37}}],"line":272}},"s":{"0":11,"1":0,"2":0,"3":0,"4":0,"5":0,"6":0,"7":0,"8":0,"9":0,"10":0,"11":0,"12":0,"13":0,"14":0,"15":0,"16":0,"17":0,"18":0,"19":0,"20":0,"21":0,"22":0,"23":0,"24":0,"25":0,"26":0,"27":0,"28":0,"29":0,"30":0,"31":0,"32":0,"33":0,"34":0,"35":0,"36":0,"37":0,"38":0,"39":0,"40":0,"41":0,"42":0,"43":0,"44":0,"45":0,"46":0,"47":0,"48":0,"49":0,"50":0,"51":0,"52":0,"53":0,"54":0,"55":0,"56":0,"57":0,"58":0,"59":0,"60":0,"61":0,"62":0,"63":0,"64":0,"65":0,"66":0,"67":0,"68":0,"69":0,"70":0,"71":0,"72":0,"73":0,"74":0,"75":0,"76":0,"77":0,"78":0,"79":0,"80":0,"81":0,"82":0,"83":0,"84":0,"85":0,"86":0,"87":0,"88":0,"89":0,"90":0,"91":0,"92":0,"93":0,"94":0,"95":0,"96":0,"97":0,"98":0,"99":0,"100":0,"101":0,"102":0,"103":0,"104":0,"105":0,"106":0,"107":0,"108":0,"109":0,"110":0,"111":0},"f":{"0":11,"1":0,"2":0,"3":0,"4":0,"5":0,"6":0,"7":0,"8":0,"9":0,"10":0,"11":0,"12":0,"13":0,"14":0,"15":0},"b":{"0":[0,0],"1":[0,0],"2":[0,0],"3":[0,0],"4":[0,0],"5":[0,0],"6":[0,0,0],"7":[0,0],"8":[0,0],"9":[0,0],"10":[0,0],"11":[0,0],"12":[0,0],"13":[0,0],"14":[0,0],"15":[0,0],"16":[0,0],"17":[0,0],"18":[0,0],"19":[0,0],"20":[0,0],"21":[0,0],"22":[0,0,0],"23":[0,0],"24":[0,0],"25":[0,0],"26":[0,0],"27":[0,0],"28":[0,0],"29":[0,0]},"meta":{"lastBranch":30,"lastFunction":16,"lastStatement":112,"seen":{"f:12:16:12:39":0,"s:13:2:280:Infinity":0,"f:22:16:22:23":1,"s:23:14:23:Infinity":1,"s:24:14:24:Infinity":2,"s:26:24:26:Infinity":3,"b:29:8:39:Infinity:undefined:undefined:undefined:undefined":0,"s:29:8:39:Infinity":4,"b:29:12:29:26:29:26:29:40":1,"s:30:25:30:Infinity":5,"s:31:24:31:Infinity":6,"f:31:36:31:41":2,"s:31:41:31:92":7,"b:31:41:31:70:31:70:31:92":2,"b:32:10:37:Infinity:undefined:undefined:undefined:undefined":3,"s:32:10:37:Infinity":8,"s:33:12:36:Infinity":9,"s:38:10:38:Infinity":10,"b:42:8:55:Infinity:undefined:undefined:undefined:undefined":4,"s:42:8:55:Infinity":11,"b:42:12:42:26:42:26:42:41":5,"s:43:16:43:Infinity":12,"s:44:24:44:Infinity":13,"s:45:26:45:Infinity":14,"f:45:44:45:49":3,"s:45:49:45:53":15,"s:46:25:46:Infinity":16,"s:47:24:47:Infinity":17,"f:47:36:47:41":4,"s:47:41:47:100":18,"b:47:41:47:53:47:53:47:78:47:78:47:100":6,"b:48:10:53:Infinity:undefined:undefined:undefined:undefined":7,"s:48:10:53:Infinity":19,"s:49:12:52:Infinity":20,"s:54:10:54:Infinity":21,"b:57:8:62:Infinity:undefined:undefined:undefined:undefined":8,"s:57:8:62:Infinity":22,"s:58:10:61:Infinity":23,"s:64:29:71:Infinity":24,"b:68:19:68:36:68:36:68:Infinity":9,"b:69:18:69:34:69:34:69:Infinity":10,"s:73:8:81:Infinity":25,"s:83:8:83:Infinity":26,"f:90:13:90:20":5,"s:91:14:91:Infinity":27,"s:92:8:92:Infinity":28,"f:99:13:99:20":6,"s:100:14:100:Infinity":29,"s:101:8:101:Infinity":30,"f:109:16:109:23":7,"s:110:14:110:Infinity":31,"s:111:25:111:Infinity":32,"b:112:8:117:Infinity:undefined:undefined:undefined:undefined":11,"s:112:8:117:Infinity":33,"s:113:10:116:Infinity":34,"b:118:8:123:Infinity:undefined:undefined:undefined:undefined":12,"s:118:8:123:Infinity":35,"s:119:10:122:Infinity":36,"s:125:24:125:Infinity":37,"s:127:8:135:Infinity":38,"s:137:8:137:Infinity":39,"f:142:20:142:37":8,"s:149:28:149:Infinity":40,"s:150:23:150:Infinity":41,"b:150:23:150:38:150:38:150:Infinity":13,"s:151:25:151:Infinity":42,"s:152:14:152:Infinity":43,"s:155:25:155:Infinity":44,"s:156:27:156:Infinity":45,"s:157:8:165:Infinity":46,"s:158:10:164:Infinity":47,"s:168:32:168:Infinity":48,"s:169:43:169:Infinity":49,"s:171:24:179:Infinity":50,"f:171:24:171:25":9,"b:172:10:172:Infinity:undefined:undefined:undefined:undefined":14,"s:172:10:172:Infinity":51,"s:172:51:172:Infinity":52,"s:173:10:173:Infinity":53,"b:174:10:178:Infinity:undefined:undefined:undefined:undefined":15,"s:174:10:178:Infinity":54,"s:175:22:175:Infinity":55,"s:176:12:176:Infinity":56,"s:177:12:177:Infinity":57,"s:181:8:181:Infinity":58,"s:183:24:190:Infinity":59,"f:183:24:183:30":10,"s:184:10:184:Infinity":60,"b:185:10:189:Infinity:undefined:undefined:undefined:undefined":16,"s:185:10:189:Infinity":61,"s:186:22:186:Infinity":62,"s:187:12:187:Infinity":63,"s:188:12:188:Infinity":64,"s:192:8:192:Infinity":65,"s:194:8:218:Infinity":66,"s:195:10:215:Infinity":67,"s:196:12:208:Infinity":68,"s:197:29:197:Infinity":69,"s:198:27:198:Infinity":70,"b:199:14:207:Infinity:undefined:undefined:undefined:undefined":17,"s:199:14:207:Infinity":71,"b:199:18:199:26:199:26:199:53":18,"s:200:16:206:Infinity":72,"b:210:12:214:Infinity:undefined:undefined:undefined:undefined":19,"s:210:12:214:Infinity":73,"s:211:14:213:Infinity":74,"f:211:38:211:39":11,"s:212:16:212:Infinity":75,"s:217:10:217:Infinity":76,"f:223:20:223:37":12,"s:224:35:224:Infinity":77,"s:225:23:225:Infinity":78,"b:225:23:225:38:225:38:225:Infinity":20,"s:226:25:226:Infinity":79,"s:227:14:227:Infinity":80,"s:230:25:230:Infinity":81,"b:231:8:234:Infinity:undefined:undefined:undefined:undefined":21,"s:231:8:234:Infinity":82,"b:231:12:231:24:231:24:231:58:231:58:231:75":22,"s:232:10:232:Infinity":83,"s:233:10:233:Infinity":84,"s:237:23:237:Infinity":85,"s:238:43:238:Infinity":86,"s:240:24:248:Infinity":87,"f:240:24:240:25":13,"b:241:10:241:Infinity:undefined:undefined:undefined:undefined":23,"s:241:10:241:Infinity":88,"s:241:63:241:Infinity":89,"s:242:10:242:Infinity":90,"b:243:10:247:Infinity:undefined:undefined:undefined:undefined":24,"s:243:10:247:Infinity":91,"s:244:22:244:Infinity":92,"s:245:12:245:Infinity":93,"s:246:12:246:Infinity":94,"s:250:8:250:Infinity":95,"s:252:24:259:Infinity":96,"f:252:24:252:30":14,"s:253:10:253:Infinity":97,"b:254:10:258:Infinity:undefined:undefined:undefined:undefined":25,"s:254:10:258:Infinity":98,"s:255:22:255:Infinity":99,"s:256:12:256:Infinity":100,"s:257:12:257:Infinity":101,"s:261:8:261:Infinity":102,"s:263:8:278:Infinity":103,"s:264:10:268:Infinity":104,"b:264:17:264:36:264:36:264:47":26,"s:265:12:267:Infinity":105,"f:265:36:265:37":15,"s:266:14:266:Infinity":106,"b:270:10:275:Infinity:undefined:undefined:undefined:undefined":27,"s:270:10:275:Infinity":107,"s:271:25:271:Infinity":108,"b:272:12:274:Infinity:undefined:undefined:undefined:undefined":28,"s:272:12:274:Infinity":109,"b:272:16:272:24:272:24:272:37":29,"s:273:14:273:Infinity":110,"s:277:10:277:Infinity":111}}} +,"/Users/lukasmay/development/projects/codewalk-district/src/trpc/routers/coordination.ts": {"path":"/Users/lukasmay/development/projects/codewalk-district/src/trpc/routers/coordination.ts","statementMap":{"0":{"start":{"line":10,"column":2},"end":{"line":40,"column":null}},"1":{"start":{"line":14,"column":14},"end":{"line":14,"column":null}},"2":{"start":{"line":15,"column":8},"end":{"line":15,"column":null}},"3":{"start":{"line":16,"column":8},"end":{"line":16,"column":null}},"4":{"start":{"line":24,"column":14},"end":{"line":24,"column":null}},"5":{"start":{"line":25,"column":24},"end":{"line":25,"column":null}},"6":{"start":{"line":26,"column":8},"end":{"line":26,"column":null}},"7":{"start":{"line":31,"column":14},"end":{"line":31,"column":null}},"8":{"start":{"line":32,"column":8},"end":{"line":32,"column":null}},"9":{"start":{"line":37,"column":14},"end":{"line":37,"column":null}},"10":{"start":{"line":38,"column":8},"end":{"line":38,"column":null}}},"fnMap":{"0":{"name":"coordinationProcedures","decl":{"start":{"line":9,"column":16},"end":{"line":9,"column":39}},"loc":{"start":{"line":9,"column":74},"end":{"line":41,"column":null}},"line":9},"1":{"name":"(anonymous_1)","decl":{"start":{"line":13,"column":16},"end":{"line":13,"column":23}},"loc":{"start":{"line":13,"column":42},"end":{"line":17,"column":7}},"line":13},"2":{"name":"(anonymous_2)","decl":{"start":{"line":23,"column":16},"end":{"line":23,"column":23}},"loc":{"start":{"line":23,"column":42},"end":{"line":27,"column":7}},"line":23},"3":{"name":"(anonymous_3)","decl":{"start":{"line":30,"column":13},"end":{"line":30,"column":20}},"loc":{"start":{"line":30,"column":32},"end":{"line":33,"column":7}},"line":30},"4":{"name":"(anonymous_4)","decl":{"start":{"line":36,"column":13},"end":{"line":36,"column":20}},"loc":{"start":{"line":36,"column":32},"end":{"line":39,"column":7}},"line":36}},"branchMap":{},"s":{"0":11,"1":0,"2":0,"3":0,"4":0,"5":0,"6":0,"7":0,"8":0,"9":0,"10":0},"f":{"0":11,"1":0,"2":0,"3":0,"4":0},"b":{},"meta":{"lastBranch":0,"lastFunction":5,"lastStatement":11,"seen":{"f:9:16:9:39":0,"s:10:2:40:Infinity":0,"f:13:16:13:23":1,"s:14:14:14:Infinity":1,"s:15:8:15:Infinity":2,"s:16:8:16:Infinity":3,"f:23:16:23:23":2,"s:24:14:24:Infinity":4,"s:25:24:25:Infinity":5,"s:26:8:26:Infinity":6,"f:30:13:30:20":3,"s:31:14:31:Infinity":7,"s:32:8:32:Infinity":8,"f:36:13:36:20":4,"s:37:14:37:Infinity":9,"s:38:8:38:Infinity":10}}} +,"/Users/lukasmay/development/projects/codewalk-district/src/trpc/routers/dispatch.ts": {"path":"/Users/lukasmay/development/projects/codewalk-district/src/trpc/routers/dispatch.ts","statementMap":{"0":{"start":{"line":10,"column":2},"end":{"line":38,"column":null}},"1":{"start":{"line":14,"column":14},"end":{"line":14,"column":null}},"2":{"start":{"line":15,"column":8},"end":{"line":15,"column":null}},"3":{"start":{"line":16,"column":8},"end":{"line":16,"column":null}},"4":{"start":{"line":21,"column":14},"end":{"line":21,"column":null}},"5":{"start":{"line":22,"column":8},"end":{"line":22,"column":null}},"6":{"start":{"line":27,"column":14},"end":{"line":27,"column":null}},"7":{"start":{"line":28,"column":8},"end":{"line":28,"column":null}},"8":{"start":{"line":34,"column":14},"end":{"line":34,"column":null}},"9":{"start":{"line":35,"column":8},"end":{"line":35,"column":null}},"10":{"start":{"line":36,"column":8},"end":{"line":36,"column":null}}},"fnMap":{"0":{"name":"dispatchProcedures","decl":{"start":{"line":9,"column":16},"end":{"line":9,"column":35}},"loc":{"start":{"line":9,"column":70},"end":{"line":39,"column":null}},"line":9},"1":{"name":"(anonymous_1)","decl":{"start":{"line":13,"column":16},"end":{"line":13,"column":23}},"loc":{"start":{"line":13,"column":42},"end":{"line":17,"column":7}},"line":13},"2":{"name":"(anonymous_2)","decl":{"start":{"line":20,"column":16},"end":{"line":20,"column":23}},"loc":{"start":{"line":20,"column":35},"end":{"line":23,"column":7}},"line":20},"3":{"name":"(anonymous_3)","decl":{"start":{"line":26,"column":13},"end":{"line":26,"column":20}},"loc":{"start":{"line":26,"column":32},"end":{"line":29,"column":7}},"line":26},"4":{"name":"(anonymous_4)","decl":{"start":{"line":33,"column":16},"end":{"line":33,"column":23}},"loc":{"start":{"line":33,"column":42},"end":{"line":37,"column":7}},"line":33}},"branchMap":{},"s":{"0":11,"1":0,"2":0,"3":0,"4":0,"5":0,"6":0,"7":0,"8":0,"9":0,"10":0},"f":{"0":11,"1":0,"2":0,"3":0,"4":0},"b":{},"meta":{"lastBranch":0,"lastFunction":5,"lastStatement":11,"seen":{"f:9:16:9:35":0,"s:10:2:38:Infinity":0,"f:13:16:13:23":1,"s:14:14:14:Infinity":1,"s:15:8:15:Infinity":2,"s:16:8:16:Infinity":3,"f:20:16:20:23":2,"s:21:14:21:Infinity":4,"s:22:8:22:Infinity":5,"f:26:13:26:20":3,"s:27:14:27:Infinity":6,"s:28:8:28:Infinity":7,"f:33:16:33:23":4,"s:34:14:34:Infinity":8,"s:35:8:35:Infinity":9,"s:36:8:36:Infinity":10}}} +,"/Users/lukasmay/development/projects/codewalk-district/src/trpc/routers/initiative.ts": {"path":"/Users/lukasmay/development/projects/codewalk-district/src/trpc/routers/initiative.ts","statementMap":{"0":{"start":{"line":11,"column":2},"end":{"line":152,"column":null}},"1":{"start":{"line":20,"column":14},"end":{"line":20,"column":null}},"2":{"start":{"line":22,"column":8},"end":{"line":33,"column":null}},"3":{"start":{"line":23,"column":16},"end":{"line":23,"column":null}},"4":{"start":{"line":24,"column":10},"end":{"line":32,"column":null}},"5":{"start":{"line":25,"column":28},"end":{"line":25,"column":null}},"6":{"start":{"line":26,"column":12},"end":{"line":31,"column":null}},"7":{"start":{"line":27,"column":14},"end":{"line":30,"column":null}},"8":{"start":{"line":35,"column":27},"end":{"line":40,"column":null}},"9":{"start":{"line":42,"column":8},"end":{"line":45,"column":null}},"10":{"start":{"line":43,"column":16},"end":{"line":43,"column":null}},"11":{"start":{"line":44,"column":10},"end":{"line":44,"column":null}},"12":{"start":{"line":47,"column":8},"end":{"line":55,"column":null}},"13":{"start":{"line":48,"column":10},"end":{"line":54,"column":null}},"14":{"start":{"line":57,"column":8},"end":{"line":57,"column":null}},"15":{"start":{"line":65,"column":14},"end":{"line":65,"column":null}},"16":{"start":{"line":66,"column":8},"end":{"line":68,"column":null}},"17":{"start":{"line":67,"column":10},"end":{"line":67,"column":null}},"18":{"start":{"line":69,"column":8},"end":{"line":69,"column":null}},"19":{"start":{"line":75,"column":14},"end":{"line":75,"column":null}},"20":{"start":{"line":76,"column":27},"end":{"line":76,"column":null}},"21":{"start":{"line":77,"column":8},"end":{"line":82,"column":null}},"22":{"start":{"line":78,"column":10},"end":{"line":81,"column":null}},"23":{"start":{"line":84,"column":73},"end":{"line":84,"column":null}},"24":{"start":{"line":85,"column":8},"end":{"line":88,"column":null}},"25":{"start":{"line":86,"column":31},"end":{"line":86,"column":null}},"26":{"start":{"line":87,"column":10},"end":{"line":87,"column":null}},"27":{"start":{"line":87,"column":46},"end":{"line":87,"column":85}},"28":{"start":{"line":90,"column":27},"end":{"line":90,"column":null}},"29":{"start":{"line":91,"column":8},"end":{"line":94,"column":null}},"30":{"start":{"line":92,"column":24},"end":{"line":92,"column":null}},"31":{"start":{"line":93,"column":10},"end":{"line":93,"column":null}},"32":{"start":{"line":93,"column":43},"end":{"line":93,"column":65}},"33":{"start":{"line":96,"column":8},"end":{"line":96,"column":null}},"34":{"start":{"line":106,"column":14},"end":{"line":106,"column":null}},"35":{"start":{"line":107,"column":32},"end":{"line":107,"column":null}},"36":{"start":{"line":108,"column":8},"end":{"line":108,"column":null}},"37":{"start":{"line":114,"column":14},"end":{"line":114,"column":null}},"38":{"start":{"line":115,"column":8},"end":{"line":115,"column":null}},"39":{"start":{"line":116,"column":8},"end":{"line":116,"column":null}},"40":{"start":{"line":127,"column":14},"end":{"line":127,"column":null}},"41":{"start":{"line":128,"column":42},"end":{"line":128,"column":null}},"42":{"start":{"line":130,"column":25},"end":{"line":130,"column":null}},"43":{"start":{"line":131,"column":8},"end":{"line":136,"column":null}},"44":{"start":{"line":132,"column":10},"end":{"line":135,"column":null}},"45":{"start":{"line":139,"column":8},"end":{"line":148,"column":null}},"46":{"start":{"line":140,"column":24},"end":{"line":140,"column":null}},"47":{"start":{"line":141,"column":29},"end":{"line":141,"column":null}},"48":{"start":{"line":141,"column":47},"end":{"line":141,"column":69}},"49":{"start":{"line":142,"column":10},"end":{"line":147,"column":null}},"50":{"start":{"line":143,"column":12},"end":{"line":146,"column":null}},"51":{"start":{"line":150,"column":8},"end":{"line":150,"column":null}}},"fnMap":{"0":{"name":"initiativeProcedures","decl":{"start":{"line":10,"column":16},"end":{"line":10,"column":37}},"loc":{"start":{"line":10,"column":72},"end":{"line":153,"column":null}},"line":10},"1":{"name":"(anonymous_1)","decl":{"start":{"line":19,"column":16},"end":{"line":19,"column":23}},"loc":{"start":{"line":19,"column":42},"end":{"line":58,"column":7}},"line":19},"2":{"name":"(anonymous_2)","decl":{"start":{"line":64,"column":13},"end":{"line":64,"column":20}},"loc":{"start":{"line":64,"column":39},"end":{"line":70,"column":7}},"line":64},"3":{"name":"(anonymous_3)","decl":{"start":{"line":74,"column":13},"end":{"line":74,"column":20}},"loc":{"start":{"line":74,"column":39},"end":{"line":97,"column":7}},"line":74},"4":{"name":"(anonymous_4)","decl":{"start":{"line":87,"column":38},"end":{"line":87,"column":39}},"loc":{"start":{"line":87,"column":46},"end":{"line":87,"column":85}},"line":87},"5":{"name":"(anonymous_5)","decl":{"start":{"line":93,"column":36},"end":{"line":93,"column":37}},"loc":{"start":{"line":93,"column":43},"end":{"line":93,"column":65}},"line":93},"6":{"name":"(anonymous_6)","decl":{"start":{"line":105,"column":16},"end":{"line":105,"column":23}},"loc":{"start":{"line":105,"column":42},"end":{"line":109,"column":7}},"line":105},"7":{"name":"(anonymous_7)","decl":{"start":{"line":113,"column":16},"end":{"line":113,"column":23}},"loc":{"start":{"line":113,"column":42},"end":{"line":117,"column":7}},"line":113},"8":{"name":"(anonymous_8)","decl":{"start":{"line":126,"column":16},"end":{"line":126,"column":23}},"loc":{"start":{"line":126,"column":42},"end":{"line":151,"column":7}},"line":126},"9":{"name":"(anonymous_9)","decl":{"start":{"line":141,"column":40},"end":{"line":141,"column":41}},"loc":{"start":{"line":141,"column":47},"end":{"line":141,"column":69}},"line":141}},"branchMap":{"0":{"loc":{"start":{"line":22,"column":8},"end":{"line":33,"column":null}},"type":"if","locations":[{"start":{"line":22,"column":8},"end":{"line":33,"column":null}},{"start":{},"end":{}}],"line":22},"1":{"loc":{"start":{"line":22,"column":12},"end":{"line":22,"column":61}},"type":"binary-expr","locations":[{"start":{"line":22,"column":12},"end":{"line":22,"column":32}},{"start":{"line":22,"column":32},"end":{"line":22,"column":61}}],"line":22},"2":{"loc":{"start":{"line":26,"column":12},"end":{"line":31,"column":null}},"type":"if","locations":[{"start":{"line":26,"column":12},"end":{"line":31,"column":null}},{"start":{},"end":{}}],"line":26},"3":{"loc":{"start":{"line":38,"column":14},"end":{"line":38,"column":null}},"type":"binary-expr","locations":[{"start":{"line":38,"column":14},"end":{"line":38,"column":37}},{"start":{"line":38,"column":37},"end":{"line":38,"column":null}}],"line":38},"4":{"loc":{"start":{"line":39,"column":14},"end":{"line":39,"column":null}},"type":"binary-expr","locations":[{"start":{"line":39,"column":14},"end":{"line":39,"column":30}},{"start":{"line":39,"column":30},"end":{"line":39,"column":null}}],"line":39},"5":{"loc":{"start":{"line":42,"column":8},"end":{"line":45,"column":null}},"type":"if","locations":[{"start":{"line":42,"column":8},"end":{"line":45,"column":null}},{"start":{},"end":{}}],"line":42},"6":{"loc":{"start":{"line":42,"column":12},"end":{"line":42,"column":61}},"type":"binary-expr","locations":[{"start":{"line":42,"column":12},"end":{"line":42,"column":32}},{"start":{"line":42,"column":32},"end":{"line":42,"column":61}}],"line":42},"7":{"loc":{"start":{"line":47,"column":8},"end":{"line":55,"column":null}},"type":"if","locations":[{"start":{"line":47,"column":8},"end":{"line":55,"column":null}},{"start":{},"end":{}}],"line":47},"8":{"loc":{"start":{"line":66,"column":8},"end":{"line":68,"column":null}},"type":"if","locations":[{"start":{"line":66,"column":8},"end":{"line":68,"column":null}},{"start":{},"end":{}}],"line":66},"9":{"loc":{"start":{"line":77,"column":8},"end":{"line":82,"column":null}},"type":"if","locations":[{"start":{"line":77,"column":8},"end":{"line":82,"column":null}},{"start":{},"end":{}}],"line":77},"10":{"loc":{"start":{"line":85,"column":8},"end":{"line":88,"column":null}},"type":"if","locations":[{"start":{"line":85,"column":8},"end":{"line":88,"column":null}},{"start":{},"end":{}}],"line":85},"11":{"loc":{"start":{"line":91,"column":8},"end":{"line":94,"column":null}},"type":"if","locations":[{"start":{"line":91,"column":8},"end":{"line":94,"column":null}},{"start":{},"end":{}}],"line":91},"12":{"loc":{"start":{"line":131,"column":8},"end":{"line":136,"column":null}},"type":"if","locations":[{"start":{"line":131,"column":8},"end":{"line":136,"column":null}},{"start":{},"end":{}}],"line":131},"13":{"loc":{"start":{"line":139,"column":8},"end":{"line":148,"column":null}},"type":"if","locations":[{"start":{"line":139,"column":8},"end":{"line":148,"column":null}},{"start":{},"end":{}}],"line":139},"14":{"loc":{"start":{"line":139,"column":12},"end":{"line":139,"column":61}},"type":"binary-expr","locations":[{"start":{"line":139,"column":12},"end":{"line":139,"column":41}},{"start":{"line":139,"column":41},"end":{"line":139,"column":61}}],"line":139},"15":{"loc":{"start":{"line":142,"column":10},"end":{"line":147,"column":null}},"type":"if","locations":[{"start":{"line":142,"column":10},"end":{"line":147,"column":null}},{"start":{},"end":{}}],"line":142}},"s":{"0":11,"1":19,"2":19,"3":0,"4":0,"5":0,"6":0,"7":0,"8":19,"9":19,"10":0,"11":0,"12":19,"13":0,"14":19,"15":0,"16":0,"17":0,"18":0,"19":0,"20":0,"21":0,"22":0,"23":0,"24":0,"25":0,"26":0,"27":0,"28":0,"29":0,"30":0,"31":0,"32":0,"33":0,"34":0,"35":0,"36":0,"37":0,"38":0,"39":0,"40":0,"41":0,"42":0,"43":0,"44":0,"45":0,"46":0,"47":0,"48":0,"49":0,"50":0,"51":0},"f":{"0":11,"1":19,"2":0,"3":0,"4":0,"5":0,"6":0,"7":0,"8":0,"9":0},"b":{"0":[0,19],"1":[19,0],"2":[0,0],"3":[19,0],"4":[19,0],"5":[0,19],"6":[19,0],"7":[0,19],"8":[0,0],"9":[0,0],"10":[0,0],"11":[0,0],"12":[0,0],"13":[0,0],"14":[0,0],"15":[0,0]},"meta":{"lastBranch":16,"lastFunction":10,"lastStatement":52,"seen":{"f:10:16:10:37":0,"s:11:2:152:Infinity":0,"f:19:16:19:23":1,"s:20:14:20:Infinity":1,"b:22:8:33:Infinity:undefined:undefined:undefined:undefined":0,"s:22:8:33:Infinity":2,"b:22:12:22:32:22:32:22:61":1,"s:23:16:23:Infinity":3,"s:24:10:32:Infinity":4,"s:25:28:25:Infinity":5,"b:26:12:31:Infinity:undefined:undefined:undefined:undefined":2,"s:26:12:31:Infinity":6,"s:27:14:30:Infinity":7,"s:35:27:40:Infinity":8,"b:38:14:38:37:38:37:38:Infinity":3,"b:39:14:39:30:39:30:39:Infinity":4,"b:42:8:45:Infinity:undefined:undefined:undefined:undefined":5,"s:42:8:45:Infinity":9,"b:42:12:42:32:42:32:42:61":6,"s:43:16:43:Infinity":10,"s:44:10:44:Infinity":11,"b:47:8:55:Infinity:undefined:undefined:undefined:undefined":7,"s:47:8:55:Infinity":12,"s:48:10:54:Infinity":13,"s:57:8:57:Infinity":14,"f:64:13:64:20":2,"s:65:14:65:Infinity":15,"b:66:8:68:Infinity:undefined:undefined:undefined:undefined":8,"s:66:8:68:Infinity":16,"s:67:10:67:Infinity":17,"s:69:8:69:Infinity":18,"f:74:13:74:20":3,"s:75:14:75:Infinity":19,"s:76:27:76:Infinity":20,"b:77:8:82:Infinity:undefined:undefined:undefined:undefined":9,"s:77:8:82:Infinity":21,"s:78:10:81:Infinity":22,"s:84:73:84:Infinity":23,"b:85:8:88:Infinity:undefined:undefined:undefined:undefined":10,"s:85:8:88:Infinity":24,"s:86:31:86:Infinity":25,"s:87:10:87:Infinity":26,"f:87:38:87:39":4,"s:87:46:87:85":27,"s:90:27:90:Infinity":28,"b:91:8:94:Infinity:undefined:undefined:undefined:undefined":11,"s:91:8:94:Infinity":29,"s:92:24:92:Infinity":30,"s:93:10:93:Infinity":31,"f:93:36:93:37":5,"s:93:43:93:65":32,"s:96:8:96:Infinity":33,"f:105:16:105:23":6,"s:106:14:106:Infinity":34,"s:107:32:107:Infinity":35,"s:108:8:108:Infinity":36,"f:113:16:113:23":7,"s:114:14:114:Infinity":37,"s:115:8:115:Infinity":38,"s:116:8:116:Infinity":39,"f:126:16:126:23":8,"s:127:14:127:Infinity":40,"s:128:42:128:Infinity":41,"s:130:25:130:Infinity":42,"b:131:8:136:Infinity:undefined:undefined:undefined:undefined":12,"s:131:8:136:Infinity":43,"s:132:10:135:Infinity":44,"b:139:8:148:Infinity:undefined:undefined:undefined:undefined":13,"s:139:8:148:Infinity":45,"b:139:12:139:41:139:41:139:61":14,"s:140:24:140:Infinity":46,"s:141:29:141:Infinity":47,"f:141:40:141:41":9,"s:141:47:141:69":48,"b:142:10:147:Infinity:undefined:undefined:undefined:undefined":15,"s:142:10:147:Infinity":49,"s:143:12:146:Infinity":50,"s:150:8:150:Infinity":51}}} +,"/Users/lukasmay/development/projects/codewalk-district/src/trpc/routers/message.ts": {"path":"/Users/lukasmay/development/projects/codewalk-district/src/trpc/routers/message.ts","statementMap":{"0":{"start":{"line":11,"column":2},"end":{"line":76,"column":null}},"1":{"start":{"line":18,"column":14},"end":{"line":18,"column":null}},"2":{"start":{"line":20,"column":23},"end":{"line":20,"column":null}},"3":{"start":{"line":22,"column":8},"end":{"line":24,"column":null}},"4":{"start":{"line":23,"column":10},"end":{"line":23,"column":null}},"5":{"start":{"line":23,"column":42},"end":{"line":23,"column":70}},"6":{"start":{"line":26,"column":8},"end":{"line":28,"column":null}},"7":{"start":{"line":27,"column":10},"end":{"line":27,"column":null}},"8":{"start":{"line":27,"column":42},"end":{"line":27,"column":67}},"9":{"start":{"line":30,"column":8},"end":{"line":30,"column":null}},"10":{"start":{"line":36,"column":14},"end":{"line":36,"column":null}},"11":{"start":{"line":37,"column":24},"end":{"line":37,"column":null}},"12":{"start":{"line":38,"column":8},"end":{"line":43,"column":null}},"13":{"start":{"line":39,"column":10},"end":{"line":42,"column":null}},"14":{"start":{"line":44,"column":8},"end":{"line":44,"column":null}},"15":{"start":{"line":53,"column":14},"end":{"line":53,"column":null}},"16":{"start":{"line":55,"column":25},"end":{"line":55,"column":null}},"17":{"start":{"line":56,"column":8},"end":{"line":61,"column":null}},"18":{"start":{"line":57,"column":10},"end":{"line":60,"column":null}},"19":{"start":{"line":63,"column":32},"end":{"line":70,"column":null}},"20":{"start":{"line":72,"column":8},"end":{"line":72,"column":null}},"21":{"start":{"line":74,"column":8},"end":{"line":74,"column":null}}},"fnMap":{"0":{"name":"messageProcedures","decl":{"start":{"line":10,"column":16},"end":{"line":10,"column":34}},"loc":{"start":{"line":10,"column":69},"end":{"line":77,"column":null}},"line":10},"1":{"name":"(anonymous_1)","decl":{"start":{"line":17,"column":13},"end":{"line":17,"column":20}},"loc":{"start":{"line":17,"column":39},"end":{"line":31,"column":7}},"line":17},"2":{"name":"(anonymous_2)","decl":{"start":{"line":23,"column":37},"end":{"line":23,"column":42}},"loc":{"start":{"line":23,"column":42},"end":{"line":23,"column":70}},"line":23},"3":{"name":"(anonymous_3)","decl":{"start":{"line":27,"column":37},"end":{"line":27,"column":42}},"loc":{"start":{"line":27,"column":42},"end":{"line":27,"column":67}},"line":27},"4":{"name":"(anonymous_4)","decl":{"start":{"line":35,"column":13},"end":{"line":35,"column":20}},"loc":{"start":{"line":35,"column":39},"end":{"line":45,"column":7}},"line":35},"5":{"name":"(anonymous_5)","decl":{"start":{"line":52,"column":16},"end":{"line":52,"column":23}},"loc":{"start":{"line":52,"column":42},"end":{"line":75,"column":7}},"line":52}},"branchMap":{"0":{"loc":{"start":{"line":22,"column":8},"end":{"line":24,"column":null}},"type":"if","locations":[{"start":{"line":22,"column":8},"end":{"line":24,"column":null}},{"start":{},"end":{}}],"line":22},"1":{"loc":{"start":{"line":26,"column":8},"end":{"line":28,"column":null}},"type":"if","locations":[{"start":{"line":26,"column":8},"end":{"line":28,"column":null}},{"start":{},"end":{}}],"line":26},"2":{"loc":{"start":{"line":38,"column":8},"end":{"line":43,"column":null}},"type":"if","locations":[{"start":{"line":38,"column":8},"end":{"line":43,"column":null}},{"start":{},"end":{}}],"line":38},"3":{"loc":{"start":{"line":56,"column":8},"end":{"line":61,"column":null}},"type":"if","locations":[{"start":{"line":56,"column":8},"end":{"line":61,"column":null}},{"start":{},"end":{}}],"line":56}},"s":{"0":11,"1":0,"2":0,"3":0,"4":0,"5":0,"6":0,"7":0,"8":0,"9":0,"10":0,"11":0,"12":0,"13":0,"14":0,"15":0,"16":0,"17":0,"18":0,"19":0,"20":0,"21":0},"f":{"0":11,"1":0,"2":0,"3":0,"4":0,"5":0},"b":{"0":[0,0],"1":[0,0],"2":[0,0],"3":[0,0]},"meta":{"lastBranch":4,"lastFunction":6,"lastStatement":22,"seen":{"f:10:16:10:34":0,"s:11:2:76:Infinity":0,"f:17:13:17:20":1,"s:18:14:18:Infinity":1,"s:20:23:20:Infinity":2,"b:22:8:24:Infinity:undefined:undefined:undefined:undefined":0,"s:22:8:24:Infinity":3,"s:23:10:23:Infinity":4,"f:23:37:23:42":2,"s:23:42:23:70":5,"b:26:8:28:Infinity:undefined:undefined:undefined:undefined":1,"s:26:8:28:Infinity":6,"s:27:10:27:Infinity":7,"f:27:37:27:42":3,"s:27:42:27:67":8,"s:30:8:30:Infinity":9,"f:35:13:35:20":4,"s:36:14:36:Infinity":10,"s:37:24:37:Infinity":11,"b:38:8:43:Infinity:undefined:undefined:undefined:undefined":2,"s:38:8:43:Infinity":12,"s:39:10:42:Infinity":13,"s:44:8:44:Infinity":14,"f:52:16:52:23":5,"s:53:14:53:Infinity":15,"s:55:25:55:Infinity":16,"b:56:8:61:Infinity:undefined:undefined:undefined:undefined":3,"s:56:8:61:Infinity":17,"s:57:10:60:Infinity":18,"s:63:32:70:Infinity":19,"s:72:8:72:Infinity":20,"s:74:8:74:Infinity":21}}} +,"/Users/lukasmay/development/projects/codewalk-district/src/trpc/routers/page.ts": {"path":"/Users/lukasmay/development/projects/codewalk-district/src/trpc/routers/page.ts","statementMap":{"0":{"start":{"line":11,"column":2},"end":{"line":116,"column":null}},"1":{"start":{"line":15,"column":14},"end":{"line":15,"column":null}},"2":{"start":{"line":16,"column":8},"end":{"line":16,"column":null}},"3":{"start":{"line":22,"column":14},"end":{"line":22,"column":null}},"4":{"start":{"line":23,"column":21},"end":{"line":23,"column":null}},"5":{"start":{"line":24,"column":8},"end":{"line":29,"column":null}},"6":{"start":{"line":25,"column":10},"end":{"line":28,"column":null}},"7":{"start":{"line":30,"column":8},"end":{"line":30,"column":null}},"8":{"start":{"line":36,"column":14},"end":{"line":36,"column":null}},"9":{"start":{"line":37,"column":27},"end":{"line":37,"column":null}},"10":{"start":{"line":38,"column":44},"end":{"line":38,"column":null}},"11":{"start":{"line":39,"column":8},"end":{"line":41,"column":null}},"12":{"start":{"line":40,"column":10},"end":{"line":40,"column":null}},"13":{"start":{"line":42,"column":8},"end":{"line":42,"column":null}},"14":{"start":{"line":48,"column":14},"end":{"line":48,"column":null}},"15":{"start":{"line":49,"column":8},"end":{"line":49,"column":null}},"16":{"start":{"line":55,"column":14},"end":{"line":55,"column":null}},"17":{"start":{"line":56,"column":8},"end":{"line":56,"column":null}},"18":{"start":{"line":66,"column":14},"end":{"line":66,"column":null}},"19":{"start":{"line":67,"column":21},"end":{"line":73,"column":null}},"20":{"start":{"line":74,"column":8},"end":{"line":78,"column":null}},"21":{"start":{"line":79,"column":8},"end":{"line":79,"column":null}},"22":{"start":{"line":90,"column":14},"end":{"line":90,"column":null}},"23":{"start":{"line":91,"column":32},"end":{"line":91,"column":null}},"24":{"start":{"line":92,"column":21},"end":{"line":92,"column":null}},"25":{"start":{"line":93,"column":8},"end":{"line":97,"column":null}},"26":{"start":{"line":98,"column":8},"end":{"line":98,"column":null}},"27":{"start":{"line":104,"column":14},"end":{"line":104,"column":null}},"28":{"start":{"line":105,"column":21},"end":{"line":105,"column":null}},"29":{"start":{"line":106,"column":8},"end":{"line":106,"column":null}},"30":{"start":{"line":107,"column":8},"end":{"line":113,"column":null}},"31":{"start":{"line":108,"column":10},"end":{"line":112,"column":null}},"32":{"start":{"line":114,"column":8},"end":{"line":114,"column":null}}},"fnMap":{"0":{"name":"pageProcedures","decl":{"start":{"line":10,"column":16},"end":{"line":10,"column":31}},"loc":{"start":{"line":10,"column":66},"end":{"line":117,"column":null}},"line":10},"1":{"name":"(anonymous_1)","decl":{"start":{"line":14,"column":13},"end":{"line":14,"column":20}},"loc":{"start":{"line":14,"column":39},"end":{"line":17,"column":7}},"line":14},"2":{"name":"(anonymous_2)","decl":{"start":{"line":21,"column":13},"end":{"line":21,"column":20}},"loc":{"start":{"line":21,"column":39},"end":{"line":31,"column":7}},"line":21},"3":{"name":"(anonymous_3)","decl":{"start":{"line":35,"column":13},"end":{"line":35,"column":20}},"loc":{"start":{"line":35,"column":39},"end":{"line":43,"column":7}},"line":35},"4":{"name":"(anonymous_4)","decl":{"start":{"line":47,"column":13},"end":{"line":47,"column":20}},"loc":{"start":{"line":47,"column":39},"end":{"line":50,"column":7}},"line":47},"5":{"name":"(anonymous_5)","decl":{"start":{"line":54,"column":13},"end":{"line":54,"column":20}},"loc":{"start":{"line":54,"column":39},"end":{"line":57,"column":7}},"line":54},"6":{"name":"(anonymous_6)","decl":{"start":{"line":65,"column":16},"end":{"line":65,"column":23}},"loc":{"start":{"line":65,"column":42},"end":{"line":80,"column":7}},"line":65},"7":{"name":"(anonymous_7)","decl":{"start":{"line":89,"column":16},"end":{"line":89,"column":23}},"loc":{"start":{"line":89,"column":42},"end":{"line":99,"column":7}},"line":89},"8":{"name":"(anonymous_8)","decl":{"start":{"line":103,"column":16},"end":{"line":103,"column":23}},"loc":{"start":{"line":103,"column":42},"end":{"line":115,"column":7}},"line":103}},"branchMap":{"0":{"loc":{"start":{"line":24,"column":8},"end":{"line":29,"column":null}},"type":"if","locations":[{"start":{"line":24,"column":8},"end":{"line":29,"column":null}},{"start":{},"end":{}}],"line":24},"1":{"loc":{"start":{"line":40,"column":22},"end":{"line":40,"column":null}},"type":"cond-expr","locations":[{"start":{"line":40,"column":52},"end":{"line":40,"column":80}},{"start":{"line":40,"column":80},"end":{"line":40,"column":null}}],"line":40},"2":{"loc":{"start":{"line":107,"column":8},"end":{"line":113,"column":null}},"type":"if","locations":[{"start":{"line":107,"column":8},"end":{"line":113,"column":null}},{"start":{},"end":{}}],"line":107}},"s":{"0":11,"1":0,"2":0,"3":0,"4":0,"5":0,"6":0,"7":0,"8":0,"9":0,"10":0,"11":0,"12":0,"13":0,"14":0,"15":0,"16":0,"17":0,"18":0,"19":0,"20":0,"21":0,"22":0,"23":0,"24":0,"25":0,"26":0,"27":0,"28":0,"29":0,"30":0,"31":0,"32":0},"f":{"0":11,"1":0,"2":0,"3":0,"4":0,"5":0,"6":0,"7":0,"8":0},"b":{"0":[0,0],"1":[0,0],"2":[0,0]},"meta":{"lastBranch":3,"lastFunction":9,"lastStatement":33,"seen":{"f:10:16:10:31":0,"s:11:2:116:Infinity":0,"f:14:13:14:20":1,"s:15:14:15:Infinity":1,"s:16:8:16:Infinity":2,"f:21:13:21:20":2,"s:22:14:22:Infinity":3,"s:23:21:23:Infinity":4,"b:24:8:29:Infinity:undefined:undefined:undefined:undefined":0,"s:24:8:29:Infinity":5,"s:25:10:28:Infinity":6,"s:30:8:30:Infinity":7,"f:35:13:35:20":3,"s:36:14:36:Infinity":8,"s:37:27:37:Infinity":9,"s:38:44:38:Infinity":10,"s:39:8:41:Infinity":11,"s:40:10:40:Infinity":12,"b:40:52:40:80:40:80:40:Infinity":1,"s:42:8:42:Infinity":13,"f:47:13:47:20":4,"s:48:14:48:Infinity":14,"s:49:8:49:Infinity":15,"f:54:13:54:20":5,"s:55:14:55:Infinity":16,"s:56:8:56:Infinity":17,"f:65:16:65:23":6,"s:66:14:66:Infinity":18,"s:67:21:73:Infinity":19,"s:74:8:78:Infinity":20,"s:79:8:79:Infinity":21,"f:89:16:89:23":7,"s:90:14:90:Infinity":22,"s:91:32:91:Infinity":23,"s:92:21:92:Infinity":24,"s:93:8:97:Infinity":25,"s:98:8:98:Infinity":26,"f:103:16:103:23":8,"s:104:14:104:Infinity":27,"s:105:21:105:Infinity":28,"s:106:8:106:Infinity":29,"b:107:8:113:Infinity:undefined:undefined:undefined:undefined":2,"s:107:8:113:Infinity":30,"s:108:10:112:Infinity":31,"s:114:8:114:Infinity":32}}} +,"/Users/lukasmay/development/projects/codewalk-district/src/trpc/routers/phase-dispatch.ts": {"path":"/Users/lukasmay/development/projects/codewalk-district/src/trpc/routers/phase-dispatch.ts","statementMap":{"0":{"start":{"line":12,"column":2},"end":{"line":93,"column":null}},"1":{"start":{"line":16,"column":14},"end":{"line":16,"column":null}},"2":{"start":{"line":17,"column":8},"end":{"line":17,"column":null}},"3":{"start":{"line":18,"column":8},"end":{"line":18,"column":null}},"4":{"start":{"line":23,"column":14},"end":{"line":23,"column":null}},"5":{"start":{"line":24,"column":8},"end":{"line":24,"column":null}},"6":{"start":{"line":29,"column":14},"end":{"line":29,"column":null}},"7":{"start":{"line":30,"column":8},"end":{"line":30,"column":null}},"8":{"start":{"line":45,"column":14},"end":{"line":45,"column":null}},"9":{"start":{"line":47,"column":27},"end":{"line":47,"column":null}},"10":{"start":{"line":48,"column":8},"end":{"line":53,"column":null}},"11":{"start":{"line":49,"column":10},"end":{"line":52,"column":null}},"12":{"start":{"line":54,"column":8},"end":{"line":59,"column":null}},"13":{"start":{"line":55,"column":10},"end":{"line":58,"column":null}},"14":{"start":{"line":61,"column":27},"end":{"line":61,"column":null}},"15":{"start":{"line":62,"column":32},"end":{"line":62,"column":null}},"16":{"start":{"line":64,"column":8},"end":{"line":77,"column":null}},"17":{"start":{"line":65,"column":23},"end":{"line":74,"column":null}},"18":{"start":{"line":75,"column":10},"end":{"line":75,"column":null}},"19":{"start":{"line":76,"column":10},"end":{"line":76,"column":null}},"20":{"start":{"line":79,"column":8},"end":{"line":89,"column":null}},"21":{"start":{"line":80,"column":10},"end":{"line":88,"column":null}},"22":{"start":{"line":81,"column":27},"end":{"line":81,"column":null}},"23":{"start":{"line":82,"column":12},"end":{"line":87,"column":null}},"24":{"start":{"line":83,"column":38},"end":{"line":83,"column":null}},"25":{"start":{"line":84,"column":14},"end":{"line":86,"column":null}},"26":{"start":{"line":85,"column":16},"end":{"line":85,"column":null}},"27":{"start":{"line":91,"column":8},"end":{"line":91,"column":null}}},"fnMap":{"0":{"name":"phaseDispatchProcedures","decl":{"start":{"line":11,"column":16},"end":{"line":11,"column":40}},"loc":{"start":{"line":11,"column":75},"end":{"line":94,"column":null}},"line":11},"1":{"name":"(anonymous_1)","decl":{"start":{"line":15,"column":16},"end":{"line":15,"column":23}},"loc":{"start":{"line":15,"column":42},"end":{"line":19,"column":7}},"line":15},"2":{"name":"(anonymous_2)","decl":{"start":{"line":22,"column":16},"end":{"line":22,"column":23}},"loc":{"start":{"line":22,"column":35},"end":{"line":25,"column":7}},"line":22},"3":{"name":"(anonymous_3)","decl":{"start":{"line":28,"column":13},"end":{"line":28,"column":20}},"loc":{"start":{"line":28,"column":32},"end":{"line":31,"column":7}},"line":28},"4":{"name":"(anonymous_4)","decl":{"start":{"line":44,"column":16},"end":{"line":44,"column":23}},"loc":{"start":{"line":44,"column":42},"end":{"line":92,"column":7}},"line":44}},"branchMap":{"0":{"loc":{"start":{"line":48,"column":8},"end":{"line":53,"column":null}},"type":"if","locations":[{"start":{"line":48,"column":8},"end":{"line":53,"column":null}},{"start":{},"end":{}}],"line":48},"1":{"loc":{"start":{"line":54,"column":8},"end":{"line":59,"column":null}},"type":"if","locations":[{"start":{"line":54,"column":8},"end":{"line":59,"column":null}},{"start":{},"end":{}}],"line":54},"2":{"loc":{"start":{"line":80,"column":10},"end":{"line":88,"column":null}},"type":"if","locations":[{"start":{"line":80,"column":10},"end":{"line":88,"column":null}},{"start":{},"end":{}}],"line":80},"3":{"loc":{"start":{"line":80,"column":14},"end":{"line":80,"column":75}},"type":"binary-expr","locations":[{"start":{"line":80,"column":14},"end":{"line":80,"column":40}},{"start":{"line":80,"column":40},"end":{"line":80,"column":75}}],"line":80},"4":{"loc":{"start":{"line":84,"column":14},"end":{"line":86,"column":null}},"type":"if","locations":[{"start":{"line":84,"column":14},"end":{"line":86,"column":null}},{"start":{},"end":{}}],"line":84}},"s":{"0":11,"1":0,"2":0,"3":0,"4":0,"5":0,"6":0,"7":0,"8":4,"9":4,"10":4,"11":0,"12":4,"13":0,"14":4,"15":4,"16":4,"17":15,"18":15,"19":15,"20":4,"21":15,"22":11,"23":11,"24":12,"25":12,"26":12,"27":4},"f":{"0":11,"1":0,"2":0,"3":0,"4":4},"b":{"0":[0,4],"1":[0,4],"2":[11,4],"3":[15,13],"4":[12,0]},"meta":{"lastBranch":5,"lastFunction":5,"lastStatement":28,"seen":{"f:11:16:11:40":0,"s:12:2:93:Infinity":0,"f:15:16:15:23":1,"s:16:14:16:Infinity":1,"s:17:8:17:Infinity":2,"s:18:8:18:Infinity":3,"f:22:16:22:23":2,"s:23:14:23:Infinity":4,"s:24:8:24:Infinity":5,"f:28:13:28:20":3,"s:29:14:29:Infinity":6,"s:30:8:30:Infinity":7,"f:44:16:44:23":4,"s:45:14:45:Infinity":8,"s:47:27:47:Infinity":9,"b:48:8:53:Infinity:undefined:undefined:undefined:undefined":0,"s:48:8:53:Infinity":10,"s:49:10:52:Infinity":11,"b:54:8:59:Infinity:undefined:undefined:undefined:undefined":1,"s:54:8:59:Infinity":12,"s:55:10:58:Infinity":13,"s:61:27:61:Infinity":14,"s:62:32:62:Infinity":15,"s:64:8:77:Infinity":16,"s:65:23:74:Infinity":17,"s:75:10:75:Infinity":18,"s:76:10:76:Infinity":19,"s:79:8:89:Infinity":20,"b:80:10:88:Infinity:undefined:undefined:undefined:undefined":2,"s:80:10:88:Infinity":21,"b:80:14:80:40:80:40:80:75":3,"s:81:27:81:Infinity":22,"s:82:12:87:Infinity":23,"s:83:38:83:Infinity":24,"b:84:14:86:Infinity:undefined:undefined:undefined:undefined":4,"s:84:14:86:Infinity":25,"s:85:16:85:Infinity":26,"s:91:8:91:Infinity":27}}} +,"/Users/lukasmay/development/projects/codewalk-district/src/trpc/routers/phase.ts": {"path":"/Users/lukasmay/development/projects/codewalk-district/src/trpc/routers/phase.ts","statementMap":{"0":{"start":{"line":14,"column":2},"end":{"line":237,"column":null}},"1":{"start":{"line":21,"column":14},"end":{"line":21,"column":null}},"2":{"start":{"line":22,"column":8},"end":{"line":26,"column":null}},"3":{"start":{"line":32,"column":14},"end":{"line":32,"column":null}},"4":{"start":{"line":33,"column":8},"end":{"line":33,"column":null}},"5":{"start":{"line":39,"column":14},"end":{"line":39,"column":null}},"6":{"start":{"line":40,"column":22},"end":{"line":40,"column":null}},"7":{"start":{"line":41,"column":8},"end":{"line":46,"column":null}},"8":{"start":{"line":42,"column":10},"end":{"line":45,"column":null}},"9":{"start":{"line":47,"column":8},"end":{"line":47,"column":null}},"10":{"start":{"line":58,"column":14},"end":{"line":58,"column":null}},"11":{"start":{"line":59,"column":32},"end":{"line":59,"column":null}},"12":{"start":{"line":60,"column":8},"end":{"line":60,"column":null}},"13":{"start":{"line":66,"column":14},"end":{"line":66,"column":null}},"14":{"start":{"line":67,"column":14},"end":{"line":67,"column":null}},"15":{"start":{"line":69,"column":22},"end":{"line":69,"column":null}},"16":{"start":{"line":70,"column":8},"end":{"line":75,"column":null}},"17":{"start":{"line":71,"column":10},"end":{"line":74,"column":null}},"18":{"start":{"line":76,"column":8},"end":{"line":81,"column":null}},"19":{"start":{"line":77,"column":10},"end":{"line":80,"column":null}},"20":{"start":{"line":84,"column":27},"end":{"line":84,"column":null}},"21":{"start":{"line":85,"column":26},"end":{"line":85,"column":null}},"22":{"start":{"line":85,"column":51},"end":{"line":85,"column":74}},"23":{"start":{"line":86,"column":8},"end":{"line":91,"column":null}},"24":{"start":{"line":87,"column":10},"end":{"line":90,"column":null}},"25":{"start":{"line":93,"column":8},"end":{"line":93,"column":null}},"26":{"start":{"line":99,"column":14},"end":{"line":99,"column":null}},"27":{"start":{"line":100,"column":8},"end":{"line":100,"column":null}},"28":{"start":{"line":101,"column":8},"end":{"line":101,"column":null}},"29":{"start":{"line":112,"column":14},"end":{"line":112,"column":null}},"30":{"start":{"line":113,"column":33},"end":{"line":113,"column":null}},"31":{"start":{"line":114,"column":8},"end":{"line":121,"column":null}},"32":{"start":{"line":115,"column":24},"end":{"line":119,"column":null}},"33":{"start":{"line":120,"column":10},"end":{"line":120,"column":null}},"34":{"start":{"line":122,"column":8},"end":{"line":122,"column":null}},"35":{"start":{"line":128,"column":14},"end":{"line":128,"column":null}},"36":{"start":{"line":129,"column":8},"end":{"line":129,"column":null}},"37":{"start":{"line":138,"column":14},"end":{"line":138,"column":null}},"38":{"start":{"line":140,"column":22},"end":{"line":140,"column":null}},"39":{"start":{"line":141,"column":8},"end":{"line":146,"column":null}},"40":{"start":{"line":142,"column":10},"end":{"line":145,"column":null}},"41":{"start":{"line":148,"column":31},"end":{"line":148,"column":null}},"42":{"start":{"line":149,"column":8},"end":{"line":154,"column":null}},"43":{"start":{"line":150,"column":10},"end":{"line":153,"column":null}},"44":{"start":{"line":156,"column":8},"end":{"line":156,"column":null}},"45":{"start":{"line":157,"column":8},"end":{"line":157,"column":null}},"46":{"start":{"line":163,"column":14},"end":{"line":163,"column":null}},"47":{"start":{"line":164,"column":29},"end":{"line":164,"column":null}},"48":{"start":{"line":165,"column":8},"end":{"line":165,"column":null}},"49":{"start":{"line":171,"column":14},"end":{"line":171,"column":null}},"50":{"start":{"line":172,"column":27},"end":{"line":172,"column":null}},"51":{"start":{"line":173,"column":8},"end":{"line":173,"column":null}},"52":{"start":{"line":182,"column":14},"end":{"line":182,"column":null}},"53":{"start":{"line":183,"column":8},"end":{"line":183,"column":null}},"54":{"start":{"line":184,"column":8},"end":{"line":184,"column":null}},"55":{"start":{"line":190,"column":14},"end":{"line":190,"column":null}},"56":{"start":{"line":191,"column":14},"end":{"line":191,"column":null}},"57":{"start":{"line":192,"column":14},"end":{"line":192,"column":null}},"58":{"start":{"line":193,"column":14},"end":{"line":193,"column":null}},"59":{"start":{"line":195,"column":22},"end":{"line":195,"column":null}},"60":{"start":{"line":196,"column":8},"end":{"line":198,"column":null}},"61":{"start":{"line":197,"column":10},"end":{"line":197,"column":null}},"62":{"start":{"line":199,"column":8},"end":{"line":201,"column":null}},"63":{"start":{"line":200,"column":10},"end":{"line":200,"column":null}},"64":{"start":{"line":203,"column":27},"end":{"line":203,"column":null}},"65":{"start":{"line":204,"column":8},"end":{"line":206,"column":null}},"66":{"start":{"line":205,"column":10},"end":{"line":205,"column":null}},"67":{"start":{"line":208,"column":27},"end":{"line":208,"column":null}},"68":{"start":{"line":209,"column":14},"end":{"line":209,"column":null}},"69":{"start":{"line":211,"column":25},"end":{"line":211,"column":null}},"70":{"start":{"line":212,"column":22},"end":{"line":212,"column":null}},"71":{"start":{"line":214,"column":8},"end":{"line":220,"column":null}},"72":{"start":{"line":215,"column":28},"end":{"line":215,"column":null}},"73":{"start":{"line":216,"column":23},"end":{"line":216,"column":null}},"74":{"start":{"line":217,"column":10},"end":{"line":219,"column":null}},"75":{"start":{"line":218,"column":12},"end":{"line":218,"column":null}},"76":{"start":{"line":222,"column":8},"end":{"line":227,"column":null}},"77":{"start":{"line":233,"column":14},"end":{"line":233,"column":null}},"78":{"start":{"line":234,"column":8},"end":{"line":234,"column":null}},"79":{"start":{"line":235,"column":8},"end":{"line":235,"column":null}}},"fnMap":{"0":{"name":"phaseProcedures","decl":{"start":{"line":13,"column":16},"end":{"line":13,"column":32}},"loc":{"start":{"line":13,"column":67},"end":{"line":238,"column":null}},"line":13},"1":{"name":"(anonymous_1)","decl":{"start":{"line":20,"column":16},"end":{"line":20,"column":23}},"loc":{"start":{"line":20,"column":42},"end":{"line":27,"column":7}},"line":20},"2":{"name":"(anonymous_2)","decl":{"start":{"line":31,"column":13},"end":{"line":31,"column":20}},"loc":{"start":{"line":31,"column":39},"end":{"line":34,"column":7}},"line":31},"3":{"name":"(anonymous_3)","decl":{"start":{"line":38,"column":13},"end":{"line":38,"column":20}},"loc":{"start":{"line":38,"column":39},"end":{"line":48,"column":7}},"line":38},"4":{"name":"(anonymous_4)","decl":{"start":{"line":57,"column":16},"end":{"line":57,"column":23}},"loc":{"start":{"line":57,"column":42},"end":{"line":61,"column":7}},"line":57},"5":{"name":"(anonymous_5)","decl":{"start":{"line":65,"column":16},"end":{"line":65,"column":23}},"loc":{"start":{"line":65,"column":42},"end":{"line":94,"column":7}},"line":65},"6":{"name":"(anonymous_6)","decl":{"start":{"line":85,"column":44},"end":{"line":85,"column":45}},"loc":{"start":{"line":85,"column":51},"end":{"line":85,"column":74}},"line":85},"7":{"name":"(anonymous_7)","decl":{"start":{"line":98,"column":16},"end":{"line":98,"column":23}},"loc":{"start":{"line":98,"column":42},"end":{"line":102,"column":7}},"line":98},"8":{"name":"(anonymous_8)","decl":{"start":{"line":111,"column":16},"end":{"line":111,"column":23}},"loc":{"start":{"line":111,"column":42},"end":{"line":123,"column":7}},"line":111},"9":{"name":"(anonymous_9)","decl":{"start":{"line":127,"column":13},"end":{"line":127,"column":20}},"loc":{"start":{"line":127,"column":39},"end":{"line":130,"column":7}},"line":127},"10":{"name":"(anonymous_10)","decl":{"start":{"line":137,"column":16},"end":{"line":137,"column":23}},"loc":{"start":{"line":137,"column":42},"end":{"line":158,"column":7}},"line":137},"11":{"name":"(anonymous_11)","decl":{"start":{"line":162,"column":13},"end":{"line":162,"column":20}},"loc":{"start":{"line":162,"column":39},"end":{"line":166,"column":7}},"line":162},"12":{"name":"(anonymous_12)","decl":{"start":{"line":170,"column":13},"end":{"line":170,"column":20}},"loc":{"start":{"line":170,"column":39},"end":{"line":174,"column":7}},"line":170},"13":{"name":"(anonymous_13)","decl":{"start":{"line":181,"column":16},"end":{"line":181,"column":23}},"loc":{"start":{"line":181,"column":42},"end":{"line":185,"column":7}},"line":181},"14":{"name":"(anonymous_14)","decl":{"start":{"line":189,"column":13},"end":{"line":189,"column":20}},"loc":{"start":{"line":189,"column":39},"end":{"line":228,"column":7}},"line":189},"15":{"name":"(anonymous_15)","decl":{"start":{"line":232,"column":16},"end":{"line":232,"column":23}},"loc":{"start":{"line":232,"column":42},"end":{"line":236,"column":7}},"line":232}},"branchMap":{"0":{"loc":{"start":{"line":41,"column":8},"end":{"line":46,"column":null}},"type":"if","locations":[{"start":{"line":41,"column":8},"end":{"line":46,"column":null}},{"start":{},"end":{}}],"line":41},"1":{"loc":{"start":{"line":70,"column":8},"end":{"line":75,"column":null}},"type":"if","locations":[{"start":{"line":70,"column":8},"end":{"line":75,"column":null}},{"start":{},"end":{}}],"line":70},"2":{"loc":{"start":{"line":76,"column":8},"end":{"line":81,"column":null}},"type":"if","locations":[{"start":{"line":76,"column":8},"end":{"line":81,"column":null}},{"start":{},"end":{}}],"line":76},"3":{"loc":{"start":{"line":86,"column":8},"end":{"line":91,"column":null}},"type":"if","locations":[{"start":{"line":86,"column":8},"end":{"line":91,"column":null}},{"start":{},"end":{}}],"line":86},"4":{"loc":{"start":{"line":141,"column":8},"end":{"line":146,"column":null}},"type":"if","locations":[{"start":{"line":141,"column":8},"end":{"line":146,"column":null}},{"start":{},"end":{}}],"line":141},"5":{"loc":{"start":{"line":149,"column":8},"end":{"line":154,"column":null}},"type":"if","locations":[{"start":{"line":149,"column":8},"end":{"line":154,"column":null}},{"start":{},"end":{}}],"line":149},"6":{"loc":{"start":{"line":196,"column":8},"end":{"line":198,"column":null}},"type":"if","locations":[{"start":{"line":196,"column":8},"end":{"line":198,"column":null}},{"start":{},"end":{}}],"line":196},"7":{"loc":{"start":{"line":199,"column":8},"end":{"line":201,"column":null}},"type":"if","locations":[{"start":{"line":199,"column":8},"end":{"line":201,"column":null}},{"start":{},"end":{}}],"line":199},"8":{"loc":{"start":{"line":204,"column":8},"end":{"line":206,"column":null}},"type":"if","locations":[{"start":{"line":204,"column":8},"end":{"line":206,"column":null}},{"start":{},"end":{}}],"line":204},"9":{"loc":{"start":{"line":217,"column":10},"end":{"line":219,"column":null}},"type":"if","locations":[{"start":{"line":217,"column":10},"end":{"line":219,"column":null}},{"start":{},"end":{}}],"line":217}},"s":{"0":11,"1":0,"2":0,"3":2,"4":2,"5":0,"6":0,"7":0,"8":0,"9":0,"10":0,"11":0,"12":0,"13":0,"14":0,"15":0,"16":0,"17":0,"18":0,"19":0,"20":0,"21":0,"22":0,"23":0,"24":0,"25":0,"26":0,"27":0,"28":0,"29":12,"30":12,"31":12,"32":15,"33":15,"34":12,"35":0,"36":0,"37":0,"38":0,"39":0,"40":0,"41":0,"42":0,"43":0,"44":0,"45":0,"46":0,"47":0,"48":0,"49":0,"50":0,"51":0,"52":0,"53":0,"54":0,"55":0,"56":0,"57":0,"58":0,"59":0,"60":0,"61":0,"62":0,"63":0,"64":0,"65":0,"66":0,"67":0,"68":0,"69":0,"70":0,"71":0,"72":0,"73":0,"74":0,"75":0,"76":0,"77":0,"78":0,"79":0},"f":{"0":11,"1":0,"2":2,"3":0,"4":0,"5":0,"6":0,"7":0,"8":12,"9":0,"10":0,"11":0,"12":0,"13":0,"14":0,"15":0},"b":{"0":[0,0],"1":[0,0],"2":[0,0],"3":[0,0],"4":[0,0],"5":[0,0],"6":[0,0],"7":[0,0],"8":[0,0],"9":[0,0]},"meta":{"lastBranch":10,"lastFunction":16,"lastStatement":80,"seen":{"f:13:16:13:32":0,"s:14:2:237:Infinity":0,"f:20:16:20:23":1,"s:21:14:21:Infinity":1,"s:22:8:26:Infinity":2,"f:31:13:31:20":2,"s:32:14:32:Infinity":3,"s:33:8:33:Infinity":4,"f:38:13:38:20":3,"s:39:14:39:Infinity":5,"s:40:22:40:Infinity":6,"b:41:8:46:Infinity:undefined:undefined:undefined:undefined":0,"s:41:8:46:Infinity":7,"s:42:10:45:Infinity":8,"s:47:8:47:Infinity":9,"f:57:16:57:23":4,"s:58:14:58:Infinity":10,"s:59:32:59:Infinity":11,"s:60:8:60:Infinity":12,"f:65:16:65:23":5,"s:66:14:66:Infinity":13,"s:67:14:67:Infinity":14,"s:69:22:69:Infinity":15,"b:70:8:75:Infinity:undefined:undefined:undefined:undefined":1,"s:70:8:75:Infinity":16,"s:71:10:74:Infinity":17,"b:76:8:81:Infinity:undefined:undefined:undefined:undefined":2,"s:76:8:81:Infinity":18,"s:77:10:80:Infinity":19,"s:84:27:84:Infinity":20,"s:85:26:85:Infinity":21,"f:85:44:85:45":6,"s:85:51:85:74":22,"b:86:8:91:Infinity:undefined:undefined:undefined:undefined":3,"s:86:8:91:Infinity":23,"s:87:10:90:Infinity":24,"s:93:8:93:Infinity":25,"f:98:16:98:23":7,"s:99:14:99:Infinity":26,"s:100:8:100:Infinity":27,"s:101:8:101:Infinity":28,"f:111:16:111:23":8,"s:112:14:112:Infinity":29,"s:113:33:113:Infinity":30,"s:114:8:121:Infinity":31,"s:115:24:119:Infinity":32,"s:120:10:120:Infinity":33,"s:122:8:122:Infinity":34,"f:127:13:127:20":9,"s:128:14:128:Infinity":35,"s:129:8:129:Infinity":36,"f:137:16:137:23":10,"s:138:14:138:Infinity":37,"s:140:22:140:Infinity":38,"b:141:8:146:Infinity:undefined:undefined:undefined:undefined":4,"s:141:8:146:Infinity":39,"s:142:10:145:Infinity":40,"s:148:31:148:Infinity":41,"b:149:8:154:Infinity:undefined:undefined:undefined:undefined":5,"s:149:8:154:Infinity":42,"s:150:10:153:Infinity":43,"s:156:8:156:Infinity":44,"s:157:8:157:Infinity":45,"f:162:13:162:20":11,"s:163:14:163:Infinity":46,"s:164:29:164:Infinity":47,"s:165:8:165:Infinity":48,"f:170:13:170:20":12,"s:171:14:171:Infinity":49,"s:172:27:172:Infinity":50,"s:173:8:173:Infinity":51,"f:181:16:181:23":13,"s:182:14:182:Infinity":52,"s:183:8:183:Infinity":53,"s:184:8:184:Infinity":54,"f:189:13:189:20":14,"s:190:14:190:Infinity":55,"s:191:14:191:Infinity":56,"s:192:14:192:Infinity":57,"s:193:14:193:Infinity":58,"s:195:22:195:Infinity":59,"b:196:8:198:Infinity:undefined:undefined:undefined:undefined":6,"s:196:8:198:Infinity":60,"s:197:10:197:Infinity":61,"b:199:8:201:Infinity:undefined:undefined:undefined:undefined":7,"s:199:8:201:Infinity":62,"s:200:10:200:Infinity":63,"s:203:27:203:Infinity":64,"b:204:8:206:Infinity:undefined:undefined:undefined:undefined":8,"s:204:8:206:Infinity":65,"s:205:10:205:Infinity":66,"s:208:27:208:Infinity":67,"s:209:14:209:Infinity":68,"s:211:25:211:Infinity":69,"s:212:22:212:Infinity":70,"s:214:8:220:Infinity":71,"s:215:28:215:Infinity":72,"s:216:23:216:Infinity":73,"b:217:10:219:Infinity:undefined:undefined:undefined:undefined":9,"s:217:10:219:Infinity":74,"s:218:12:218:Infinity":75,"s:222:8:227:Infinity":76,"f:232:16:232:23":15,"s:233:14:233:Infinity":77,"s:234:8:234:Infinity":78,"s:235:8:235:Infinity":79}}} +,"/Users/lukasmay/development/projects/codewalk-district/src/trpc/routers/preview.ts": {"path":"/Users/lukasmay/development/projects/codewalk-district/src/trpc/routers/preview.ts","statementMap":{"0":{"start":{"line":10,"column":2},"end":{"line":50,"column":null}},"1":{"start":{"line":19,"column":14},"end":{"line":19,"column":null}},"2":{"start":{"line":20,"column":8},"end":{"line":20,"column":null}},"3":{"start":{"line":28,"column":14},"end":{"line":28,"column":null}},"4":{"start":{"line":29,"column":8},"end":{"line":29,"column":null}},"5":{"start":{"line":30,"column":8},"end":{"line":30,"column":null}},"6":{"start":{"line":38,"column":14},"end":{"line":38,"column":null}},"7":{"start":{"line":39,"column":8},"end":{"line":39,"column":null}},"8":{"start":{"line":47,"column":14},"end":{"line":47,"column":null}},"9":{"start":{"line":48,"column":8},"end":{"line":48,"column":null}}},"fnMap":{"0":{"name":"previewProcedures","decl":{"start":{"line":9,"column":16},"end":{"line":9,"column":34}},"loc":{"start":{"line":9,"column":69},"end":{"line":51,"column":null}},"line":9},"1":{"name":"(anonymous_1)","decl":{"start":{"line":18,"column":16},"end":{"line":18,"column":23}},"loc":{"start":{"line":18,"column":42},"end":{"line":21,"column":7}},"line":18},"2":{"name":"(anonymous_2)","decl":{"start":{"line":27,"column":16},"end":{"line":27,"column":23}},"loc":{"start":{"line":27,"column":42},"end":{"line":31,"column":7}},"line":27},"3":{"name":"(anonymous_3)","decl":{"start":{"line":37,"column":13},"end":{"line":37,"column":20}},"loc":{"start":{"line":37,"column":39},"end":{"line":40,"column":7}},"line":37},"4":{"name":"(anonymous_4)","decl":{"start":{"line":46,"column":13},"end":{"line":46,"column":20}},"loc":{"start":{"line":46,"column":39},"end":{"line":49,"column":7}},"line":46}},"branchMap":{},"s":{"0":11,"1":0,"2":0,"3":0,"4":0,"5":0,"6":0,"7":0,"8":0,"9":0},"f":{"0":11,"1":0,"2":0,"3":0,"4":0},"b":{},"meta":{"lastBranch":0,"lastFunction":5,"lastStatement":10,"seen":{"f:9:16:9:34":0,"s:10:2:50:Infinity":0,"f:18:16:18:23":1,"s:19:14:19:Infinity":1,"s:20:8:20:Infinity":2,"f:27:16:27:23":2,"s:28:14:28:Infinity":3,"s:29:8:29:Infinity":4,"s:30:8:30:Infinity":5,"f:37:13:37:20":3,"s:38:14:38:Infinity":6,"s:39:8:39:Infinity":7,"f:46:13:46:20":4,"s:47:14:47:Infinity":8,"s:48:8:48:Infinity":9}}} +,"/Users/lukasmay/development/projects/codewalk-district/src/trpc/routers/project.ts": {"path":"/Users/lukasmay/development/projects/codewalk-district/src/trpc/routers/project.ts","statementMap":{"0":{"start":{"line":15,"column":2},"end":{"line":156,"column":null}},"1":{"start":{"line":23,"column":14},"end":{"line":23,"column":null}},"2":{"start":{"line":26,"column":8},"end":{"line":41,"column":null}},"3":{"start":{"line":27,"column":10},"end":{"line":31,"column":null}},"4":{"start":{"line":33,"column":23},"end":{"line":33,"column":null}},"5":{"start":{"line":34,"column":10},"end":{"line":39,"column":null}},"6":{"start":{"line":35,"column":12},"end":{"line":38,"column":null}},"7":{"start":{"line":40,"column":10},"end":{"line":40,"column":null}},"8":{"start":{"line":43,"column":8},"end":{"line":70,"column":null}},"9":{"start":{"line":44,"column":16},"end":{"line":44,"column":null}},"10":{"start":{"line":46,"column":10},"end":{"line":54,"column":null}},"11":{"start":{"line":47,"column":12},"end":{"line":47,"column":null}},"12":{"start":{"line":49,"column":12},"end":{"line":49,"column":null}},"13":{"start":{"line":50,"column":12},"end":{"line":53,"column":null}},"14":{"start":{"line":57,"column":35},"end":{"line":57,"column":null}},"15":{"start":{"line":58,"column":10},"end":{"line":69,"column":null}},"16":{"start":{"line":59,"column":27},"end":{"line":59,"column":null}},"17":{"start":{"line":60,"column":12},"end":{"line":68,"column":null}},"18":{"start":{"line":62,"column":14},"end":{"line":62,"column":null}},"19":{"start":{"line":63,"column":14},"end":{"line":63,"column":null}},"20":{"start":{"line":64,"column":14},"end":{"line":67,"column":null}},"21":{"start":{"line":72,"column":8},"end":{"line":72,"column":null}},"22":{"start":{"line":77,"column":14},"end":{"line":77,"column":null}},"23":{"start":{"line":78,"column":8},"end":{"line":78,"column":null}},"24":{"start":{"line":84,"column":14},"end":{"line":84,"column":null}},"25":{"start":{"line":85,"column":24},"end":{"line":85,"column":null}},"26":{"start":{"line":86,"column":8},"end":{"line":91,"column":null}},"27":{"start":{"line":87,"column":10},"end":{"line":90,"column":null}},"28":{"start":{"line":92,"column":8},"end":{"line":92,"column":null}},"29":{"start":{"line":98,"column":14},"end":{"line":98,"column":null}},"30":{"start":{"line":99,"column":24},"end":{"line":99,"column":null}},"31":{"start":{"line":100,"column":8},"end":{"line":103,"column":null}},"32":{"start":{"line":101,"column":16},"end":{"line":101,"column":null}},"33":{"start":{"line":102,"column":10},"end":{"line":102,"column":null}},"34":{"start":{"line":104,"column":8},"end":{"line":104,"column":null}},"35":{"start":{"line":105,"column":8},"end":{"line":105,"column":null}},"36":{"start":{"line":114,"column":14},"end":{"line":114,"column":null}},"37":{"start":{"line":115,"column":32},"end":{"line":115,"column":null}},"38":{"start":{"line":116,"column":25},"end":{"line":116,"column":null}},"39":{"start":{"line":117,"column":8},"end":{"line":122,"column":null}},"40":{"start":{"line":118,"column":10},"end":{"line":121,"column":null}},"41":{"start":{"line":125,"column":8},"end":{"line":134,"column":null}},"42":{"start":{"line":126,"column":16},"end":{"line":126,"column":null}},"43":{"start":{"line":127,"column":25},"end":{"line":127,"column":null}},"44":{"start":{"line":128,"column":10},"end":{"line":133,"column":null}},"45":{"start":{"line":129,"column":12},"end":{"line":132,"column":null}},"46":{"start":{"line":136,"column":8},"end":{"line":136,"column":null}},"47":{"start":{"line":142,"column":14},"end":{"line":142,"column":null}},"48":{"start":{"line":143,"column":8},"end":{"line":143,"column":null}},"49":{"start":{"line":152,"column":14},"end":{"line":152,"column":null}},"50":{"start":{"line":153,"column":8},"end":{"line":153,"column":null}},"51":{"start":{"line":154,"column":8},"end":{"line":154,"column":null}}},"fnMap":{"0":{"name":"projectProcedures","decl":{"start":{"line":14,"column":16},"end":{"line":14,"column":34}},"loc":{"start":{"line":14,"column":69},"end":{"line":157,"column":null}},"line":14},"1":{"name":"(anonymous_1)","decl":{"start":{"line":22,"column":16},"end":{"line":22,"column":23}},"loc":{"start":{"line":22,"column":42},"end":{"line":73,"column":7}},"line":22},"2":{"name":"(anonymous_2)","decl":{"start":{"line":62,"column":74},"end":{"line":62,"column":80}},"loc":{"start":{"line":62,"column":80},"end":{"line":62,"column":82}},"line":62},"3":{"name":"(anonymous_3)","decl":{"start":{"line":76,"column":13},"end":{"line":76,"column":20}},"loc":{"start":{"line":76,"column":32},"end":{"line":79,"column":7}},"line":76},"4":{"name":"(anonymous_4)","decl":{"start":{"line":83,"column":13},"end":{"line":83,"column":20}},"loc":{"start":{"line":83,"column":39},"end":{"line":93,"column":7}},"line":83},"5":{"name":"(anonymous_5)","decl":{"start":{"line":97,"column":16},"end":{"line":97,"column":23}},"loc":{"start":{"line":97,"column":42},"end":{"line":106,"column":7}},"line":97},"6":{"name":"(anonymous_6)","decl":{"start":{"line":102,"column":70},"end":{"line":102,"column":76}},"loc":{"start":{"line":102,"column":76},"end":{"line":102,"column":78}},"line":102},"7":{"name":"(anonymous_7)","decl":{"start":{"line":113,"column":16},"end":{"line":113,"column":23}},"loc":{"start":{"line":113,"column":42},"end":{"line":137,"column":7}},"line":113},"8":{"name":"(anonymous_8)","decl":{"start":{"line":141,"column":13},"end":{"line":141,"column":20}},"loc":{"start":{"line":141,"column":39},"end":{"line":144,"column":7}},"line":141},"9":{"name":"(anonymous_9)","decl":{"start":{"line":151,"column":16},"end":{"line":151,"column":23}},"loc":{"start":{"line":151,"column":42},"end":{"line":155,"column":7}},"line":151}},"branchMap":{"0":{"loc":{"start":{"line":30,"column":16},"end":{"line":30,"column":null}},"type":"binary-expr","locations":[{"start":{"line":30,"column":16},"end":{"line":30,"column":39}},{"start":{"line":30,"column":39},"end":{"line":30,"column":null}}],"line":30},"1":{"loc":{"start":{"line":34,"column":10},"end":{"line":39,"column":null}},"type":"if","locations":[{"start":{"line":34,"column":10},"end":{"line":39,"column":null}},{"start":{},"end":{}}],"line":34},"2":{"loc":{"start":{"line":34,"column":14},"end":{"line":34,"column":64}},"type":"binary-expr","locations":[{"start":{"line":34,"column":14},"end":{"line":34,"column":40}},{"start":{"line":34,"column":40},"end":{"line":34,"column":64}}],"line":34},"3":{"loc":{"start":{"line":43,"column":8},"end":{"line":70,"column":null}},"type":"if","locations":[{"start":{"line":43,"column":8},"end":{"line":70,"column":null}},{"start":{},"end":{}}],"line":43},"4":{"loc":{"start":{"line":57,"column":35},"end":{"line":57,"column":null}},"type":"binary-expr","locations":[{"start":{"line":57,"column":35},"end":{"line":57,"column":58}},{"start":{"line":57,"column":58},"end":{"line":57,"column":null}}],"line":57},"5":{"loc":{"start":{"line":58,"column":10},"end":{"line":69,"column":null}},"type":"if","locations":[{"start":{"line":58,"column":10},"end":{"line":69,"column":null}},{"start":{},"end":{}}],"line":58},"6":{"loc":{"start":{"line":60,"column":12},"end":{"line":68,"column":null}},"type":"if","locations":[{"start":{"line":60,"column":12},"end":{"line":68,"column":null}},{"start":{},"end":{}}],"line":60},"7":{"loc":{"start":{"line":86,"column":8},"end":{"line":91,"column":null}},"type":"if","locations":[{"start":{"line":86,"column":8},"end":{"line":91,"column":null}},{"start":{},"end":{}}],"line":86},"8":{"loc":{"start":{"line":100,"column":8},"end":{"line":103,"column":null}},"type":"if","locations":[{"start":{"line":100,"column":8},"end":{"line":103,"column":null}},{"start":{},"end":{}}],"line":100},"9":{"loc":{"start":{"line":100,"column":12},"end":{"line":100,"column":42}},"type":"binary-expr","locations":[{"start":{"line":100,"column":12},"end":{"line":100,"column":23}},{"start":{"line":100,"column":23},"end":{"line":100,"column":42}}],"line":100},"10":{"loc":{"start":{"line":117,"column":8},"end":{"line":122,"column":null}},"type":"if","locations":[{"start":{"line":117,"column":8},"end":{"line":122,"column":null}},{"start":{},"end":{}}],"line":117},"11":{"loc":{"start":{"line":125,"column":8},"end":{"line":134,"column":null}},"type":"if","locations":[{"start":{"line":125,"column":8},"end":{"line":134,"column":null}},{"start":{},"end":{}}],"line":125},"12":{"loc":{"start":{"line":125,"column":12},"end":{"line":125,"column":74}},"type":"binary-expr","locations":[{"start":{"line":125,"column":12},"end":{"line":125,"column":34}},{"start":{"line":125,"column":34},"end":{"line":125,"column":55}},{"start":{"line":125,"column":55},"end":{"line":125,"column":74}}],"line":125},"13":{"loc":{"start":{"line":128,"column":10},"end":{"line":133,"column":null}},"type":"if","locations":[{"start":{"line":128,"column":10},"end":{"line":133,"column":null}},{"start":{},"end":{}}],"line":128}},"s":{"0":11,"1":0,"2":0,"3":0,"4":0,"5":0,"6":0,"7":0,"8":0,"9":0,"10":0,"11":0,"12":0,"13":0,"14":0,"15":0,"16":0,"17":0,"18":0,"19":0,"20":0,"21":0,"22":0,"23":0,"24":0,"25":0,"26":0,"27":0,"28":0,"29":0,"30":0,"31":0,"32":0,"33":0,"34":0,"35":0,"36":0,"37":0,"38":0,"39":0,"40":0,"41":0,"42":0,"43":0,"44":0,"45":0,"46":0,"47":0,"48":0,"49":0,"50":0,"51":0},"f":{"0":11,"1":0,"2":0,"3":0,"4":0,"5":0,"6":0,"7":0,"8":0,"9":0},"b":{"0":[0,0],"1":[0,0],"2":[0,0],"3":[0,0],"4":[0,0],"5":[0,0],"6":[0,0],"7":[0,0],"8":[0,0],"9":[0,0],"10":[0,0],"11":[0,0],"12":[0,0,0],"13":[0,0]},"meta":{"lastBranch":14,"lastFunction":10,"lastStatement":52,"seen":{"f:14:16:14:34":0,"s:15:2:156:Infinity":0,"f:22:16:22:23":1,"s:23:14:23:Infinity":1,"s:26:8:41:Infinity":2,"s:27:10:31:Infinity":3,"b:30:16:30:39:30:39:30:Infinity":0,"s:33:23:33:Infinity":4,"b:34:10:39:Infinity:undefined:undefined:undefined:undefined":1,"s:34:10:39:Infinity":5,"b:34:14:34:40:34:40:34:64":2,"s:35:12:38:Infinity":6,"s:40:10:40:Infinity":7,"b:43:8:70:Infinity:undefined:undefined:undefined:undefined":3,"s:43:8:70:Infinity":8,"s:44:16:44:Infinity":9,"s:46:10:54:Infinity":10,"s:47:12:47:Infinity":11,"s:49:12:49:Infinity":12,"s:50:12:53:Infinity":13,"s:57:35:57:Infinity":14,"b:57:35:57:58:57:58:57:Infinity":4,"b:58:10:69:Infinity:undefined:undefined:undefined:undefined":5,"s:58:10:69:Infinity":15,"s:59:27:59:Infinity":16,"b:60:12:68:Infinity:undefined:undefined:undefined:undefined":6,"s:60:12:68:Infinity":17,"s:62:14:62:Infinity":18,"f:62:74:62:80":2,"s:63:14:63:Infinity":19,"s:64:14:67:Infinity":20,"s:72:8:72:Infinity":21,"f:76:13:76:20":3,"s:77:14:77:Infinity":22,"s:78:8:78:Infinity":23,"f:83:13:83:20":4,"s:84:14:84:Infinity":24,"s:85:24:85:Infinity":25,"b:86:8:91:Infinity:undefined:undefined:undefined:undefined":7,"s:86:8:91:Infinity":26,"s:87:10:90:Infinity":27,"s:92:8:92:Infinity":28,"f:97:16:97:23":5,"s:98:14:98:Infinity":29,"s:99:24:99:Infinity":30,"b:100:8:103:Infinity:undefined:undefined:undefined:undefined":8,"s:100:8:103:Infinity":31,"b:100:12:100:23:100:23:100:42":9,"s:101:16:101:Infinity":32,"s:102:10:102:Infinity":33,"f:102:70:102:76":6,"s:104:8:104:Infinity":34,"s:105:8:105:Infinity":35,"f:113:16:113:23":7,"s:114:14:114:Infinity":36,"s:115:32:115:Infinity":37,"s:116:25:116:Infinity":38,"b:117:8:122:Infinity:undefined:undefined:undefined:undefined":10,"s:117:8:122:Infinity":39,"s:118:10:121:Infinity":40,"b:125:8:134:Infinity:undefined:undefined:undefined:undefined":11,"s:125:8:134:Infinity":41,"b:125:12:125:34:125:34:125:55:125:55:125:74":12,"s:126:16:126:Infinity":42,"s:127:25:127:Infinity":43,"b:128:10:133:Infinity:undefined:undefined:undefined:undefined":13,"s:128:10:133:Infinity":44,"s:129:12:132:Infinity":45,"s:136:8:136:Infinity":46,"f:141:13:141:20":8,"s:142:14:142:Infinity":47,"s:143:8:143:Infinity":48,"f:151:16:151:23":9,"s:152:14:152:Infinity":49,"s:153:8:153:Infinity":50,"s:154:8:154:Infinity":51}}} +,"/Users/lukasmay/development/projects/codewalk-district/src/trpc/routers/subscription.ts": {"path":"/Users/lukasmay/development/projects/codewalk-district/src/trpc/routers/subscription.ts","statementMap":{"0":{"start":{"line":16,"column":2},"end":{"line":44,"column":null}},"1":{"start":{"line":20,"column":23},"end":{"line":20,"column":null}},"2":{"start":{"line":21,"column":8},"end":{"line":21,"column":null}},"3":{"start":{"line":27,"column":23},"end":{"line":27,"column":null}},"4":{"start":{"line":28,"column":8},"end":{"line":28,"column":null}},"5":{"start":{"line":34,"column":23},"end":{"line":34,"column":null}},"6":{"start":{"line":35,"column":8},"end":{"line":35,"column":null}},"7":{"start":{"line":41,"column":23},"end":{"line":41,"column":null}},"8":{"start":{"line":42,"column":8},"end":{"line":42,"column":null}}},"fnMap":{"0":{"name":"subscriptionProcedures","decl":{"start":{"line":15,"column":16},"end":{"line":15,"column":39}},"loc":{"start":{"line":15,"column":74},"end":{"line":45,"column":null}},"line":15},"1":{"name":"(anonymous_1)","decl":{"start":{"line":19,"column":20},"end":{"line":19,"column":37}},"loc":{"start":{"line":19,"column":43},"end":{"line":22,"column":7}},"line":19},"2":{"name":"(anonymous_2)","decl":{"start":{"line":26,"column":20},"end":{"line":26,"column":37}},"loc":{"start":{"line":26,"column":43},"end":{"line":29,"column":7}},"line":26},"3":{"name":"(anonymous_3)","decl":{"start":{"line":33,"column":20},"end":{"line":33,"column":37}},"loc":{"start":{"line":33,"column":43},"end":{"line":36,"column":7}},"line":33},"4":{"name":"(anonymous_4)","decl":{"start":{"line":40,"column":20},"end":{"line":40,"column":37}},"loc":{"start":{"line":40,"column":43},"end":{"line":43,"column":7}},"line":40}},"branchMap":{"0":{"loc":{"start":{"line":20,"column":23},"end":{"line":20,"column":null}},"type":"binary-expr","locations":[{"start":{"line":20,"column":23},"end":{"line":20,"column":38}},{"start":{"line":20,"column":38},"end":{"line":20,"column":null}}],"line":20},"1":{"loc":{"start":{"line":27,"column":23},"end":{"line":27,"column":null}},"type":"binary-expr","locations":[{"start":{"line":27,"column":23},"end":{"line":27,"column":38}},{"start":{"line":27,"column":38},"end":{"line":27,"column":null}}],"line":27},"2":{"loc":{"start":{"line":34,"column":23},"end":{"line":34,"column":null}},"type":"binary-expr","locations":[{"start":{"line":34,"column":23},"end":{"line":34,"column":38}},{"start":{"line":34,"column":38},"end":{"line":34,"column":null}}],"line":34},"3":{"loc":{"start":{"line":41,"column":23},"end":{"line":41,"column":null}},"type":"binary-expr","locations":[{"start":{"line":41,"column":23},"end":{"line":41,"column":38}},{"start":{"line":41,"column":38},"end":{"line":41,"column":null}}],"line":41}},"s":{"0":11,"1":0,"2":0,"3":0,"4":0,"5":0,"6":0,"7":0,"8":0},"f":{"0":11,"1":0,"2":0,"3":0,"4":0},"b":{"0":[0,0],"1":[0,0],"2":[0,0],"3":[0,0]},"meta":{"lastBranch":4,"lastFunction":5,"lastStatement":9,"seen":{"f:15:16:15:39":0,"s:16:2:44:Infinity":0,"f:19:20:19:37":1,"s:20:23:20:Infinity":1,"b:20:23:20:38:20:38:20:Infinity":0,"s:21:8:21:Infinity":2,"f:26:20:26:37":2,"s:27:23:27:Infinity":3,"b:27:23:27:38:27:38:27:Infinity":1,"s:28:8:28:Infinity":4,"f:33:20:33:37":3,"s:34:23:34:Infinity":5,"b:34:23:34:38:34:38:34:Infinity":2,"s:35:8:35:Infinity":6,"f:40:20:40:37":4,"s:41:23:41:Infinity":7,"b:41:23:41:38:41:38:41:Infinity":3,"s:42:8:42:Infinity":8}}} +,"/Users/lukasmay/development/projects/codewalk-district/src/trpc/routers/system.ts": {"path":"/Users/lukasmay/development/projects/codewalk-district/src/trpc/routers/system.ts","statementMap":{"0":{"start":{"line":13,"column":36},"end":{"line":17,"column":null}},"1":{"start":{"line":21,"column":33},"end":{"line":27,"column":null}},"2":{"start":{"line":31,"column":36},"end":{"line":38,"column":null}},"3":{"start":{"line":43,"column":2},"end":{"line":109,"column":null}},"4":{"start":{"line":47,"column":23},"end":{"line":49,"column":null}},"5":{"start":{"line":51,"column":8},"end":{"line":55,"column":null}},"6":{"start":{"line":61,"column":23},"end":{"line":63,"column":null}},"7":{"start":{"line":65,"column":8},"end":{"line":72,"column":null}},"8":{"start":{"line":77,"column":23},"end":{"line":79,"column":null}},"9":{"start":{"line":81,"column":14},"end":{"line":81,"column":null}},"10":{"start":{"line":82,"column":28},"end":{"line":82,"column":null}},"11":{"start":{"line":83,"column":26},"end":{"line":83,"column":null}},"12":{"start":{"line":85,"column":25},"end":{"line":87,"column":null}},"13":{"start":{"line":86,"column":26},"end":{"line":86,"column":130}},"14":{"start":{"line":89,"column":14},"end":{"line":89,"column":null}},"15":{"start":{"line":90,"column":28},"end":{"line":90,"column":null}},"16":{"start":{"line":92,"column":25},"end":{"line":101,"column":null}},"17":{"start":{"line":94,"column":29},"end":{"line":94,"column":null}},"18":{"start":{"line":95,"column":12},"end":{"line":98,"column":null}},"19":{"start":{"line":96,"column":20},"end":{"line":96,"column":null}},"20":{"start":{"line":97,"column":14},"end":{"line":97,"column":null}},"21":{"start":{"line":97,"column":20},"end":{"line":97,"column":45}},"22":{"start":{"line":97,"column":45},"end":{"line":97,"column":64}},"23":{"start":{"line":97,"column":74},"end":{"line":97,"column":94}},"24":{"start":{"line":99,"column":12},"end":{"line":99,"column":null}},"25":{"start":{"line":103,"column":8},"end":{"line":107,"column":null}}},"fnMap":{"0":{"name":"systemProcedures","decl":{"start":{"line":42,"column":16},"end":{"line":42,"column":33}},"loc":{"start":{"line":42,"column":68},"end":{"line":110,"column":null}},"line":42},"1":{"name":"(anonymous_1)","decl":{"start":{"line":46,"column":13},"end":{"line":46,"column":14}},"loc":{"start":{"line":46,"column":42},"end":{"line":56,"column":7}},"line":46},"2":{"name":"(anonymous_2)","decl":{"start":{"line":60,"column":13},"end":{"line":60,"column":14}},"loc":{"start":{"line":60,"column":42},"end":{"line":73,"column":7}},"line":60},"3":{"name":"(anonymous_3)","decl":{"start":{"line":76,"column":13},"end":{"line":76,"column":20}},"loc":{"start":{"line":76,"column":32},"end":{"line":108,"column":7}},"line":76},"4":{"name":"(anonymous_4)","decl":{"start":{"line":86,"column":26},"end":{"line":86,"column":37}},"loc":{"start":{"line":86,"column":26},"end":{"line":86,"column":130}},"line":86},"5":{"name":"(anonymous_5)","decl":{"start":{"line":93,"column":26},"end":{"line":93,"column":32}},"loc":{"start":{"line":93,"column":43},"end":{"line":100,"column":11}},"line":93}},"branchMap":{"0":{"loc":{"start":{"line":47,"column":23},"end":{"line":49,"column":null}},"type":"cond-expr","locations":[{"start":{"line":48,"column":12},"end":{"line":48,"column":null}},{"start":{"line":49,"column":12},"end":{"line":49,"column":null}}],"line":47},"1":{"loc":{"start":{"line":61,"column":23},"end":{"line":63,"column":null}},"type":"cond-expr","locations":[{"start":{"line":62,"column":12},"end":{"line":62,"column":null}},{"start":{"line":63,"column":12},"end":{"line":63,"column":null}}],"line":61},"2":{"loc":{"start":{"line":67,"column":23},"end":{"line":67,"column":null}},"type":"binary-expr","locations":[{"start":{"line":67,"column":23},"end":{"line":67,"column":61}},{"start":{"line":67,"column":61},"end":{"line":67,"column":null}}],"line":67},"3":{"loc":{"start":{"line":77,"column":23},"end":{"line":79,"column":null}},"type":"cond-expr","locations":[{"start":{"line":78,"column":12},"end":{"line":78,"column":null}},{"start":{"line":79,"column":12},"end":{"line":79,"column":null}}],"line":77},"4":{"loc":{"start":{"line":83,"column":26},"end":{"line":83,"column":null}},"type":"cond-expr","locations":[{"start":{"line":83,"column":45},"end":{"line":83,"column":77}},{"start":{"line":83,"column":77},"end":{"line":83,"column":null}}],"line":83},"5":{"loc":{"start":{"line":86,"column":99},"end":{"line":86,"column":129}},"type":"binary-expr","locations":[{"start":{"line":86,"column":99},"end":{"line":86,"column":120}},{"start":{"line":86,"column":120},"end":{"line":86,"column":129}}],"line":86},"6":{"loc":{"start":{"line":95,"column":12},"end":{"line":98,"column":null}},"type":"if","locations":[{"start":{"line":95,"column":12},"end":{"line":98,"column":null}},{"start":{},"end":{}}],"line":95},"7":{"loc":{"start":{"line":104,"column":62},"end":{"line":104,"column":105}},"type":"binary-expr","locations":[{"start":{"line":104,"column":62},"end":{"line":104,"column":100}},{"start":{"line":104,"column":100},"end":{"line":104,"column":105}}],"line":104}},"s":{"0":11,"1":11,"2":11,"3":11,"4":9,"5":9,"6":10,"7":10,"8":0,"9":0,"10":0,"11":0,"12":0,"13":0,"14":0,"15":0,"16":0,"17":0,"18":0,"19":0,"20":0,"21":0,"22":0,"23":0,"24":0,"25":0},"f":{"0":11,"1":9,"2":10,"3":0,"4":0,"5":0},"b":{"0":[8,1],"1":[9,1],"2":[10,1],"3":[0,0],"4":[0,0],"5":[0,0],"6":[0,0],"7":[0,0]},"meta":{"lastBranch":8,"lastFunction":6,"lastStatement":26,"seen":{"s:13:36:17:Infinity":0,"s:21:33:27:Infinity":1,"s:31:36:38:Infinity":2,"f:42:16:42:33":0,"s:43:2:109:Infinity":3,"f:46:13:46:14":1,"s:47:23:49:Infinity":4,"b:48:12:48:Infinity:49:12:49:Infinity":0,"s:51:8:55:Infinity":5,"f:60:13:60:14":2,"s:61:23:63:Infinity":6,"b:62:12:62:Infinity:63:12:63:Infinity":1,"s:65:8:72:Infinity":7,"b:67:23:67:61:67:61:67:Infinity":2,"f:76:13:76:20":3,"s:77:23:79:Infinity":8,"b:78:12:78:Infinity:79:12:79:Infinity":3,"s:81:14:81:Infinity":9,"s:82:28:82:Infinity":10,"s:83:26:83:Infinity":11,"b:83:45:83:77:83:77:83:Infinity":4,"s:85:25:87:Infinity":12,"f:86:26:86:37":4,"s:86:26:86:130":13,"b:86:99:86:120:86:120:86:129":5,"s:89:14:89:Infinity":14,"s:90:28:90:Infinity":15,"s:92:25:101:Infinity":16,"f:93:26:93:32":5,"s:94:29:94:Infinity":17,"b:95:12:98:Infinity:undefined:undefined:undefined:undefined":6,"s:95:12:98:Infinity":18,"s:96:20:96:Infinity":19,"s:97:14:97:Infinity":20,"s:97:20:97:45":21,"s:97:45:97:64":22,"s:97:74:97:94":23,"s:99:12:99:Infinity":24,"s:103:8:107:Infinity":25,"b:104:62:104:100:104:100:104:105":7}}} +,"/Users/lukasmay/development/projects/codewalk-district/src/trpc/routers/task.ts": {"path":"/Users/lukasmay/development/projects/codewalk-district/src/trpc/routers/task.ts","statementMap":{"0":{"start":{"line":16,"column":2},"end":{"line":161,"column":null}},"1":{"start":{"line":20,"column":14},"end":{"line":20,"column":null}},"2":{"start":{"line":21,"column":8},"end":{"line":21,"column":null}},"3":{"start":{"line":27,"column":14},"end":{"line":27,"column":null}},"4":{"start":{"line":28,"column":21},"end":{"line":28,"column":null}},"5":{"start":{"line":29,"column":8},"end":{"line":34,"column":null}},"6":{"start":{"line":30,"column":10},"end":{"line":33,"column":null}},"7":{"start":{"line":35,"column":8},"end":{"line":35,"column":null}},"8":{"start":{"line":44,"column":14},"end":{"line":44,"column":null}},"9":{"start":{"line":45,"column":25},"end":{"line":45,"column":null}},"10":{"start":{"line":46,"column":8},"end":{"line":51,"column":null}},"11":{"start":{"line":47,"column":10},"end":{"line":50,"column":null}},"12":{"start":{"line":52,"column":8},"end":{"line":52,"column":null}},"13":{"start":{"line":65,"column":14},"end":{"line":65,"column":null}},"14":{"start":{"line":66,"column":14},"end":{"line":66,"column":null}},"15":{"start":{"line":68,"column":27},"end":{"line":68,"column":null}},"16":{"start":{"line":69,"column":8},"end":{"line":74,"column":null}},"17":{"start":{"line":70,"column":10},"end":{"line":73,"column":null}},"18":{"start":{"line":76,"column":8},"end":{"line":84,"column":null}},"19":{"start":{"line":97,"column":14},"end":{"line":97,"column":null}},"20":{"start":{"line":98,"column":14},"end":{"line":98,"column":null}},"21":{"start":{"line":100,"column":22},"end":{"line":100,"column":null}},"22":{"start":{"line":101,"column":8},"end":{"line":106,"column":null}},"23":{"start":{"line":102,"column":10},"end":{"line":105,"column":null}},"24":{"start":{"line":108,"column":8},"end":{"line":116,"column":null}},"25":{"start":{"line":126,"column":14},"end":{"line":126,"column":null}},"26":{"start":{"line":127,"column":8},"end":{"line":127,"column":null}},"27":{"start":{"line":133,"column":14},"end":{"line":133,"column":null}},"28":{"start":{"line":134,"column":22},"end":{"line":134,"column":null}},"29":{"start":{"line":135,"column":8},"end":{"line":135,"column":null}},"30":{"start":{"line":135,"column":35},"end":{"line":135,"column":58}},"31":{"start":{"line":141,"column":14},"end":{"line":141,"column":null}},"32":{"start":{"line":142,"column":22},"end":{"line":142,"column":null}},"33":{"start":{"line":143,"column":8},"end":{"line":143,"column":null}},"34":{"start":{"line":143,"column":35},"end":{"line":143,"column":58}},"35":{"start":{"line":149,"column":14},"end":{"line":149,"column":null}},"36":{"start":{"line":150,"column":8},"end":{"line":150,"column":null}},"37":{"start":{"line":151,"column":8},"end":{"line":151,"column":null}},"38":{"start":{"line":157,"column":14},"end":{"line":157,"column":null}},"39":{"start":{"line":158,"column":8},"end":{"line":158,"column":null}},"40":{"start":{"line":159,"column":8},"end":{"line":159,"column":null}}},"fnMap":{"0":{"name":"taskProcedures","decl":{"start":{"line":15,"column":16},"end":{"line":15,"column":31}},"loc":{"start":{"line":15,"column":66},"end":{"line":162,"column":null}},"line":15},"1":{"name":"(anonymous_1)","decl":{"start":{"line":19,"column":13},"end":{"line":19,"column":20}},"loc":{"start":{"line":19,"column":39},"end":{"line":22,"column":7}},"line":19},"2":{"name":"(anonymous_2)","decl":{"start":{"line":26,"column":13},"end":{"line":26,"column":20}},"loc":{"start":{"line":26,"column":39},"end":{"line":36,"column":7}},"line":26},"3":{"name":"(anonymous_3)","decl":{"start":{"line":43,"column":16},"end":{"line":43,"column":23}},"loc":{"start":{"line":43,"column":42},"end":{"line":53,"column":7}},"line":43},"4":{"name":"(anonymous_4)","decl":{"start":{"line":64,"column":16},"end":{"line":64,"column":23}},"loc":{"start":{"line":64,"column":42},"end":{"line":85,"column":7}},"line":64},"5":{"name":"(anonymous_5)","decl":{"start":{"line":96,"column":16},"end":{"line":96,"column":23}},"loc":{"start":{"line":96,"column":42},"end":{"line":117,"column":7}},"line":96},"6":{"name":"(anonymous_6)","decl":{"start":{"line":125,"column":13},"end":{"line":125,"column":20}},"loc":{"start":{"line":125,"column":39},"end":{"line":128,"column":7}},"line":125},"7":{"name":"(anonymous_7)","decl":{"start":{"line":132,"column":13},"end":{"line":132,"column":20}},"loc":{"start":{"line":132,"column":39},"end":{"line":136,"column":7}},"line":132},"8":{"name":"(anonymous_8)","decl":{"start":{"line":135,"column":28},"end":{"line":135,"column":29}},"loc":{"start":{"line":135,"column":35},"end":{"line":135,"column":58}},"line":135},"9":{"name":"(anonymous_9)","decl":{"start":{"line":140,"column":13},"end":{"line":140,"column":20}},"loc":{"start":{"line":140,"column":39},"end":{"line":144,"column":7}},"line":140},"10":{"name":"(anonymous_10)","decl":{"start":{"line":143,"column":28},"end":{"line":143,"column":29}},"loc":{"start":{"line":143,"column":35},"end":{"line":143,"column":58}},"line":143},"11":{"name":"(anonymous_11)","decl":{"start":{"line":148,"column":16},"end":{"line":148,"column":23}},"loc":{"start":{"line":148,"column":42},"end":{"line":152,"column":7}},"line":148},"12":{"name":"(anonymous_12)","decl":{"start":{"line":156,"column":16},"end":{"line":156,"column":23}},"loc":{"start":{"line":156,"column":42},"end":{"line":160,"column":7}},"line":156}},"branchMap":{"0":{"loc":{"start":{"line":29,"column":8},"end":{"line":34,"column":null}},"type":"if","locations":[{"start":{"line":29,"column":8},"end":{"line":34,"column":null}},{"start":{},"end":{}}],"line":29},"1":{"loc":{"start":{"line":46,"column":8},"end":{"line":51,"column":null}},"type":"if","locations":[{"start":{"line":46,"column":8},"end":{"line":51,"column":null}},{"start":{},"end":{}}],"line":46},"2":{"loc":{"start":{"line":69,"column":8},"end":{"line":74,"column":null}},"type":"if","locations":[{"start":{"line":69,"column":8},"end":{"line":74,"column":null}},{"start":{},"end":{}}],"line":69},"3":{"loc":{"start":{"line":79,"column":23},"end":{"line":79,"column":null}},"type":"binary-expr","locations":[{"start":{"line":79,"column":23},"end":{"line":79,"column":44}},{"start":{"line":79,"column":44},"end":{"line":79,"column":null}}],"line":79},"4":{"loc":{"start":{"line":80,"column":20},"end":{"line":80,"column":null}},"type":"binary-expr","locations":[{"start":{"line":80,"column":20},"end":{"line":80,"column":38}},{"start":{"line":80,"column":38},"end":{"line":80,"column":null}}],"line":80},"5":{"loc":{"start":{"line":81,"column":16},"end":{"line":81,"column":null}},"type":"binary-expr","locations":[{"start":{"line":81,"column":16},"end":{"line":81,"column":30}},{"start":{"line":81,"column":30},"end":{"line":81,"column":null}}],"line":81},"6":{"loc":{"start":{"line":82,"column":28},"end":{"line":82,"column":null}},"type":"binary-expr","locations":[{"start":{"line":82,"column":28},"end":{"line":82,"column":54}},{"start":{"line":82,"column":54},"end":{"line":82,"column":null}}],"line":82},"7":{"loc":{"start":{"line":101,"column":8},"end":{"line":106,"column":null}},"type":"if","locations":[{"start":{"line":101,"column":8},"end":{"line":106,"column":null}},{"start":{},"end":{}}],"line":101},"8":{"loc":{"start":{"line":111,"column":23},"end":{"line":111,"column":null}},"type":"binary-expr","locations":[{"start":{"line":111,"column":23},"end":{"line":111,"column":44}},{"start":{"line":111,"column":44},"end":{"line":111,"column":null}}],"line":111},"9":{"loc":{"start":{"line":112,"column":20},"end":{"line":112,"column":null}},"type":"binary-expr","locations":[{"start":{"line":112,"column":20},"end":{"line":112,"column":38}},{"start":{"line":112,"column":38},"end":{"line":112,"column":null}}],"line":112},"10":{"loc":{"start":{"line":113,"column":16},"end":{"line":113,"column":null}},"type":"binary-expr","locations":[{"start":{"line":113,"column":16},"end":{"line":113,"column":30}},{"start":{"line":113,"column":30},"end":{"line":113,"column":null}}],"line":113},"11":{"loc":{"start":{"line":114,"column":28},"end":{"line":114,"column":null}},"type":"binary-expr","locations":[{"start":{"line":114,"column":28},"end":{"line":114,"column":54}},{"start":{"line":114,"column":54},"end":{"line":114,"column":null}}],"line":114}},"s":{"0":11,"1":4,"2":4,"3":0,"4":0,"5":0,"6":0,"7":0,"8":0,"9":0,"10":0,"11":0,"12":0,"13":0,"14":0,"15":0,"16":0,"17":0,"18":0,"19":7,"20":7,"21":7,"22":7,"23":0,"24":7,"25":0,"26":0,"27":0,"28":0,"29":0,"30":0,"31":0,"32":0,"33":0,"34":0,"35":0,"36":0,"37":0,"38":0,"39":0,"40":0},"f":{"0":11,"1":4,"2":0,"3":0,"4":0,"5":7,"6":0,"7":0,"8":0,"9":0,"10":0,"11":0,"12":0},"b":{"0":[0,0],"1":[0,0],"2":[0,0],"3":[0,0],"4":[0,0],"5":[0,0],"6":[0,0],"7":[0,7],"8":[7,5],"9":[7,0],"10":[7,0],"11":[7,0]},"meta":{"lastBranch":12,"lastFunction":13,"lastStatement":41,"seen":{"f:15:16:15:31":0,"s:16:2:161:Infinity":0,"f:19:13:19:20":1,"s:20:14:20:Infinity":1,"s:21:8:21:Infinity":2,"f:26:13:26:20":2,"s:27:14:27:Infinity":3,"s:28:21:28:Infinity":4,"b:29:8:34:Infinity:undefined:undefined:undefined:undefined":0,"s:29:8:34:Infinity":5,"s:30:10:33:Infinity":6,"s:35:8:35:Infinity":7,"f:43:16:43:23":3,"s:44:14:44:Infinity":8,"s:45:25:45:Infinity":9,"b:46:8:51:Infinity:undefined:undefined:undefined:undefined":1,"s:46:8:51:Infinity":10,"s:47:10:50:Infinity":11,"s:52:8:52:Infinity":12,"f:64:16:64:23":4,"s:65:14:65:Infinity":13,"s:66:14:66:Infinity":14,"s:68:27:68:Infinity":15,"b:69:8:74:Infinity:undefined:undefined:undefined:undefined":2,"s:69:8:74:Infinity":16,"s:70:10:73:Infinity":17,"s:76:8:84:Infinity":18,"b:79:23:79:44:79:44:79:Infinity":3,"b:80:20:80:38:80:38:80:Infinity":4,"b:81:16:81:30:81:30:81:Infinity":5,"b:82:28:82:54:82:54:82:Infinity":6,"f:96:16:96:23":5,"s:97:14:97:Infinity":19,"s:98:14:98:Infinity":20,"s:100:22:100:Infinity":21,"b:101:8:106:Infinity:undefined:undefined:undefined:undefined":7,"s:101:8:106:Infinity":22,"s:102:10:105:Infinity":23,"s:108:8:116:Infinity":24,"b:111:23:111:44:111:44:111:Infinity":8,"b:112:20:112:38:112:38:112:Infinity":9,"b:113:16:113:30:113:30:113:Infinity":10,"b:114:28:114:54:114:54:114:Infinity":11,"f:125:13:125:20":6,"s:126:14:126:Infinity":25,"s:127:8:127:Infinity":26,"f:132:13:132:20":7,"s:133:14:133:Infinity":27,"s:134:22:134:Infinity":28,"s:135:8:135:Infinity":29,"f:135:28:135:29":8,"s:135:35:135:58":30,"f:140:13:140:20":9,"s:141:14:141:Infinity":31,"s:142:22:142:Infinity":32,"s:143:8:143:Infinity":33,"f:143:28:143:29":10,"s:143:35:143:58":34,"f:148:16:148:23":11,"s:149:14:149:Infinity":35,"s:150:8:150:Infinity":36,"s:151:8:151:Infinity":37,"f:156:16:156:23":12,"s:157:14:157:Infinity":38,"s:158:8:158:Infinity":39,"s:159:8:159:Infinity":40}}} +} diff --git a/coverage/favicon.png b/coverage/favicon.png new file mode 100644 index 0000000..c1525b8 Binary files /dev/null and b/coverage/favicon.png differ diff --git a/coverage/index.html b/coverage/index.html new file mode 100644 index 0000000..9fa7ecf --- /dev/null +++ b/coverage/index.html @@ -0,0 +1,521 @@ + + + + + + Code coverage report for All files + + + + + + + + + +
+
+

All files

+
+ +
+ 45.8% + Statements + 2291/5002 +
+ + +
+ 37.26% + Branches + 938/2517 +
+ + +
+ 49.23% + Functions + 453/920 +
+ + +
+ 46.26% + Lines + 2214/4785 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
FileStatementsBranchesFunctionsLines
packages/shared/src +
+
40%38/9531.25%15/4856.25%9/1641.25%33/80
src +
+
3.12%1/320%0/433.33%1/33.12%1/32
src/agent +
+
44.7%679/151933.29%292/87746.96%85/18145.27%656/1449
src/agent/accounts +
+
4.13%5/1210%0/900%0/114.31%5/116
src/agent/credentials +
+
4.34%4/920%0/500%0/104.65%4/86
src/agent/lifecycle +
+
52.45%139/26549.31%72/14652.94%18/3452.71%136/258
src/agent/prompts +
+
69.23%18/2616.66%1/660%6/1069.23%18/26
src/agent/providers +
+
33.33%3/950%1/225%1/433.33%3/9
src/agent/providers/parsers +
+
8.06%5/621.88%1/5320%1/58.62%5/58
src/cli +
+
62.5%5/833.33%2/666.66%2/362.5%5/8
src/config +
+
5.55%1/180%0/70%0/45.55%1/18
src/coordination +
+
94.44%102/10885%34/4089.47%17/1995.28%101/106
src/db +
+
55.2%53/960%0/840.81%20/4948.19%40/83
src/db/repositories +
+
0%0/00%0/00%0/00%0/0
src/db/repositories/drizzle +
+
57.29%157/27458.64%95/16261.6%69/11257.79%152/263
src/dispatch +
+
75%168/22459.64%68/11495.45%21/2274.77%166/222
src/events +
+
100%7/7100%0/0100%6/6100%7/7
src/execution +
+
1.01%1/990%0/400%0/121.13%1/88
src/git +
+
64.64%117/18170.49%43/6157.69%15/2665.71%115/175
src/logger +
+
80%4/537.5%3/8100%2/275%3/4
src/logging +
+
95.09%97/10291.42%32/3593.75%30/3294.94%94/99
src/preview +
+
62.18%199/32064.41%105/16349.05%26/5362.45%188/301
src/process +
+
80.73%88/10985.36%35/4171.42%20/2880.37%86/107
src/server +
+
71.27%129/18162.66%47/7568.42%26/3873.14%128/175
src/test +
+
86.13%87/10155%11/2086.48%32/3786%86/100
src/test/integration/real-providers +
+
10.84%9/834.65%2/430%0/1611.39%9/79
src/trpc +
+
27.45%14/510%0/1012.5%1/828.57%14/49
src/trpc/routers +
+
19.77%161/81419.36%79/40825.13%45/17919.94%157/787
+
+
+
+ + + + + + + + \ No newline at end of file diff --git a/coverage/packages/shared/src/index.html b/coverage/packages/shared/src/index.html new file mode 100644 index 0000000..c7d7815 --- /dev/null +++ b/coverage/packages/shared/src/index.html @@ -0,0 +1,131 @@ + + + + + + Code coverage report for packages/shared/src + + + + + + + + + +
+
+

All files packages/shared/src

+
+ +
+ 40% + Statements + 38/95 +
+ + +
+ 31.25% + Branches + 15/48 +
+ + +
+ 56.25% + Functions + 9/16 +
+ + +
+ 41.25% + Lines + 33/80 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
FileStatementsBranchesFunctionsLines
index.ts +
+
0%0/00%0/00%0/00%0/0
utils.ts +
+
40%38/9531.25%15/4856.25%9/1641.25%33/80
+
+
+
+ + + + + + + + \ No newline at end of file diff --git a/coverage/packages/shared/src/index.ts.html b/coverage/packages/shared/src/index.ts.html new file mode 100644 index 0000000..900a0e8 --- /dev/null +++ b/coverage/packages/shared/src/index.ts.html @@ -0,0 +1,94 @@ + + + + + + Code coverage report for packages/shared/src/index.ts + + + + + + + + + +
+
+

All files / packages/shared/src index.ts

+
+ +
+ 0% + Statements + 0/0 +
+ + +
+ 0% + Branches + 0/0 +
+ + +
+ 0% + Functions + 0/0 +
+ + +
+ 0% + Lines + 0/0 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+

+
1 +2 +3 +4  +  +  + 
export type { AppRouter } from './trpc.js';
+export type { Initiative, Phase, Task, Agent, Message, PendingQuestions, QuestionItem, SubscriptionEvent, Project, ChangeSet, ChangeSetEntry } from './types.js';
+export { sortByPriorityAndQueueTime, topologicalSortPhases, groupPhasesByDependencyLevel, type SortableItem, type PhaseForSort, type DependencyEdge, type PipelineColumn } from './utils.js';
+ 
+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/coverage/packages/shared/src/utils.ts.html b/coverage/packages/shared/src/utils.ts.html new file mode 100644 index 0000000..7f071ba --- /dev/null +++ b/coverage/packages/shared/src/utils.ts.html @@ -0,0 +1,676 @@ + + + + + + Code coverage report for packages/shared/src/utils.ts + + + + + + + + + +
+
+

All files / packages/shared/src utils.ts

+
+ +
+ 40% + Statements + 38/95 +
+ + +
+ 31.25% + Branches + 15/48 +
+ + +
+ 56.25% + Functions + 9/16 +
+ + +
+ 41.25% + Lines + 33/80 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+

+
1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 +30 +31 +32 +33 +34 +35 +36 +37 +38 +39 +40 +41 +42 +43 +44 +45 +46 +47 +48 +49 +50 +51 +52 +53 +54 +55 +56 +57 +58 +59 +60 +61 +62 +63 +64 +65 +66 +67 +68 +69 +70 +71 +72 +73 +74 +75 +76 +77 +78 +79 +80 +81 +82 +83 +84 +85 +86 +87 +88 +89 +90 +91 +92 +93 +94 +95 +96 +97 +98 +99 +100 +101 +102 +103 +104 +105 +106 +107 +108 +109 +110 +111 +112 +113 +114 +115 +116 +117 +118 +119 +120 +121 +122 +123 +124 +125 +126 +127 +128 +129 +130 +131 +132 +133 +134 +135 +136 +137 +138 +139 +140 +141 +142 +143 +144 +145 +146 +147 +148 +149 +150 +151 +152 +153 +154 +155 +156 +157 +158 +159 +160 +161 +162 +163 +164 +165 +166 +167 +168 +169 +170 +171 +172 +173 +174 +175 +176 +177 +178 +179 +180 +181 +182 +183 +184 +185 +186 +187 +188 +189 +190 +191 +192 +193 +194 +195 +196 +197 +198  +  +  +  +  +  +  +  +  +  +  +  +1x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +10x +  +23x +9x +9x +  +9x +23x +23x +  +  +9x +10x +9x +10x +  +  +  +9x +23x +10x +  +9x +  +9x +  +21x +21x +21x +  +21x +7x +7x +7x +6x +  +  +  +  +  +9x +1x +1x +3x +1x +1x +  +  +9x +  +  +  +40x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  + 
/**
+ * Shared utility functions that can be used across frontend and backend.
+ */
+ 
+export interface SortableItem {
+  priority: 'low' | 'medium' | 'high';
+  createdAt: Date | string;
+}
+ 
+/**
+ * Priority order mapping for sorting (higher number = higher priority)
+ */
+const PRIORITY_ORDER = {
+  high: 3,
+  medium: 2,
+  low: 1,
+} as const;
+ 
+/**
+ * Sorts items by priority (high to low) then by queue time (oldest first).
+ * This ensures high-priority items come first, but within the same priority,
+ * items are processed in FIFO order.
+ */
+export function sortByPriorityAndQueueTime<T extends SortableItem>(items: T[]): T[] {
+  return [...items].sort((a, b) => {
+    // First sort by priority (high to low)
+    const priorityDiff = PRIORITY_ORDER[b.priority] - PRIORITY_ORDER[a.priority];
+    if (priorityDiff !== 0) {
+      return priorityDiff;
+    }
+ 
+    // Within same priority, sort by creation time (oldest first - FIFO)
+    const aTime = typeof a.createdAt === 'string' ? new Date(a.createdAt) : a.createdAt;
+    const bTime = typeof b.createdAt === 'string' ? new Date(b.createdAt) : b.createdAt;
+    return aTime.getTime() - bTime.getTime();
+  });
+}
+ 
+// ---------------------------------------------------------------------------
+// Topological Phase Sorting
+// ---------------------------------------------------------------------------
+ 
+export interface PhaseForSort {
+  id: string;
+  createdAt: Date | string;
+}
+ 
+export interface DependencyEdge {
+  phaseId: string;
+  dependsOnPhaseId: string;
+}
+ 
+/**
+ * Topologically sort phases by their dependency edges (Kahn's algorithm).
+ * Phases with no dependencies come first. Deterministic tiebreaker: createdAt ascending.
+ * Phases involved in cycles are appended at the end, sorted by createdAt.
+ */
+export function topologicalSortPhases<T extends PhaseForSort>(
+  phases: T[],
+  edges: DependencyEdge[],
+): T[] {
+  if (phases.length === 0) return [];
+ 
+  const phaseMap = new Map(phases.map((p) => [p.id, p]));
+  const inDegree = new Map<string, number>();
+  const adjacency = new Map<string, string[]>(); // dependsOnPhaseId -> phaseIds that depend on it
+ 
+  for (const p of phases) {
+    inDegree.set(p.id, 0);
+    adjacency.set(p.id, []);
+  }
+ 
+  for (const edge of edges) {
+    if (!phaseMap.has(edge.phaseId) || !phaseMap.has(edge.dependsOnPhaseId)) continue;
+    inDegree.set(edge.phaseId, (inDegree.get(edge.phaseId) ?? 0) + 1);
+    adjacency.get(edge.dependsOnPhaseId)!.push(edge.phaseId);
+  }
+ 
+  // Seed queue with zero in-degree phases, sorted by createdAt
+  const queue = phases
+    .filter((p) => (inDegree.get(p.id) ?? 0) === 0)
+    .sort((a, b) => toTime(a.createdAt) - toTime(b.createdAt));
+ 
+  const result: T[] = [];
+ 
+  while (queue.length > 0) {
+    // Pick the earliest-created from the queue
+    queue.sort((a, b) => toTime(a.createdAt) - toTime(b.createdAt));
+    const current = queue.shift()!;
+    result.push(current);
+ 
+    for (const neighborId of adjacency.get(current.id) ?? []) {
+      const newDeg = (inDegree.get(neighborId) ?? 1) - 1;
+      inDegree.set(neighborId, newDeg);
+      if (newDeg === 0) {
+        queue.push(phaseMap.get(neighborId)!);
+      }
+    }
+  }
+ 
+  // Append any phases caught in cycles, sorted by createdAt
+  if (result.length < phases.length) {
+    const inResult = new Set(result.map((p) => p.id));
+    const remaining = phases
+      .filter((p) => !inResult.has(p.id))
+      .sort((a, b) => toTime(a.createdAt) - toTime(b.createdAt));
+    result.push(...remaining);
+  }
+ 
+  return result;
+}
+ 
+function toTime(d: Date | string): number {
+  return typeof d === 'string' ? new Date(d).getTime() : d.getTime();
+}
+ 
+// ---------------------------------------------------------------------------
+// Pipeline Column Grouping
+// ---------------------------------------------------------------------------
+ 
+export interface PipelineColumn<T> {
+  depth: number;
+  phases: T[];
+}
+ 
+/**
+ * Groups phases into pipeline columns by dependency depth.
+ * Depth 0 = no dependencies, depth N = longest path from a root is N.
+ * Phases within a column are sorted by createdAt ascending.
+ * Phases in cycles are placed in the last column + 1.
+ */
+export function groupPhasesByDependencyLevel<T extends PhaseForSort>(
+  phases: T[],
+  edges: DependencyEdge[],
+): PipelineColumn<T>[] {
+  if (phases.length === 0) return [];
+ 
+  const phaseIds = new Set(phases.map((p) => p.id));
+ 
+  // Build adjacency: for each phase, what does it depend on?
+  const dependsOn = new Map<string, string[]>();
+  for (const p of phases) dependsOn.set(p.id, []);
+  for (const edge of edges) {
+    if (!phaseIds.has(edge.phaseId) || !phaseIds.has(edge.dependsOnPhaseId)) continue;
+    dependsOn.get(edge.phaseId)!.push(edge.dependsOnPhaseId);
+  }
+ 
+  // Compute depth via recursive longest path with cycle detection
+  const depthCache = new Map<string, number>();
+  const visiting = new Set<string>();
+ 
+  function computeDepth(id: string): number {
+    if (depthCache.has(id)) return depthCache.get(id)!;
+    if (visiting.has(id)) return -1; // cycle detected
+ 
+    visiting.add(id);
+    const deps = dependsOn.get(id) ?? [];
+    let maxDepth = 0;
+    for (const depId of deps) {
+      const d = computeDepth(depId);
+      if (d === -1) {
+        visiting.delete(id);
+        return -1;
+      }
+      maxDepth = Math.max(maxDepth, d + 1);
+    }
+    visiting.delete(id);
+    depthCache.set(id, maxDepth);
+    return maxDepth;
+  }
+ 
+  // Compute depths
+  let maxValidDepth = 0;
+  for (const p of phases) {
+    const d = computeDepth(p.id);
+    if (d >= 0) maxValidDepth = Math.max(maxValidDepth, d);
+  }
+ 
+  // Group by depth
+  const columnMap = new Map<number, T[]>();
+  for (const p of phases) {
+    const d = depthCache.get(p.id);
+    const depth = d != null && d >= 0 ? d : maxValidDepth + 1; // cycles go last
+    if (!columnMap.has(depth)) columnMap.set(depth, []);
+    columnMap.get(depth)!.push(p);
+  }
+ 
+  // Sort phases within each column by createdAt
+  const columns: PipelineColumn<T>[] = [];
+  const sortedDepths = [...columnMap.keys()].sort((a, b) => a - b);
+  for (const depth of sortedDepths) {
+    const phasesInCol = columnMap.get(depth)!;
+    phasesInCol.sort((a, b) => toTime(a.createdAt) - toTime(b.createdAt));
+    columns.push({ depth, phases: phasesInCol });
+  }
+ 
+  return columns;
+}
+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/coverage/prettify.css b/coverage/prettify.css new file mode 100644 index 0000000..b317a7c --- /dev/null +++ b/coverage/prettify.css @@ -0,0 +1 @@ +.pln{color:#000}@media screen{.str{color:#080}.kwd{color:#008}.com{color:#800}.typ{color:#606}.lit{color:#066}.pun,.opn,.clo{color:#660}.tag{color:#008}.atn{color:#606}.atv{color:#080}.dec,.var{color:#606}.fun{color:red}}@media print,projection{.str{color:#060}.kwd{color:#006;font-weight:bold}.com{color:#600;font-style:italic}.typ{color:#404;font-weight:bold}.lit{color:#044}.pun,.opn,.clo{color:#440}.tag{color:#006;font-weight:bold}.atn{color:#404}.atv{color:#060}}pre.prettyprint{padding:2px;border:1px solid #888}ol.linenums{margin-top:0;margin-bottom:0}li.L0,li.L1,li.L2,li.L3,li.L5,li.L6,li.L7,li.L8{list-style-type:none}li.L1,li.L3,li.L5,li.L7,li.L9{background:#eee} diff --git a/coverage/prettify.js b/coverage/prettify.js new file mode 100644 index 0000000..b322523 --- /dev/null +++ b/coverage/prettify.js @@ -0,0 +1,2 @@ +/* eslint-disable */ +window.PR_SHOULD_USE_CONTINUATION=true;(function(){var h=["break,continue,do,else,for,if,return,while"];var u=[h,"auto,case,char,const,default,double,enum,extern,float,goto,int,long,register,short,signed,sizeof,static,struct,switch,typedef,union,unsigned,void,volatile"];var p=[u,"catch,class,delete,false,import,new,operator,private,protected,public,this,throw,true,try,typeof"];var l=[p,"alignof,align_union,asm,axiom,bool,concept,concept_map,const_cast,constexpr,decltype,dynamic_cast,explicit,export,friend,inline,late_check,mutable,namespace,nullptr,reinterpret_cast,static_assert,static_cast,template,typeid,typename,using,virtual,where"];var x=[p,"abstract,boolean,byte,extends,final,finally,implements,import,instanceof,null,native,package,strictfp,super,synchronized,throws,transient"];var R=[x,"as,base,by,checked,decimal,delegate,descending,dynamic,event,fixed,foreach,from,group,implicit,in,interface,internal,into,is,lock,object,out,override,orderby,params,partial,readonly,ref,sbyte,sealed,stackalloc,string,select,uint,ulong,unchecked,unsafe,ushort,var"];var r="all,and,by,catch,class,else,extends,false,finally,for,if,in,is,isnt,loop,new,no,not,null,of,off,on,or,return,super,then,true,try,unless,until,when,while,yes";var w=[p,"debugger,eval,export,function,get,null,set,undefined,var,with,Infinity,NaN"];var s="caller,delete,die,do,dump,elsif,eval,exit,foreach,for,goto,if,import,last,local,my,next,no,our,print,package,redo,require,sub,undef,unless,until,use,wantarray,while,BEGIN,END";var I=[h,"and,as,assert,class,def,del,elif,except,exec,finally,from,global,import,in,is,lambda,nonlocal,not,or,pass,print,raise,try,with,yield,False,True,None"];var f=[h,"alias,and,begin,case,class,def,defined,elsif,end,ensure,false,in,module,next,nil,not,or,redo,rescue,retry,self,super,then,true,undef,unless,until,when,yield,BEGIN,END"];var H=[h,"case,done,elif,esac,eval,fi,function,in,local,set,then,until"];var A=[l,R,w,s+I,f,H];var e=/^(DIR|FILE|vector|(de|priority_)?queue|list|stack|(const_)?iterator|(multi)?(set|map)|bitset|u?(int|float)\d*)/;var C="str";var z="kwd";var j="com";var O="typ";var G="lit";var L="pun";var F="pln";var m="tag";var E="dec";var J="src";var P="atn";var n="atv";var N="nocode";var M="(?:^^\\.?|[+-]|\\!|\\!=|\\!==|\\#|\\%|\\%=|&|&&|&&=|&=|\\(|\\*|\\*=|\\+=|\\,|\\-=|\\->|\\/|\\/=|:|::|\\;|<|<<|<<=|<=|=|==|===|>|>=|>>|>>=|>>>|>>>=|\\?|\\@|\\[|\\^|\\^=|\\^\\^|\\^\\^=|\\{|\\||\\|=|\\|\\||\\|\\|=|\\~|break|case|continue|delete|do|else|finally|instanceof|return|throw|try|typeof)\\s*";function k(Z){var ad=0;var S=false;var ac=false;for(var V=0,U=Z.length;V122)){if(!(al<65||ag>90)){af.push([Math.max(65,ag)|32,Math.min(al,90)|32])}if(!(al<97||ag>122)){af.push([Math.max(97,ag)&~32,Math.min(al,122)&~32])}}}}af.sort(function(av,au){return(av[0]-au[0])||(au[1]-av[1])});var ai=[];var ap=[NaN,NaN];for(var ar=0;arat[0]){if(at[1]+1>at[0]){an.push("-")}an.push(T(at[1]))}}an.push("]");return an.join("")}function W(al){var aj=al.source.match(new RegExp("(?:\\[(?:[^\\x5C\\x5D]|\\\\[\\s\\S])*\\]|\\\\u[A-Fa-f0-9]{4}|\\\\x[A-Fa-f0-9]{2}|\\\\[0-9]+|\\\\[^ux0-9]|\\(\\?[:!=]|[\\(\\)\\^]|[^\\x5B\\x5C\\(\\)\\^]+)","g"));var ah=aj.length;var an=[];for(var ak=0,am=0;ak=2&&ai==="["){aj[ak]=X(ag)}else{if(ai!=="\\"){aj[ak]=ag.replace(/[a-zA-Z]/g,function(ao){var ap=ao.charCodeAt(0);return"["+String.fromCharCode(ap&~32,ap|32)+"]"})}}}}return aj.join("")}var aa=[];for(var V=0,U=Z.length;V=0;){S[ac.charAt(ae)]=Y}}var af=Y[1];var aa=""+af;if(!ag.hasOwnProperty(aa)){ah.push(af);ag[aa]=null}}ah.push(/[\0-\uffff]/);V=k(ah)})();var X=T.length;var W=function(ah){var Z=ah.sourceCode,Y=ah.basePos;var ad=[Y,F];var af=0;var an=Z.match(V)||[];var aj={};for(var ae=0,aq=an.length;ae=5&&"lang-"===ap.substring(0,5);if(am&&!(ai&&typeof ai[1]==="string")){am=false;ap=J}if(!am){aj[ag]=ap}}var ab=af;af+=ag.length;if(!am){ad.push(Y+ab,ap)}else{var al=ai[1];var ak=ag.indexOf(al);var ac=ak+al.length;if(ai[2]){ac=ag.length-ai[2].length;ak=ac-al.length}var ar=ap.substring(5);B(Y+ab,ag.substring(0,ak),W,ad);B(Y+ab+ak,al,q(ar,al),ad);B(Y+ab+ac,ag.substring(ac),W,ad)}}ah.decorations=ad};return W}function i(T){var W=[],S=[];if(T.tripleQuotedStrings){W.push([C,/^(?:\'\'\'(?:[^\'\\]|\\[\s\S]|\'{1,2}(?=[^\']))*(?:\'\'\'|$)|\"\"\"(?:[^\"\\]|\\[\s\S]|\"{1,2}(?=[^\"]))*(?:\"\"\"|$)|\'(?:[^\\\']|\\[\s\S])*(?:\'|$)|\"(?:[^\\\"]|\\[\s\S])*(?:\"|$))/,null,"'\""])}else{if(T.multiLineStrings){W.push([C,/^(?:\'(?:[^\\\']|\\[\s\S])*(?:\'|$)|\"(?:[^\\\"]|\\[\s\S])*(?:\"|$)|\`(?:[^\\\`]|\\[\s\S])*(?:\`|$))/,null,"'\"`"])}else{W.push([C,/^(?:\'(?:[^\\\'\r\n]|\\.)*(?:\'|$)|\"(?:[^\\\"\r\n]|\\.)*(?:\"|$))/,null,"\"'"])}}if(T.verbatimStrings){S.push([C,/^@\"(?:[^\"]|\"\")*(?:\"|$)/,null])}var Y=T.hashComments;if(Y){if(T.cStyleComments){if(Y>1){W.push([j,/^#(?:##(?:[^#]|#(?!##))*(?:###|$)|.*)/,null,"#"])}else{W.push([j,/^#(?:(?:define|elif|else|endif|error|ifdef|include|ifndef|line|pragma|undef|warning)\b|[^\r\n]*)/,null,"#"])}S.push([C,/^<(?:(?:(?:\.\.\/)*|\/?)(?:[\w-]+(?:\/[\w-]+)+)?[\w-]+\.h|[a-z]\w*)>/,null])}else{W.push([j,/^#[^\r\n]*/,null,"#"])}}if(T.cStyleComments){S.push([j,/^\/\/[^\r\n]*/,null]);S.push([j,/^\/\*[\s\S]*?(?:\*\/|$)/,null])}if(T.regexLiterals){var X=("/(?=[^/*])(?:[^/\\x5B\\x5C]|\\x5C[\\s\\S]|\\x5B(?:[^\\x5C\\x5D]|\\x5C[\\s\\S])*(?:\\x5D|$))+/");S.push(["lang-regex",new RegExp("^"+M+"("+X+")")])}var V=T.types;if(V){S.push([O,V])}var U=(""+T.keywords).replace(/^ | $/g,"");if(U.length){S.push([z,new RegExp("^(?:"+U.replace(/[\s,]+/g,"|")+")\\b"),null])}W.push([F,/^\s+/,null," \r\n\t\xA0"]);S.push([G,/^@[a-z_$][a-z_$@0-9]*/i,null],[O,/^(?:[@_]?[A-Z]+[a-z][A-Za-z_$@0-9]*|\w+_t\b)/,null],[F,/^[a-z_$][a-z_$@0-9]*/i,null],[G,new RegExp("^(?:0x[a-f0-9]+|(?:\\d(?:_\\d+)*\\d*(?:\\.\\d*)?|\\.\\d\\+)(?:e[+\\-]?\\d+)?)[a-z]*","i"),null,"0123456789"],[F,/^\\[\s\S]?/,null],[L,/^.[^\s\w\.$@\'\"\`\/\#\\]*/,null]);return g(W,S)}var K=i({keywords:A,hashComments:true,cStyleComments:true,multiLineStrings:true,regexLiterals:true});function Q(V,ag){var U=/(?:^|\s)nocode(?:\s|$)/;var ab=/\r\n?|\n/;var ac=V.ownerDocument;var S;if(V.currentStyle){S=V.currentStyle.whiteSpace}else{if(window.getComputedStyle){S=ac.defaultView.getComputedStyle(V,null).getPropertyValue("white-space")}}var Z=S&&"pre"===S.substring(0,3);var af=ac.createElement("LI");while(V.firstChild){af.appendChild(V.firstChild)}var W=[af];function ae(al){switch(al.nodeType){case 1:if(U.test(al.className)){break}if("BR"===al.nodeName){ad(al);if(al.parentNode){al.parentNode.removeChild(al)}}else{for(var an=al.firstChild;an;an=an.nextSibling){ae(an)}}break;case 3:case 4:if(Z){var am=al.nodeValue;var aj=am.match(ab);if(aj){var ai=am.substring(0,aj.index);al.nodeValue=ai;var ah=am.substring(aj.index+aj[0].length);if(ah){var ak=al.parentNode;ak.insertBefore(ac.createTextNode(ah),al.nextSibling)}ad(al);if(!ai){al.parentNode.removeChild(al)}}}break}}function ad(ak){while(!ak.nextSibling){ak=ak.parentNode;if(!ak){return}}function ai(al,ar){var aq=ar?al.cloneNode(false):al;var ao=al.parentNode;if(ao){var ap=ai(ao,1);var an=al.nextSibling;ap.appendChild(aq);for(var am=an;am;am=an){an=am.nextSibling;ap.appendChild(am)}}return aq}var ah=ai(ak.nextSibling,0);for(var aj;(aj=ah.parentNode)&&aj.nodeType===1;){ah=aj}W.push(ah)}for(var Y=0;Y=S){ah+=2}if(V>=ap){Z+=2}}}var t={};function c(U,V){for(var S=V.length;--S>=0;){var T=V[S];if(!t.hasOwnProperty(T)){t[T]=U}else{if(window.console){console.warn("cannot override language handler %s",T)}}}}function q(T,S){if(!(T&&t.hasOwnProperty(T))){T=/^\s*]*(?:>|$)/],[j,/^<\!--[\s\S]*?(?:-\->|$)/],["lang-",/^<\?([\s\S]+?)(?:\?>|$)/],["lang-",/^<%([\s\S]+?)(?:%>|$)/],[L,/^(?:<[%?]|[%?]>)/],["lang-",/^]*>([\s\S]+?)<\/xmp\b[^>]*>/i],["lang-js",/^]*>([\s\S]*?)(<\/script\b[^>]*>)/i],["lang-css",/^]*>([\s\S]*?)(<\/style\b[^>]*>)/i],["lang-in.tag",/^(<\/?[a-z][^<>]*>)/i]]),["default-markup","htm","html","mxml","xhtml","xml","xsl"]);c(g([[F,/^[\s]+/,null," \t\r\n"],[n,/^(?:\"[^\"]*\"?|\'[^\']*\'?)/,null,"\"'"]],[[m,/^^<\/?[a-z](?:[\w.:-]*\w)?|\/?>$/i],[P,/^(?!style[\s=]|on)[a-z](?:[\w:-]*\w)?/i],["lang-uq.val",/^=\s*([^>\'\"\s]*(?:[^>\'\"\s\/]|\/(?=\s)))/],[L,/^[=<>\/]+/],["lang-js",/^on\w+\s*=\s*\"([^\"]+)\"/i],["lang-js",/^on\w+\s*=\s*\'([^\']+)\'/i],["lang-js",/^on\w+\s*=\s*([^\"\'>\s]+)/i],["lang-css",/^style\s*=\s*\"([^\"]+)\"/i],["lang-css",/^style\s*=\s*\'([^\']+)\'/i],["lang-css",/^style\s*=\s*([^\"\'>\s]+)/i]]),["in.tag"]);c(g([],[[n,/^[\s\S]+/]]),["uq.val"]);c(i({keywords:l,hashComments:true,cStyleComments:true,types:e}),["c","cc","cpp","cxx","cyc","m"]);c(i({keywords:"null,true,false"}),["json"]);c(i({keywords:R,hashComments:true,cStyleComments:true,verbatimStrings:true,types:e}),["cs"]);c(i({keywords:x,cStyleComments:true}),["java"]);c(i({keywords:H,hashComments:true,multiLineStrings:true}),["bsh","csh","sh"]);c(i({keywords:I,hashComments:true,multiLineStrings:true,tripleQuotedStrings:true}),["cv","py"]);c(i({keywords:s,hashComments:true,multiLineStrings:true,regexLiterals:true}),["perl","pl","pm"]);c(i({keywords:f,hashComments:true,multiLineStrings:true,regexLiterals:true}),["rb"]);c(i({keywords:w,cStyleComments:true,regexLiterals:true}),["js"]);c(i({keywords:r,hashComments:3,cStyleComments:true,multilineStrings:true,tripleQuotedStrings:true,regexLiterals:true}),["coffee"]);c(g([],[[C,/^[\s\S]+/]]),["regex"]);function d(V){var U=V.langExtension;try{var S=a(V.sourceNode);var T=S.sourceCode;V.sourceCode=T;V.spans=S.spans;V.basePos=0;q(U,T)(V);D(V)}catch(W){if("console" in window){console.log(W&&W.stack?W.stack:W)}}}function y(W,V,U){var S=document.createElement("PRE");S.innerHTML=W;if(U){Q(S,U)}var T={langExtension:V,numberLines:U,sourceNode:S};d(T);return S.innerHTML}function b(ad){function Y(af){return document.getElementsByTagName(af)}var ac=[Y("pre"),Y("code"),Y("xmp")];var T=[];for(var aa=0;aa=0){var ah=ai.match(ab);var am;if(!ah&&(am=o(aj))&&"CODE"===am.tagName){ah=am.className.match(ab)}if(ah){ah=ah[1]}var al=false;for(var ak=aj.parentNode;ak;ak=ak.parentNode){if((ak.tagName==="pre"||ak.tagName==="code"||ak.tagName==="xmp")&&ak.className&&ak.className.indexOf("prettyprint")>=0){al=true;break}}if(!al){var af=aj.className.match(/\blinenums\b(?::(\d+))?/);af=af?af[1]&&af[1].length?+af[1]:true:false;if(af){Q(aj,af)}S={langExtension:ah,sourceNode:aj,numberLines:af};d(S)}}}if(X]*(?:>|$)/],[PR.PR_COMMENT,/^<\!--[\s\S]*?(?:-\->|$)/],[PR.PR_PUNCTUATION,/^(?:<[%?]|[%?]>)/],["lang-",/^<\?([\s\S]+?)(?:\?>|$)/],["lang-",/^<%([\s\S]+?)(?:%>|$)/],["lang-",/^]*>([\s\S]+?)<\/xmp\b[^>]*>/i],["lang-handlebars",/^]*type\s*=\s*['"]?text\/x-handlebars-template['"]?\b[^>]*>([\s\S]*?)(<\/script\b[^>]*>)/i],["lang-js",/^]*>([\s\S]*?)(<\/script\b[^>]*>)/i],["lang-css",/^]*>([\s\S]*?)(<\/style\b[^>]*>)/i],["lang-in.tag",/^(<\/?[a-z][^<>]*>)/i],[PR.PR_DECLARATION,/^{{[#^>/]?\s*[\w.][^}]*}}/],[PR.PR_DECLARATION,/^{{&?\s*[\w.][^}]*}}/],[PR.PR_DECLARATION,/^{{{>?\s*[\w.][^}]*}}}/],[PR.PR_COMMENT,/^{{![^}]*}}/]]),["handlebars","hbs"]);PR.registerLangHandler(PR.createSimpleLexer([[PR.PR_PLAIN,/^[ \t\r\n\f]+/,null," \t\r\n\f"]],[[PR.PR_STRING,/^\"(?:[^\n\r\f\\\"]|\\(?:\r\n?|\n|\f)|\\[\s\S])*\"/,null],[PR.PR_STRING,/^\'(?:[^\n\r\f\\\']|\\(?:\r\n?|\n|\f)|\\[\s\S])*\'/,null],["lang-css-str",/^url\(([^\)\"\']*)\)/i],[PR.PR_KEYWORD,/^(?:url|rgb|\!important|@import|@page|@media|@charset|inherit)(?=[^\-\w]|$)/i,null],["lang-css-kw",/^(-?(?:[_a-z]|(?:\\[0-9a-f]+ ?))(?:[_a-z0-9\-]|\\(?:\\[0-9a-f]+ ?))*)\s*:/i],[PR.PR_COMMENT,/^\/\*[^*]*\*+(?:[^\/*][^*]*\*+)*\//],[PR.PR_COMMENT,/^(?:)/],[PR.PR_LITERAL,/^(?:\d+|\d*\.\d+)(?:%|[a-z]+)?/i],[PR.PR_LITERAL,/^#(?:[0-9a-f]{3}){1,2}/i],[PR.PR_PLAIN,/^-?(?:[_a-z]|(?:\\[\da-f]+ ?))(?:[_a-z\d\-]|\\(?:\\[\da-f]+ ?))*/i],[PR.PR_PUNCTUATION,/^[^\s\w\'\"]+/]]),["css"]);PR.registerLangHandler(PR.createSimpleLexer([],[[PR.PR_KEYWORD,/^-?(?:[_a-z]|(?:\\[\da-f]+ ?))(?:[_a-z\d\-]|\\(?:\\[\da-f]+ ?))*/i]]),["css-kw"]);PR.registerLangHandler(PR.createSimpleLexer([],[[PR.PR_STRING,/^[^\)\"\']+/]]),["css-str"]); diff --git a/coverage/sort-arrow-sprite.png b/coverage/sort-arrow-sprite.png new file mode 100644 index 0000000..6ed6831 Binary files /dev/null and b/coverage/sort-arrow-sprite.png differ diff --git a/coverage/sorter.js b/coverage/sorter.js new file mode 100644 index 0000000..4ed70ae --- /dev/null +++ b/coverage/sorter.js @@ -0,0 +1,210 @@ +/* eslint-disable */ +var addSorting = (function() { + 'use strict'; + var cols, + currentSort = { + index: 0, + desc: false + }; + + // returns the summary table element + function getTable() { + return document.querySelector('.coverage-summary'); + } + // returns the thead element of the summary table + function getTableHeader() { + return getTable().querySelector('thead tr'); + } + // returns the tbody element of the summary table + function getTableBody() { + return getTable().querySelector('tbody'); + } + // returns the th element for nth column + function getNthColumn(n) { + return getTableHeader().querySelectorAll('th')[n]; + } + + function onFilterInput() { + const searchValue = document.getElementById('fileSearch').value; + const rows = document.getElementsByTagName('tbody')[0].children; + + // Try to create a RegExp from the searchValue. If it fails (invalid regex), + // it will be treated as a plain text search + let searchRegex; + try { + searchRegex = new RegExp(searchValue, 'i'); // 'i' for case-insensitive + } catch (error) { + searchRegex = null; + } + + for (let i = 0; i < rows.length; i++) { + const row = rows[i]; + let isMatch = false; + + if (searchRegex) { + // If a valid regex was created, use it for matching + isMatch = searchRegex.test(row.textContent); + } else { + // Otherwise, fall back to the original plain text search + isMatch = row.textContent + .toLowerCase() + .includes(searchValue.toLowerCase()); + } + + row.style.display = isMatch ? '' : 'none'; + } + } + + // loads the search box + function addSearchBox() { + var template = document.getElementById('filterTemplate'); + var templateClone = template.content.cloneNode(true); + templateClone.getElementById('fileSearch').oninput = onFilterInput; + template.parentElement.appendChild(templateClone); + } + + // loads all columns + function loadColumns() { + var colNodes = getTableHeader().querySelectorAll('th'), + colNode, + cols = [], + col, + i; + + for (i = 0; i < colNodes.length; i += 1) { + colNode = colNodes[i]; + col = { + key: colNode.getAttribute('data-col'), + sortable: !colNode.getAttribute('data-nosort'), + type: colNode.getAttribute('data-type') || 'string' + }; + cols.push(col); + if (col.sortable) { + col.defaultDescSort = col.type === 'number'; + colNode.innerHTML = + colNode.innerHTML + ''; + } + } + return cols; + } + // attaches a data attribute to every tr element with an object + // of data values keyed by column name + function loadRowData(tableRow) { + var tableCols = tableRow.querySelectorAll('td'), + colNode, + col, + data = {}, + i, + val; + for (i = 0; i < tableCols.length; i += 1) { + colNode = tableCols[i]; + col = cols[i]; + val = colNode.getAttribute('data-value'); + if (col.type === 'number') { + val = Number(val); + } + data[col.key] = val; + } + return data; + } + // loads all row data + function loadData() { + var rows = getTableBody().querySelectorAll('tr'), + i; + + for (i = 0; i < rows.length; i += 1) { + rows[i].data = loadRowData(rows[i]); + } + } + // sorts the table using the data for the ith column + function sortByIndex(index, desc) { + var key = cols[index].key, + sorter = function(a, b) { + a = a.data[key]; + b = b.data[key]; + return a < b ? -1 : a > b ? 1 : 0; + }, + finalSorter = sorter, + tableBody = document.querySelector('.coverage-summary tbody'), + rowNodes = tableBody.querySelectorAll('tr'), + rows = [], + i; + + if (desc) { + finalSorter = function(a, b) { + return -1 * sorter(a, b); + }; + } + + for (i = 0; i < rowNodes.length; i += 1) { + rows.push(rowNodes[i]); + tableBody.removeChild(rowNodes[i]); + } + + rows.sort(finalSorter); + + for (i = 0; i < rows.length; i += 1) { + tableBody.appendChild(rows[i]); + } + } + // removes sort indicators for current column being sorted + function removeSortIndicators() { + var col = getNthColumn(currentSort.index), + cls = col.className; + + cls = cls.replace(/ sorted$/, '').replace(/ sorted-desc$/, ''); + col.className = cls; + } + // adds sort indicators for current column being sorted + function addSortIndicators() { + getNthColumn(currentSort.index).className += currentSort.desc + ? ' sorted-desc' + : ' sorted'; + } + // adds event listeners for all sorter widgets + function enableUI() { + var i, + el, + ithSorter = function ithSorter(i) { + var col = cols[i]; + + return function() { + var desc = col.defaultDescSort; + + if (currentSort.index === i) { + desc = !currentSort.desc; + } + sortByIndex(i, desc); + removeSortIndicators(); + currentSort.index = i; + currentSort.desc = desc; + addSortIndicators(); + }; + }; + for (i = 0; i < cols.length; i += 1) { + if (cols[i].sortable) { + // add the click event handler on the th so users + // dont have to click on those tiny arrows + el = getNthColumn(i).querySelector('.sorter').parentElement; + if (el.addEventListener) { + el.addEventListener('click', ithSorter(i)); + } else { + el.attachEvent('onclick', ithSorter(i)); + } + } + } + } + // adds sorting functionality to the UI + return function() { + if (!getTable()) { + return; + } + cols = loadColumns(); + loadData(); + addSearchBox(); + addSortIndicators(); + enableUI(); + }; +})(); + +window.addEventListener('load', addSorting); diff --git a/coverage/src/agent/accounts/index.html b/coverage/src/agent/accounts/index.html new file mode 100644 index 0000000..c6ae379 --- /dev/null +++ b/coverage/src/agent/accounts/index.html @@ -0,0 +1,146 @@ + + + + + + Code coverage report for src/agent/accounts + + + + + + + + + +
+
+

All files src/agent/accounts

+
+ +
+ 4.13% + Statements + 5/121 +
+ + +
+ 0% + Branches + 0/90 +
+ + +
+ 0% + Functions + 0/11 +
+ + +
+ 4.31% + Lines + 5/116 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
FileStatementsBranchesFunctionsLines
paths.ts +
+
0%0/1100%0/00%0/10%0/1
setup.ts +
+
0%0/3100%0/00%0/10%0/3
usage.ts +
+
4.27%5/1170%0/900%0/94.46%5/112
+
+
+
+ + + + + + + + \ No newline at end of file diff --git a/coverage/src/agent/accounts/paths.ts.html b/coverage/src/agent/accounts/paths.ts.html new file mode 100644 index 0000000..a6541ad --- /dev/null +++ b/coverage/src/agent/accounts/paths.ts.html @@ -0,0 +1,100 @@ + + + + + + Code coverage report for src/agent/accounts/paths.ts + + + + + + + + + +
+
+

All files / src/agent/accounts paths.ts

+
+ +
+ 0% + Statements + 0/1 +
+ + +
+ 100% + Branches + 0/0 +
+ + +
+ 0% + Functions + 0/1 +
+ + +
+ 0% + Lines + 0/1 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+

+
1 +2 +3 +4 +5 +6  +  +  +  +  + 
import { join } from 'node:path';
+ 
+export function getAccountConfigDir(workspaceRoot: string, accountId: string): string {
+  return join(workspaceRoot, '.cw', 'accounts', accountId);
+}
+ 
+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/coverage/src/agent/accounts/setup.ts.html b/coverage/src/agent/accounts/setup.ts.html new file mode 100644 index 0000000..266d426 --- /dev/null +++ b/coverage/src/agent/accounts/setup.ts.html @@ -0,0 +1,130 @@ + + + + + + Code coverage report for src/agent/accounts/setup.ts + + + + + + + + + +
+
+

All files / src/agent/accounts setup.ts

+
+ +
+ 0% + Statements + 0/3 +
+ + +
+ 100% + Branches + 0/0 +
+ + +
+ 0% + Functions + 0/1 +
+ + +
+ 0% + Lines + 0/3 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+

+
1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16  +  +  +  +  +  +  +  +  +  +  +  +  +  +  + 
import { mkdirSync, writeFileSync } from 'node:fs';
+import { join } from 'node:path';
+ 
+export function setupAccountConfigDir(
+  configDir: string,
+  extracted: { configJson: object; credentials: string },
+): void {
+  mkdirSync(configDir, { recursive: true });
+ 
+  // Write .claude.json
+  writeFileSync(join(configDir, '.claude.json'), JSON.stringify(extracted.configJson, null, 2));
+ 
+  // Write .credentials.json
+  writeFileSync(join(configDir, '.credentials.json'), extracted.credentials);
+}
+ 
+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/coverage/src/agent/accounts/usage.ts.html b/coverage/src/agent/accounts/usage.ts.html new file mode 100644 index 0000000..39fd4e1 --- /dev/null +++ b/coverage/src/agent/accounts/usage.ts.html @@ -0,0 +1,1207 @@ + + + + + + Code coverage report for src/agent/accounts/usage.ts + + + + + + + + + +
+
+

All files / src/agent/accounts usage.ts

+
+ +
+ 4.27% + Statements + 5/117 +
+ + +
+ 0% + Branches + 0/90 +
+ + +
+ 0% + Functions + 0/9 +
+ + +
+ 4.46% + Lines + 5/112 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+

+
1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 +30 +31 +32 +33 +34 +35 +36 +37 +38 +39 +40 +41 +42 +43 +44 +45 +46 +47 +48 +49 +50 +51 +52 +53 +54 +55 +56 +57 +58 +59 +60 +61 +62 +63 +64 +65 +66 +67 +68 +69 +70 +71 +72 +73 +74 +75 +76 +77 +78 +79 +80 +81 +82 +83 +84 +85 +86 +87 +88 +89 +90 +91 +92 +93 +94 +95 +96 +97 +98 +99 +100 +101 +102 +103 +104 +105 +106 +107 +108 +109 +110 +111 +112 +113 +114 +115 +116 +117 +118 +119 +120 +121 +122 +123 +124 +125 +126 +127 +128 +129 +130 +131 +132 +133 +134 +135 +136 +137 +138 +139 +140 +141 +142 +143 +144 +145 +146 +147 +148 +149 +150 +151 +152 +153 +154 +155 +156 +157 +158 +159 +160 +161 +162 +163 +164 +165 +166 +167 +168 +169 +170 +171 +172 +173 +174 +175 +176 +177 +178 +179 +180 +181 +182 +183 +184 +185 +186 +187 +188 +189 +190 +191 +192 +193 +194 +195 +196 +197 +198 +199 +200 +201 +202 +203 +204 +205 +206 +207 +208 +209 +210 +211 +212 +213 +214 +215 +216 +217 +218 +219 +220 +221 +222 +223 +224 +225 +226 +227 +228 +229 +230 +231 +232 +233 +234 +235 +236 +237 +238 +239 +240 +241 +242 +243 +244 +245 +246 +247 +248 +249 +250 +251 +252 +253 +254 +255 +256 +257 +258 +259 +260 +261 +262 +263 +264 +265 +266 +267 +268 +269 +270 +271 +272 +273 +274 +275 +276 +277 +278 +279 +280 +281 +282 +283 +284 +285 +286 +287 +288 +289 +290 +291 +292 +293 +294 +295 +296 +297 +298 +299 +300 +301 +302 +303 +304 +305 +306 +307 +308 +309 +310 +311 +312 +313 +314 +315 +316 +317 +318 +319 +320 +321 +322 +323 +324 +325 +326 +327 +328 +329 +330 +331 +332 +333 +334 +335 +336 +337 +338 +339 +340 +341 +342 +343 +344 +345 +346 +347 +348 +349 +350 +351 +352 +353 +354 +355 +356 +357 +358 +359 +360 +361 +362 +363 +364 +365 +366 +367 +368 +369 +370 +371 +372 +373 +374 +375  +  +  +  +  +  +  +  +  +18x +  +18x +18x +18x +18x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  + 
import { readFileSync, existsSync, writeFileSync, mkdirSync } from 'node:fs';
+import { join, dirname } from 'node:path';
+import type { Account } from '../../db/schema.js';
+import type { AgentInfo } from '../types.js';
+import type { AccountCredentialManager } from '../credentials/types.js';
+import { createModuleLogger } from '../../logger/index.js';
+import { getAccountConfigDir } from './paths.js';
+import { setupAccountConfigDir } from './setup.js';
+ 
+const log = createModuleLogger('account-usage');
+ 
+const USAGE_API_URL = 'https://api.anthropic.com/api/oauth/usage';
+const TOKEN_REFRESH_URL = 'https://console.anthropic.com/v1/oauth/token';
+const OAUTH_CLIENT_ID = '9d1c250a-e61b-44d9-88ed-5944d1962f5e';
+const TOKEN_REFRESH_BUFFER_MS = 300_000; // 5 minutes
+ 
+export interface OAuthCredentials {
+  accessToken: string;
+  refreshToken: string | null;
+  expiresAt: number | null; // ms epoch, null for setup tokens
+  subscriptionType: string | null;
+  rateLimitTier: string | null;
+}
+ 
+export interface UsageTier {
+  utilization: number;
+  resets_at: string | null;
+}
+ 
+export interface AccountUsage {
+  five_hour: UsageTier | null;
+  seven_day: UsageTier | null;
+  seven_day_sonnet: UsageTier | null;
+  seven_day_opus: UsageTier | null;
+  extra_usage: {
+    is_enabled: boolean;
+    monthly_limit: number | null;
+    used_credits: number | null;
+    utilization: number | null;
+  } | null;
+}
+ 
+export interface AccountHealthResult {
+  id: string;
+  email: string;
+  provider: string;
+  credentialsValid: boolean;
+  tokenValid: boolean;
+  tokenExpiresAt: string | null;
+  subscriptionType: string | null;
+  error: string | null;
+  usage: AccountUsage | null;
+  isExhausted: boolean;
+  exhaustedUntil: string | null;
+  lastUsedAt: string | null;
+  agentCount: number;
+  activeAgentCount: number;
+}
+ 
+function readCredentials(configDir: string): OAuthCredentials | null {
+  try {
+    const credPath = join(configDir, '.credentials.json');
+    if (!existsSync(credPath)) return null;
+    const raw = readFileSync(credPath, 'utf-8');
+    const parsed = JSON.parse(raw);
+    const oauth = parsed.claudeAiOauth;
+    if (!oauth || !oauth.accessToken) return null;
+    return {
+      accessToken: oauth.accessToken,
+      refreshToken: oauth.refreshToken ?? null,
+      expiresAt: oauth.expiresAt ?? null,
+      subscriptionType: oauth.subscriptionType ?? null,
+      rateLimitTier: oauth.rateLimitTier ?? null,
+    };
+  } catch {
+    return null;
+  }
+}
+ 
+function isTokenExpired(credentials: OAuthCredentials): boolean {
+  if (!credentials.expiresAt) return false; // Setup tokens without expiry are treated as non-expired
+  return credentials.expiresAt < Date.now() + TOKEN_REFRESH_BUFFER_MS;
+}
+ 
+/**
+ * Write credentials back to the config directory.
+ * Matches ccswitch's update_credentials_with_token() behavior.
+ */
+function writeCredentials(
+  configDir: string,
+  accessToken: string,
+  refreshToken: string,
+  expiresIn: number,
+): void {
+  const credPath = join(configDir, '.credentials.json');
+ 
+  // Read existing credentials to preserve other fields
+  let existing: Record<string, unknown> = {};
+  try {
+    if (existsSync(credPath)) {
+      existing = JSON.parse(readFileSync(credPath, 'utf-8'));
+    }
+  } catch {
+    // Start fresh if can't read
+  }
+ 
+  // Calculate expiry in milliseconds (matching ccswitch behavior)
+  const nowMs = Date.now();
+  const expiresAt = nowMs + (expiresIn * 1000);
+ 
+  // Update claudeAiOauth section
+  const claudeAiOauth = (existing.claudeAiOauth as Record<string, unknown>) ?? {};
+  claudeAiOauth.accessToken = accessToken;
+  claudeAiOauth.refreshToken = refreshToken;
+  claudeAiOauth.expiresAt = expiresAt;
+  existing.claudeAiOauth = claudeAiOauth;
+ 
+  // Ensure directory exists
+  mkdirSync(dirname(credPath), { recursive: true });
+ 
+  // Write back (compact JSON for consistency with ccswitch)
+  writeFileSync(credPath, JSON.stringify(existing));
+  log.debug({ configDir }, 'credentials written after token refresh');
+}
+ 
+async function refreshToken(
+  refreshTokenStr: string,
+): Promise<{ accessToken: string; refreshToken: string; expiresIn: number } | null> {
+  try {
+    const response = await fetch(TOKEN_REFRESH_URL, {
+      method: 'POST',
+      headers: { 'Content-Type': 'application/json' },
+      body: JSON.stringify({
+        grant_type: 'refresh_token',
+        refresh_token: refreshTokenStr,
+        client_id: OAUTH_CLIENT_ID,
+        scope: 'user:inference user:profile',
+      }),
+    });
+    if (!response.ok) return null;
+    const data = await response.json();
+    return {
+      accessToken: data.access_token,
+      refreshToken: data.refresh_token,
+      expiresIn: data.expires_in,
+    };
+  } catch {
+    return null;
+  }
+}
+ 
+type FetchUsageResult =
+  | { ok: true; usage: AccountUsage }
+  | { ok: false; status: number; statusText: string }
+  | { ok: false; status: 0; statusText: string };
+ 
+async function fetchUsage(accessToken: string): Promise<FetchUsageResult> {
+  try {
+    const response = await fetch(USAGE_API_URL, {
+      method: 'GET',
+      headers: {
+        Authorization: `Bearer ${accessToken}`,
+        'anthropic-beta': 'oauth-2025-04-20',
+        'Content-Type': 'application/json',
+      },
+    });
+    if (!response.ok) {
+      return { ok: false, status: response.status, statusText: response.statusText };
+    }
+    const data = await response.json();
+    return {
+      ok: true,
+      usage: {
+        five_hour: data.five_hour ?? null,
+        seven_day: data.seven_day ?? null,
+        seven_day_sonnet: data.seven_day_sonnet ?? null,
+        seven_day_opus: data.seven_day_opus ?? null,
+        extra_usage: data.extra_usage ?? null,
+      },
+    };
+  } catch (err) {
+    return { ok: false, status: 0, statusText: err instanceof Error ? err.message : 'Network error' };
+  }
+}
+ 
+export async function checkAccountHealth(
+  account: Account,
+  agents: AgentInfo[],
+  credentialManager?: AccountCredentialManager,
+  workspaceRoot?: string,
+): Promise<AccountHealthResult> {
+  const configDir = workspaceRoot ? getAccountConfigDir(workspaceRoot, account.id) : null;
+ 
+  const accountAgents = agents.filter((a) => a.accountId === account.id);
+  const activeAgents = accountAgents.filter(
+    (a) => a.status === 'running' || a.status === 'waiting_for_input',
+  );
+ 
+  const base: AccountHealthResult = {
+    id: account.id,
+    email: account.email,
+    provider: account.provider,
+    credentialsValid: false,
+    tokenValid: false,
+    tokenExpiresAt: null,
+    subscriptionType: null,
+    error: null,
+    usage: null,
+    isExhausted: account.isExhausted,
+    exhaustedUntil: account.exhaustedUntil?.toISOString() ?? null,
+    lastUsedAt: account.lastUsedAt?.toISOString() ?? null,
+    agentCount: accountAgents.length,
+    activeAgentCount: activeAgents.length,
+  };
+ 
+  if (!configDir) {
+    return { ...base, error: 'Cannot derive config dir: workspaceRoot not provided' };
+  }
+ 
+  // Ensure DB credentials are written to disk so file-based checks can find them
+  if (account.configJson && account.credentials) {
+    try {
+      setupAccountConfigDir(configDir, {
+        configJson: JSON.parse(account.configJson),
+        credentials: account.credentials,
+      });
+    } catch (err) {
+      log.warn({ accountId: account.id, err: err instanceof Error ? err.message : String(err) }, 'failed to sync DB credentials to disk');
+    }
+  }
+ 
+  try {
+    // Use credential manager if provided, otherwise fall back to direct functions
+    let accessToken: string;
+    let currentExpiresAt: number | null;
+    let subscriptionType: string | null = null;
+ 
+    if (credentialManager) {
+      const result = await credentialManager.ensureValid(configDir, account.id);
+      if (!result.valid || !result.credentials) {
+        return {
+          ...base,
+          credentialsValid: result.credentials !== null,
+          error: result.error ?? 'Credentials validation failed',
+        };
+      }
+      accessToken = result.credentials.accessToken;
+      currentExpiresAt = result.credentials.expiresAt;
+      subscriptionType = result.credentials.subscriptionType;
+    } else {
+      // Legacy path: direct function calls
+      const credentials = readCredentials(configDir);
+      if (!credentials) {
+        return {
+          ...base,
+          error: 'Credentials file not found or unreadable',
+        };
+      }
+ 
+      accessToken = credentials.accessToken;
+      currentExpiresAt = credentials.expiresAt;
+      subscriptionType = credentials.subscriptionType;
+ 
+      if (isTokenExpired(credentials)) {
+        if (!credentials.refreshToken) {
+          log.warn({ accountId: account.id }, 'setup token expired, no refresh token');
+          return {
+            ...base,
+            credentialsValid: true,
+            error: 'Setup token expired, no refresh token available',
+          };
+        }
+        log.info({ accountId: account.id, email: account.email }, 'token expired, refreshing');
+        const refreshed = await refreshToken(credentials.refreshToken);
+        if (!refreshed) {
+          log.warn({ accountId: account.id }, 'token refresh failed');
+          return {
+            ...base,
+            credentialsValid: true,
+            error: 'Token expired and refresh failed',
+          };
+        }
+        accessToken = refreshed.accessToken;
+ 
+        // Persist the refreshed credentials back to disk
+        const newRefreshToken = refreshed.refreshToken || credentials.refreshToken;
+        writeCredentials(configDir, accessToken, newRefreshToken, refreshed.expiresIn);
+        currentExpiresAt = Date.now() + (refreshed.expiresIn * 1000);
+        log.info({ accountId: account.id, expiresIn: refreshed.expiresIn }, 'token refreshed and persisted');
+      }
+    }
+ 
+    const isSetupToken = !currentExpiresAt;
+    const usageResult = await fetchUsage(accessToken);
+ 
+    if (!usageResult.ok) {
+      const statusDetail = usageResult.status > 0
+        ? `HTTP ${usageResult.status} ${usageResult.statusText}`
+        : usageResult.statusText;
+ 
+      if (isSetupToken) {
+        // Setup tokens often can't query the usage API — not a hard error
+        return {
+          ...base,
+          credentialsValid: true,
+          tokenValid: true,
+          tokenExpiresAt: null,
+          subscriptionType,
+          error: `Usage API unavailable for setup token (${statusDetail}). Run \`claude\` with this account to complete OAuth setup.`,
+        };
+      }
+ 
+      return {
+        ...base,
+        credentialsValid: true,
+        error: `Usage API request failed: ${statusDetail}`,
+      };
+    }
+ 
+    return {
+      ...base,
+      credentialsValid: true,
+      tokenValid: true,
+      tokenExpiresAt: currentExpiresAt ? new Date(currentExpiresAt).toISOString() : null,
+      subscriptionType,
+      usage: usageResult.usage,
+    };
+  } catch (err) {
+    return {
+      ...base,
+      error: err instanceof Error ? err.message : String(err),
+    };
+  }
+}
+ 
+/**
+ * Ensure account credentials are valid and refreshed if needed.
+ * Call this before spawning an agent to ensure the credentials file
+ * has fresh tokens that the agent subprocess can use.
+ *
+ * Returns true if credentials are valid (or were successfully refreshed).
+ * Returns false if credentials are missing or refresh failed.
+ *
+ * @deprecated Use AccountCredentialManager.ensureValid() instead for event emission support.
+ */
+export async function ensureAccountCredentials(configDir: string): Promise<boolean> {
+  const credentials = readCredentials(configDir);
+  if (!credentials) {
+    log.warn({ configDir }, 'no credentials found');
+    return false;
+  }
+ 
+  if (!isTokenExpired(credentials)) {
+    log.debug({ configDir }, 'credentials valid, no refresh needed');
+    return true;
+  }
+ 
+  if (!credentials.refreshToken) {
+    log.error({ configDir }, 'setup token expired, no refresh token available');
+    return false;
+  }
+ 
+  log.info({ configDir }, 'credentials expired, refreshing before spawn');
+  const refreshed = await refreshToken(credentials.refreshToken);
+  if (!refreshed) {
+    log.error({ configDir }, 'failed to refresh credentials');
+    return false;
+  }
+ 
+  const newRefreshToken = refreshed.refreshToken || credentials.refreshToken;
+  writeCredentials(configDir, refreshed.accessToken, newRefreshToken, refreshed.expiresIn);
+  log.info({ configDir, expiresIn: refreshed.expiresIn }, 'credentials refreshed before spawn');
+  return true;
+}
+ 
+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/coverage/src/agent/alias.ts.html b/coverage/src/agent/alias.ts.html new file mode 100644 index 0000000..2a24f4b --- /dev/null +++ b/coverage/src/agent/alias.ts.html @@ -0,0 +1,187 @@ + + + + + + Code coverage report for src/agent/alias.ts + + + + + + + + + +
+
+

All files / src/agent alias.ts

+
+ +
+ 12.5% + Statements + 1/8 +
+ + +
+ 0% + Branches + 0/2 +
+ + +
+ 0% + Functions + 0/1 +
+ + +
+ 14.28% + Lines + 1/7 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+

+
1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 +30 +31 +32 +33 +34 +35  +  +  +  +  +  +  +  +  +  +15x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  + 
/**
+ * Agent Alias Generator
+ *
+ * Generates unique funny aliases for agents using adjective-animal combinations.
+ * E.g., "jolly-penguin", "bold-eagle", "swift-otter".
+ */
+ 
+import { uniqueNamesGenerator, adjectives, animals } from 'unique-names-generator';
+import type { AgentRepository } from '../db/repositories/agent-repository.js';
+ 
+const MAX_RETRIES = 10;
+ 
+/**
+ * Generate a unique agent alias that doesn't collide with existing agent names.
+ *
+ * @param repository - Agent repository to check for name collisions
+ * @returns A unique adjective-animal alias (e.g., "jolly-penguin")
+ */
+export async function generateUniqueAlias(repository: AgentRepository): Promise<string> {
+  for (let i = 0; i < MAX_RETRIES; i++) {
+    const alias = uniqueNamesGenerator({
+      dictionaries: [adjectives, animals],
+      separator: '-',
+      style: 'lowerCase',
+    });
+ 
+    const existing = await repository.findByName(alias);
+    if (!existing) {
+      return alias;
+    }
+  }
+ 
+  throw new Error(`Failed to generate unique alias after ${MAX_RETRIES} attempts`);
+}
+ 
+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/coverage/src/agent/cleanup-manager.ts.html b/coverage/src/agent/cleanup-manager.ts.html new file mode 100644 index 0000000..7b1bfa1 --- /dev/null +++ b/coverage/src/agent/cleanup-manager.ts.html @@ -0,0 +1,1663 @@ + + + + + + Code coverage report for src/agent/cleanup-manager.ts + + + + + + + + + +
+
+

All files / src/agent cleanup-manager.ts

+
+ +
+ 10.32% + Statements + 22/213 +
+ + +
+ 2.06% + Branches + 2/97 +
+ + +
+ 23.8% + Functions + 5/21 +
+ + +
+ 10.47% + Lines + 22/210 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+

+
1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 +30 +31 +32 +33 +34 +35 +36 +37 +38 +39 +40 +41 +42 +43 +44 +45 +46 +47 +48 +49 +50 +51 +52 +53 +54 +55 +56 +57 +58 +59 +60 +61 +62 +63 +64 +65 +66 +67 +68 +69 +70 +71 +72 +73 +74 +75 +76 +77 +78 +79 +80 +81 +82 +83 +84 +85 +86 +87 +88 +89 +90 +91 +92 +93 +94 +95 +96 +97 +98 +99 +100 +101 +102 +103 +104 +105 +106 +107 +108 +109 +110 +111 +112 +113 +114 +115 +116 +117 +118 +119 +120 +121 +122 +123 +124 +125 +126 +127 +128 +129 +130 +131 +132 +133 +134 +135 +136 +137 +138 +139 +140 +141 +142 +143 +144 +145 +146 +147 +148 +149 +150 +151 +152 +153 +154 +155 +156 +157 +158 +159 +160 +161 +162 +163 +164 +165 +166 +167 +168 +169 +170 +171 +172 +173 +174 +175 +176 +177 +178 +179 +180 +181 +182 +183 +184 +185 +186 +187 +188 +189 +190 +191 +192 +193 +194 +195 +196 +197 +198 +199 +200 +201 +202 +203 +204 +205 +206 +207 +208 +209 +210 +211 +212 +213 +214 +215 +216 +217 +218 +219 +220 +221 +222 +223 +224 +225 +226 +227 +228 +229 +230 +231 +232 +233 +234 +235 +236 +237 +238 +239 +240 +241 +242 +243 +244 +245 +246 +247 +248 +249 +250 +251 +252 +253 +254 +255 +256 +257 +258 +259 +260 +261 +262 +263 +264 +265 +266 +267 +268 +269 +270 +271 +272 +273 +274 +275 +276 +277 +278 +279 +280 +281 +282 +283 +284 +285 +286 +287 +288 +289 +290 +291 +292 +293 +294 +295 +296 +297 +298 +299 +300 +301 +302 +303 +304 +305 +306 +307 +308 +309 +310 +311 +312 +313 +314 +315 +316 +317 +318 +319 +320 +321 +322 +323 +324 +325 +326 +327 +328 +329 +330 +331 +332 +333 +334 +335 +336 +337 +338 +339 +340 +341 +342 +343 +344 +345 +346 +347 +348 +349 +350 +351 +352 +353 +354 +355 +356 +357 +358 +359 +360 +361 +362 +363 +364 +365 +366 +367 +368 +369 +370 +371 +372 +373 +374 +375 +376 +377 +378 +379 +380 +381 +382 +383 +384 +385 +386 +387 +388 +389 +390 +391 +392 +393 +394 +395 +396 +397 +398 +399 +400 +401 +402 +403 +404 +405 +406 +407 +408 +409 +410 +411 +412 +413 +414 +415 +416 +417 +418 +419 +420 +421 +422 +423 +424 +425 +426 +427 +428 +429 +430 +431 +432 +433 +434 +435 +436 +437 +438 +439 +440 +441 +442 +443 +444 +445 +446 +447 +448 +449 +450 +451 +452 +453 +454 +455 +456 +457 +458 +459 +460 +461 +462 +463 +464 +465 +466 +467 +468 +469 +470 +471 +472 +473 +474 +475 +476 +477 +478 +479 +480 +481 +482 +483 +484 +485 +486 +487 +488 +489 +490 +491 +492 +493 +494 +495 +496 +497 +498 +499 +500 +501 +502 +503 +504 +505 +506 +507 +508 +509 +510 +511 +512 +513 +514 +515 +516 +517 +518 +519 +520 +521 +522 +523 +524 +525 +526 +527  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +15x +15x +  +  +  +23x +23x +23x +23x +23x +23x +  +  +  +  +  +  +3x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +3x +  +3x +3x +  +3x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +3x +3x +  +3x +  +  +  +  +  +3x +  +  +3x +3x +3x +  +  +  +  +  +  +  +  +  +  +3x +3x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  + 
/**
+ * CleanupManager — Worktree, branch, and log cleanup for agents.
+ *
+ * Extracted from MultiProviderAgentManager. Handles all filesystem
+ * and git cleanup operations, plus orphan detection and reconciliation.
+ */
+ 
+import { promisify } from 'node:util';
+import { execFile } from 'node:child_process';
+import { readFile, readdir, rm, cp, mkdir } from 'node:fs/promises';
+import { existsSync } from 'node:fs';
+import { join } from 'node:path';
+import type { AgentRepository } from '../db/repositories/agent-repository.js';
+import type { ProjectRepository } from '../db/repositories/project-repository.js';
+import type { EventBus, AgentCrashedEvent } from '../events/index.js';
+import { createModuleLogger } from '../logger/index.js';
+import { SimpleGitWorktreeManager } from '../git/manager.js';
+import { getProjectCloneDir } from '../git/project-clones.js';
+import { getStreamParser } from './providers/parsers/index.js';
+import { FileTailer } from './file-tailer.js';
+import { getProvider } from './providers/registry.js';
+import type { StreamEvent } from './providers/parsers/index.js';
+import type { SignalManager } from './lifecycle/signal-manager.js';
+import { isPidAlive } from './process-manager.js';
+ 
+const log = createModuleLogger('cleanup-manager');
+const execFileAsync = promisify(execFile);
+ 
+export class CleanupManager {
+  constructor(
+    private workspaceRoot: string,
+    private repository: AgentRepository,
+    private projectRepository: ProjectRepository,
+    private eventBus?: EventBus,
+    private debug: boolean = false,
+    private signalManager?: SignalManager,
+  ) {}
+ 
+  /**
+   * Resolve the agent's working directory path.
+   */
+  private getAgentWorkdir(alias: string): string {
+    return join(this.workspaceRoot, 'agent-workdirs', alias);
+  }
+ 
+  /**
+   * Resolve the actual working directory for an agent, probing for the
+   * workspace/ subdirectory used by standalone agents.
+   */
+  private resolveAgentCwd(worktreeId: string): string {
+    const base = this.getAgentWorkdir(worktreeId);
+    const workspaceSub = join(base, 'workspace');
+    if (!existsSync(join(base, '.cw', 'output')) && existsSync(join(workspaceSub, '.cw'))) {
+      return workspaceSub;
+    }
+    return base;
+  }
+ 
+  /**
+   * Remove git worktrees for an agent.
+   * Handles both initiative-linked (multi-project) and standalone agents.
+   */
+  async removeAgentWorktrees(alias: string, initiativeId: string | null): Promise<void> {
+    const agentWorkdir = this.getAgentWorkdir(alias);
+ 
+    try {
+      await readdir(agentWorkdir);
+    } catch {
+      return;
+    }
+ 
+    if (initiativeId) {
+      const projects = await this.projectRepository.findProjectsByInitiativeId(initiativeId);
+      for (const project of projects) {
+        try {
+          const clonePath = join(this.workspaceRoot, getProjectCloneDir(project.name, project.id));
+          const wm = new SimpleGitWorktreeManager(clonePath, undefined, agentWorkdir);
+          await wm.remove(project.name);
+        } catch (err) {
+          log.warn({ alias, project: project.name, err: err instanceof Error ? err.message : String(err) }, 'failed to remove project worktree');
+        }
+      }
+    } else {
+      try {
+        const wm = new SimpleGitWorktreeManager(this.workspaceRoot, undefined, agentWorkdir);
+        await wm.remove('workspace');
+      } catch (err) {
+        log.warn({ alias, err: err instanceof Error ? err.message : String(err) }, 'failed to remove standalone worktree');
+      }
+    }
+ 
+    await rm(agentWorkdir, { recursive: true, force: true });
+    await this.pruneWorktrees(initiativeId);
+  }
+ 
+  /**
+   * Delete agent/<alias> branches from all relevant repos.
+   */
+  async removeAgentBranches(alias: string, initiativeId: string | null): Promise<void> {
+    const branchName = `agent/${alias}`;
+    const repoPaths: string[] = [];
+ 
+    Iif (initiativeId) {
+      const projects = await this.projectRepository.findProjectsByInitiativeId(initiativeId);
+      for (const project of projects) {
+        repoPaths.push(join(this.workspaceRoot, getProjectCloneDir(project.name, project.id)));
+      }
+    } else {
+      repoPaths.push(this.workspaceRoot);
+    }
+ 
+    for (const repoPath of repoPaths) {
+      try {
+        await execFileAsync('git', ['branch', '-D', branchName], { cwd: repoPath });
+      } catch {
+        // Branch may not exist
+      }
+    }
+  }
+ 
+  /**
+   * Remove log directory for an agent.
+   */
+  async removeAgentLogs(agentName: string): Promise<void> {
+    const logDir = join(this.workspaceRoot, '.cw', 'agent-logs', agentName);
+    await rm(logDir, { recursive: true, force: true });
+  }
+ 
+  /**
+   * Run git worktree prune on all relevant repos.
+   */
+  async pruneWorktrees(initiativeId: string | null): Promise<void> {
+    const repoPaths: string[] = [];
+ 
+    if (initiativeId) {
+      const projects = await this.projectRepository.findProjectsByInitiativeId(initiativeId);
+      for (const project of projects) {
+        repoPaths.push(join(this.workspaceRoot, getProjectCloneDir(project.name, project.id)));
+      }
+    } else {
+      repoPaths.push(this.workspaceRoot);
+    }
+ 
+    for (const repoPath of repoPaths) {
+      try {
+        await execFileAsync('git', ['worktree', 'prune'], { cwd: repoPath });
+      } catch (err) {
+        log.warn({ repoPath, err: err instanceof Error ? err.message : String(err) }, 'failed to prune worktrees');
+      }
+    }
+  }
+ 
+  /**
+   * Clean up orphaned agent workdirs (directories with no matching DB agent).
+   */
+  async cleanupOrphanedWorkdirs(): Promise<void> {
+    const workdirsPath = join(this.workspaceRoot, 'agent-workdirs');
+    let entries: string[];
+    try {
+      entries = await readdir(workdirsPath);
+    } catch {
+      return;
+    }
+ 
+    const agents = await this.repository.findAll();
+    const knownAliases = new Set(agents.map(a => a.name));
+ 
+    for (const entry of entries) {
+      if (!knownAliases.has(entry)) {
+        log.info({ orphan: entry }, 'removing orphaned agent workdir');
+        try {
+          await rm(join(workdirsPath, entry), { recursive: true, force: true });
+        } catch (err) {
+          log.warn({ orphan: entry, err: err instanceof Error ? err.message : String(err) }, 'failed to remove orphaned workdir');
+        }
+      }
+    }
+ 
+    try {
+      await execFileAsync('git', ['worktree', 'prune'], { cwd: this.workspaceRoot });
+    } catch { /* ignore */ }
+ 
+    const reposPath = join(this.workspaceRoot, 'repos');
+    try {
+      const repoDirs = await readdir(reposPath);
+      for (const repoDir of repoDirs) {
+        try {
+          await execFileAsync('git', ['worktree', 'prune'], { cwd: join(reposPath, repoDir) });
+        } catch { /* ignore */ }
+      }
+    } catch { /* no repos dir */ }
+  }
+ 
+  /**
+   * Clean up orphaned agent log directories (directories with no matching DB agent).
+   */
+  async cleanupOrphanedLogs(): Promise<void> {
+    const logsPath = join(this.workspaceRoot, '.cw', 'agent-logs');
+    let entries: string[];
+    try {
+      entries = await readdir(logsPath);
+    } catch {
+      return;
+    }
+ 
+    const agents = await this.repository.findAll();
+    const knownNames = new Set(agents.map(a => a.name));
+ 
+    for (const entry of entries) {
+      if (!knownNames.has(entry)) {
+        log.info({ orphan: entry }, 'removing orphaned agent log dir');
+        try {
+          await rm(join(logsPath, entry), { recursive: true, force: true });
+        } catch (err) {
+          log.warn({ orphan: entry, err: err instanceof Error ? err.message : String(err) }, 'failed to remove orphaned log dir');
+        }
+      }
+    }
+  }
+ 
+  /**
+   * Get the relative subdirectory names of dirty worktrees for an agent.
+   * Returns an empty array if all worktrees are clean or the workdir doesn't exist.
+   */
+  async getDirtyWorktreePaths(alias: string, initiativeId: string | null): Promise<string[]> {
+    const agentWorkdir = this.getAgentWorkdir(alias);
+ 
+    try {
+      await readdir(agentWorkdir);
+    } catch {
+      return [];
+    }
+ 
+    const worktreePaths: { absPath: string; name: string }[] = [];
+ 
+    if (initiativeId) {
+      const projects = await this.projectRepository.findProjectsByInitiativeId(initiativeId);
+      for (const project of projects) {
+        worktreePaths.push({ absPath: join(agentWorkdir, project.name), name: project.name });
+      }
+    } else {
+      worktreePaths.push({ absPath: join(agentWorkdir, 'workspace'), name: 'workspace' });
+    }
+ 
+    const dirty: string[] = [];
+    for (const { absPath, name } of worktreePaths) {
+      try {
+        const { stdout } = await execFileAsync('git', ['status', '--porcelain'], { cwd: absPath });
+        if (stdout.trim().length > 0) dirty.push(name);
+      } catch {
+        dirty.push(name);
+      }
+    }
+    return dirty;
+  }
+ 
+  /**
+   * Check if all project worktrees for an agent are clean (no uncommitted/untracked files).
+   */
+  async isWorkdirClean(alias: string, initiativeId: string | null): Promise<boolean> {
+    const dirty = await this.getDirtyWorktreePaths(alias, initiativeId);
+    if (dirty.length > 0) {
+      log.info({ alias, dirtyWorktrees: dirty }, 'workdir has uncommitted changes');
+    }
+    return dirty.length === 0;
+  }
+ 
+  /**
+   * Archive agent workdir and logs to .cw/debug/ before removal.
+   */
+  async archiveForDebug(alias: string, agentId: string): Promise<void> {
+    const agentWorkdir = this.getAgentWorkdir(alias);
+    const debugWorkdir = join(this.workspaceRoot, '.cw', 'debug', 'workdirs', alias);
+    const logDir = join(this.workspaceRoot, '.cw', 'agent-logs', alias);
+    const debugLogDir = join(this.workspaceRoot, '.cw', 'debug', 'agent-logs', alias);
+ 
+    try {
+      if (existsSync(agentWorkdir)) {
+        await mkdir(join(this.workspaceRoot, '.cw', 'debug', 'workdirs'), { recursive: true });
+        await cp(agentWorkdir, debugWorkdir, { recursive: true });
+        log.debug({ alias, debugWorkdir }, 'archived workdir for debug');
+      }
+    } catch (err) {
+      log.warn({ alias, err: err instanceof Error ? err.message : String(err) }, 'failed to archive workdir for debug');
+    }
+ 
+    try {
+      if (existsSync(logDir)) {
+        await mkdir(join(this.workspaceRoot, '.cw', 'debug', 'agent-logs'), { recursive: true });
+        await cp(logDir, debugLogDir, { recursive: true });
+        log.debug({ agentId, debugLogDir }, 'archived logs for debug');
+      }
+    } catch (err) {
+      log.warn({ agentId, err: err instanceof Error ? err.message : String(err) }, 'failed to archive logs for debug');
+    }
+  }
+ 
+  /**
+   * Auto-cleanup agent workdir after successful completion.
+   * Removes worktrees and logs but preserves branches and DB record.
+   */
+  async autoCleanupAfterCompletion(
+    agentId: string,
+    alias: string,
+    initiativeId: string | null,
+  ): Promise<{ clean: boolean; removed: boolean }> {
+    const agentWorkdir = this.getAgentWorkdir(alias);
+ 
+    // Idempotent: if workdir is already gone, nothing to do
+    if (!existsSync(agentWorkdir)) {
+      return { clean: true, removed: true };
+    }
+ 
+    const clean = await this.isWorkdirClean(alias, initiativeId);
+    if (!clean) {
+      return { clean: false, removed: false };
+    }
+ 
+    if (this.debug) {
+      await this.archiveForDebug(alias, agentId);
+    }
+ 
+    try {
+      await this.removeAgentWorktrees(alias, initiativeId);
+    } catch (err) {
+      log.warn({ agentId, alias, err: err instanceof Error ? err.message : String(err) }, 'auto-cleanup: failed to remove worktrees');
+    }
+ 
+    try {
+      await this.removeAgentLogs(alias);
+    } catch (err) {
+      log.warn({ agentId, err: err instanceof Error ? err.message : String(err) }, 'auto-cleanup: failed to remove logs');
+    }
+ 
+    log.info({ agentId, alias }, 'auto-cleanup: workdir and logs removed');
+    return { clean: true, removed: true };
+  }
+ 
+  /**
+   * Reconcile agent state after server restart.
+   * Checks all agents in 'running' status:
+   * - If PID is still alive: create FileTailer to resume streaming
+   * - If PID is dead but output file exists: process the output
+   * - Otherwise: mark as crashed
+   *
+   * @param activeAgents - Shared map from manager to register live agents
+   * @param onStreamEvent - Callback for stream events from tailer
+   * @param onAgentOutput - Callback to process raw agent output
+   * @param pollForCompletion - Callback to start polling for completion
+   */
+  async reconcileAfterRestart(
+    activeAgents: Map<string, {
+      agentId: string;
+      pid: number;
+      tailer: FileTailer;
+      outputFilePath: string;
+      agentCwd?: string;
+    }>,
+    onStreamEvent: (agentId: string, event: StreamEvent) => void,
+    onAgentOutput: (agentId: string, rawOutput: string, provider: NonNullable<ReturnType<typeof getProvider>>) => Promise<void>,
+    pollForCompletion: (agentId: string, pid: number) => void,
+    onRawContent?: (agentId: string, agentName: string, content: string) => void,
+  ): Promise<void> {
+    const runningAgents = await this.repository.findByStatus('running');
+    log.info({ runningCount: runningAgents.length }, 'reconciling agents after restart');
+ 
+    for (const agent of runningAgents) {
+      const alive = agent.pid ? isPidAlive(agent.pid) : false;
+      log.info({ agentId: agent.id, pid: agent.pid, alive }, 'reconcile: checking agent');
+ 
+      if (alive && agent.outputFilePath) {
+        log.debug({ agentId: agent.id, pid: agent.pid }, 'reconcile: resuming streaming for alive agent');
+ 
+        const parser = getStreamParser(agent.provider);
+        const tailer = new FileTailer({
+          filePath: agent.outputFilePath,
+          agentId: agent.id,
+          parser,
+          onEvent: (event) => onStreamEvent(agent.id, event),
+          startFromBeginning: false,
+          onRawContent: onRawContent
+            ? (content) => onRawContent(agent.id, agent.name, content)
+            : undefined,
+        });
+ 
+        tailer.start().catch((err) => {
+          log.warn({ agentId: agent.id, err: err instanceof Error ? err.message : String(err) }, 'failed to start tailer during reconcile');
+        });
+ 
+        const pid = agent.pid!;
+ 
+        // Resolve actual agent cwd — standalone agents run in workspace/ subdir
+        const resolvedCwd = this.resolveAgentCwd(agent.worktreeId);
+ 
+        activeAgents.set(agent.id, {
+          agentId: agent.id,
+          pid,
+          tailer,
+          outputFilePath: agent.outputFilePath,
+          agentCwd: resolvedCwd,
+        });
+ 
+        pollForCompletion(agent.id, pid);
+      } else if (agent.outputFilePath) {
+        // CRITICAL FIX: Check for signal.json completion FIRST before parsing raw output
+        // Resolve actual agent cwd — standalone agents run in workspace/ subdir
+        const agentWorkdir = this.resolveAgentCwd(agent.worktreeId);
+        const hasValidSignal = this.signalManager ? await this.signalManager.readSignal(agentWorkdir) : null;
+ 
+        if (hasValidSignal) {
+          log.debug({ agentId: agent.id }, 'found valid signal.json, processing as completion');
+          try {
+            const signalFile = join(agentWorkdir, '.cw/output/signal.json');
+            const signalContent = await readFile(signalFile, 'utf-8');
+            const provider = getProvider(agent.provider);
+            if (provider) {
+              await onAgentOutput(agent.id, signalContent, provider);
+              continue;
+            }
+          } catch (err) {
+            log.error({
+              agentId: agent.id,
+              err: err instanceof Error ? err.message : String(err)
+            }, 'reconcile: failed to process signal.json');
+            // Fall through to raw output processing
+          }
+        }
+ 
+        try {
+          const rawOutput = await readFile(agent.outputFilePath, 'utf-8');
+          if (rawOutput.trim()) {
+            const provider = getProvider(agent.provider);
+            if (provider) {
+              // Check if agent actually completed successfully before processing
+              const hasCompletionResult = this.checkForCompletionResult(rawOutput);
+              if (hasCompletionResult) {
+                log.info({ agentId: agent.id }, 'reconcile: processing completed agent output');
+                try {
+                  await onAgentOutput(agent.id, rawOutput, provider);
+                  continue;
+                } catch (err) {
+                  log.error({
+                    agentId: agent.id,
+                    err: err instanceof Error ? err.message : String(err)
+                  }, 'reconcile: failed to process completed agent output');
+                  // Mark as crashed since processing failed
+                  await this.repository.update(agent.id, { status: 'crashed' });
+                  this.emitCrashed(agent, `Failed to process output: ${err instanceof Error ? err.message : String(err)}`);
+                  continue;
+                }
+              }
+            }
+          }
+        } catch (readErr) {
+          log.warn({
+            agentId: agent.id,
+            err: readErr instanceof Error ? readErr.message : String(readErr)
+          }, 'reconcile: failed to read output file');
+        }
+        log.warn({ agentId: agent.id }, 'reconcile: marking agent crashed (no valid output)');
+        await this.repository.update(agent.id, { status: 'crashed' });
+        this.emitCrashed(agent, 'Server restarted, agent output not found or invalid');
+      } else {
+        log.warn({ agentId: agent.id }, 'reconcile: marking agent crashed');
+        await this.repository.update(agent.id, { status: 'crashed' });
+        this.emitCrashed(agent, 'Server restarted while agent was running');
+      }
+    }
+ 
+    try {
+      await this.cleanupOrphanedWorkdirs();
+    } catch (err) {
+      log.warn({ err: err instanceof Error ? err.message : String(err) }, 'orphaned workdir cleanup failed');
+    }
+    try {
+      await this.cleanupOrphanedLogs();
+    } catch (err) {
+      log.warn({ err: err instanceof Error ? err.message : String(err) }, 'orphaned log cleanup failed');
+    }
+  }
+ 
+  /**
+   * Check if the agent output contains a completion result line.
+   * This indicates the agent finished successfully, even if processing fails.
+   */
+  private checkForCompletionResult(rawOutput: string): boolean {
+    try {
+      const lines = rawOutput.trim().split('\n');
+      for (const line of lines) {
+        try {
+          const parsed = JSON.parse(line);
+          // Look for Claude CLI result events with success status
+          if (parsed.type === 'result' && parsed.subtype === 'success') {
+            return true;
+          }
+          // Look for other providers' completion indicators
+          if (parsed.status === 'done' || parsed.status === 'questions') {
+            return true;
+          }
+        } catch { /* skip non-JSON lines */ }
+      }
+    } catch { /* invalid output format */ }
+    return false;
+  }
+ 
+  /**
+   * Emit a crashed event for an agent.
+   */
+  private emitCrashed(agent: { id: string; name: string; taskId: string | null }, error: string): void {
+    if (this.eventBus) {
+      const event: AgentCrashedEvent = {
+        type: 'agent:crashed',
+        timestamp: new Date(),
+        payload: {
+          agentId: agent.id,
+          name: agent.name,
+          taskId: agent.taskId ?? '',
+          error,
+        },
+      };
+      this.eventBus.emit(event);
+    }
+  }
+ 
+ 
+}
+ 
+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/coverage/src/agent/content-serializer.ts.html b/coverage/src/agent/content-serializer.ts.html new file mode 100644 index 0000000..d240c04 --- /dev/null +++ b/coverage/src/agent/content-serializer.ts.html @@ -0,0 +1,463 @@ + + + + + + Code coverage report for src/agent/content-serializer.ts + + + + + + + + + +
+
+

All files / src/agent content-serializer.ts

+
+ +
+ 4.76% + Statements + 2/42 +
+ + +
+ 0% + Branches + 0/24 +
+ + +
+ 0% + Functions + 0/7 +
+ + +
+ 5.26% + Lines + 2/38 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+

+
1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 +30 +31 +32 +33 +34 +35 +36 +37 +38 +39 +40 +41 +42 +43 +44 +45 +46 +47 +48 +49 +50 +51 +52 +53 +54 +55 +56 +57 +58 +59 +60 +61 +62 +63 +64 +65 +66 +67 +68 +69 +70 +71 +72 +73 +74 +75 +76 +77 +78 +79 +80 +81 +82 +83 +84 +85 +86 +87 +88 +89 +90 +91 +92 +93 +94 +95 +96 +97 +98 +99 +100 +101 +102 +103 +104 +105 +106 +107 +108 +109 +110 +111 +112 +113 +114 +115 +116 +117 +118 +119 +120 +121 +122 +123 +124 +125 +126 +127  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +21x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +21x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  + 
/**
+ * Content Serializer
+ *
+ * Converts Tiptap JSON page tree into markdown for agent prompts.
+ * Uses @tiptap/markdown's MarkdownManager for standard node serialization,
+ * with custom handling only for pageLink nodes.
+ */
+ 
+import { Node, type JSONContent } from '@tiptap/core';
+import StarterKit from '@tiptap/starter-kit';
+import Link from '@tiptap/extension-link';
+import { MarkdownManager } from '@tiptap/markdown';
+ 
+/**
+ * Minimal page shape needed for serialization.
+ */
+export interface PageForSerialization {
+  id: string;
+  parentPageId: string | null;
+  title: string;
+  content: string | null; // JSON string from Tiptap
+  sortOrder: number;
+}
+ 
+/**
+ * Server-side pageLink node — only needs schema definition + markdown rendering.
+ */
+const ServerPageLink = Node.create({
+  name: 'pageLink',
+  group: 'block',
+  atom: true,
+ 
+  addAttributes() {
+    return {
+      pageId: { default: null },
+    };
+  },
+ 
+  renderMarkdown(node: JSONContent) {
+    const pageId = (node.attrs?.pageId as string) ?? '';
+    return `[[page:${pageId}]]\n\n`;
+  },
+});
+ 
+let _manager: MarkdownManager | null = null;
+ 
+function getManager(): MarkdownManager {
+  if (!_manager) {
+    _manager = new MarkdownManager({
+      extensions: [StarterKit, Link, ServerPageLink],
+    });
+  }
+  return _manager;
+}
+ 
+/**
+ * Convert a Tiptap JSON document to markdown.
+ */
+export function tiptapJsonToMarkdown(json: unknown): string {
+  if (!json || typeof json !== 'object') return '';
+ 
+  const doc = json as JSONContent;
+  if (doc.type !== 'doc' || !Array.isArray(doc.content)) return '';
+ 
+  return getManager().serialize(doc).trim();
+}
+ 
+/**
+ * Serialize an array of pages into a single markdown document.
+ * Pages are organized as a tree (root first, then children by sortOrder).
+ *
+ * Each page is marked with <!-- page:$id --> so the agent can reference them.
+ */
+export function serializePageTree(pages: PageForSerialization[]): string {
+  if (pages.length === 0) return '';
+ 
+  // Build parent→children map
+  const childrenMap = new Map<string | null, PageForSerialization[]>();
+  for (const page of pages) {
+    const parentKey = page.parentPageId;
+    if (!childrenMap.has(parentKey)) {
+      childrenMap.set(parentKey, []);
+    }
+    childrenMap.get(parentKey)!.push(page);
+  }
+ 
+  // Sort children by sortOrder
+  for (const children of childrenMap.values()) {
+    children.sort((a, b) => a.sortOrder - b.sortOrder);
+  }
+ 
+  // Render tree depth-first
+  const sections: string[] = [];
+ 
+  function renderPage(page: PageForSerialization, depth: number): void {
+    const headerPrefix = '#'.repeat(Math.min(depth + 1, 6));
+    let section = `<!-- page:${page.id} -->\n${headerPrefix} ${page.title}`;
+ 
+    if (page.content) {
+      try {
+        const parsed = JSON.parse(page.content);
+        const md = tiptapJsonToMarkdown(parsed);
+        if (md.trim()) {
+          section += `\n\n${md}`;
+        }
+      } catch {
+        // Invalid JSON — skip content
+      }
+    }
+ 
+    sections.push(section);
+ 
+    const children = childrenMap.get(page.id) ?? [];
+    for (const child of children) {
+      renderPage(child, depth + 1);
+    }
+  }
+ 
+  // Start from root pages (parentPageId is null)
+  const roots = childrenMap.get(null) ?? [];
+  for (const root of roots) {
+    renderPage(root, 1);
+  }
+ 
+  return sections.join('\n\n');
+}
+ 
+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/coverage/src/agent/credential-handler.ts.html b/coverage/src/agent/credential-handler.ts.html new file mode 100644 index 0000000..3e92c7b --- /dev/null +++ b/coverage/src/agent/credential-handler.ts.html @@ -0,0 +1,709 @@ + + + + + + Code coverage report for src/agent/credential-handler.ts + + + + + + + + + +
+
+

All files / src/agent credential-handler.ts

+
+ +
+ 13.58% + Statements + 11/81 +
+ + +
+ 7.69% + Branches + 3/39 +
+ + +
+ 30% + Functions + 3/10 +
+ + +
+ 13.33% + Lines + 10/75 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+

+
1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 +30 +31 +32 +33 +34 +35 +36 +37 +38 +39 +40 +41 +42 +43 +44 +45 +46 +47 +48 +49 +50 +51 +52 +53 +54 +55 +56 +57 +58 +59 +60 +61 +62 +63 +64 +65 +66 +67 +68 +69 +70 +71 +72 +73 +74 +75 +76 +77 +78 +79 +80 +81 +82 +83 +84 +85 +86 +87 +88 +89 +90 +91 +92 +93 +94 +95 +96 +97 +98 +99 +100 +101 +102 +103 +104 +105 +106 +107 +108 +109 +110 +111 +112 +113 +114 +115 +116 +117 +118 +119 +120 +121 +122 +123 +124 +125 +126 +127 +128 +129 +130 +131 +132 +133 +134 +135 +136 +137 +138 +139 +140 +141 +142 +143 +144 +145 +146 +147 +148 +149 +150 +151 +152 +153 +154 +155 +156 +157 +158 +159 +160 +161 +162 +163 +164 +165 +166 +167 +168 +169 +170 +171 +172 +173 +174 +175 +176 +177 +178 +179 +180 +181 +182 +183 +184 +185 +186 +187 +188 +189 +190 +191 +192 +193 +194 +195 +196 +197 +198 +199 +200 +201 +202 +203 +204 +205 +206 +207 +208 +209  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +15x +  +  +15x +  +  +  +23x +23x +23x +  +  +  +  +  +  +  +  +8x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +10x +10x +  +10x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +10x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  + 
/**
+ * CredentialHandler — Account selection, credential management, and exhaustion handling.
+ *
+ * Extracted from MultiProviderAgentManager. Handles account lifecycle:
+ * selecting the next available account, writing credentials to disk,
+ * ensuring they're fresh, and marking accounts as exhausted on failure.
+ */
+ 
+import { readFileSync, existsSync } from 'node:fs';
+import { join } from 'node:path';
+import type { AccountRepository } from '../db/repositories/account-repository.js';
+import type { AccountCredentialManager } from './credentials/types.js';
+import type { Account } from '../db/schema.js';
+import { ensureAccountCredentials } from './accounts/usage.js';
+import { getAccountConfigDir } from './accounts/paths.js';
+import { setupAccountConfigDir } from './accounts/setup.js';
+import { createModuleLogger } from '../logger/index.js';
+ 
+const log = createModuleLogger('credential-handler');
+ 
+/** Default exhaustion duration: 5 hours */
+const DEFAULT_EXHAUSTION_HOURS = 5;
+ 
+export class CredentialHandler {
+  constructor(
+    private workspaceRoot: string,
+    private accountRepository?: AccountRepository,
+    private credentialManager?: AccountCredentialManager,
+  ) {}
+ 
+  /**
+   * Select the next available account for a provider.
+   * Clears expired exhaustion, returns least-recently-used non-exhausted account.
+   * Returns null if no accounts are available.
+   */
+  async selectAccount(providerName: string): Promise<{ account: Account; accountId: string; configDir: string } | null> {
+    Eif (!this.accountRepository) return null;
+ 
+    await this.accountRepository.clearExpiredExhaustion();
+    const account = await this.accountRepository.findNextAvailable(providerName);
+    if (!account) return null;
+ 
+    const configDir = getAccountConfigDir(this.workspaceRoot, account.id);
+    await this.accountRepository.updateLastUsed(account.id);
+ 
+    return { account, accountId: account.id, configDir };
+  }
+ 
+  /**
+   * Write account credentials from DB to the convention-based config directory.
+   * Must be called before ensureCredentials so the files exist on disk.
+   */
+  writeCredentialsToDisk(account: Account, configDir: string): void {
+    if (account.configJson && account.credentials) {
+      setupAccountConfigDir(configDir, {
+        configJson: JSON.parse(account.configJson),
+        credentials: account.credentials,
+      });
+      log.debug({ accountId: account.id, configDir }, 'wrote account credentials from DB to disk');
+    } else {
+      log.warn({ accountId: account.id }, 'account has no stored credentials in DB');
+    }
+  }
+ 
+  /**
+   * Read refreshed credentials from disk and persist back to DB.
+   * Called after credential refresh to keep DB in sync.
+   */
+  async persistRefreshedCredentials(accountId: string, configDir: string): Promise<void> {
+    if (!this.accountRepository) return;
+    try {
+      const credPath = join(configDir, '.credentials.json');
+      const credentials = readFileSync(credPath, 'utf-8');
+      await this.accountRepository.updateCredentials(accountId, credentials);
+      log.debug({ accountId }, 'persisted refreshed credentials back to DB');
+    } catch (err) {
+      log.warn({ accountId, err: err instanceof Error ? err.message : String(err) }, 'failed to persist refreshed credentials to DB');
+    }
+  }
+ 
+  /**
+   * Ensure credentials are valid before spawn/resume.
+   * Uses credentialManager if available, otherwise falls back to legacy function.
+   * Returns { valid, refreshed } so callers can persist refresh back to DB.
+   */
+  async ensureCredentials(configDir: string, accountId?: string): Promise<{ valid: boolean; refreshed: boolean }> {
+    if (this.credentialManager) {
+      const result = await this.credentialManager.ensureValid(configDir, accountId);
+      return { valid: result.valid, refreshed: result.refreshed };
+    }
+    const valid = await ensureAccountCredentials(configDir);
+    return { valid, refreshed: false };
+  }
+ 
+  /**
+   * Read the access token from a config directory's .credentials.json.
+   * Returns null if credentials file is missing or malformed.
+   * Used for CLAUDE_CODE_OAUTH_TOKEN env var injection.
+   */
+  readAccessToken(configDir: string): string | null {
+    try {
+      const credPath = join(configDir, '.credentials.json');
+      if (!existsSync(credPath)) return null;
+      const raw = readFileSync(credPath, 'utf-8');
+      const parsed = JSON.parse(raw);
+      return parsed.claudeAiOauth?.accessToken ?? null;
+    } catch {
+      return null;
+    }
+  }
+ 
+  /**
+   * Prepare process environment with account credentials.
+   * Writes credentials to disk, ensures freshness, injects OAuth token.
+   * Used by spawn, resumeForCommit, and resumeInternal.
+   */
+  async prepareProcessEnv(
+    providerEnv: Record<string, string>,
+    provider: { configDirEnv?: string },
+    accountId: string | null,
+  ): Promise<{ processEnv: Record<string, string>; accountConfigDir: string | null }> {
+    const processEnv: Record<string, string> = { ...providerEnv };
+    let accountConfigDir: string | null = null;
+ 
+    Iif (accountId && provider.configDirEnv && this.accountRepository) {
+      accountConfigDir = getAccountConfigDir(this.workspaceRoot, accountId);
+      const account = await this.accountRepository.findById(accountId);
+      if (account) {
+        this.writeCredentialsToDisk(account, accountConfigDir);
+      }
+      processEnv[provider.configDirEnv] = accountConfigDir;
+ 
+      const { valid, refreshed } = await this.ensureCredentials(accountConfigDir, accountId);
+      if (!valid) {
+        log.warn({ accountId }, 'failed to refresh credentials');
+      }
+      if (refreshed) {
+        await this.persistRefreshedCredentials(accountId, accountConfigDir);
+      }
+ 
+      const accessToken = this.readAccessToken(accountConfigDir);
+      if (accessToken) {
+        processEnv['CLAUDE_CODE_OAUTH_TOKEN'] = accessToken;
+        log.debug({ accountId }, 'CLAUDE_CODE_OAUTH_TOKEN injected');
+      }
+    }
+ 
+    return { processEnv, accountConfigDir };
+  }
+ 
+  /**
+   * Check if an error message indicates usage limit exhaustion.
+   */
+  isUsageLimitError(errorMessage: string): boolean {
+    const patterns = [
+      'usage limit',
+      'rate limit',
+      'quota exceeded',
+      'too many requests',
+      'capacity',
+      'exhausted',
+    ];
+    const lower = errorMessage.toLowerCase();
+    return patterns.some((p) => lower.includes(p));
+  }
+ 
+  /**
+   * Handle account exhaustion: mark current account exhausted and find next available.
+   * Returns the new account info if failover succeeded, null otherwise.
+   * Does NOT re-spawn — the caller (manager) handles that.
+   */
+  async handleExhaustion(
+    accountId: string,
+    providerName: string,
+  ): Promise<{ account: Account; accountId: string; configDir: string } | null> {
+    if (!this.accountRepository) return null;
+ 
+    log.warn({ accountId, provider: providerName }, 'account exhausted, attempting failover');
+ 
+    // Mark current account as exhausted
+    const exhaustedUntil = new Date(Date.now() + DEFAULT_EXHAUSTION_HOURS * 60 * 60 * 1000);
+    await this.accountRepository.markExhausted(accountId, exhaustedUntil);
+ 
+    // Find next available account
+    const nextAccount = await this.accountRepository.findNextAvailable(providerName);
+    if (!nextAccount) {
+      log.warn({ accountId }, 'account failover failed, no accounts available');
+      return null;
+    }
+    log.info({ previousAccountId: accountId, newAccountId: nextAccount.id }, 'account failover successful');
+ 
+    // Write credentials and ensure they're fresh
+    const nextConfigDir = getAccountConfigDir(this.workspaceRoot, nextAccount.id);
+    this.writeCredentialsToDisk(nextAccount, nextConfigDir);
+    const { valid, refreshed } = await this.ensureCredentials(nextConfigDir, nextAccount.id);
+    if (!valid) {
+      log.warn({ newAccountId: nextAccount.id }, 'failed to refresh failover account credentials');
+      return null;
+    }
+    if (refreshed) {
+      await this.persistRefreshedCredentials(nextAccount.id, nextConfigDir);
+    }
+ 
+    await this.accountRepository.updateLastUsed(nextAccount.id);
+ 
+    return { account: nextAccount, accountId: nextAccount.id, configDir: nextConfigDir };
+  }
+}
+ 
+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/coverage/src/agent/credentials/default-credential-manager.ts.html b/coverage/src/agent/credentials/default-credential-manager.ts.html new file mode 100644 index 0000000..23cb24c --- /dev/null +++ b/coverage/src/agent/credentials/default-credential-manager.ts.html @@ -0,0 +1,1075 @@ + + + + + + Code coverage report for src/agent/credentials/default-credential-manager.ts + + + + + + + + + +
+
+

All files / src/agent/credentials default-credential-manager.ts

+
+ +
+ 4.34% + Statements + 4/92 +
+ + +
+ 0% + Branches + 0/50 +
+ + +
+ 0% + Functions + 0/10 +
+ + +
+ 4.65% + Lines + 4/86 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+

+
1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 +30 +31 +32 +33 +34 +35 +36 +37 +38 +39 +40 +41 +42 +43 +44 +45 +46 +47 +48 +49 +50 +51 +52 +53 +54 +55 +56 +57 +58 +59 +60 +61 +62 +63 +64 +65 +66 +67 +68 +69 +70 +71 +72 +73 +74 +75 +76 +77 +78 +79 +80 +81 +82 +83 +84 +85 +86 +87 +88 +89 +90 +91 +92 +93 +94 +95 +96 +97 +98 +99 +100 +101 +102 +103 +104 +105 +106 +107 +108 +109 +110 +111 +112 +113 +114 +115 +116 +117 +118 +119 +120 +121 +122 +123 +124 +125 +126 +127 +128 +129 +130 +131 +132 +133 +134 +135 +136 +137 +138 +139 +140 +141 +142 +143 +144 +145 +146 +147 +148 +149 +150 +151 +152 +153 +154 +155 +156 +157 +158 +159 +160 +161 +162 +163 +164 +165 +166 +167 +168 +169 +170 +171 +172 +173 +174 +175 +176 +177 +178 +179 +180 +181 +182 +183 +184 +185 +186 +187 +188 +189 +190 +191 +192 +193 +194 +195 +196 +197 +198 +199 +200 +201 +202 +203 +204 +205 +206 +207 +208 +209 +210 +211 +212 +213 +214 +215 +216 +217 +218 +219 +220 +221 +222 +223 +224 +225 +226 +227 +228 +229 +230 +231 +232 +233 +234 +235 +236 +237 +238 +239 +240 +241 +242 +243 +244 +245 +246 +247 +248 +249 +250 +251 +252 +253 +254 +255 +256 +257 +258 +259 +260 +261 +262 +263 +264 +265 +266 +267 +268 +269 +270 +271 +272 +273 +274 +275 +276 +277 +278 +279 +280 +281 +282 +283 +284 +285 +286 +287 +288 +289 +290 +291 +292 +293 +294 +295 +296 +297 +298 +299 +300 +301 +302 +303 +304 +305 +306 +307 +308 +309 +310 +311 +312 +313 +314 +315 +316 +317 +318 +319 +320 +321 +322 +323 +324 +325 +326 +327 +328 +329 +330 +331  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +8x +  +  +8x +  +  +8x +  +  +8x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  + 
/**
+ * Default Account Credential Manager
+ *
+ * File-based adapter implementing AccountCredentialManager port.
+ * Reads/writes credentials from ~/.cw/accounts/<uuid>/.credentials.json
+ * and emits events on credential state changes.
+ */
+ 
+import { readFileSync, existsSync, writeFileSync, mkdirSync } from 'node:fs';
+import { join, dirname } from 'node:path';
+import type { EventBus } from '../../events/index.js';
+import type {
+  AccountCredentialManager,
+  OAuthCredentials,
+  RefreshResult,
+  CredentialValidationResult,
+} from './types.js';
+import type {
+  AccountCredentialsRefreshedEvent,
+  AccountCredentialsExpiredEvent,
+  AccountCredentialsValidatedEvent,
+} from '../../events/types.js';
+import { createModuleLogger } from '../../logger/index.js';
+ 
+const log = createModuleLogger('credential-manager');
+ 
+/** Anthropic OAuth token refresh endpoint */
+const TOKEN_REFRESH_URL = 'https://console.anthropic.com/v1/oauth/token';
+ 
+/** OAuth client ID for Claude CLI */
+const OAUTH_CLIENT_ID = '9d1c250a-e61b-44d9-88ed-5944d1962f5e';
+ 
+/** Buffer before expiry to trigger refresh (5 minutes) */
+const TOKEN_REFRESH_BUFFER_MS = 300_000;
+ 
+/**
+ * DefaultAccountCredentialManager - File-based credential management with event emission.
+ *
+ * Implements the AccountCredentialManager port for managing OAuth credentials
+ * stored in account config directories.
+ */
+export class DefaultAccountCredentialManager implements AccountCredentialManager {
+  constructor(private eventBus?: EventBus) {}
+ 
+  /**
+   * Read credentials from a config directory.
+   */
+  read(configDir: string): OAuthCredentials | null {
+    try {
+      const credPath = join(configDir, '.credentials.json');
+      if (!existsSync(credPath)) return null;
+ 
+      const raw = readFileSync(credPath, 'utf-8');
+      const parsed = JSON.parse(raw);
+      const oauth = parsed.claudeAiOauth;
+ 
+      if (!oauth || !oauth.accessToken) return null;
+ 
+      return {
+        accessToken: oauth.accessToken,
+        refreshToken: oauth.refreshToken ?? null,
+        expiresAt: oauth.expiresAt ?? null,
+        subscriptionType: oauth.subscriptionType ?? null,
+        rateLimitTier: oauth.rateLimitTier ?? null,
+      };
+    } catch {
+      return null;
+    }
+  }
+ 
+  /**
+   * Check if credentials are expired or about to expire.
+   */
+  isExpired(credentials: OAuthCredentials): boolean {
+    if (!credentials.expiresAt) return false; // Setup tokens without expiry are treated as non-expired
+    return credentials.expiresAt < Date.now() + TOKEN_REFRESH_BUFFER_MS;
+  }
+ 
+  /**
+   * Refresh an access token using the refresh token.
+   */
+  async refresh(configDir: string, refreshToken: string): Promise<RefreshResult | null> {
+    try {
+      const response = await fetch(TOKEN_REFRESH_URL, {
+        method: 'POST',
+        headers: { 'Content-Type': 'application/json' },
+        body: JSON.stringify({
+          grant_type: 'refresh_token',
+          refresh_token: refreshToken,
+          client_id: OAUTH_CLIENT_ID,
+          scope: 'user:inference user:profile',
+        }),
+      });
+ 
+      if (!response.ok) {
+        log.warn({ configDir, status: response.status }, 'token refresh failed');
+        return null;
+      }
+ 
+      const data = await response.json();
+      return {
+        accessToken: data.access_token,
+        refreshToken: data.refresh_token,
+        expiresIn: data.expires_in,
+      };
+    } catch (err) {
+      log.error({ configDir, err: err instanceof Error ? err.message : String(err) }, 'token refresh error');
+      return null;
+    }
+  }
+ 
+  /**
+   * Write updated credentials to the config directory.
+   */
+  write(
+    configDir: string,
+    accessToken: string,
+    refreshToken: string,
+    expiresIn: number,
+  ): void {
+    const credPath = join(configDir, '.credentials.json');
+ 
+    // Read existing credentials to preserve other fields
+    let existing: Record<string, unknown> = {};
+    try {
+      if (existsSync(credPath)) {
+        existing = JSON.parse(readFileSync(credPath, 'utf-8'));
+      }
+    } catch {
+      // Start fresh if can't read
+    }
+ 
+    // Calculate expiry in milliseconds
+    const nowMs = Date.now();
+    const expiresAt = nowMs + expiresIn * 1000;
+ 
+    // Update claudeAiOauth section
+    const claudeAiOauth = (existing.claudeAiOauth as Record<string, unknown>) ?? {};
+    claudeAiOauth.accessToken = accessToken;
+    claudeAiOauth.refreshToken = refreshToken;
+    claudeAiOauth.expiresAt = expiresAt;
+    existing.claudeAiOauth = claudeAiOauth;
+ 
+    // Ensure directory exists
+    mkdirSync(dirname(credPath), { recursive: true });
+ 
+    // Write back (compact JSON for consistency)
+    writeFileSync(credPath, JSON.stringify(existing));
+    log.debug({ configDir }, 'credentials written after token refresh');
+  }
+ 
+  /**
+   * Ensure credentials are valid, refreshing if needed.
+   */
+  async ensureValid(configDir: string, accountId?: string): Promise<CredentialValidationResult> {
+    const credentials = this.read(configDir);
+ 
+    if (!credentials) {
+      log.warn({ configDir, accountId }, 'no credentials found');
+      this.emitExpired(accountId, 'credentials_missing', 'Credentials file not found');
+      return {
+        valid: false,
+        credentials: null,
+        error: 'Credentials file not found',
+        refreshed: false,
+      };
+    }
+ 
+    if (!this.isExpired(credentials)) {
+      log.debug({ configDir, accountId }, 'credentials valid, no refresh needed');
+      this.emitValidated(accountId, true, credentials.expiresAt, false);
+      return {
+        valid: true,
+        credentials,
+        error: null,
+        refreshed: false,
+      };
+    }
+ 
+    // Credentials expired — attempt refresh if we have a refresh token
+    if (!credentials.refreshToken) {
+      log.warn({ configDir, accountId }, 'setup token expired, no refresh token available');
+      this.emitExpired(accountId, 'token_expired', 'Setup token expired, no refresh token available');
+      return {
+        valid: false,
+        credentials: null,
+        error: 'Setup token expired, no refresh token available',
+        refreshed: false,
+      };
+    }
+ 
+    log.info({ configDir, accountId }, 'credentials expired, refreshing');
+    const previousExpiresAt = credentials.expiresAt;
+    const refreshed = await this.refresh(configDir, credentials.refreshToken);
+ 
+    if (!refreshed) {
+      log.error({ configDir, accountId }, 'failed to refresh credentials');
+      this.emitExpired(accountId, 'refresh_failed', 'Token refresh failed');
+      return {
+        valid: false,
+        credentials: null,
+        error: 'Token refresh failed',
+        refreshed: false,
+      };
+    }
+ 
+    // Write refreshed credentials
+    const newRefreshToken = refreshed.refreshToken || credentials.refreshToken;
+    this.write(configDir, refreshed.accessToken, newRefreshToken, refreshed.expiresIn);
+ 
+    const newExpiresAt = Date.now() + refreshed.expiresIn * 1000;
+    log.info({ configDir, accountId, expiresIn: refreshed.expiresIn }, 'credentials refreshed');
+ 
+    this.emitRefreshed(accountId, newExpiresAt, previousExpiresAt);
+    this.emitValidated(accountId, true, newExpiresAt, true);
+ 
+    // Read back updated credentials
+    const updatedCredentials = this.read(configDir);
+    return {
+      valid: true,
+      credentials: updatedCredentials,
+      error: null,
+      refreshed: true,
+    };
+  }
+ 
+  /**
+   * Validate credentials without attempting refresh.
+   */
+  async validate(configDir: string, accountId?: string): Promise<CredentialValidationResult> {
+    const credentials = this.read(configDir);
+ 
+    if (!credentials) {
+      this.emitValidated(accountId, false, null, false);
+      return {
+        valid: false,
+        credentials: null,
+        error: 'Credentials file not found',
+        refreshed: false,
+      };
+    }
+ 
+    const expired = this.isExpired(credentials);
+    this.emitValidated(accountId, !expired, credentials.expiresAt, false);
+ 
+    if (expired) {
+      return {
+        valid: false,
+        credentials,
+        error: 'Token expired',
+        refreshed: false,
+      };
+    }
+ 
+    return {
+      valid: true,
+      credentials,
+      error: null,
+      refreshed: false,
+    };
+  }
+ 
+  /**
+   * Emit credentials refreshed event.
+   */
+  private emitRefreshed(
+    accountId: string | undefined,
+    expiresAt: number,
+    previousExpiresAt: number | null,
+  ): void {
+    if (!this.eventBus) return;
+ 
+    const event: AccountCredentialsRefreshedEvent = {
+      type: 'account:credentials_refreshed',
+      timestamp: new Date(),
+      payload: {
+        accountId: accountId ?? null,
+        expiresAt,
+        previousExpiresAt,
+      },
+    };
+    this.eventBus.emit(event);
+  }
+ 
+  /**
+   * Emit credentials expired event.
+   */
+  private emitExpired(
+    accountId: string | undefined,
+    reason: 'token_expired' | 'refresh_failed' | 'credentials_missing',
+    error: string | null,
+  ): void {
+    if (!this.eventBus) return;
+ 
+    const event: AccountCredentialsExpiredEvent = {
+      type: 'account:credentials_expired',
+      timestamp: new Date(),
+      payload: {
+        accountId: accountId ?? null,
+        reason,
+        error,
+      },
+    };
+    this.eventBus.emit(event);
+  }
+ 
+  /**
+   * Emit credentials validated event.
+   */
+  private emitValidated(
+    accountId: string | undefined,
+    valid: boolean,
+    expiresAt: number | null,
+    wasRefreshed: boolean,
+  ): void {
+    if (!this.eventBus) return;
+ 
+    const event: AccountCredentialsValidatedEvent = {
+      type: 'account:credentials_validated',
+      timestamp: new Date(),
+      payload: {
+        accountId: accountId ?? null,
+        valid,
+        expiresAt,
+        wasRefreshed,
+      },
+    };
+    this.eventBus.emit(event);
+  }
+}
+ 
+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/coverage/src/agent/credentials/index.html b/coverage/src/agent/credentials/index.html new file mode 100644 index 0000000..beffb71 --- /dev/null +++ b/coverage/src/agent/credentials/index.html @@ -0,0 +1,131 @@ + + + + + + Code coverage report for src/agent/credentials + + + + + + + + + +
+
+

All files src/agent/credentials

+
+ +
+ 4.34% + Statements + 4/92 +
+ + +
+ 0% + Branches + 0/50 +
+ + +
+ 0% + Functions + 0/10 +
+ + +
+ 4.65% + Lines + 4/86 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
FileStatementsBranchesFunctionsLines
default-credential-manager.ts +
+
4.34%4/920%0/500%0/104.65%4/86
index.ts +
+
0%0/00%0/00%0/00%0/0
+
+
+
+ + + + + + + + \ No newline at end of file diff --git a/coverage/src/agent/credentials/index.ts.html b/coverage/src/agent/credentials/index.ts.html new file mode 100644 index 0000000..02dd1fe --- /dev/null +++ b/coverage/src/agent/credentials/index.ts.html @@ -0,0 +1,136 @@ + + + + + + Code coverage report for src/agent/credentials/index.ts + + + + + + + + + +
+
+

All files / src/agent/credentials index.ts

+
+ +
+ 0% + Statements + 0/0 +
+ + +
+ 0% + Branches + 0/0 +
+ + +
+ 0% + Functions + 0/0 +
+ + +
+ 0% + Lines + 0/0 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+

+
1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  + 
/**
+ * Credentials Module - Public API
+ *
+ * Exports the AccountCredentialManager port interface and default adapter.
+ * All modules should import from this index file.
+ */
+ 
+// Port interface and types
+export type {
+  AccountCredentialManager,
+  OAuthCredentials,
+  RefreshResult,
+  CredentialValidationResult,
+} from './types.js';
+ 
+// Adapter implementation
+export { DefaultAccountCredentialManager } from './default-credential-manager.js';
+ 
+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/coverage/src/agent/file-io.ts.html b/coverage/src/agent/file-io.ts.html new file mode 100644 index 0000000..632aefe --- /dev/null +++ b/coverage/src/agent/file-io.ts.html @@ -0,0 +1,1213 @@ + + + + + + Code coverage report for src/agent/file-io.ts + + + + + + + + + +
+
+

All files / src/agent file-io.ts

+
+ +
+ 76.61% + Statements + 95/124 +
+ + +
+ 69.76% + Branches + 60/86 +
+ + +
+ 100% + Functions + 14/14 +
+ + +
+ 76.27% + Lines + 90/118 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+

+
1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 +30 +31 +32 +33 +34 +35 +36 +37 +38 +39 +40 +41 +42 +43 +44 +45 +46 +47 +48 +49 +50 +51 +52 +53 +54 +55 +56 +57 +58 +59 +60 +61 +62 +63 +64 +65 +66 +67 +68 +69 +70 +71 +72 +73 +74 +75 +76 +77 +78 +79 +80 +81 +82 +83 +84 +85 +86 +87 +88 +89 +90 +91 +92 +93 +94 +95 +96 +97 +98 +99 +100 +101 +102 +103 +104 +105 +106 +107 +108 +109 +110 +111 +112 +113 +114 +115 +116 +117 +118 +119 +120 +121 +122 +123 +124 +125 +126 +127 +128 +129 +130 +131 +132 +133 +134 +135 +136 +137 +138 +139 +140 +141 +142 +143 +144 +145 +146 +147 +148 +149 +150 +151 +152 +153 +154 +155 +156 +157 +158 +159 +160 +161 +162 +163 +164 +165 +166 +167 +168 +169 +170 +171 +172 +173 +174 +175 +176 +177 +178 +179 +180 +181 +182 +183 +184 +185 +186 +187 +188 +189 +190 +191 +192 +193 +194 +195 +196 +197 +198 +199 +200 +201 +202 +203 +204 +205 +206 +207 +208 +209 +210 +211 +212 +213 +214 +215 +216 +217 +218 +219 +220 +221 +222 +223 +224 +225 +226 +227 +228 +229 +230 +231 +232 +233 +234 +235 +236 +237 +238 +239 +240 +241 +242 +243 +244 +245 +246 +247 +248 +249 +250 +251 +252 +253 +254 +255 +256 +257 +258 +259 +260 +261 +262 +263 +264 +265 +266 +267 +268 +269 +270 +271 +272 +273 +274 +275 +276 +277 +278 +279 +280 +281 +282 +283 +284 +285 +286 +287 +288 +289 +290 +291 +292 +293 +294 +295 +296 +297 +298 +299 +300 +301 +302 +303 +304 +305 +306 +307 +308 +309 +310 +311 +312 +313 +314 +315 +316 +317 +318 +319 +320 +321 +322 +323 +324 +325 +326 +327 +328 +329 +330 +331 +332 +333 +334 +335 +336 +337 +338 +339 +340 +341 +342 +343 +344 +345 +346 +347 +348 +349 +350 +351 +352 +353 +354 +355 +356 +357 +358 +359 +360 +361 +362 +363 +364 +365 +366 +367 +368 +369 +370 +371 +372 +373 +374 +375 +376 +377  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +101x +  +  +  +  +  +  +  +5x +5x +20x +19x +  +  +  +  +  +  +  +  +19x +  +19x +  +  +19x +  +  +5x +5x +1x +1x +  +5x +  +  +  +5x +5x +  +  +5x +  +  +  +  +  +5x +  +5x +1x +1x +  +  +  +  +  +  +  +  +  +1x +1x +  +  +5x +1x +1x +  +1x +2x +2x +  +  +  +  +  +  +  +  +2x +  +  +  +  +  +  +  +2x +2x +2x +  +  +  +5x +1x +1x +1x +1x +1x +  +  +  +  +1x +  +  +  +  +  +  +  +1x +1x +  +  +5x +1x +1x +  +  +  +  +  +  +  +  +  +  +1x +1x +  +  +  +5x +  +5x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +5x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +5x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +14x +14x +14x +14x +  +4x +  +  +  +  +  +  +  +14x +  +7x +7x +7x +7x +8x +7x +7x +7x +7x +7x +  +  +  +  +7x +  +  +  +7x +7x +7x +  +3x +3x +  +  +  +  +  +  +3x +3x +2x +2x +2x +  +  +  +  +  +  +  +  +  +3x +3x +2x +2x +2x +  +  +  +  +  +  +  +  +  +  +  +2x +2x +1x +1x +  +  +  +  +  +  +  +  +  +  +6x +6x +2x +2x +  +  +  +  +  +  +  + 
/**
+ * File-Based Agent I/O
+ *
+ * Writes context as input files before agent spawn and reads output files after completion.
+ * Uses YAML frontmatter (gray-matter) for structured metadata and markdown bodies.
+ *
+ * Input: .cw/input/ — written by system before spawn
+ * Output: .cw/output/ — written by agent during execution
+ */
+ 
+import { mkdirSync, writeFileSync, readdirSync, existsSync } from 'node:fs';
+import { readFileSync } from 'node:fs';
+import { join } from 'node:path';
+import matter from 'gray-matter';
+import { nanoid } from 'nanoid';
+import { tiptapJsonToMarkdown } from './content-serializer.js';
+import type { AgentInputContext } from './types.js';
+ 
+// Re-export for convenience
+export type { AgentInputContext } from './types.js';
+ 
+// =============================================================================
+// TYPES
+// =============================================================================
+ 
+export interface WriteInputFilesOptions extends AgentInputContext {
+  agentWorkdir: string;
+}
+ 
+export interface ParsedSummary {
+  body: string;
+  filesModified?: string[];
+}
+ 
+export interface ParsedPhaseFile {
+  id: string;
+  title: string;
+  dependencies: string[];
+  body: string;
+}
+ 
+export interface ParsedTaskFile {
+  id: string;
+  title: string;
+  category: string;
+  type: string;
+  dependencies: string[];
+  body: string;
+}
+ 
+export interface ParsedDecisionFile {
+  id: string;
+  topic: string;
+  decision: string;
+  reason: string;
+  body: string;
+}
+ 
+export interface ParsedPageFile {
+  pageId: string;
+  title: string;
+  summary: string;
+  body: string;
+}
+ 
+// =============================================================================
+// ID GENERATION
+// =============================================================================
+ 
+export function generateId(): string {
+  return nanoid();
+}
+ 
+// =============================================================================
+// INPUT FILE WRITING
+// =============================================================================
+ 
+function formatFrontmatter(data: Record<string, unknown>, body: string = ''): string {
+  const lines: string[] = ['---'];
+  for (const [key, value] of Object.entries(data)) {
+    if (value === undefined || value === null) continue;
+    Iif (Array.isArray(value)) {
+      if (value.length === 0) {
+        lines.push(`${key}: []`);
+      } else {
+        lines.push(`${key}:`);
+        for (const item of value) {
+          lines.push(`  - ${String(item)}`);
+        }
+      }
+    I} else if (value instanceof Date) {
+      lines.push(`${key}: "${value.toISOString()}"`);
+    I} else if (typeof value === 'string' && (value.includes('\n') || value.includes(':'))) {
+      lines.push(`${key}: ${JSON.stringify(value)}`);
+    } else {
+      lines.push(`${key}: ${String(value)}`);
+    }
+  }
+  lines.push('---');
+  if (body) {
+    lines.push('');
+    lines.push(body);
+  }
+  return lines.join('\n') + '\n';
+}
+ 
+export function writeInputFiles(options: WriteInputFilesOptions): void {
+  const inputDir = join(options.agentWorkdir, '.cw', 'input');
+  mkdirSync(inputDir, { recursive: true });
+ 
+  // Write expected working directory marker for verification
+  writeFileSync(
+    join(inputDir, '../expected-pwd.txt'),
+    options.agentWorkdir,
+    'utf-8'
+  );
+ 
+  const manifestFiles: string[] = [];
+ 
+  if (options.initiative) {
+    const ini = options.initiative;
+    const content = formatFrontmatter(
+      {
+        id: ini.id,
+        name: ini.name,
+        status: ini.status,
+        mergeRequiresApproval: ini.mergeRequiresApproval,
+        branch: ini.branch,
+      },
+      '',
+    );
+    writeFileSync(join(inputDir, 'initiative.md'), content, 'utf-8');
+    manifestFiles.push('initiative.md');
+  }
+ 
+  if (options.pages && options.pages.length > 0) {
+    const pagesDir = join(inputDir, 'pages');
+    mkdirSync(pagesDir, { recursive: true });
+ 
+    for (const page of options.pages) {
+      let bodyMarkdown = '';
+      Iif (page.content) {
+        try {
+          const parsed = JSON.parse(page.content);
+          bodyMarkdown = tiptapJsonToMarkdown(parsed);
+        } catch {
+          // Invalid JSON content — skip
+        }
+      }
+ 
+      const content = formatFrontmatter(
+        {
+          title: page.title,
+          parentPageId: page.parentPageId,
+          sortOrder: page.sortOrder,
+        },
+        bodyMarkdown,
+      );
+      const filename = `pages/${page.id}.md`;
+      writeFileSync(join(pagesDir, `${page.id}.md`), content, 'utf-8');
+      manifestFiles.push(filename);
+    }
+  }
+ 
+  if (options.phase) {
+    const ph = options.phase;
+    let bodyMarkdown = '';
+    Eif (ph.content) {
+      try {
+        bodyMarkdown = tiptapJsonToMarkdown(JSON.parse(ph.content));
+      } catch {
+        // Invalid JSON content — skip
+      }
+    }
+    const content = formatFrontmatter(
+      {
+        id: ph.id,
+        name: ph.name,
+        status: ph.status,
+      },
+      bodyMarkdown,
+    );
+    writeFileSync(join(inputDir, 'phase.md'), content, 'utf-8');
+    manifestFiles.push('phase.md');
+  }
+ 
+  if (options.task) {
+    const t = options.task;
+    const content = formatFrontmatter(
+      {
+        id: t.id,
+        name: t.name,
+        category: t.category,
+        type: t.type,
+        priority: t.priority,
+        status: t.status,
+      },
+      t.description ?? '',
+    );
+    writeFileSync(join(inputDir, 'task.md'), content, 'utf-8');
+    manifestFiles.push('task.md');
+  }
+ 
+  // Write read-only context directories
+  const contextFiles: string[] = [];
+ 
+  Iif (options.phases && options.phases.length > 0) {
+    const phasesDir = join(inputDir, 'context', 'phases');
+    mkdirSync(phasesDir, { recursive: true });
+ 
+    for (const ph of options.phases) {
+      let bodyMarkdown = '';
+      if (ph.content) {
+        try {
+          bodyMarkdown = tiptapJsonToMarkdown(JSON.parse(ph.content));
+        } catch {
+          // Invalid JSON content — skip
+        }
+      }
+      const content = formatFrontmatter(
+        {
+          id: ph.id,
+          name: ph.name,
+          status: ph.status,
+          dependsOn: ph.dependsOn ?? [],
+        },
+        bodyMarkdown,
+      );
+      const filename = `context/phases/${ph.id}.md`;
+      writeFileSync(join(phasesDir, `${ph.id}.md`), content, 'utf-8');
+      contextFiles.push(filename);
+    }
+  }
+ 
+  Iif (options.tasks && options.tasks.length > 0) {
+    const tasksDir = join(inputDir, 'context', 'tasks');
+    mkdirSync(tasksDir, { recursive: true });
+ 
+    for (const t of options.tasks) {
+      const content = formatFrontmatter(
+        {
+          id: t.id,
+          name: t.name,
+          phaseId: t.phaseId,
+          parentTaskId: t.parentTaskId,
+          category: t.category,
+          type: t.type,
+          priority: t.priority,
+          status: t.status,
+        },
+        t.description ?? '',
+      );
+      const filename = `context/tasks/${t.id}.md`;
+      writeFileSync(join(tasksDir, `${t.id}.md`), content, 'utf-8');
+      contextFiles.push(filename);
+    }
+  }
+ 
+  // Write manifest listing exactly which files were created
+  writeFileSync(
+    join(inputDir, 'manifest.json'),
+    JSON.stringify({
+      files: manifestFiles,
+      contextFiles,
+      agentId: options.agentId ?? null,
+      agentName: options.agentName ?? null,
+    }) + '\n',
+    'utf-8',
+  );
+}
+ 
+// =============================================================================
+// OUTPUT FILE READING
+// =============================================================================
+ 
+export function readFrontmatterFile(filePath: string): { data: Record<string, unknown>; body: string } | null {
+  try {
+    const raw = readFileSync(filePath, 'utf-8');
+    const parsed = matter(raw);
+    return { data: parsed.data as Record<string, unknown>, body: parsed.content.trim() };
+  } catch {
+    return null;
+  }
+}
+ 
+function readFrontmatterDir<T>(
+  dirPath: string,
+  mapper: (data: Record<string, unknown>, body: string, filename: string) => T | null,
+): T[] {
+  if (!existsSync(dirPath)) return [];
+ 
+  const results: T[] = [];
+  try {
+    const entries = readdirSync(dirPath);
+    for (const entry of entries) {
+      if (!entry.endsWith('.md')) continue;
+      const filePath = join(dirPath, entry);
+      const parsed = readFrontmatterFile(filePath);
+      Iif (!parsed) continue;
+      const mapped = mapper(parsed.data, parsed.body, entry);
+      Eif (mapped) results.push(mapped);
+    }
+  } catch {
+    // Directory read error — return empty
+  }
+  return results;
+}
+ 
+export function readSummary(agentWorkdir: string): ParsedSummary | null {
+  const filePath = join(agentWorkdir, '.cw', 'output', 'SUMMARY.md');
+  const parsed = readFrontmatterFile(filePath);
+  if (!parsed) return null;
+ 
+  const filesModified = parsed.data.files_modified;
+  return {
+    body: parsed.body,
+    filesModified: Array.isArray(filesModified) ? filesModified.map(String) : undefined,
+  };
+}
+ 
+export function readPhaseFiles(agentWorkdir: string): ParsedPhaseFile[] {
+  const dirPath = join(agentWorkdir, '.cw', 'output', 'phases');
+  return readFrontmatterDir(dirPath, (data, body, filename) => {
+    const id = filename.replace(/\.md$/, '');
+    const deps = Array.isArray(data.dependencies) ? data.dependencies.map(String) : [];
+    return {
+      id,
+      title: String(data.title ?? ''),
+      dependencies: deps,
+      body,
+    };
+  });
+}
+ 
+export function readTaskFiles(agentWorkdir: string): ParsedTaskFile[] {
+  const dirPath = join(agentWorkdir, '.cw', 'output', 'tasks');
+  return readFrontmatterDir(dirPath, (data, body, filename) => {
+    const id = filename.replace(/\.md$/, '');
+    const deps = Array.isArray(data.dependencies) ? data.dependencies.map(String) : [];
+    return {
+      id,
+      title: String(data.title ?? ''),
+      category: String(data.category ?? 'execute'),
+      type: String(data.type ?? 'auto'),
+      dependencies: deps,
+      body,
+    };
+  });
+}
+ 
+export function readDecisionFiles(agentWorkdir: string): ParsedDecisionFile[] {
+  const dirPath = join(agentWorkdir, '.cw', 'output', 'decisions');
+  return readFrontmatterDir(dirPath, (data, body, filename) => {
+    const id = filename.replace(/\.md$/, '');
+    return {
+      id,
+      topic: String(data.topic ?? ''),
+      decision: String(data.decision ?? ''),
+      reason: String(data.reason ?? ''),
+      body,
+    };
+  });
+}
+ 
+export function readPageFiles(agentWorkdir: string): ParsedPageFile[] {
+  const dirPath = join(agentWorkdir, '.cw', 'output', 'pages');
+  return readFrontmatterDir(dirPath, (data, body, filename) => {
+    const pageId = filename.replace(/\.md$/, '');
+    return {
+      pageId,
+      title: String(data.title ?? ''),
+      summary: String(data.summary ?? ''),
+      body,
+    };
+  });
+}
+ 
+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/coverage/src/agent/file-tailer.ts.html b/coverage/src/agent/file-tailer.ts.html new file mode 100644 index 0000000..89909df --- /dev/null +++ b/coverage/src/agent/file-tailer.ts.html @@ -0,0 +1,856 @@ + + + + + + Code coverage report for src/agent/file-tailer.ts + + + + + + + + + +
+
+

All files / src/agent file-tailer.ts

+
+ +
+ 3.26% + Statements + 3/92 +
+ + +
+ 0% + Branches + 0/53 +
+ + +
+ 0% + Functions + 0/13 +
+ + +
+ 3.4% + Lines + 3/88 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+

+
1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 +30 +31 +32 +33 +34 +35 +36 +37 +38 +39 +40 +41 +42 +43 +44 +45 +46 +47 +48 +49 +50 +51 +52 +53 +54 +55 +56 +57 +58 +59 +60 +61 +62 +63 +64 +65 +66 +67 +68 +69 +70 +71 +72 +73 +74 +75 +76 +77 +78 +79 +80 +81 +82 +83 +84 +85 +86 +87 +88 +89 +90 +91 +92 +93 +94 +95 +96 +97 +98 +99 +100 +101 +102 +103 +104 +105 +106 +107 +108 +109 +110 +111 +112 +113 +114 +115 +116 +117 +118 +119 +120 +121 +122 +123 +124 +125 +126 +127 +128 +129 +130 +131 +132 +133 +134 +135 +136 +137 +138 +139 +140 +141 +142 +143 +144 +145 +146 +147 +148 +149 +150 +151 +152 +153 +154 +155 +156 +157 +158 +159 +160 +161 +162 +163 +164 +165 +166 +167 +168 +169 +170 +171 +172 +173 +174 +175 +176 +177 +178 +179 +180 +181 +182 +183 +184 +185 +186 +187 +188 +189 +190 +191 +192 +193 +194 +195 +196 +197 +198 +199 +200 +201 +202 +203 +204 +205 +206 +207 +208 +209 +210 +211 +212 +213 +214 +215 +216 +217 +218 +219 +220 +221 +222 +223 +224 +225 +226 +227 +228 +229 +230 +231 +232 +233 +234 +235 +236 +237 +238 +239 +240 +241 +242 +243 +244 +245 +246 +247 +248 +249 +250 +251 +252 +253 +254 +255 +256 +257 +258  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +14x +  +  +14x +  +  +14x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  + 
/**
+ * File Tailer
+ *
+ * Watches an output file and emits parsed events in real-time.
+ * Used for crash-resilient agent spawning where subprocesses write
+ * directly to files instead of using pipes.
+ *
+ * Uses fs.watch() for efficient change detection with a poll fallback
+ * since fs.watch isn't 100% reliable on all platforms.
+ */
+ 
+import { watch, type FSWatcher } from 'node:fs';
+import { open, stat } from 'node:fs/promises';
+import type { FileHandle } from 'node:fs/promises';
+import type { StreamParser, StreamEvent } from './providers/stream-types.js';
+import { createModuleLogger } from '../logger/index.js';
+ 
+const log = createModuleLogger('file-tailer');
+ 
+/** Poll interval for fallback polling (ms) */
+const POLL_INTERVAL_MS = 500;
+ 
+/** Read buffer size (bytes) */
+const READ_BUFFER_SIZE = 64 * 1024;
+ 
+export interface FileTailerOptions {
+  /** Path to the output file to watch */
+  filePath: string;
+  /** Agent ID for logging */
+  agentId: string;
+  /** Parser to convert lines to stream events */
+  parser: StreamParser;
+  /** Optional callback for each stream event */
+  onEvent?: (event: StreamEvent) => void;
+  /** If true, read from beginning of file; otherwise tail only new content (default: false) */
+  startFromBeginning?: boolean;
+  /** Callback for raw file content chunks (for DB persistence + event emission) */
+  onRawContent?: (content: string) => void;
+}
+ 
+/**
+ * FileTailer watches a file for changes and emits parsed stream events.
+ *
+ * Behavior:
+ * - Uses fs.watch() for efficient change detection
+ * - Falls back to polling every 500ms (fs.watch misses events sometimes)
+ * - Reads new content incrementally, splits into lines
+ * - Feeds each line to the parser, emits resulting events
+ * - Handles partial lines at buffer boundaries
+ */
+export class FileTailer {
+  private position = 0;
+  private watcher: FSWatcher | null = null;
+  private pollInterval: NodeJS.Timeout | null = null;
+  private fileHandle: FileHandle | null = null;
+  private stopped = false;
+  private partialLine = '';
+  private reading = false;
+ 
+  private readonly filePath: string;
+  private readonly agentId: string;
+  private readonly parser: StreamParser;
+  private readonly onEvent?: (event: StreamEvent) => void;
+  private readonly startFromBeginning: boolean;
+  private readonly onRawContent?: (content: string) => void;
+ 
+  constructor(options: FileTailerOptions) {
+    this.filePath = options.filePath;
+    this.agentId = options.agentId;
+    this.parser = options.parser;
+    this.onEvent = options.onEvent;
+    this.startFromBeginning = options.startFromBeginning ?? false;
+    this.onRawContent = options.onRawContent;
+  }
+ 
+  /**
+   * Start watching the file for changes.
+   * Initializes position, starts fs.watch, and begins poll fallback.
+   */
+  async start(): Promise<void> {
+    if (this.stopped) return;
+ 
+    log.debug({ filePath: this.filePath, agentId: this.agentId }, 'starting file tailer');
+ 
+    try {
+      // Open file for reading
+      this.fileHandle = await open(this.filePath, 'r');
+ 
+      // Set initial position
+      if (this.startFromBeginning) {
+        this.position = 0;
+      } else {
+        // Seek to end
+        const stats = await stat(this.filePath);
+        this.position = stats.size;
+      }
+ 
+      // Start fs.watch for efficient change detection
+      this.watcher = watch(this.filePath, (eventType) => {
+        if (eventType === 'change' && !this.stopped) {
+          this.readNewContent().catch((err) => {
+            log.warn({ err: err instanceof Error ? err.message : String(err), agentId: this.agentId }, 'error reading new content');
+          });
+        }
+      });
+ 
+      this.watcher.on('error', (err) => {
+        log.warn({ err: err instanceof Error ? err.message : String(err), agentId: this.agentId }, 'watcher error');
+      });
+ 
+      // Start poll fallback (fs.watch misses events sometimes)
+      this.pollInterval = setInterval(() => {
+        if (!this.stopped) {
+          this.readNewContent().catch((err) => {
+            log.warn({ err: err instanceof Error ? err.message : String(err), agentId: this.agentId }, 'poll read error');
+          });
+        }
+      }, POLL_INTERVAL_MS);
+ 
+      // If starting from beginning, do initial read
+      if (this.startFromBeginning) {
+        await this.readNewContent();
+      }
+    } catch (err) {
+      log.error({ err: err instanceof Error ? err.message : String(err), filePath: this.filePath }, 'failed to start file tailer');
+    }
+  }
+ 
+  /**
+   * Read new content from the file since last position.
+   * Splits into lines, feeds to parser, emits events.
+   */
+  private async readNewContent(): Promise<void> {
+    if (this.stopped || !this.fileHandle || this.reading) return;
+ 
+    this.reading = true;
+    try {
+      // Check current file size
+      const stats = await stat(this.filePath);
+      if (stats.size <= this.position) {
+        return; // No new content
+      }
+ 
+      // Read new bytes
+      const bytesToRead = stats.size - this.position;
+      const buffer = Buffer.alloc(Math.min(bytesToRead, READ_BUFFER_SIZE));
+      const { bytesRead } = await this.fileHandle.read(buffer, 0, buffer.length, this.position);
+ 
+      if (bytesRead === 0) return;
+ 
+      this.position += bytesRead;
+ 
+      // Fire raw content callback for DB persistence (before line splitting)
+      const rawChunk = buffer.toString('utf-8', 0, bytesRead);
+      if (this.onRawContent) {
+        this.onRawContent(rawChunk);
+      }
+ 
+      // Convert to string and process lines
+      const content = this.partialLine + rawChunk;
+      const lines = content.split('\n');
+ 
+      // Last element is either empty (if content ended with \n) or a partial line
+      this.partialLine = lines.pop() ?? '';
+ 
+      // Process complete lines
+      for (const line of lines) {
+        if (line.trim()) {
+          this.processLine(line);
+        }
+      }
+ 
+      // If there's more content to read, schedule another read
+      if (stats.size > this.position) {
+        setImmediate(() => {
+          this.readNewContent().catch(() => {});
+        });
+      }
+    } finally {
+      this.reading = false;
+    }
+  }
+ 
+  /**
+   * Process a single line through the parser and emit events.
+   */
+  private processLine(line: string): void {
+    const events = this.parser.parseLine(line);
+ 
+    for (const event of events) {
+      if (this.onEvent) {
+        this.onEvent(event);
+      }
+    }
+  }
+ 
+  /**
+   * Stop watching the file.
+   * Cleans up watcher, poll timer, and file handle.
+   */
+  async stop(): Promise<void> {
+    if (this.stopped) return;
+ 
+    this.stopped = true;
+    log.debug({ filePath: this.filePath, agentId: this.agentId }, 'stopping file tailer');
+ 
+    // Close watcher
+    if (this.watcher) {
+      this.watcher.close();
+      this.watcher = null;
+    }
+ 
+    // Clear poll timer
+    if (this.pollInterval) {
+      clearInterval(this.pollInterval);
+      this.pollInterval = null;
+    }
+ 
+    // Do one final read to catch any remaining content
+    try {
+      await this.readNewContent();
+ 
+      // Process any remaining partial line
+      if (this.partialLine.trim()) {
+        this.processLine(this.partialLine);
+        this.partialLine = '';
+      }
+ 
+      // Signal end of stream to parser
+      const endEvents = this.parser.end();
+      for (const event of endEvents) {
+        if (this.onEvent) {
+          this.onEvent(event);
+        }
+      }
+    } catch {
+      // Ignore errors during cleanup
+    }
+ 
+    // Close file handle
+    if (this.fileHandle) {
+      try {
+        await this.fileHandle.close();
+      } catch {
+        // Ignore close errors
+      }
+      this.fileHandle = null;
+    }
+  }
+ 
+  /**
+   * Check if the tailer has been stopped.
+   */
+  get isStopped(): boolean {
+    return this.stopped;
+  }
+}
+ 
+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/coverage/src/agent/index.html b/coverage/src/agent/index.html new file mode 100644 index 0000000..f4b8dee --- /dev/null +++ b/coverage/src/agent/index.html @@ -0,0 +1,296 @@ + + + + + + Code coverage report for src/agent + + + + + + + + + +
+
+

All files src/agent

+
+ +
+ 44.7% + Statements + 679/1519 +
+ + +
+ 33.29% + Branches + 292/877 +
+ + +
+ 46.96% + Functions + 85/181 +
+ + +
+ 45.27% + Lines + 656/1449 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
FileStatementsBranchesFunctionsLines
alias.ts +
+
12.5%1/80%0/20%0/114.28%1/7
cleanup-manager.ts +
+
10.32%22/2132.06%2/9723.8%5/2110.47%22/210
content-serializer.ts +
+
4.76%2/420%0/240%0/75.26%2/38
credential-handler.ts +
+
13.58%11/817.69%3/3930%3/1013.33%10/75
file-io.ts +
+
76.61%95/12469.76%60/86100%14/1476.27%90/118
file-tailer.ts +
+
3.26%3/920%0/530%0/133.4%3/88
index.ts +
+
0%0/00%0/00%0/00%0/0
manager.ts +
+
48.11%166/34536.41%59/16232.72%18/5548.28%155/321
markdown-to-tiptap.ts +
+
14.28%1/70%0/40%0/214.28%1/7
mock-manager.ts +
+
88%110/12569.76%60/8694.73%18/1988.61%109/123
output-handler.ts +
+
49.56%169/34130.85%79/25675%15/2050.76%166/327
process-manager.ts +
+
68.88%93/13542.64%29/6863.15%12/1970.54%91/129
schema.ts +
+
100%6/6100%0/0100%0/0100%6/6
+
+
+
+ + + + + + + + \ No newline at end of file diff --git a/coverage/src/agent/index.ts.html b/coverage/src/agent/index.ts.html new file mode 100644 index 0000000..5e06a3a --- /dev/null +++ b/coverage/src/agent/index.ts.html @@ -0,0 +1,337 @@ + + + + + + Code coverage report for src/agent/index.ts + + + + + + + + + +
+
+

All files / src/agent index.ts

+
+ +
+ 0% + Statements + 0/0 +
+ + +
+ 0% + Branches + 0/0 +
+ + +
+ 0% + Functions + 0/0 +
+ + +
+ 0% + Lines + 0/0 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+

+
1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 +30 +31 +32 +33 +34 +35 +36 +37 +38 +39 +40 +41 +42 +43 +44 +45 +46 +47 +48 +49 +50 +51 +52 +53 +54 +55 +56 +57 +58 +59 +60 +61 +62 +63 +64 +65 +66 +67 +68 +69 +70 +71 +72 +73 +74 +75 +76 +77 +78 +79 +80 +81 +82 +83 +84 +85  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  + 
/**
+ * Agent Module - Public API
+ *
+ * Exports the AgentManager port interface and related types.
+ * All consumers should import from this index file.
+ */
+ 
+// Port interface and types
+export type {
+  AgentStatus,
+  SpawnAgentOptions,
+  AgentInfo,
+  AgentResult,
+  AgentManager,
+  AgentInputContext,
+} from './types.js';
+ 
+// Adapter implementations
+export { MultiProviderAgentManager } from './manager.js';
+/** @deprecated Use MultiProviderAgentManager instead */
+export { MultiProviderAgentManager as ClaudeAgentManager } from './manager.js';
+export { MockAgentManager, type MockAgentScenario } from './mock-manager.js';
+ 
+// Provider registry
+export {
+  getProvider,
+  listProviders,
+  registerProvider,
+  loadProvidersFromFile,
+  PROVIDER_PRESETS,
+} from './providers/index.js';
+export type { AgentProviderConfig } from './providers/index.js';
+ 
+// Agent prompts
+export {
+  buildDiscussPrompt,
+  buildPlanPrompt,
+  buildExecutePrompt,
+  buildRefinePrompt,
+  buildDetailPrompt,
+} from './prompts/index.js';
+ 
+// Schema
+export { agentSignalSchema, agentSignalJsonSchema } from './schema.js';
+export type { AgentSignal } from './schema.js';
+// Backward compat
+export { agentOutputSchema, agentOutputJsonSchema } from './schema.js';
+ 
+// File I/O
+export {
+  writeInputFiles,
+  readSummary,
+  readPhaseFiles,
+  readTaskFiles,
+  readDecisionFiles,
+  readPageFiles,
+  generateId,
+} from './file-io.js';
+export type {
+  WriteInputFilesOptions,
+  ParsedSummary,
+  ParsedPhaseFile,
+  ParsedTaskFile,
+  ParsedDecisionFile,
+  ParsedPageFile,
+} from './file-io.js';
+ 
+// Content serializer
+export { serializePageTree, tiptapJsonToMarkdown } from './content-serializer.js';
+export type { PageForSerialization } from './content-serializer.js';
+ 
+// Alias generator
+export { generateUniqueAlias } from './alias.js';
+ 
+// File tailer for crash-resilient streaming
+export { FileTailer } from './file-tailer.js';
+export type { FileTailerOptions } from './file-tailer.js';
+ 
+// Extracted manager helpers
+export { ProcessManager } from './process-manager.js';
+export { CredentialHandler } from './credential-handler.js';
+export { OutputHandler } from './output-handler.js';
+export type { ActiveAgent } from './output-handler.js';
+export { CleanupManager } from './cleanup-manager.js';
+ 
+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/coverage/src/agent/lifecycle/cleanup-strategy.ts.html b/coverage/src/agent/lifecycle/cleanup-strategy.ts.html new file mode 100644 index 0000000..c0a6fa1 --- /dev/null +++ b/coverage/src/agent/lifecycle/cleanup-strategy.ts.html @@ -0,0 +1,406 @@ + + + + + + Code coverage report for src/agent/lifecycle/cleanup-strategy.ts + + + + + + + + + +
+
+

All files / src/agent/lifecycle cleanup-strategy.ts

+
+ +
+ 6.06% + Statements + 2/33 +
+ + +
+ 0% + Branches + 0/21 +
+ + +
+ 33.33% + Functions + 1/3 +
+ + +
+ 6.06% + Lines + 2/33 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+

+
1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 +30 +31 +32 +33 +34 +35 +36 +37 +38 +39 +40 +41 +42 +43 +44 +45 +46 +47 +48 +49 +50 +51 +52 +53 +54 +55 +56 +57 +58 +59 +60 +61 +62 +63 +64 +65 +66 +67 +68 +69 +70 +71 +72 +73 +74 +75 +76 +77 +78 +79 +80 +81 +82 +83 +84 +85 +86 +87 +88 +89 +90 +91 +92 +93 +94 +95 +96 +97 +98 +99 +100 +101 +102 +103 +104 +105 +106 +107 +108  +  +  +  +  +  +  +  +  +  +15x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +23x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  + 
/**
+ * CleanupStrategy — Centralized cleanup logic based on debug mode and agent state.
+ *
+ * Determines when and how to clean up agent workdirs and resources.
+ * Supports archive mode for debugging vs. immediate cleanup for production.
+ */
+ 
+import { createModuleLogger } from '../../logger/index.js';
+import type { CleanupManager } from '../cleanup-manager.js';
+ 
+const log = createModuleLogger('cleanup-strategy');
+ 
+export type CleanupAction = 'remove' | 'archive' | 'preserve';
+ 
+export interface AgentInfo {
+  id: string;
+  name: string;
+  status: string;
+  initiativeId?: string | null;
+  worktreeId: string;
+}
+ 
+export interface CleanupStrategy {
+  shouldCleanup(agent: AgentInfo, isDebugMode: boolean): Promise<CleanupAction>;
+  executeCleanup(agent: AgentInfo, action: CleanupAction): Promise<void>;
+}
+ 
+export class DefaultCleanupStrategy implements CleanupStrategy {
+  constructor(private cleanupManager: CleanupManager) {}
+ 
+  /**
+   * Determine what cleanup action should be taken for an agent.
+   * Considers agent status and debug mode setting.
+   */
+  async shouldCleanup(agent: AgentInfo, isDebugMode: boolean): Promise<CleanupAction> {
+    log.debug({
+      agentId: agent.id,
+      name: agent.name,
+      status: agent.status,
+      isDebugMode
+    }, 'evaluating cleanup action for agent');
+ 
+    // Never cleanup agents waiting for user input
+    if (agent.status === 'waiting_for_input') {
+      log.debug({ agentId: agent.id, status: agent.status }, 'preserving agent waiting for input');
+      return 'preserve';
+    }
+ 
+    // Never cleanup running agents
+    if (agent.status === 'running') {
+      log.debug({ agentId: agent.id, status: agent.status }, 'preserving running agent');
+      return 'preserve';
+    }
+ 
+    // For completed/idle/crashed agents, decide based on debug mode
+    if (agent.status === 'idle' || agent.status === 'completed' || agent.status === 'crashed') {
+      if (isDebugMode) {
+        log.debug({ agentId: agent.id, status: agent.status }, 'archiving agent in debug mode');
+        return 'archive';
+      } else {
+        log.debug({ agentId: agent.id, status: agent.status }, 'removing agent in production mode');
+        return 'remove';
+      }
+    }
+ 
+    // For stopped agents, clean up immediately regardless of debug mode
+    if (agent.status === 'stopped') {
+      log.debug({ agentId: agent.id, status: agent.status }, 'removing stopped agent');
+      return 'remove';
+    }
+ 
+    // Default to preserve for any unrecognized status
+    log.debug({ agentId: agent.id, status: agent.status }, 'preserving agent with unrecognized status');
+    return 'preserve';
+  }
+ 
+  /**
+   * Execute the determined cleanup action.
+   */
+  async executeCleanup(agent: AgentInfo, action: CleanupAction): Promise<void> {
+    log.debug({
+      agentId: agent.id,
+      name: agent.name,
+      action
+    }, 'executing cleanup action');
+ 
+    switch (action) {
+      case 'remove':
+        await this.cleanupManager.removeAgentWorktrees(agent.name, agent.initiativeId ?? null);
+        await this.cleanupManager.removeAgentBranches(agent.name, agent.initiativeId ?? null);
+        await this.cleanupManager.removeAgentLogs(agent.id);
+        log.info({ agentId: agent.id, name: agent.name }, 'agent workdir and resources removed');
+        break;
+ 
+      case 'archive':
+        await this.cleanupManager.archiveForDebug(agent.worktreeId, agent.id);
+        log.info({ agentId: agent.id, name: agent.name }, 'agent workdir archived for debugging');
+        break;
+ 
+      case 'preserve':
+        log.debug({ agentId: agent.id, name: agent.name }, 'agent workdir preserved');
+        break;
+ 
+      default:
+        log.warn({ agentId: agent.id, action }, 'unknown cleanup action, preserving by default');
+    }
+  }
+}
+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/coverage/src/agent/lifecycle/controller.ts.html b/coverage/src/agent/lifecycle/controller.ts.html new file mode 100644 index 0000000..439e96d --- /dev/null +++ b/coverage/src/agent/lifecycle/controller.ts.html @@ -0,0 +1,1156 @@ + + + + + + Code coverage report for src/agent/lifecycle/controller.ts + + + + + + + + + +
+
+

All files / src/agent/lifecycle controller.ts

+
+ +
+ 11.23% + Statements + 10/89 +
+ + +
+ 2.56% + Branches + 1/39 +
+ + +
+ 8.33% + Functions + 1/12 +
+ + +
+ 11.62% + Lines + 10/86 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+

+
1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 +30 +31 +32 +33 +34 +35 +36 +37 +38 +39 +40 +41 +42 +43 +44 +45 +46 +47 +48 +49 +50 +51 +52 +53 +54 +55 +56 +57 +58 +59 +60 +61 +62 +63 +64 +65 +66 +67 +68 +69 +70 +71 +72 +73 +74 +75 +76 +77 +78 +79 +80 +81 +82 +83 +84 +85 +86 +87 +88 +89 +90 +91 +92 +93 +94 +95 +96 +97 +98 +99 +100 +101 +102 +103 +104 +105 +106 +107 +108 +109 +110 +111 +112 +113 +114 +115 +116 +117 +118 +119 +120 +121 +122 +123 +124 +125 +126 +127 +128 +129 +130 +131 +132 +133 +134 +135 +136 +137 +138 +139 +140 +141 +142 +143 +144 +145 +146 +147 +148 +149 +150 +151 +152 +153 +154 +155 +156 +157 +158 +159 +160 +161 +162 +163 +164 +165 +166 +167 +168 +169 +170 +171 +172 +173 +174 +175 +176 +177 +178 +179 +180 +181 +182 +183 +184 +185 +186 +187 +188 +189 +190 +191 +192 +193 +194 +195 +196 +197 +198 +199 +200 +201 +202 +203 +204 +205 +206 +207 +208 +209 +210 +211 +212 +213 +214 +215 +216 +217 +218 +219 +220 +221 +222 +223 +224 +225 +226 +227 +228 +229 +230 +231 +232 +233 +234 +235 +236 +237 +238 +239 +240 +241 +242 +243 +244 +245 +246 +247 +248 +249 +250 +251 +252 +253 +254 +255 +256 +257 +258 +259 +260 +261 +262 +263 +264 +265 +266 +267 +268 +269 +270 +271 +272 +273 +274 +275 +276 +277 +278 +279 +280 +281 +282 +283 +284 +285 +286 +287 +288 +289 +290 +291 +292 +293 +294 +295 +296 +297 +298 +299 +300 +301 +302 +303 +304 +305 +306 +307 +308 +309 +310 +311 +312 +313 +314 +315 +316 +317 +318 +319 +320 +321 +322 +323 +324 +325 +326 +327 +328 +329 +330 +331 +332 +333 +334 +335 +336 +337 +338 +339 +340 +341 +342 +343 +344 +345 +346 +347 +348 +349 +350 +351 +352 +353 +354 +355 +356 +357 +358  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +15x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +23x +23x +23x +23x +23x +23x +23x +23x +23x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  + 
/**
+ * AgentLifecycleController — Unified orchestrator for complete agent lifecycle.
+ *
+ * Replaces scattered lifecycle logic with comprehensive orchestration including:
+ * - Always clear signal.json before spawn/resume
+ * - Robust process completion waiting
+ * - Retry up to 3 times with comprehensive error handling
+ * - Auth/usage limit error detection with account switching
+ * - Missing signal recovery with instruction prompts
+ * - Debug mode archival vs production cleanup
+ */
+ 
+import { createModuleLogger } from '../../logger/index.js';
+import type { AgentRepository } from '../../db/repositories/agent-repository.js';
+import type { AccountRepository } from '../../db/repositories/account-repository.js';
+import type { ProcessManager } from '../process-manager.js';
+import type { CleanupManager } from '../cleanup-manager.js';
+import type { SpawnAgentOptions } from '../types.js';
+import type { SignalManager, SignalData } from './signal-manager.js';
+import type { RetryPolicy, AgentError } from './retry-policy.js';
+import { AgentExhaustedError, AgentFailureError } from './retry-policy.js';
+import type { AgentErrorAnalyzer } from './error-analyzer.js';
+import type { CleanupStrategy, AgentInfo } from './cleanup-strategy.js';
+ 
+const log = createModuleLogger('lifecycle-controller');
+ 
+export interface CompletionResult {
+  success: boolean;
+  signal?: SignalData;
+  error?: Error;
+  exitCode?: number | null;
+  stderr?: string;
+}
+ 
+export interface ResumeAgentOptions {
+  agentId: string;
+  answers: Record<string, string>;
+}
+ 
+export class AgentLifecycleController {
+  constructor(
+    private signalManager: SignalManager,
+    private retryPolicy: RetryPolicy,
+    private errorAnalyzer: AgentErrorAnalyzer,
+    private processManager: ProcessManager,
+    private repository: AgentRepository,
+    private cleanupManager: CleanupManager,
+    private cleanupStrategy: CleanupStrategy,
+    private accountRepository?: AccountRepository,
+    private debug: boolean = false,
+  ) {}
+ 
+  /**
+   * Execute spawn operation with comprehensive retry and error handling.
+   * Always clears signal.json before starting and waits for process completion.
+   */
+  async spawnWithRetry(
+    spawnFn: (options: SpawnAgentOptions) => Promise<AgentInfo>,
+    options: SpawnAgentOptions
+  ): Promise<AgentInfo> {
+    log.info({
+      taskId: options.taskId,
+      provider: options.provider,
+      initiativeId: options.initiativeId,
+      mode: options.mode
+    }, 'starting agent spawn with retry');
+ 
+    return this.executeWithRetry('spawn', spawnFn, options);
+  }
+ 
+  /**
+   * Execute resume operation with comprehensive retry and error handling.
+   * Always clears signal.json before resuming and waits for process completion.
+   */
+  async resumeWithRetry(
+    resumeFn: (agentId: string, answers: Record<string, string>) => Promise<void>,
+    options: ResumeAgentOptions
+  ): Promise<void> {
+    log.info({
+      agentId: options.agentId,
+      answerKeys: Object.keys(options.answers)
+    }, 'starting agent resume with retry');
+ 
+    await this.executeWithRetry('resume', async () => {
+      await resumeFn(options.agentId, options.answers);
+      const agent = await this.repository.findById(options.agentId);
+      if (!agent) throw new Error(`Agent '${options.agentId}' not found after resume`);
+      return this.toAgentInfo(agent);
+    }, options);
+  }
+ 
+  /**
+   * Main retry orchestrator for spawn/resume operations.
+   */
+  private async executeWithRetry<T>(
+    operation: 'spawn' | 'resume',
+    operationFn: (options: T) => Promise<AgentInfo>,
+    options: T
+  ): Promise<AgentInfo> {
+ 
+    for (let attempt = 1; attempt <= this.retryPolicy.maxAttempts; attempt++) {
+      try {
+        log.debug({ operation, attempt, maxAttempts: this.retryPolicy.maxAttempts }, 'starting attempt');
+ 
+        // Execute operation
+        const agent = await operationFn(options);
+        const agentWorkdir = this.processManager.getAgentWorkdir(agent.worktreeId);
+ 
+        // CRITICAL: Always clear signal.json before start
+        log.debug({ agentId: agent.id, agentWorkdir }, 'clearing signal.json before process start');
+        await this.signalManager.clearSignal(agentWorkdir);
+ 
+        // Wait for process completion with robust detection
+        const result = await this.waitForCompletion(agent);
+ 
+        if (result.success) {
+          // Handle post-completion cleanup
+          await this.handlePostCompletion(agent);
+          log.info({
+            agentId: agent.id,
+            name: agent.name,
+            attempt,
+            operation
+          }, 'agent lifecycle completed successfully');
+          return agent;
+        }
+ 
+        // Analyze error and determine retry strategy
+        const agentError = await this.errorAnalyzer.analyzeError(
+          result.error || new Error('Unknown completion failure'),
+          result.exitCode,
+          result.stderr,
+          agentWorkdir
+        );
+ 
+        // Persist error to DB if required
+        if (agentError.shouldPersistToDB) {
+          await this.persistError(agent.id, agentError);
+        }
+ 
+        // Handle account switching for usage limits
+        if (agentError.requiresAccountSwitch) {
+          await this.handleAccountExhaustion(agent.id);
+          throw new AgentExhaustedError(agentError.message, agentError);
+        }
+ 
+        // Check if should retry
+        if (!this.retryPolicy.shouldRetry(agentError, attempt)) {
+          log.warn({
+            agentId: agent.id,
+            errorType: agentError.type,
+            attempt,
+            maxAttempts: this.retryPolicy.maxAttempts
+          }, 'max retry attempts reached or error not retriable');
+          throw new AgentFailureError(agentError.message, agentError);
+        }
+ 
+        // Handle special retry cases
+        if (agentError.type === 'missing_signal') {
+          // This would need to modify the options to add instruction prompt
+          // For now, log the special case
+          log.info({
+            agentId: agent.id,
+            attempt
+          }, 'will retry with missing signal instruction (not yet implemented)');
+        }
+ 
+        // Wait before retry
+        const delay = this.retryPolicy.getRetryDelay(attempt);
+        log.info({
+          agentId: agent.id,
+          attempt,
+          delay,
+          errorType: agentError.type,
+          errorMessage: agentError.message
+        }, 'retrying after delay');
+        await this.delay(delay);
+ 
+      } catch (error) {
+        if (error instanceof AgentExhaustedError || error instanceof AgentFailureError) {
+          throw error; // Don't retry these
+        }
+ 
+        if (attempt === this.retryPolicy.maxAttempts) {
+          log.error({
+            operation,
+            attempt,
+            error: error instanceof Error ? error.message : String(error)
+          }, 'final attempt failed, giving up');
+          throw error;
+        }
+ 
+        log.warn({
+          operation,
+          attempt,
+          error: error instanceof Error ? error.message : String(error)
+        }, 'attempt failed, will retry');
+      }
+    }
+ 
+    throw new Error('Unexpected: retry loop completed without success or terminal error');
+  }
+ 
+  /**
+   * Wait for process completion with robust signal detection.
+   * Replaces scattered completion detection with unified approach.
+   */
+  private async waitForCompletion(agent: AgentInfo): Promise<CompletionResult> {
+    const agentWorkdir = this.processManager.getAgentWorkdir(agent.worktreeId);
+ 
+    log.debug({
+      agentId: agent.id,
+      name: agent.name,
+      agentWorkdir
+    }, 'waiting for process completion');
+ 
+    // Wait for process to exit (this would need integration with ProcessManager)
+    // For now, simulate with a timeout approach
+    // TODO: Implement waitForProcessCompletion in ProcessManager
+ 
+    // Wait for signal within reasonable timeout (30 seconds)
+    const signal = await this.signalManager.waitForSignal(agentWorkdir, 30000);
+ 
+    if (signal) {
+      log.debug({
+        agentId: agent.id,
+        signalStatus: signal.status
+      }, 'agent completed with valid signal');
+      return { success: true, signal };
+    }
+ 
+    // No signal found - this is an error condition
+    log.warn({
+      agentId: agent.id,
+      agentWorkdir
+    }, 'process completed without valid signal.json');
+ 
+    return {
+      success: false,
+      error: new Error('Process completed without valid signal.json'),
+      exitCode: null // Would get from ProcessManager
+    };
+  }
+ 
+  /**
+   * Handle post-completion cleanup based on agent status and debug mode.
+   */
+  private async handlePostCompletion(agent: AgentInfo): Promise<void> {
+    // Only cleanup if agent is not waiting for user input
+    if (agent.status === 'waiting_for_input') {
+      log.debug({ agentId: agent.id }, 'agent waiting for input, skipping cleanup');
+      return;
+    }
+ 
+    try {
+      const cleanupAction = await this.cleanupStrategy.shouldCleanup(agent, this.debug);
+      await this.cleanupStrategy.executeCleanup(agent, cleanupAction);
+ 
+      log.debug({
+        agentId: agent.id,
+        name: agent.name,
+        cleanupAction
+      }, 'post-completion cleanup executed');
+    } catch (error) {
+      log.warn({
+        agentId: agent.id,
+        error: error instanceof Error ? error.message : String(error)
+      }, 'post-completion cleanup failed');
+    }
+  }
+ 
+  /**
+   * Persist error details to database for debugging.
+   */
+  private async persistError(agentId: string, error: AgentError): Promise<void> {
+    try {
+      const errorData = {
+        errorType: error.type,
+        errorMessage: error.message,
+        exitCode: error.exitCode,
+        isTransient: error.isTransient,
+        requiresAccountSwitch: error.requiresAccountSwitch,
+        updatedAt: new Date(),
+      };
+ 
+      // This would need database schema updates to store error details
+      // For now, just update with basic error info
+      await this.repository.update(agentId, {
+        exitCode: error.exitCode,
+        updatedAt: new Date(),
+      });
+ 
+      log.debug({
+        agentId,
+        errorType: error.type,
+        exitCode: error.exitCode
+      }, 'error details persisted to database');
+    } catch (dbError) {
+      log.warn({
+        agentId,
+        error: dbError instanceof Error ? dbError.message : String(dbError)
+      }, 'failed to persist error to database');
+    }
+  }
+ 
+  /**
+   * Handle account exhaustion by marking account as exhausted.
+   */
+  private async handleAccountExhaustion(agentId: string): Promise<void> {
+    if (!this.accountRepository) {
+      log.debug({ agentId }, 'no account repository available for exhaustion handling');
+      return;
+    }
+ 
+    try {
+      const agent = await this.repository.findById(agentId);
+      if (!agent?.accountId) {
+        log.debug({ agentId }, 'agent has no account ID for exhaustion handling');
+        return;
+      }
+ 
+      // Mark account as exhausted for 1 hour
+      const exhaustedUntil = new Date(Date.now() + 60 * 60 * 1000);
+      await this.accountRepository.markExhausted(agent.accountId, exhaustedUntil);
+ 
+      log.info({
+        agentId,
+        accountId: agent.accountId,
+        exhaustedUntil
+      }, 'marked account as exhausted due to usage limits');
+    } catch (error) {
+      log.warn({
+        agentId,
+        error: error instanceof Error ? error.message : String(error)
+      }, 'failed to mark account as exhausted');
+    }
+  }
+ 
+  /**
+   * Simple delay utility for retry backoff.
+   */
+  private delay(ms: number): Promise<void> {
+    return new Promise(resolve => setTimeout(resolve, ms));
+  }
+ 
+  /**
+   * Convert database agent record to AgentInfo.
+   */
+  private toAgentInfo(agent: any): AgentInfo {
+    return {
+      id: agent.id,
+      name: agent.name,
+      status: agent.status,
+      initiativeId: agent.initiativeId,
+      worktreeId: agent.worktreeId,
+    };
+  }
+}
+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/coverage/src/agent/lifecycle/error-analyzer.ts.html b/coverage/src/agent/lifecycle/error-analyzer.ts.html new file mode 100644 index 0000000..9f77afd --- /dev/null +++ b/coverage/src/agent/lifecycle/error-analyzer.ts.html @@ -0,0 +1,781 @@ + + + + + + Code coverage report for src/agent/lifecycle/error-analyzer.ts + + + + + + + + + +
+
+

All files / src/agent/lifecycle error-analyzer.ts

+
+ +
+ 88.63% + Statements + 39/44 +
+ + +
+ 81.25% + Branches + 39/48 +
+ + +
+ 85.71% + Functions + 6/7 +
+ + +
+ 90.24% + Lines + 37/41 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+

+
1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 +30 +31 +32 +33 +34 +35 +36 +37 +38 +39 +40 +41 +42 +43 +44 +45 +46 +47 +48 +49 +50 +51 +52 +53 +54 +55 +56 +57 +58 +59 +60 +61 +62 +63 +64 +65 +66 +67 +68 +69 +70 +71 +72 +73 +74 +75 +76 +77 +78 +79 +80 +81 +82 +83 +84 +85 +86 +87 +88 +89 +90 +91 +92 +93 +94 +95 +96 +97 +98 +99 +100 +101 +102 +103 +104 +105 +106 +107 +108 +109 +110 +111 +112 +113 +114 +115 +116 +117 +118 +119 +120 +121 +122 +123 +124 +125 +126 +127 +128 +129 +130 +131 +132 +133 +134 +135 +136 +137 +138 +139 +140 +141 +142 +143 +144 +145 +146 +147 +148 +149 +150 +151 +152 +153 +154 +155 +156 +157 +158 +159 +160 +161 +162 +163 +164 +165 +166 +167 +168 +169 +170 +171 +172 +173 +174 +175 +176 +177 +178 +179 +180 +181 +182 +183 +184 +185 +186 +187 +188 +189 +190 +191 +192 +193 +194 +195 +196 +197 +198 +199 +200 +201 +202 +203 +204 +205 +206 +207 +208 +209 +210 +211 +212 +213 +214 +215 +216 +217 +218 +219 +220 +221 +222 +223 +224 +225 +226 +227 +228 +229 +230 +231 +232 +233  +  +  +  +  +  +  +  +  +  +  +  +16x +  +  +16x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +44x +  +  +  +  +  +  +  +  +  +  +  +21x +21x +  +21x +  +  +  +  +  +  +  +21x +4x +  +  +  +  +  +  +  +  +  +  +  +17x +4x +  +  +  +  +  +  +  +  +  +  +  +13x +2x +  +  +  +  +  +  +  +  +  +  +  +11x +2x +2x +1x +1x +  +  +  +  +  +  +  +  +  +  +  +  +10x +  +  +  +6x +  +6x +  +  +  +  +  +  +  +  +  +  +  +4x +  +  +  +  +  +21x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +61x +347x +  +  +  +  +  +  +  +  +6x +  +  +  +  +  +  +6x +6x +4x +4x +  +  +  +2x +1x +1x +  +  +  +  +1x +1x +  +  +  +  +  +  +  +  +6x +  +  +  +  +  +1x +1x +  + 
/**
+ * ErrorAnalyzer — Intelligent error classification and handling strategies.
+ *
+ * Analyzes various error conditions from agent processes and classifies them
+ * for appropriate retry and recovery strategies. Replaces scattered error
+ * handling with centralized, comprehensive error analysis.
+ */
+ 
+import { createModuleLogger } from '../../logger/index.js';
+import type { SignalManager } from './signal-manager.js';
+import type { AgentError, AgentErrorType } from './retry-policy.js';
+ 
+const log = createModuleLogger('error-analyzer');
+ 
+// Common error patterns for different providers
+const ERROR_PATTERNS = {
+  auth_failure: [
+    /unauthorized/i,
+    /invalid.*(token|key|credential)/i,
+    /authentication.*failed/i,
+    /401/,
+    /access.*denied/i,
+    /invalid.*session/i,
+    /expired.*token/i,
+  ],
+  usage_limit: [
+    /rate.*(limit|exceeded)/i,
+    /quota.*exceeded/i,
+    /too.*many.*requests/i,
+    /429/,
+    /usage.*limit/i,
+    /throttled/i,
+    /credit.*insufficient/i,
+    /api.*limit.*reached/i,
+  ],
+  timeout: [
+    /timeout/i,
+    /timed.*out/i,
+    /deadline.*exceeded/i,
+    /connection.*timeout/i,
+    /read.*timeout/i,
+  ],
+  process_crash: [
+    /segmentation.*fault/i,
+    /core.*dumped/i,
+    /fatal.*error/i,
+    /killed/i,
+    /aborted/i,
+  ],
+};
+ 
+export class AgentErrorAnalyzer {
+  constructor(private signalManager: SignalManager) {}
+ 
+  /**
+   * Analyze an error and classify it for retry strategy.
+   * Combines multiple signals: error message, exit code, stderr, and workdir state.
+   */
+  async analyzeError(
+    error: Error | string,
+    exitCode?: number | null,
+    stderr?: string,
+    agentWorkdir?: string
+  ): Promise<AgentError> {
+    const errorMessage = error instanceof Error ? error.message : String(error);
+    const fullContext = [errorMessage, stderr].filter(Boolean).join(' ');
+ 
+    log.debug({
+      errorMessage,
+      exitCode,
+      hasStderr: !!stderr,
+      hasWorkdir: !!agentWorkdir
+    }, 'analyzing agent error');
+ 
+    // Check for auth failure patterns
+    if (this.matchesPattern(fullContext, ERROR_PATTERNS.auth_failure)) {
+      return {
+        type: 'auth_failure',
+        message: errorMessage,
+        isTransient: true,
+        requiresAccountSwitch: false,
+        shouldPersistToDB: true,
+        exitCode,
+        originalError: error instanceof Error ? error : undefined,
+      };
+    }
+ 
+    // Check for usage limit patterns
+    if (this.matchesPattern(fullContext, ERROR_PATTERNS.usage_limit)) {
+      return {
+        type: 'usage_limit',
+        message: errorMessage,
+        isTransient: false,
+        requiresAccountSwitch: true,
+        shouldPersistToDB: true,
+        exitCode,
+        originalError: error instanceof Error ? error : undefined,
+      };
+    }
+ 
+    // Check for timeout patterns
+    if (this.matchesPattern(fullContext, ERROR_PATTERNS.timeout)) {
+      return {
+        type: 'timeout',
+        message: errorMessage,
+        isTransient: true,
+        requiresAccountSwitch: false,
+        shouldPersistToDB: true,
+        exitCode,
+        originalError: error instanceof Error ? error : undefined,
+      };
+    }
+ 
+    // Special case: process completed successfully but no signal.json
+    if (agentWorkdir && exitCode === 0) {
+      const hasSignal = await this.signalManager.checkSignalExists(agentWorkdir);
+      if (!hasSignal) {
+        log.debug({ agentWorkdir }, 'process completed successfully but no signal.json found');
+        return {
+          type: 'missing_signal',
+          message: 'Process completed successfully but no signal.json was generated',
+          isTransient: true,
+          requiresAccountSwitch: false,
+          shouldPersistToDB: false,
+          exitCode,
+          originalError: error instanceof Error ? error : undefined,
+        };
+      }
+    }
+ 
+    // Check for process crash patterns
+    if (this.matchesPattern(fullContext, ERROR_PATTERNS.process_crash) ||
+        (exitCode !== null && exitCode !== 0 && exitCode !== undefined)) {
+ 
+      // Determine if crash is transient based on exit code and patterns
+      const isTransient = this.isTransientCrash(exitCode, stderr);
+ 
+      return {
+        type: 'process_crash',
+        message: errorMessage,
+        isTransient,
+        requiresAccountSwitch: false,
+        shouldPersistToDB: true,
+        exitCode,
+        originalError: error instanceof Error ? error : undefined,
+      };
+    }
+ 
+    // Unknown error type
+    log.debug({
+      errorMessage,
+      exitCode,
+      stderr: stderr?.substring(0, 200) + '...'
+    }, 'error does not match known patterns, classifying as unknown');
+ 
+    return {
+      type: 'unknown',
+      message: errorMessage,
+      isTransient: false,
+      requiresAccountSwitch: false,
+      shouldPersistToDB: true,
+      exitCode,
+      originalError: error instanceof Error ? error : undefined,
+    };
+  }
+ 
+  /**
+   * Validate credentials with a brief test request using invalid token.
+   * This helps distinguish between token expiry vs. account exhaustion.
+   */
+  async validateTokenWithInvalidRequest(accountId: string): Promise<boolean> {
+    // User requirement: "brief check with invalid access token to determine behavior"
+    // This would need integration with credential system and is provider-specific
+    // For now, return true to indicate token appears valid
+    log.debug({ accountId }, 'token validation requested (not yet implemented)');
+    return true;
+  }
+ 
+  /**
+   * Check if error message or stderr matches any of the given patterns.
+   */
+  private matchesPattern(text: string, patterns: RegExp[]): boolean {
+    Iif (!text) return false;
+    return patterns.some(pattern => pattern.test(text));
+  }
+ 
+  /**
+   * Determine if a process crash is likely transient (can be retried).
+   * Based on exit codes and stderr content.
+   */
+  private isTransientCrash(exitCode?: number | null, stderr?: string): boolean {
+    // Exit codes that indicate transient failures
+    const transientExitCodes = new Set([
+      130, // SIGINT (interrupted)
+      143, // SIGTERM (terminated)
+      124, // timeout command
+      1,   // Generic error (might be transient)
+    ]);
+ 
+    Eif (exitCode !== null && exitCode !== undefined) {
+      if (transientExitCodes.has(exitCode)) {
+        log.debug({ exitCode }, 'exit code indicates transient failure');
+        return true;
+      }
+ 
+      // Very high exit codes often indicate system issues
+      if (exitCode > 128 && exitCode < 256) {
+        log.debug({ exitCode }, 'signal-based exit code may be transient');
+        return true;
+      }
+    }
+ 
+    // Check stderr for transient patterns
+    Eif (stderr) {
+      const transientPatterns = [
+        /temporary/i,
+        /network.*error/i,
+        /connection.*refused/i,
+        /service.*unavailable/i,
+        /disk.*full/i,
+        /out.*of.*memory/i,
+      ];
+ 
+      Iif (transientPatterns.some(pattern => pattern.test(stderr))) {
+        log.debug({ stderr: stderr.substring(0, 100) + '...' }, 'stderr indicates transient failure');
+        return true;
+      }
+    }
+ 
+    log.debug({ exitCode, hasStderr: !!stderr }, 'crash appears non-transient');
+    return false;
+  }
+}
+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/coverage/src/agent/lifecycle/factory.ts.html b/coverage/src/agent/lifecycle/factory.ts.html new file mode 100644 index 0000000..eac6b53 --- /dev/null +++ b/coverage/src/agent/lifecycle/factory.ts.html @@ -0,0 +1,256 @@ + + + + + + Code coverage report for src/agent/lifecycle/factory.ts + + + + + + + + + +
+
+

All files / src/agent/lifecycle factory.ts

+
+ +
+ 100% + Statements + 7/7 +
+ + +
+ 100% + Branches + 1/1 +
+ + +
+ 100% + Functions + 1/1 +
+ + +
+ 100% + Lines + 7/7 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+

+
1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 +30 +31 +32 +33 +34 +35 +36 +37 +38 +39 +40 +41 +42 +43 +44 +45 +46 +47 +48 +49 +50 +51 +52 +53 +54 +55 +56 +57 +58  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +23x +  +  +23x +23x +23x +23x +  +  +23x +  +  +  +  +  +  +  +  +  +  +  +23x + 
/**
+ * Lifecycle Factory — Wire up all lifecycle components with proper dependencies.
+ *
+ * Creates and configures the complete lifecycle management system with all
+ * dependencies properly injected. Provides simple entry point for integration.
+ */
+ 
+import { FileSystemSignalManager } from './signal-manager.js';
+import { DefaultRetryPolicy } from './retry-policy.js';
+import { AgentErrorAnalyzer } from './error-analyzer.js';
+import { DefaultCleanupStrategy } from './cleanup-strategy.js';
+import { AgentLifecycleController } from './controller.js';
+import type { AgentRepository } from '../../db/repositories/agent-repository.js';
+import type { AccountRepository } from '../../db/repositories/account-repository.js';
+import type { ProcessManager } from '../process-manager.js';
+import type { CleanupManager } from '../cleanup-manager.js';
+ 
+export interface LifecycleFactoryOptions {
+  repository: AgentRepository;
+  processManager: ProcessManager;
+  cleanupManager: CleanupManager;
+  accountRepository?: AccountRepository;
+  debug?: boolean;
+}
+ 
+/**
+ * Create a fully configured AgentLifecycleController with all dependencies.
+ */
+export function createLifecycleController(options: LifecycleFactoryOptions): AgentLifecycleController {
+  const {
+    repository,
+    processManager,
+    cleanupManager,
+    accountRepository,
+    debug = false
+  } = options;
+ 
+  // Create core components
+  const signalManager = new FileSystemSignalManager();
+  const retryPolicy = new DefaultRetryPolicy();
+  const errorAnalyzer = new AgentErrorAnalyzer(signalManager);
+  const cleanupStrategy = new DefaultCleanupStrategy(cleanupManager);
+ 
+  // Wire up the main controller
+  const lifecycleController = new AgentLifecycleController(
+    signalManager,
+    retryPolicy,
+    errorAnalyzer,
+    processManager,
+    repository,
+    cleanupManager,
+    cleanupStrategy,
+    accountRepository,
+    debug
+  );
+ 
+  return lifecycleController;
+}
+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/coverage/src/agent/lifecycle/index.html b/coverage/src/agent/lifecycle/index.html new file mode 100644 index 0000000..3973935 --- /dev/null +++ b/coverage/src/agent/lifecycle/index.html @@ -0,0 +1,206 @@ + + + + + + Code coverage report for src/agent/lifecycle + + + + + + + + + +
+
+

All files src/agent/lifecycle

+
+ +
+ 52.45% + Statements + 139/265 +
+ + +
+ 49.31% + Branches + 72/146 +
+ + +
+ 52.94% + Functions + 18/34 +
+ + +
+ 52.71% + Lines + 136/258 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
FileStatementsBranchesFunctionsLines
cleanup-strategy.ts +
+
6.06%2/330%0/2133.33%1/36.06%2/33
controller.ts +
+
11.23%10/892.56%1/398.33%1/1211.62%10/86
error-analyzer.ts +
+
88.63%39/4481.25%39/4885.71%6/790.24%37/41
factory.ts +
+
100%7/7100%1/1100%1/1100%7/7
instructions.ts +
+
100%2/2100%0/0100%1/1100%2/2
retry-policy.ts +
+
80%24/3090.9%10/1150%2/480%24/30
signal-manager.ts +
+
91.66%55/6080.76%21/26100%6/691.52%54/59
+
+
+
+ + + + + + + + \ No newline at end of file diff --git a/coverage/src/agent/lifecycle/instructions.ts.html b/coverage/src/agent/lifecycle/instructions.ts.html new file mode 100644 index 0000000..f8baa81 --- /dev/null +++ b/coverage/src/agent/lifecycle/instructions.ts.html @@ -0,0 +1,166 @@ + + + + + + Code coverage report for src/agent/lifecycle/instructions.ts + + + + + + + + + +
+
+

All files / src/agent/lifecycle instructions.ts

+
+ +
+ 100% + Statements + 2/2 +
+ + +
+ 100% + Branches + 0/0 +
+ + +
+ 100% + Functions + 1/1 +
+ + +
+ 100% + Lines + 2/2 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+

+
1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28  +  +  +  +1x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +4x + 
/**
+ * Instructions for agent retry scenarios
+ */
+ 
+export const MISSING_SIGNAL_INSTRUCTION = `
+ 
+IMPORTANT: Your previous execution completed but did not generate the required signal.json file.
+ 
+Please ensure you complete your task and create a signal.json file at .cw/output/signal.json with one of these formats:
+ 
+For successful completion:
+{"status": "done"}
+ 
+For questions requiring user input:
+{"status": "questions", "questions": [{"id": "q1", "question": "Your question here"}]}
+ 
+For errors:
+{"status": "error", "error": "Description of the error"}
+ 
+Please retry your task and ensure the signal.json file is properly created.
+`;
+ 
+/**
+ * Adds an instruction to the beginning of a prompt
+ */
+export function addInstructionToPrompt(originalPrompt: string, instruction: string): string {
+  return `${instruction.trim()}\n\n${originalPrompt}`;
+}
+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/coverage/src/agent/lifecycle/retry-policy.ts.html b/coverage/src/agent/lifecycle/retry-policy.ts.html new file mode 100644 index 0000000..89f4474 --- /dev/null +++ b/coverage/src/agent/lifecycle/retry-policy.ts.html @@ -0,0 +1,445 @@ + + + + + + Code coverage report for src/agent/lifecycle/retry-policy.ts + + + + + + + + + +
+
+

All files / src/agent/lifecycle retry-policy.ts

+
+ +
+ 80% + Statements + 24/30 +
+ + +
+ 90.9% + Branches + 10/11 +
+ + +
+ 50% + Functions + 2/4 +
+ + +
+ 80% + Lines + 24/30 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+

+
1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 +30 +31 +32 +33 +34 +35 +36 +37 +38 +39 +40 +41 +42 +43 +44 +45 +46 +47 +48 +49 +50 +51 +52 +53 +54 +55 +56 +57 +58 +59 +60 +61 +62 +63 +64 +65 +66 +67 +68 +69 +70 +71 +72 +73 +74 +75 +76 +77 +78 +79 +80 +81 +82 +83 +84 +85 +86 +87 +88 +89 +90 +91 +92 +93 +94 +95 +96 +97 +98 +99 +100 +101 +102 +103 +104 +105 +106 +107 +108 +109 +110 +111 +112 +113 +114 +115 +116 +117 +118 +119 +120 +121  +  +  +  +  +  +  +  +  +16x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +35x +35x +  +  +19x +5x +  +  +  +  +5x +  +  +14x +  +  +2x +2x +  +  +  +2x +2x +  +  +  +2x +2x +  +  +  +4x +4x +  +  +  +  +  +4x +  +  +  +2x +2x +  +  +  +  +2x +2x +  +  +  +  +5x +5x +  +5x +5x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  + 
/**
+ * RetryPolicy — Comprehensive retry logic with error-specific handling.
+ *
+ * Implements intelligent retry strategies for different types of agent failures.
+ * Replaces scattered retry logic with unified, configurable policies.
+ */
+ 
+import { createModuleLogger } from '../../logger/index.js';
+ 
+const log = createModuleLogger('retry-policy');
+ 
+export type AgentErrorType =
+  | 'auth_failure'     // 401 errors, invalid tokens
+  | 'usage_limit'      // Rate limiting, quota exceeded
+  | 'missing_signal'   // Process completed but no signal.json
+  | 'process_crash'    // Process exited with error code
+  | 'timeout'          // Process timed out
+  | 'unknown';         // Unclassified errors
+ 
+export interface AgentError {
+  type: AgentErrorType;
+  message: string;
+  isTransient: boolean;         // Can this error be resolved by retrying?
+  requiresAccountSwitch: boolean; // Should we switch to next account?
+  shouldPersistToDB: boolean;   // Should this error be saved for debugging?
+  exitCode?: number | null;
+  signal?: string | null;
+  originalError?: Error;
+}
+ 
+export interface RetryPolicy {
+  readonly maxAttempts: number;
+  readonly backoffMs: number[];
+  shouldRetry(error: AgentError, attempt: number): boolean;
+  getRetryDelay(attempt: number): number;
+}
+ 
+export class DefaultRetryPolicy implements RetryPolicy {
+  readonly maxAttempts = 3;
+  readonly backoffMs = [1000, 2000, 4000]; // 1s, 2s, 4s exponential backoff
+ 
+  shouldRetry(error: AgentError, attempt: number): boolean {
+    if (attempt >= this.maxAttempts) {
+      log.debug({
+        errorType: error.type,
+        attempt,
+        maxAttempts: this.maxAttempts
+      }, 'max retry attempts reached');
+      return false;
+    }
+ 
+    switch (error.type) {
+      case 'auth_failure':
+        // Retry auth failures - tokens might be refreshed
+        log.debug({ attempt, errorType: error.type }, 'retrying auth failure');
+        return true;
+ 
+      case 'usage_limit':
+        // Don't retry usage limits - need account switch
+        log.debug({ attempt, errorType: error.type }, 'not retrying usage limit - requires account switch');
+        return false;
+ 
+      case 'missing_signal':
+        // Retry missing signal - add instruction prompt
+        log.debug({ attempt, errorType: error.type }, 'retrying missing signal with instruction');
+        return true;
+ 
+      case 'process_crash':
+        // Only retry transient crashes
+        const shouldRetryTransient = error.isTransient;
+        log.debug({
+          attempt,
+          errorType: error.type,
+          isTransient: error.isTransient,
+          shouldRetry: shouldRetryTransient
+        }, 'process crash retry decision');
+        return shouldRetryTransient;
+ 
+      case 'timeout':
+        // Retry timeouts up to max attempts
+        log.debug({ attempt, errorType: error.type }, 'retrying timeout');
+        return true;
+ 
+      case 'unknown':
+      default:
+        // Don't retry unknown errors by default
+        log.debug({ attempt, errorType: error.type }, 'not retrying unknown error');
+        return false;
+    }
+  }
+ 
+  getRetryDelay(attempt: number): number {
+    const index = Math.min(attempt - 1, this.backoffMs.length - 1);
+    const delay = this.backoffMs[index] || this.backoffMs[this.backoffMs.length - 1];
+ 
+    log.debug({ attempt, delay }, 'retry delay calculated');
+    return delay;
+  }
+}
+ 
+/**
+ * AgentExhaustedError - Special error indicating account needs switching.
+ * When thrown, caller should attempt account failover rather than retry.
+ */
+export class AgentExhaustedError extends Error {
+  constructor(message: string, public readonly originalError?: AgentError) {
+    super(message);
+    this.name = 'AgentExhaustedError';
+  }
+}
+ 
+/**
+ * AgentFailureError - Terminal failure that cannot be retried.
+ * Indicates all retry attempts have been exhausted or error is non-retriable.
+ */
+export class AgentFailureError extends Error {
+  constructor(message: string, public readonly originalError?: AgentError) {
+    super(message);
+    this.name = 'AgentFailureError';
+  }
+}
+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/coverage/src/agent/lifecycle/signal-manager.ts.html b/coverage/src/agent/lifecycle/signal-manager.ts.html new file mode 100644 index 0000000..3771ff3 --- /dev/null +++ b/coverage/src/agent/lifecycle/signal-manager.ts.html @@ -0,0 +1,616 @@ + + + + + + Code coverage report for src/agent/lifecycle/signal-manager.ts + + + + + + + + + +
+
+

All files / src/agent/lifecycle signal-manager.ts

+
+ +
+ 91.66% + Statements + 55/60 +
+ + +
+ 80.76% + Branches + 21/26 +
+ + +
+ 100% + Functions + 6/6 +
+ + +
+ 91.52% + Lines + 54/59 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+

+
1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 +30 +31 +32 +33 +34 +35 +36 +37 +38 +39 +40 +41 +42 +43 +44 +45 +46 +47 +48 +49 +50 +51 +52 +53 +54 +55 +56 +57 +58 +59 +60 +61 +62 +63 +64 +65 +66 +67 +68 +69 +70 +71 +72 +73 +74 +75 +76 +77 +78 +79 +80 +81 +82 +83 +84 +85 +86 +87 +88 +89 +90 +91 +92 +93 +94 +95 +96 +97 +98 +99 +100 +101 +102 +103 +104 +105 +106 +107 +108 +109 +110 +111 +112 +113 +114 +115 +116 +117 +118 +119 +120 +121 +122 +123 +124 +125 +126 +127 +128 +129 +130 +131 +132 +133 +134 +135 +136 +137 +138 +139 +140 +141 +142 +143 +144 +145 +146 +147 +148 +149 +150 +151 +152 +153 +154 +155 +156 +157 +158 +159 +160 +161 +162 +163 +164 +165 +166 +167 +168 +169 +170 +171 +172 +173 +174 +175 +176 +177 +178  +  +  +  +  +  +  +  +  +  +  +  +16x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +2x +2x +2x +1x +  +1x +  +  +  +  +1x +  +  +  +  +  +  +  +3x +3x +  +  +  +  +  +  +  +12x +  +12x +12x +4x +  +  +8x +8x +  +8x +1x +1x +  +  +7x +  +  +7x +1x +1x +  +  +5x +5x +  +  +1x +  +  +  +  +1x +  +  +  +  +  +  +  +  +3x +3x +3x +  +3x +  +3x +5x +5x +2x +  +  +  +  +  +2x +  +  +  +3x +3x +3x +  +  +1x +  +  +  +  +  +1x +  +  +  +  +  +  +  +4x +4x +1x +  +  +  +3x +3x +1x +  +  +2x +2x +  +2x +  +  +  +  +2x +4x +1x +  +  +  +1x +1x +  +  +  +  +  +  + 
/**
+ * SignalManager — Centralized signal.json operations with atomic file handling.
+ *
+ * Provides robust signal.json management with proper error handling and atomic
+ * operations. Replaces scattered signal detection logic throughout the codebase.
+ */
+ 
+import { readFile, unlink, stat } from 'node:fs/promises';
+import { existsSync } from 'node:fs';
+import { join } from 'node:path';
+import { createModuleLogger } from '../../logger/index.js';
+ 
+const log = createModuleLogger('signal-manager');
+ 
+export interface SignalData {
+  status: 'done' | 'questions' | 'error';
+  questions?: Array<{
+    id: string;
+    question: string;
+    options?: string[];
+  }>;
+  error?: string;
+}
+ 
+export interface SignalManager {
+  clearSignal(agentWorkdir: string): Promise<void>;
+  checkSignalExists(agentWorkdir: string): Promise<boolean>;
+  readSignal(agentWorkdir: string): Promise<SignalData | null>;
+  waitForSignal(agentWorkdir: string, timeoutMs: number): Promise<SignalData | null>;
+  validateSignalFile(signalPath: string): Promise<boolean>;
+}
+ 
+export class FileSystemSignalManager implements SignalManager {
+  /**
+   * Clear signal.json file atomically. Always called before spawn/resume.
+   * This prevents race conditions in completion detection.
+   */
+  async clearSignal(agentWorkdir: string): Promise<void> {
+    const signalPath = join(agentWorkdir, '.cw/output/signal.json');
+    try {
+      await unlink(signalPath);
+      log.debug({ agentWorkdir, signalPath }, 'signal.json cleared successfully');
+    } catch (error: any) {
+      Iif (error.code !== 'ENOENT') {
+        log.warn({ agentWorkdir, signalPath, error: error.message }, 'failed to clear signal.json');
+        throw error;
+      }
+      // File doesn't exist - that's fine, it's already "cleared"
+      log.debug({ agentWorkdir, signalPath }, 'signal.json already absent (nothing to clear)');
+    }
+  }
+ 
+  /**
+   * Check if signal.json file exists synchronously.
+   */
+  async checkSignalExists(agentWorkdir: string): Promise<boolean> {
+    const signalPath = join(agentWorkdir, '.cw/output/signal.json');
+    return existsSync(signalPath);
+  }
+ 
+  /**
+   * Read and parse signal.json file with robust error handling.
+   * Returns null if file doesn't exist or is invalid.
+   */
+  async readSignal(agentWorkdir: string): Promise<SignalData | null> {
+    const signalPath = join(agentWorkdir, '.cw/output/signal.json');
+ 
+    try {
+      if (!existsSync(signalPath)) {
+        return null;
+      }
+ 
+      const content = await readFile(signalPath, 'utf-8');
+      const trimmed = content.trim();
+ 
+      if (!trimmed) {
+        log.debug({ agentWorkdir, signalPath }, 'signal.json is empty');
+        return null;
+      }
+ 
+      const signal = JSON.parse(trimmed) as SignalData;
+ 
+      // Basic validation
+      if (!signal.status || !['done', 'questions', 'error'].includes(signal.status)) {
+        log.warn({ agentWorkdir, signalPath, signal }, 'signal.json has invalid status');
+        return null;
+      }
+ 
+      log.debug({ agentWorkdir, signalPath, status: signal.status }, 'signal.json read successfully');
+      return signal;
+ 
+    } catch (error) {
+      log.warn({
+        agentWorkdir,
+        signalPath,
+        error: error instanceof Error ? error.message : String(error)
+      }, 'failed to read or parse signal.json');
+      return null;
+    }
+  }
+ 
+  /**
+   * Wait for signal.json to appear and be valid, with exponential backoff polling.
+   * Returns null if timeout is reached or signal is never valid.
+   */
+  async waitForSignal(agentWorkdir: string, timeoutMs: number): Promise<SignalData | null> {
+    const startTime = Date.now();
+    const signalPath = join(agentWorkdir, '.cw/output/signal.json');
+    let attempt = 0;
+ 
+    log.debug({ agentWorkdir, timeoutMs }, 'waiting for signal.json to appear');
+ 
+    while (Date.now() - startTime < timeoutMs) {
+      const signal = await this.readSignal(agentWorkdir);
+      if (signal) {
+        log.debug({
+          agentWorkdir,
+          signalPath,
+          status: signal.status,
+          waitTime: Date.now() - startTime
+        }, 'signal.json found and valid');
+        return signal;
+      }
+ 
+      // Exponential backoff: 100ms, 200ms, 400ms, 800ms, then 1s max
+      const delay = Math.min(100 * Math.pow(2, attempt), 1000);
+      await new Promise(resolve => setTimeout(resolve, delay));
+      attempt++;
+    }
+ 
+    log.debug({
+      agentWorkdir,
+      signalPath,
+      timeoutMs,
+      totalWaitTime: Date.now() - startTime
+    }, 'timeout waiting for signal.json');
+    return null;
+  }
+ 
+  /**
+   * Validate that a signal file is complete and properly formatted.
+   * Used to detect if file is still being written vs. truly missing/incomplete.
+   */
+  async validateSignalFile(signalPath: string): Promise<boolean> {
+    try {
+      if (!existsSync(signalPath)) {
+        return false;
+      }
+ 
+      // Check file is not empty and appears complete
+      const stats = await stat(signalPath);
+      if (stats.size === 0) {
+        return false;
+      }
+ 
+      const content = await readFile(signalPath, 'utf-8');
+      const trimmed = content.trim();
+ 
+      Iif (!trimmed) {
+        return false;
+      }
+ 
+      // Check if JSON structure appears complete
+      const endsCorrectly = trimmed.endsWith('}') || trimmed.endsWith(']');
+      if (!endsCorrectly) {
+        return false;
+      }
+ 
+      // Try to parse as JSON to ensure it's valid
+      JSON.parse(trimmed);
+      return true;
+ 
+    } catch (error) {
+      log.debug({ signalPath, error: error instanceof Error ? error.message : String(error) }, 'signal file validation failed');
+      return false;
+    }
+  }
+}
+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/coverage/src/agent/manager.ts.html b/coverage/src/agent/manager.ts.html new file mode 100644 index 0000000..74bb2c1 --- /dev/null +++ b/coverage/src/agent/manager.ts.html @@ -0,0 +1,2926 @@ + + + + + + Code coverage report for src/agent/manager.ts + + + + + + + + + +
+
+

All files / src/agent manager.ts

+
+ +
+ 48.11% + Statements + 166/345 +
+ + +
+ 36.41% + Branches + 59/162 +
+ + +
+ 32.72% + Functions + 18/55 +
+ + +
+ 48.28% + Lines + 155/321 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+

+
1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 +30 +31 +32 +33 +34 +35 +36 +37 +38 +39 +40 +41 +42 +43 +44 +45 +46 +47 +48 +49 +50 +51 +52 +53 +54 +55 +56 +57 +58 +59 +60 +61 +62 +63 +64 +65 +66 +67 +68 +69 +70 +71 +72 +73 +74 +75 +76 +77 +78 +79 +80 +81 +82 +83 +84 +85 +86 +87 +88 +89 +90 +91 +92 +93 +94 +95 +96 +97 +98 +99 +100 +101 +102 +103 +104 +105 +106 +107 +108 +109 +110 +111 +112 +113 +114 +115 +116 +117 +118 +119 +120 +121 +122 +123 +124 +125 +126 +127 +128 +129 +130 +131 +132 +133 +134 +135 +136 +137 +138 +139 +140 +141 +142 +143 +144 +145 +146 +147 +148 +149 +150 +151 +152 +153 +154 +155 +156 +157 +158 +159 +160 +161 +162 +163 +164 +165 +166 +167 +168 +169 +170 +171 +172 +173 +174 +175 +176 +177 +178 +179 +180 +181 +182 +183 +184 +185 +186 +187 +188 +189 +190 +191 +192 +193 +194 +195 +196 +197 +198 +199 +200 +201 +202 +203 +204 +205 +206 +207 +208 +209 +210 +211 +212 +213 +214 +215 +216 +217 +218 +219 +220 +221 +222 +223 +224 +225 +226 +227 +228 +229 +230 +231 +232 +233 +234 +235 +236 +237 +238 +239 +240 +241 +242 +243 +244 +245 +246 +247 +248 +249 +250 +251 +252 +253 +254 +255 +256 +257 +258 +259 +260 +261 +262 +263 +264 +265 +266 +267 +268 +269 +270 +271 +272 +273 +274 +275 +276 +277 +278 +279 +280 +281 +282 +283 +284 +285 +286 +287 +288 +289 +290 +291 +292 +293 +294 +295 +296 +297 +298 +299 +300 +301 +302 +303 +304 +305 +306 +307 +308 +309 +310 +311 +312 +313 +314 +315 +316 +317 +318 +319 +320 +321 +322 +323 +324 +325 +326 +327 +328 +329 +330 +331 +332 +333 +334 +335 +336 +337 +338 +339 +340 +341 +342 +343 +344 +345 +346 +347 +348 +349 +350 +351 +352 +353 +354 +355 +356 +357 +358 +359 +360 +361 +362 +363 +364 +365 +366 +367 +368 +369 +370 +371 +372 +373 +374 +375 +376 +377 +378 +379 +380 +381 +382 +383 +384 +385 +386 +387 +388 +389 +390 +391 +392 +393 +394 +395 +396 +397 +398 +399 +400 +401 +402 +403 +404 +405 +406 +407 +408 +409 +410 +411 +412 +413 +414 +415 +416 +417 +418 +419 +420 +421 +422 +423 +424 +425 +426 +427 +428 +429 +430 +431 +432 +433 +434 +435 +436 +437 +438 +439 +440 +441 +442 +443 +444 +445 +446 +447 +448 +449 +450 +451 +452 +453 +454 +455 +456 +457 +458 +459 +460 +461 +462 +463 +464 +465 +466 +467 +468 +469 +470 +471 +472 +473 +474 +475 +476 +477 +478 +479 +480 +481 +482 +483 +484 +485 +486 +487 +488 +489 +490 +491 +492 +493 +494 +495 +496 +497 +498 +499 +500 +501 +502 +503 +504 +505 +506 +507 +508 +509 +510 +511 +512 +513 +514 +515 +516 +517 +518 +519 +520 +521 +522 +523 +524 +525 +526 +527 +528 +529 +530 +531 +532 +533 +534 +535 +536 +537 +538 +539 +540 +541 +542 +543 +544 +545 +546 +547 +548 +549 +550 +551 +552 +553 +554 +555 +556 +557 +558 +559 +560 +561 +562 +563 +564 +565 +566 +567 +568 +569 +570 +571 +572 +573 +574 +575 +576 +577 +578 +579 +580 +581 +582 +583 +584 +585 +586 +587 +588 +589 +590 +591 +592 +593 +594 +595 +596 +597 +598 +599 +600 +601 +602 +603 +604 +605 +606 +607 +608 +609 +610 +611 +612 +613 +614 +615 +616 +617 +618 +619 +620 +621 +622 +623 +624 +625 +626 +627 +628 +629 +630 +631 +632 +633 +634 +635 +636 +637 +638 +639 +640 +641 +642 +643 +644 +645 +646 +647 +648 +649 +650 +651 +652 +653 +654 +655 +656 +657 +658 +659 +660 +661 +662 +663 +664 +665 +666 +667 +668 +669 +670 +671 +672 +673 +674 +675 +676 +677 +678 +679 +680 +681 +682 +683 +684 +685 +686 +687 +688 +689 +690 +691 +692 +693 +694 +695 +696 +697 +698 +699 +700 +701 +702 +703 +704 +705 +706 +707 +708 +709 +710 +711 +712 +713 +714 +715 +716 +717 +718 +719 +720 +721 +722 +723 +724 +725 +726 +727 +728 +729 +730 +731 +732 +733 +734 +735 +736 +737 +738 +739 +740 +741 +742 +743 +744 +745 +746 +747 +748 +749 +750 +751 +752 +753 +754 +755 +756 +757 +758 +759 +760 +761 +762 +763 +764 +765 +766 +767 +768 +769 +770 +771 +772 +773 +774 +775 +776 +777 +778 +779 +780 +781 +782 +783 +784 +785 +786 +787 +788 +789 +790 +791 +792 +793 +794 +795 +796 +797 +798 +799 +800 +801 +802 +803 +804 +805 +806 +807 +808 +809 +810 +811 +812 +813 +814 +815 +816 +817 +818 +819 +820 +821 +822 +823 +824 +825 +826 +827 +828 +829 +830 +831 +832 +833 +834 +835 +836 +837 +838 +839 +840 +841 +842 +843 +844 +845 +846 +847 +848 +849 +850 +851 +852 +853 +854 +855 +856 +857 +858 +859 +860 +861 +862 +863 +864 +865 +866 +867 +868 +869 +870 +871 +872 +873 +874 +875 +876 +877 +878 +879 +880 +881 +882 +883 +884 +885 +886 +887 +888 +889 +890 +891 +892 +893 +894 +895 +896 +897 +898 +899 +900 +901 +902 +903 +904 +905 +906 +907 +908 +909 +910 +911 +912 +913 +914 +915 +916 +917 +918 +919 +920 +921 +922 +923 +924 +925 +926 +927 +928 +929 +930 +931 +932 +933 +934 +935 +936 +937 +938 +939 +940 +941 +942 +943 +944 +945 +946 +947 +948  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +15x +  +  +38x +  +38x +38x +  +  +  +  +  +  +  +  +23x +23x +23x +23x +23x +23x +23x +23x +23x +23x +23x +23x +  +23x +23x +23x +23x +23x +23x +  +  +  +  +  +  +  +  +23x +23x +  +  +  +  +  +  +  +  +  +  +6x +6x +6x +6x +  +  +  +  +  +  +  +  +  +  +  +10x +10x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +9x +  +  +  +  +  +  +  +9x +9x +9x +  +9x +9x +  +  +  +  +  +9x +9x +9x +9x +1x +  +  +  +  +8x +8x +  +  +8x +8x +  +8x +8x +  +  +  +  +  +  +  +  +  +  +  +  +  +8x +  +  +8x +  +  +  +  +8x +  +  +  +  +  +  +  +  +  +  +  +  +  +8x +8x +8x +  +  +  +8x +8x +  +  +  +  +  +  +  +8x +8x +  +  +  +  +8x +  +  +  +  +  +  +  +  +  +  +8x +  +  +8x +  +  +8x +  +  +  +  +  +8x +8x +  +9x +  +  +  +  +  +  +  +  +  +  +9x +  +8x +  +  +  +  +  +  +  +8x +  +  +  +  +  +9x +  +  +8x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +9x +  +  +  +  +  +9x +9x +9x +  +  +9x +8x +  +  +  +  +8x +  +  +  +8x +  +  +8x +  +8x +  +8x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +3x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +4x +4x +3x +  +3x +3x +2x +2x +  +3x +  +  +3x +  +3x +  +3x +3x +  +  +  +  +3x +  +  +  +  +  +  +  +1x +1x +  +  +  +  +  +  +2x +2x +  +  +  +  +  +  +2x +2x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +4x +  +  +  +  +  +  +  +4x +4x +4x +1x +  +3x +1x +  +2x +  +2x +2x +2x +  +  +  +2x +2x +  +  +2x +2x +2x +  +  +  +  +  +2x +  +2x +2x +  +  +2x +  +  +2x +2x +4x +  +  +  +  +2x +2x +  +  +  +2x +  +  +  +  +  +2x +  +2x +2x +2x +  +2x +2x +  +  +  +  +2x +  +  +2x +  +  +2x +  +2x +  +  +  +  +  +  +1x +  +  +  +  +  +  +  +  +  +  +  +  +  +4x +4x +3x +  +  +3x +3x +2x +2x +  +3x +  +  +3x +  +  +3x +  +  +3x +  +  +  +3x +  +  +  +  +  +3x +  +  +3x +3x +  +  +  +  +3x +  +3x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +11x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  + 
/**
+ * Multi-Provider Agent Manager — Orchestrator
+ *
+ * Implementation of AgentManager port supporting multiple CLI providers.
+ * Delegates to extracted helpers:
+ * - ProcessManager: subprocess spawn/kill/poll, worktree creation, command building
+ * - CredentialHandler: account selection, credential write/refresh, exhaustion handling
+ * - OutputHandler: stream events, signal parsing, file reading, result capture
+ * - CleanupManager: worktree/branch/log removal, orphan cleanup, reconciliation
+ */
+ 
+import type {
+  AgentManager,
+  AgentInfo,
+  SpawnAgentOptions,
+  AgentResult,
+  AgentStatus,
+  AgentMode,
+  PendingQuestions,
+} from './types.js';
+import type { AgentRepository } from '../db/repositories/agent-repository.js';
+import type { AccountRepository } from '../db/repositories/account-repository.js';
+import type { ProjectRepository } from '../db/repositories/project-repository.js';
+import type { ChangeSetRepository } from '../db/repositories/change-set-repository.js';
+import type { PhaseRepository } from '../db/repositories/phase-repository.js';
+import type { TaskRepository } from '../db/repositories/task-repository.js';
+import type { PageRepository } from '../db/repositories/page-repository.js';
+import type { LogChunkRepository } from '../db/repositories/log-chunk-repository.js';
+import { generateUniqueAlias } from './alias.js';
+import type {
+  EventBus,
+  AgentSpawnedEvent,
+  AgentStoppedEvent,
+  AgentResumedEvent,
+  AgentDeletedEvent,
+  ProcessCrashedEvent,
+} from '../events/index.js';
+import { writeInputFiles } from './file-io.js';
+import { buildWorkspaceLayout, buildInterAgentCommunication } from './prompts/index.js';
+import { getProvider } from './providers/registry.js';
+import { createModuleLogger } from '../logger/index.js';
+import { join } from 'node:path';
+import { unlink, readFile } from 'node:fs/promises';
+import { existsSync, writeFileSync } from 'node:fs';
+import type { AccountCredentialManager } from './credentials/types.js';
+import { ProcessManager } from './process-manager.js';
+import { CredentialHandler } from './credential-handler.js';
+import { OutputHandler, type ActiveAgent } from './output-handler.js';
+import { CleanupManager } from './cleanup-manager.js';
+import { createLifecycleController } from './lifecycle/factory.js';
+import type { AgentLifecycleController } from './lifecycle/controller.js';
+import { AgentExhaustedError, AgentFailureError } from './lifecycle/retry-policy.js';
+import { FileSystemSignalManager } from './lifecycle/signal-manager.js';
+import type { SignalManager } from './lifecycle/signal-manager.js';
+ 
+const log = createModuleLogger('agent-manager');
+ 
+export class MultiProviderAgentManager implements AgentManager {
+  private static readonly MAX_COMMIT_RETRIES = 1;
+ 
+  private activeAgents: Map<string, ActiveAgent> = new Map();
+  private commitRetryCount: Map<string, number> = new Map();
+  private processManager: ProcessManager;
+  private credentialHandler: CredentialHandler;
+  private outputHandler: OutputHandler;
+  private cleanupManager: CleanupManager;
+  private lifecycleController: AgentLifecycleController;
+  private signalManager: SignalManager;
+ 
+  constructor(
+    private repository: AgentRepository,
+    private workspaceRoot: string,
+    private projectRepository: ProjectRepository,
+    private accountRepository?: AccountRepository,
+    private eventBus?: EventBus,
+    private credentialManager?: AccountCredentialManager,
+    private changeSetRepository?: ChangeSetRepository,
+    private phaseRepository?: PhaseRepository,
+    private taskRepository?: TaskRepository,
+    private pageRepository?: PageRepository,
+    private logChunkRepository?: LogChunkRepository,
+    private debug: boolean = false,
+  ) {
+    this.signalManager = new FileSystemSignalManager();
+    this.processManager = new ProcessManager(workspaceRoot, projectRepository);
+    this.credentialHandler = new CredentialHandler(workspaceRoot, accountRepository, credentialManager);
+    this.outputHandler = new OutputHandler(repository, eventBus, changeSetRepository, phaseRepository, taskRepository, pageRepository, this.signalManager);
+    this.cleanupManager = new CleanupManager(workspaceRoot, repository, projectRepository, eventBus, debug, this.signalManager);
+    this.lifecycleController = createLifecycleController({
+      repository,
+      processManager: this.processManager,
+      cleanupManager: this.cleanupManager,
+      accountRepository,
+      debug,
+    });
+ 
+    // Listen for process crashed events to handle agents specially
+    Eif (eventBus) {
+      eventBus.on('process:crashed', async (event: ProcessCrashedEvent) => {
+        await this.handleProcessCrashed(event.payload.processId, event.payload.exitCode, event.payload.signal);
+      });
+    }
+  }
+ 
+  /**
+   * Centralized cleanup of all in-memory state for an agent.
+   * Cancels polling timer, removes from activeAgents and commitRetryCount.
+   */
+  private cleanupAgentState(agentId: string): void {
+    const active = this.activeAgents.get(agentId);
+    if (active?.cancelPoll) active.cancelPoll();
+    this.activeAgents.delete(agentId);
+    this.commitRetryCount.delete(agentId);
+  }
+ 
+  /**
+   * Create a fire-and-forget callback for persisting raw output chunks to the DB.
+   * Returns undefined if no logChunkRepository is configured.
+   */
+  private createLogChunkCallback(
+    agentId: string,
+    agentName: string,
+    sessionNumber: number,
+  ): ((content: string) => void) | undefined {
+    const repo = this.logChunkRepository;
+    Eif (!repo) return undefined;
+ 
+    return (content) => {
+      repo.insertChunk({ agentId, agentName, sessionNumber, content })
+        .then(() => {
+          if (this.eventBus) {
+            this.eventBus.emit({
+              type: 'agent:output' as const,
+              timestamp: new Date(),
+              payload: { agentId, stream: 'stdout', data: content },
+            });
+          }
+        })
+        .catch(err => log.warn({ agentId, err: err instanceof Error ? err.message : String(err) }, 'failed to persist log chunk'));
+    };
+  }
+ 
+  /**
+   * Spawn a new agent using the unified lifecycle controller.
+   * Features comprehensive retry, error handling, and cleanup.
+   */
+  async spawnWithLifecycle(options: SpawnAgentOptions): Promise<AgentInfo> {
+    log.info({
+      taskId: options.taskId,
+      provider: options.provider,
+      initiativeId: options.initiativeId,
+      mode: options.mode
+    }, 'spawning agent with unified lifecycle management');
+ 
+    let spawnedAgent: AgentInfo | undefined;
+    await this.lifecycleController.spawnWithRetry(
+      async (opts) => {
+        const agent = await this.spawnInternal(opts);
+        spawnedAgent = agent;
+        return { id: agent.id, name: agent.name, status: agent.status, initiativeId: agent.initiativeId, worktreeId: agent.worktreeId };
+      },
+      options
+    );
+    return spawnedAgent!;
+  }
+ 
+  /**
+   * Spawn a new agent to work on a task (legacy method).
+   * Consider using spawnWithLifecycle for better error handling.
+   */
+  async spawn(options: SpawnAgentOptions): Promise<AgentInfo> {
+    return this.spawnInternal(options);
+  }
+ 
+  /**
+   * Internal spawn implementation without lifecycle management.
+   * Used by both legacy spawn() and new lifecycle-managed spawn.
+   */
+  private async spawnInternal(options: SpawnAgentOptions): Promise<AgentInfo> {
+    const { taskId, cwd, mode = 'execute', provider: providerName = 'claude', initiativeId, baseBranch, branchName } = options;
+    let { prompt } = options;
+    log.info({ taskId, provider: providerName, initiativeId, mode, baseBranch, branchName }, 'spawn requested');
+ 
+    const provider = getProvider(providerName);
+    Iif (!provider) {
+      throw new Error(`Unknown provider: '${providerName}'. Available: claude, codex, gemini, cursor, auggie, amp, opencode`);
+    }
+ 
+    // Generate or validate name
+    let name: string;
+    if (options.name) {
+      name = options.name;
+      const existing = await this.repository.findByName(name);
+      if (existing) {
+        throw new Error(`Agent with name '${name}' already exists`);
+      }
+    } else E{
+      name = await generateUniqueAlias(this.repository);
+    }
+    const alias = name;
+    log.debug({ alias }, 'alias generated');
+ 
+    // 1. Account selection
+    let accountId: string | null = null;
+    let accountConfigDir: string | null = null;
+ 
+    const accountResult = await this.credentialHandler.selectAccount(providerName);
+    Iif (accountResult) {
+      accountId = accountResult.accountId;
+      accountConfigDir = accountResult.configDir;
+ 
+      this.credentialHandler.writeCredentialsToDisk(accountResult.account, accountConfigDir);
+      const { valid, refreshed } = await this.credentialHandler.ensureCredentials(accountConfigDir, accountId);
+      if (!valid) {
+        log.warn({ alias, accountId }, 'failed to refresh account credentials, proceeding anyway');
+      }
+      if (refreshed) {
+        await this.credentialHandler.persistRefreshedCredentials(accountId, accountConfigDir);
+      }
+    }
+ 
+    Iif (accountId) {
+      log.info({ alias, accountId }, 'account selected');
+    } else {
+      log.debug('no accounts available, spawning without account');
+    }
+ 
+    // 2. Create isolated worktrees
+    let agentCwd: string;
+    Iif (initiativeId) {
+      log.debug({ alias, initiativeId, baseBranch, branchName }, 'creating initiative-based worktrees');
+      agentCwd = await this.processManager.createProjectWorktrees(alias, initiativeId, baseBranch, branchName);
+ 
+      // Log projects linked to the initiative
+      const projects = await this.projectRepository.findProjectsByInitiativeId(initiativeId);
+      log.info({
+        alias,
+        initiativeId,
+        projectCount: projects.length,
+        projects: projects.map(p => ({ name: p.name, url: p.url })),
+        agentCwd
+      }, 'initiative-based agent workdir created');
+    } else {
+      log.debug({ alias }, 'creating standalone worktree');
+      agentCwd = await this.processManager.createStandaloneWorktree(alias);
+      log.info({ alias, agentCwd }, 'standalone agent workdir created');
+    }
+ 
+    // Verify the final agentCwd exists
+    const cwdVerified = existsSync(agentCwd);
+    log.info({
+      alias,
+      agentCwd,
+      cwdVerified,
+      initiativeBasedAgent: !!initiativeId
+    }, 'agent workdir setup completed');
+ 
+    // 2b. Append workspace layout to prompt now that worktrees exist
+    const workspaceSection = buildWorkspaceLayout(agentCwd);
+    Iif (workspaceSection) {
+      prompt = prompt + workspaceSection;
+    }
+ 
+    // 3. Create agent record
+    const agent = await this.repository.create({
+      name: alias,
+      taskId: taskId ?? null,
+      initiativeId: initiativeId ?? null,
+      sessionId: null,
+      worktreeId: alias,
+      status: 'running',
+      mode,
+      provider: providerName,
+      accountId,
+    });
+    const agentId = agent.id;
+ 
+    // 3a. Append inter-agent communication instructions with actual agent ID
+    prompt = prompt + buildInterAgentCommunication(agentId);
+ 
+    // 3b. Write input files (after agent creation so we can include agentId/agentName)
+    Iif (options.inputContext) {
+      writeInputFiles({ agentWorkdir: agentCwd, ...options.inputContext, agentId, agentName: alias });
+      log.debug({ alias }, 'input files written');
+    }
+ 
+    // 4. Build spawn command
+    const { command, args, env: providerEnv } = this.processManager.buildSpawnCommand(provider, prompt);
+    const finalCwd = cwd ?? agentCwd;
+ 
+    log.info({
+      agentId,
+      alias,
+      command,
+      args: args.join(' '),
+      finalCwd,
+      customCwdProvided: !!cwd,
+      providerEnv: Object.keys(providerEnv)
+    }, 'spawn command built');
+ 
+    // 5. Prepare process environment with credentials
+    const { processEnv } = await this.credentialHandler.prepareProcessEnv(providerEnv, provider, accountId);
+ 
+    log.debug({
+      agentId,
+      finalProcessEnv: Object.keys(processEnv),
+      hasAccountConfig: !!accountId,
+      hasOAuthToken: !!processEnv['CLAUDE_CODE_OAUTH_TOKEN'],
+    }, 'process environment prepared');
+ 
+    // 6. Spawn detached subprocess
+    const { pid, outputFilePath, tailer } = this.processManager.spawnDetached(
+      agentId, alias, command, args, cwd ?? agentCwd, processEnv, providerName, prompt,
+      (event) => this.outputHandler.handleStreamEvent(agentId, event, this.activeAgents.get(agentId)),
+      this.createLogChunkCallback(agentId, alias, 1),
+    );
+ 
+    await this.repository.update(agentId, { pid, outputFilePath });
+ 
+    // Write spawn diagnostic file for post-execution verification
+    const diagnostic = {
+      timestamp: new Date().toISOString(),
+      agentId,
+      alias,
+      intendedCwd: finalCwd,
+      worktreeId: agent.worktreeId,
+      provider: providerName,
+      command,
+      args,
+      env: processEnv,
+      cwdExistsAtSpawn: existsSync(finalCwd),
+      initiativeId: initiativeId || null,
+      customCwdProvided: !!cwd,
+      accountId: accountId || null,
+    };
+ 
+    writeFileSync(
+      join(finalCwd, '.cw', 'spawn-diagnostic.json'),
+      JSON.stringify(diagnostic, null, 2),
+      'utf-8'
+    );
+ 
+    const activeEntry: ActiveAgent = { agentId, pid, tailer, outputFilePath, agentCwd: finalCwd };
+    this.activeAgents.set(agentId, activeEntry);
+    log.info({ agentId, alias, pid, diagnosticWritten: true }, 'detached subprocess started with diagnostic');
+ 
+    // Emit spawned event
+    if (this.eventBus) {
+      const event: AgentSpawnedEvent = {
+        type: 'agent:spawned',
+        timestamp: new Date(),
+        payload: { agentId, name: alias, taskId: taskId ?? null, worktreeId: alias, provider: providerName },
+      };
+      this.eventBus.emit(event);
+    }
+ 
+    // Start polling for completion
+    const { cancel } = this.processManager.pollForCompletion(
+      agentId, pid,
+      () => this.handleDetachedAgentCompletion(agentId),
+      () => this.activeAgents.get(agentId)?.tailer,
+    );
+    activeEntry.cancelPoll = cancel;
+ 
+    return this.toAgentInfo(agent);
+  }
+ 
+  /**
+   * Handle completion of a detached agent.
+   */
+  private async handleDetachedAgentCompletion(agentId: string): Promise<void> {
+    if (!this.activeAgents.has(agentId)) return;
+ 
+    const active = this.activeAgents.get(agentId);
+    await this.outputHandler.handleCompletion(
+      agentId,
+      active,
+      (alias) => this.processManager.getAgentWorkdir(alias),
+    );
+ 
+    // Sync credentials back to DB if the agent had an account
+    await this.syncCredentialsPostCompletion(agentId);
+ 
+    this.cleanupAgentState(agentId);
+ 
+    // Auto-cleanup workdir after completion
+    await this.tryAutoCleanup(agentId);
+  }
+ 
+  /**
+   * Attempt auto-cleanup of agent workdir after completion.
+   * If dirty and retries remain, resumes the agent to commit changes.
+   */
+  private async tryAutoCleanup(agentId: string): Promise<void> {
+    try {
+      const agent = await this.repository.findById(agentId);
+      if (!agent || agent.status !== 'idle') return;
+ 
+      const { clean, removed } = await this.cleanupManager.autoCleanupAfterCompletion(
+        agentId, agent.name, agent.initiativeId,
+      );
+ 
+      if (removed) {
+        this.commitRetryCount.delete(agentId);
+        log.info({ agentId, alias: agent.name }, 'auto-cleanup completed');
+        return;
+      }
+ 
+      if (!clean) {
+        const retries = this.commitRetryCount.get(agentId) ?? 0;
+        if (retries < MultiProviderAgentManager.MAX_COMMIT_RETRIES) {
+          this.commitRetryCount.set(agentId, retries + 1);
+          const resumed = await this.resumeForCommit(agentId);
+          if (resumed) {
+            log.info({ agentId, alias: agent.name, retry: retries + 1 }, 'resumed agent to commit uncommitted changes');
+            return;
+          }
+        }
+        log.warn({ agentId, alias: agent.name }, 'agent workdir has uncommitted changes after max retries, leaving in place');
+        this.commitRetryCount.delete(agentId);
+      }
+    } catch (err) {
+      log.warn({ agentId, err: err instanceof Error ? err.message : String(err) }, 'auto-cleanup failed');
+      this.commitRetryCount.delete(agentId);
+    }
+  }
+ 
+  /**
+   * Resume an agent's session with a prompt to commit uncommitted changes.
+   * Returns false if the agent can't be resumed (no session, provider doesn't support resume).
+   */
+  private async resumeForCommit(agentId: string): Promise<boolean> {
+    const agent = await this.repository.findById(agentId);
+    if (!agent?.sessionId) return false;
+ 
+    const provider = getProvider(agent.provider);
+    if (!provider || provider.resumeStyle === 'none') return false;
+ 
+    // Check which specific worktrees are dirty — skip resume if all clean
+    const dirtyPaths = await this.cleanupManager.getDirtyWorktreePaths(agent.name, agent.initiativeId);
+    if (dirtyPaths.length === 0) return false;
+ 
+    const dirtyList = dirtyPaths.map(p => `- \`${p}/\``).join('\n');
+    const commitPrompt =
+      'You have uncommitted changes in the following project directories:\n' +
+      dirtyList + '\n\n' +
+      'For each directory listed above, `cd` into it, then run `git add -A && git commit -m "<message>"` ' +
+      'with an appropriate commit message describing the work. Do not make any other changes.';
+ 
+    await this.repository.update(agentId, { status: 'running', pendingQuestions: null, result: null });
+ 
+    const agentCwd = this.processManager.getAgentWorkdir(agent.worktreeId);
+    const { command, args, env: providerEnv } = this.processManager.buildResumeCommand(provider, agent.sessionId, commitPrompt);
+ 
+    const { processEnv } = await this.credentialHandler.prepareProcessEnv(providerEnv, provider, agent.accountId);
+ 
+    const prevActive = this.activeAgents.get(agentId);
+    prevActive?.cancelPoll?.();
+    if (prevActive?.tailer) {
+      await prevActive.tailer.stop();
+    }
+ 
+    // Determine session number for commit retry
+    let commitSessionNumber = 1;
+    if (this.logChunkRepository) {
+      commitSessionNumber = (await this.logChunkRepository.getSessionCount(agentId)) + 1;
+    }
+ 
+    const { pid, outputFilePath, tailer } = this.processManager.spawnDetached(
+      agentId, agent.name, command, args, agentCwd, processEnv, provider.name, commitPrompt,
+      (event) => this.outputHandler.handleStreamEvent(agentId, event, this.activeAgents.get(agentId)),
+      this.createLogChunkCallback(agentId, agent.name, commitSessionNumber),
+    );
+ 
+    await this.repository.update(agentId, { pid, outputFilePath });
+    const commitActiveEntry: ActiveAgent = { agentId, pid, tailer, outputFilePath };
+    this.activeAgents.set(agentId, commitActiveEntry);
+ 
+    const { cancel: commitCancel } = this.processManager.pollForCompletion(
+      agentId, pid,
+      () => this.handleDetachedAgentCompletion(agentId),
+      () => this.activeAgents.get(agentId)?.tailer,
+    );
+    commitActiveEntry.cancelPoll = commitCancel;
+ 
+    return true;
+  }
+ 
+  /**
+   * Sync credentials from agent's config dir back to DB after completion.
+   * The subprocess may have refreshed tokens mid-session; this ensures
+   * the DB stays current and the next spawn uses fresh tokens.
+   */
+  private async syncCredentialsPostCompletion(agentId: string): Promise<void> {
+    Eif (!this.accountRepository) return;
+ 
+    try {
+      const agent = await this.repository.findById(agentId);
+      if (!agent?.accountId) return;
+ 
+      const { getAccountConfigDir } = await import('./accounts/paths.js');
+      const configDir = getAccountConfigDir(this.workspaceRoot, agent.accountId);
+      await this.credentialHandler.persistRefreshedCredentials(agent.accountId, configDir);
+      log.debug({ agentId, accountId: agent.accountId }, 'post-completion credential sync done');
+    } catch (err) {
+      log.warn({ agentId, err: err instanceof Error ? err.message : String(err) }, 'post-completion credential sync failed');
+    }
+  }
+ 
+  /**
+   * Stop a running agent.
+   */
+  async stop(agentId: string): Promise<void> {
+    const agent = await this.repository.findById(agentId);
+    if (!agent) throw new Error(`Agent '${agentId}' not found`);
+    log.info({ agentId, name: agent.name }, 'stopping agent');
+ 
+    const active = this.activeAgents.get(agentId);
+    if (active) {
+      try { process.kill(active.pid, 'SIGTERM'); } catch { /* already exited */ }
+      await active.tailer.stop();
+    }
+    this.cleanupAgentState(agentId);
+ 
+    // Sync credentials before marking stopped
+    await this.syncCredentialsPostCompletion(agentId);
+ 
+    await this.repository.update(agentId, { status: 'stopped', pendingQuestions: null });
+ 
+    Eif (this.eventBus) {
+      const event: AgentStoppedEvent = {
+        type: 'agent:stopped',
+        timestamp: new Date(),
+        payload: { agentId, name: agent.name, taskId: agent.taskId ?? '', reason: 'user_requested' },
+      };
+      this.eventBus.emit(event);
+    }
+  }
+ 
+  /**
+   * List all agents with their current status.
+   */
+  async list(): Promise<AgentInfo[]> {
+    const agents = await this.repository.findAll();
+    return agents.map((a) => this.toAgentInfo(a));
+  }
+ 
+  /**
+   * Get a specific agent by ID.
+   */
+  async get(agentId: string): Promise<AgentInfo | null> {
+    const agent = await this.repository.findById(agentId);
+    return agent ? this.toAgentInfo(agent) : null;
+  }
+ 
+  /**
+   * Get a specific agent by name.
+   */
+  async getByName(name: string): Promise<AgentInfo | null> {
+    const agent = await this.repository.findByName(name);
+    return agent ? this.toAgentInfo(agent) : null;
+  }
+ 
+  /**
+   * Resume an agent using the unified lifecycle controller.
+   * Features comprehensive retry, error handling, and cleanup.
+   */
+  async resumeWithLifecycle(agentId: string, answers: Record<string, string>): Promise<void> {
+    log.info({
+      agentId,
+      answerKeys: Object.keys(answers)
+    }, 'resuming agent with unified lifecycle management');
+ 
+    await this.lifecycleController.resumeWithRetry(
+      (id, modifiedAnswers) => this.resumeInternal(id, modifiedAnswers),
+      { agentId, answers }
+    );
+  }
+ 
+  /**
+   * Resume an agent that's waiting for input (legacy method).
+   * Consider using resumeWithLifecycle for better error handling.
+   */
+  async resume(agentId: string, answers: Record<string, string>): Promise<void> {
+    return this.resumeInternal(agentId, answers);
+  }
+ 
+  /**
+   * Internal resume implementation without lifecycle management.
+   * Used by both legacy resume() and new lifecycle-managed resume.
+   */
+  private async resumeInternal(agentId: string, answers: Record<string, string>): Promise<void> {
+    const agent = await this.repository.findById(agentId);
+    Iif (!agent) throw new Error(`Agent '${agentId}' not found`);
+    if (agent.status !== 'waiting_for_input') {
+      throw new Error(`Agent '${agent.name}' is not waiting for input (status: ${agent.status})`);
+    }
+    if (!agent.sessionId) {
+      throw new Error(`Agent '${agent.name}' has no session to resume`);
+    }
+    log.info({ agentId, sessionId: agent.sessionId, provider: agent.provider }, 'resuming agent');
+ 
+    const provider = getProvider(agent.provider);
+    Iif (!provider) throw new Error(`Unknown provider: '${agent.provider}'`);
+    Iif (provider.resumeStyle === 'none') {
+      throw new Error(`Provider '${provider.name}' does not support resume`);
+    }
+ 
+    const agentCwd = this.processManager.getAgentWorkdir(agent.worktreeId);
+    const prompt = this.outputHandler.formatAnswersAsPrompt(answers);
+ 
+    // Clear previous signal.json to ensure clean completion detection
+    const signalPath = join(agentCwd, '.cw/output/signal.json');
+    try {
+      await unlink(signalPath);
+      log.debug({ agentId, signalPath }, 'cleared previous signal.json for resume');
+    } catch {
+      // File might not exist, which is fine
+    }
+ 
+    await this.repository.update(agentId, { status: 'running', pendingQuestions: null, result: null });
+ 
+    const { command, args, env: providerEnv } = this.processManager.buildResumeCommand(provider, agent.sessionId, prompt);
+    log.debug({ command, args: args.join(' ') }, 'resume command built');
+ 
+    // Prepare process environment with credentials
+    const { processEnv } = await this.credentialHandler.prepareProcessEnv(providerEnv, provider, agent.accountId);
+ 
+    // Stop previous tailer and cancel previous poll
+    const prevActive = this.activeAgents.get(agentId);
+    prevActive?.cancelPoll?.();
+    Iif (prevActive?.tailer) {
+      await prevActive.tailer.stop();
+    }
+ 
+    // Determine session number for this resume
+    let resumeSessionNumber = 1;
+    Iif (this.logChunkRepository) {
+      resumeSessionNumber = (await this.logChunkRepository.getSessionCount(agentId)) + 1;
+    }
+ 
+    const { pid, outputFilePath, tailer } = this.processManager.spawnDetached(
+      agentId, agent.name, command, args, agentCwd, processEnv, provider.name, prompt,
+      (event) => this.outputHandler.handleStreamEvent(agentId, event, this.activeAgents.get(agentId)),
+      this.createLogChunkCallback(agentId, agent.name, resumeSessionNumber),
+    );
+ 
+    await this.repository.update(agentId, { pid, outputFilePath });
+ 
+    const resumeActiveEntry: ActiveAgent = { agentId, pid, tailer, outputFilePath };
+    this.activeAgents.set(agentId, resumeActiveEntry);
+    log.info({ agentId, pid }, 'resume detached subprocess started');
+ 
+    Eif (this.eventBus) {
+      const event: AgentResumedEvent = {
+        type: 'agent:resumed',
+        timestamp: new Date(),
+        payload: { agentId, name: agent.name, taskId: agent.taskId ?? '', sessionId: agent.sessionId },
+      };
+      this.eventBus.emit(event);
+    }
+ 
+    const { cancel: resumeCancel } = this.processManager.pollForCompletion(
+      agentId, pid,
+      () => this.handleDetachedAgentCompletion(agentId),
+      () => this.activeAgents.get(agentId)?.tailer,
+    );
+    resumeActiveEntry.cancelPoll = resumeCancel;
+  }
+ 
+  /**
+   * Get the result of an agent's work.
+   */
+  async getResult(agentId: string): Promise<AgentResult | null> {
+    return this.outputHandler.getResult(agentId, this.activeAgents.get(agentId));
+  }
+ 
+  /**
+   * Get pending questions for an agent waiting for input.
+   */
+  async getPendingQuestions(agentId: string): Promise<PendingQuestions | null> {
+    return this.outputHandler.getPendingQuestions(agentId, this.activeAgents.get(agentId));
+  }
+ 
+  /**
+   * Delete an agent and clean up all associated resources.
+   */
+  async delete(agentId: string): Promise<void> {
+    const agent = await this.repository.findById(agentId);
+    if (!agent) throw new Error(`Agent '${agentId}' not found`);
+    log.info({ agentId, name: agent.name }, 'deleting agent');
+ 
+    // 1. Kill process, stop tailer, clear all in-memory state
+    const active = this.activeAgents.get(agentId);
+    if (active) {
+      try { process.kill(active.pid, 'SIGTERM'); } catch { /* already exited */ }
+      await active.tailer.stop();
+    }
+    this.cleanupAgentState(agentId);
+ 
+    // 2. Best-effort cleanup
+    try { await this.cleanupManager.removeAgentWorktrees(agent.name, agent.initiativeId); }
+    catch (err) { log.warn({ agentId, err: err instanceof Error ? err.message : String(err) }, 'failed to remove worktrees'); }
+ 
+    try { await this.cleanupManager.removeAgentBranches(agent.name, agent.initiativeId); }
+    catch (err) { log.warn({ agentId, err: err instanceof Error ? err.message : String(err) }, 'failed to remove branches'); }
+ 
+    try { await this.cleanupManager.removeAgentLogs(agent.name); }
+    catch (err) { log.warn({ agentId, err: err instanceof Error ? err.message : String(err) }, 'failed to remove logs'); }
+ 
+    // 3b. Delete log chunks from DB
+    Iif (this.logChunkRepository) {
+      try { await this.logChunkRepository.deleteByAgentId(agentId); }
+      catch (err) { log.warn({ agentId, err: err instanceof Error ? err.message : String(err) }, 'failed to delete log chunks'); }
+    }
+ 
+    // 4. Delete DB record
+    await this.repository.delete(agentId);
+ 
+    // 5. Emit deleted event
+    Eif (this.eventBus) {
+      const event: AgentDeletedEvent = {
+        type: 'agent:deleted',
+        timestamp: new Date(),
+        payload: { agentId, name: agent.name },
+      };
+      this.eventBus.emit(event);
+    }
+    log.info({ agentId, name: agent.name }, 'agent deleted');
+  }
+ 
+  /**
+   * Dismiss an agent.
+   */
+  async dismiss(agentId: string): Promise<void> {
+    const agent = await this.repository.findById(agentId);
+    if (!agent) throw new Error(`Agent '${agentId}' not found`);
+    log.info({ agentId, name: agent.name }, 'dismissing agent');
+ 
+    this.cleanupAgentState(agentId);
+ 
+    await this.repository.update(agentId, {
+      userDismissedAt: new Date(),
+      updatedAt: new Date(),
+    });
+ 
+    log.info({ agentId, name: agent.name }, 'agent dismissed');
+  }
+ 
+  /**
+   * Clean up orphaned agent workdirs.
+   */
+  async cleanupOrphanedWorkdirs(): Promise<void> {
+    return this.cleanupManager.cleanupOrphanedWorkdirs();
+  }
+ 
+  /**
+   * Clean up orphaned agent log directories.
+   */
+  async cleanupOrphanedLogs(): Promise<void> {
+    return this.cleanupManager.cleanupOrphanedLogs();
+  }
+ 
+  /**
+   * Reconcile agent state after server restart.
+   */
+  async reconcileAfterRestart(): Promise<void> {
+    const reconcileLogChunkRepo = this.logChunkRepository;
+    await this.cleanupManager.reconcileAfterRestart(
+      this.activeAgents,
+      (agentId, event) => this.outputHandler.handleStreamEvent(agentId, event, this.activeAgents.get(agentId)),
+      (agentId, rawOutput, provider) => this.outputHandler.processAgentOutput(agentId, rawOutput, provider, (alias) => this.processManager.getAgentWorkdir(alias)),
+      (agentId, pid) => {
+        const { cancel } = this.processManager.pollForCompletion(
+          agentId, pid,
+          () => this.handleDetachedAgentCompletion(agentId),
+          () => this.activeAgents.get(agentId)?.tailer,
+        );
+        const active = this.activeAgents.get(agentId);
+        if (active) active.cancelPoll = cancel;
+      },
+      reconcileLogChunkRepo
+        ? (agentId, agentName, content) => {
+            // Determine session number asynchronously — use fire-and-forget
+            reconcileLogChunkRepo.getSessionCount(agentId).then(count => {
+              return reconcileLogChunkRepo.insertChunk({
+                agentId,
+                agentName,
+                sessionNumber: count + 1,
+                content,
+              });
+            }).catch(err => log.warn({ agentId, err: err instanceof Error ? err.message : String(err) }, 'failed to persist log chunk during reconciliation'));
+          }
+        : undefined,
+    );
+  }
+ 
+  /**
+   * Handle process crashed event specifically for agents.
+   * Check if the agent actually completed successfully despite the non-zero exit code.
+   */
+  private async handleProcessCrashed(processId: string, exitCode: number | null, signal: string | null): Promise<void> {
+    try {
+      // Check if this is an agent process
+      const agent = await this.repository.findById(processId);
+      if (!agent) {
+        return; // Not our agent
+      }
+ 
+      // Store exit code and signal for debugging
+      await this.repository.update(processId, { exitCode });
+ 
+      log.info({
+        agentId: processId,
+        name: agent.name,
+        exitCode,
+        signal,
+        outputFilePath: agent.outputFilePath
+      }, 'agent process crashed, analyzing completion status');
+ 
+      // Check if the agent has output that indicates successful completion
+      if (agent.outputFilePath) {
+        const hasCompletion = await this.checkAgentCompletionResult(agent.worktreeId);
+        if (hasCompletion) {
+          log.info({
+            agentId: processId,
+            name: agent.name,
+            exitCode,
+            signal
+          }, 'agent marked as crashed but completed successfully - completion already handled by polling');
+ 
+          // Note: We don't call handleCompletion() here because the polling handler
+          // (handleDetachedAgentCompletion) already processes completions. The mutex
+          // in OutputHandler.handleCompletion() prevents duplicate processing.
+ 
+          log.info({
+            agentId: processId,
+            name: agent.name,
+            exitCode
+          }, 'completion detection confirmed - deferring to polling handler');
+        } else {
+          log.warn({
+            agentId: processId,
+            name: agent.name,
+            exitCode,
+            signal,
+            outputFilePath: agent.outputFilePath
+          }, 'agent crashed and no successful completion detected - marking as truly crashed');
+ 
+          // Only mark as crashed if agent truly crashed (no completion detected)
+          await this.repository.update(processId, { status: 'crashed' });
+        }
+      } else {
+        log.warn({
+          agentId: processId,
+          name: agent.name,
+          exitCode,
+          signal
+        }, 'agent crashed with no output file path - marking as crashed');
+ 
+        await this.repository.update(processId, { status: 'crashed' });
+      }
+    } catch (err) {
+      log.error({
+        processId,
+        exitCode,
+        signal,
+        err: err instanceof Error ? err.message : String(err)
+      }, 'failed to check agent completion after crash');
+    }
+  }
+ 
+  /**
+   * Check if agent completed successfully by reading signal.json file.
+   * Probes the workspace/ subdirectory for standalone agents.
+   */
+  private async checkAgentCompletionResult(worktreeId: string): Promise<boolean> {
+    try {
+      // Resolve actual agent workdir — standalone agents have .cw inside workspace/ subdir
+      let agentWorkdir = this.processManager.getAgentWorkdir(worktreeId);
+      const workspaceSub = join(agentWorkdir, 'workspace');
+      if (!existsSync(join(agentWorkdir, '.cw', 'output')) && existsSync(join(workspaceSub, '.cw'))) {
+        agentWorkdir = workspaceSub;
+      }
+ 
+      const signalPath = join(agentWorkdir, '.cw/output/signal.json');
+ 
+      if (!existsSync(signalPath)) {
+        log.debug({ worktreeId, signalPath }, 'no signal.json found - agent not completed');
+        return false;
+      }
+ 
+      const signalContent = await readFile(signalPath, 'utf-8');
+      const signal = JSON.parse(signalContent);
+ 
+      // Agent completed if status is done, questions, or error
+      const completed = signal.status === 'done' || signal.status === 'questions' || signal.status === 'error';
+ 
+      if (completed) {
+        log.debug({ worktreeId, signal }, 'agent completion detected via signal.json');
+      } else {
+        log.debug({ worktreeId, signal }, 'signal.json found but status indicates incomplete');
+      }
+ 
+      return completed;
+ 
+    } catch (err) {
+      log.warn({ worktreeId, err: err instanceof Error ? err.message : String(err) }, 'failed to read or parse signal.json');
+      return false;
+    }
+  }
+ 
+  /**
+   * Convert database agent record to AgentInfo.
+   */
+  private toAgentInfo(agent: {
+    id: string;
+    name: string;
+    taskId: string | null;
+    initiativeId: string | null;
+    sessionId: string | null;
+    worktreeId: string;
+    status: string;
+    mode: string;
+    provider: string;
+    accountId: string | null;
+    createdAt: Date;
+    updatedAt: Date;
+    userDismissedAt?: Date | null;
+  }): AgentInfo {
+    return {
+      id: agent.id,
+      name: agent.name,
+      taskId: agent.taskId ?? '',
+      initiativeId: agent.initiativeId,
+      sessionId: agent.sessionId,
+      worktreeId: agent.worktreeId,
+      status: agent.status as AgentStatus,
+      mode: agent.mode as AgentMode,
+      provider: agent.provider,
+      accountId: agent.accountId,
+      createdAt: agent.createdAt,
+      updatedAt: agent.updatedAt,
+      userDismissedAt: agent.userDismissedAt,
+    };
+  }
+}
+ 
+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/coverage/src/agent/markdown-to-tiptap.ts.html b/coverage/src/agent/markdown-to-tiptap.ts.html new file mode 100644 index 0000000..bf832bc --- /dev/null +++ b/coverage/src/agent/markdown-to-tiptap.ts.html @@ -0,0 +1,181 @@ + + + + + + Code coverage report for src/agent/markdown-to-tiptap.ts + + + + + + + + + +
+
+

All files / src/agent markdown-to-tiptap.ts

+
+ +
+ 14.28% + Statements + 1/7 +
+ + +
+ 0% + Branches + 0/4 +
+ + +
+ 0% + Functions + 0/2 +
+ + +
+ 14.28% + Lines + 1/7 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+

+
1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 +30 +31 +32 +33  +  +  +  +  +  +  +  +  +  +  +  +20x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  + 
/**
+ * Server-side Markdown → Tiptap JSON converter.
+ *
+ * Uses @tiptap/markdown's MarkdownManager.parse() — the same approach
+ * as content-serializer.ts but in reverse direction.
+ * No DOM needed, no new dependencies.
+ */
+ 
+import StarterKit from '@tiptap/starter-kit';
+import Link from '@tiptap/extension-link';
+import { MarkdownManager } from '@tiptap/markdown';
+ 
+let _manager: MarkdownManager | null = null;
+ 
+function getManager(): MarkdownManager {
+  if (!_manager) {
+    _manager = new MarkdownManager({
+      extensions: [StarterKit, Link],
+    });
+  }
+  return _manager;
+}
+ 
+/**
+ * Convert a markdown string to Tiptap JSON document.
+ */
+export function markdownToTiptapJson(markdown: string): object {
+  if (!markdown.trim()) {
+    return { type: 'doc', content: [{ type: 'paragraph' }] };
+  }
+  return getManager().parse(markdown);
+}
+ 
+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/coverage/src/agent/mock-manager.ts.html b/coverage/src/agent/mock-manager.ts.html new file mode 100644 index 0000000..009bc1f --- /dev/null +++ b/coverage/src/agent/mock-manager.ts.html @@ -0,0 +1,1546 @@ + + + + + + Code coverage report for src/agent/mock-manager.ts + + + + + + + + + +
+
+

All files / src/agent mock-manager.ts

+
+ +
+ 88% + Statements + 110/125 +
+ + +
+ 69.76% + Branches + 60/86 +
+ + +
+ 94.73% + Functions + 18/19 +
+ + +
+ 88.61% + Lines + 109/123 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+

+
1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 +30 +31 +32 +33 +34 +35 +36 +37 +38 +39 +40 +41 +42 +43 +44 +45 +46 +47 +48 +49 +50 +51 +52 +53 +54 +55 +56 +57 +58 +59 +60 +61 +62 +63 +64 +65 +66 +67 +68 +69 +70 +71 +72 +73 +74 +75 +76 +77 +78 +79 +80 +81 +82 +83 +84 +85 +86 +87 +88 +89 +90 +91 +92 +93 +94 +95 +96 +97 +98 +99 +100 +101 +102 +103 +104 +105 +106 +107 +108 +109 +110 +111 +112 +113 +114 +115 +116 +117 +118 +119 +120 +121 +122 +123 +124 +125 +126 +127 +128 +129 +130 +131 +132 +133 +134 +135 +136 +137 +138 +139 +140 +141 +142 +143 +144 +145 +146 +147 +148 +149 +150 +151 +152 +153 +154 +155 +156 +157 +158 +159 +160 +161 +162 +163 +164 +165 +166 +167 +168 +169 +170 +171 +172 +173 +174 +175 +176 +177 +178 +179 +180 +181 +182 +183 +184 +185 +186 +187 +188 +189 +190 +191 +192 +193 +194 +195 +196 +197 +198 +199 +200 +201 +202 +203 +204 +205 +206 +207 +208 +209 +210 +211 +212 +213 +214 +215 +216 +217 +218 +219 +220 +221 +222 +223 +224 +225 +226 +227 +228 +229 +230 +231 +232 +233 +234 +235 +236 +237 +238 +239 +240 +241 +242 +243 +244 +245 +246 +247 +248 +249 +250 +251 +252 +253 +254 +255 +256 +257 +258 +259 +260 +261 +262 +263 +264 +265 +266 +267 +268 +269 +270 +271 +272 +273 +274 +275 +276 +277 +278 +279 +280 +281 +282 +283 +284 +285 +286 +287 +288 +289 +290 +291 +292 +293 +294 +295 +296 +297 +298 +299 +300 +301 +302 +303 +304 +305 +306 +307 +308 +309 +310 +311 +312 +313 +314 +315 +316 +317 +318 +319 +320 +321 +322 +323 +324 +325 +326 +327 +328 +329 +330 +331 +332 +333 +334 +335 +336 +337 +338 +339 +340 +341 +342 +343 +344 +345 +346 +347 +348 +349 +350 +351 +352 +353 +354 +355 +356 +357 +358 +359 +360 +361 +362 +363 +364 +365 +366 +367 +368 +369 +370 +371 +372 +373 +374 +375 +376 +377 +378 +379 +380 +381 +382 +383 +384 +385 +386 +387 +388 +389 +390 +391 +392 +393 +394 +395 +396 +397 +398 +399 +400 +401 +402 +403 +404 +405 +406 +407 +408 +409 +410 +411 +412 +413 +414 +415 +416 +417 +418 +419 +420 +421 +422 +423 +424 +425 +426 +427 +428 +429 +430 +431 +432 +433 +434 +435 +436 +437 +438 +439 +440 +441 +442 +443 +444 +445 +446 +447 +448 +449 +450 +451 +452 +453 +454 +455 +456 +457 +458 +459 +460 +461 +462 +463 +464 +465 +466 +467 +468 +469 +470 +471 +472 +473 +474 +475 +476 +477 +478 +479 +480 +481 +482 +483 +484 +485 +486 +487 +488  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +9x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +126x +126x +  +  +  +  +126x +126x +  +  +  +  +  +  +  +63x +  +  +  +  +  +  +1x +  +  +  +  +  +  +  +  +  +126x +126x +  +  +126x +79x +1x +  +  +  +125x +125x +125x +125x +  +  +125x +  +126x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +126x +  +  +  +  +126x +  +  +126x +124x +  +  +  +  +  +  +  +  +  +  +124x +  +  +  +125x +  +125x +  +  +  +  +  +  +137x +  +137x +107x +  +  +137x +137x +137x +  +  +  +  +  +  +  +74x +4x +3x +7x +  +60x +  +  +  +  +  +  +  +107x +107x +  +107x +  +107x +  +74x +  +  +  +  +74x +74x +  +74x +74x +74x +  +  +  +  +  +  +  +  +  +74x +  +74x +  +  +13x +  +  +  +13x +13x +  +13x +13x +  +  +  +  +  +  +  +  +  +13x +  +13x +  +  +20x +20x +20x +  +  +  +20x +20x +  +  +  +  +  +  +  +  +  +  +20x +  +20x +  +  +  +  +  +  +  +  +  +2x +2x +1x +  +  +  +1x +1x +1x +  +  +1x +1x +  +1x +1x +  +  +  +  +  +  +  +  +  +1x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +79x +  +  +  +  +  +  +31x +31x +  +  +  +  +  +  +12x +11x +11x +  +  +1x +  +  +  +  +  +  +  +  +  +  +  +  +14x +14x +1x +  +  +13x +1x +  +  +  +  +12x +  +  +  +  +12x +12x +12x +  +  +12x +12x +  +  +  +  +  +  +  +  +  +12x +  +  +  +  +  +  +12x +14x +  +  +  +  +  +  +14x +  +  +  +  +  +  +  +  +9x +9x +  +  +  +  +  +  +15x +15x +  +  +  +  +  +  +  +2x +2x +  +  +2x +2x +2x +  +  +  +  +  +  +  +129x +125x +124x +  +  +129x +129x +  +  + 
/**
+ * Mock Agent Manager Adapter
+ *
+ * Implementation of AgentManager port for test scenarios.
+ * Simulates configurable agent behaviors (success, crash, waiting_for_input)
+ * without spawning real Claude agents.
+ */
+ 
+import { randomUUID } from 'crypto';
+import type {
+  AgentManager,
+  AgentInfo,
+  AgentMode,
+  SpawnAgentOptions,
+  AgentResult,
+  AgentStatus,
+  PendingQuestions,
+  QuestionItem,
+} from './types.js';
+import type {
+  EventBus,
+  AgentSpawnedEvent,
+  AgentStoppedEvent,
+  AgentCrashedEvent,
+  AgentResumedEvent,
+  AgentDeletedEvent,
+  AgentWaitingEvent,
+} from '../events/index.js';
+ 
+/**
+ * Scenario configuration for mock agent behavior.
+ * Matches the simplified agent signal schema: done, questions, or error.
+ * Mode-specific stopped reasons are derived from the agent's mode.
+ */
+export type MockAgentScenario =
+  | {
+      status: 'done';
+      result?: string;
+      filesModified?: string[];
+      delay?: number;
+    }
+  | {
+      status: 'questions';
+      questions: QuestionItem[];
+      delay?: number;
+    }
+  | {
+      status: 'error';
+      error: string;
+      delay?: number;
+    };
+ 
+/**
+ * Internal agent record with scenario and timer tracking.
+ */
+interface MockAgentRecord {
+  info: AgentInfo;
+  scenario: MockAgentScenario;
+  result?: AgentResult;
+  pendingQuestions?: PendingQuestions;
+  completionTimer?: ReturnType<typeof setTimeout>;
+}
+ 
+/**
+ * Default scenario: immediate success with generic message.
+ */
+const DEFAULT_SCENARIO: MockAgentScenario = {
+  status: 'done',
+  result: 'Task completed successfully',
+  filesModified: [],
+  delay: 0,
+};
+ 
+/**
+ * MockAgentManager - Adapter implementing AgentManager port for testing.
+ *
+ * Enables E2E testing of dispatch/coordination flows without spawning
+ * real Claude agents. Simulates configurable agent behaviors and
+ * emits proper lifecycle events.
+ */
+export class MockAgentManager implements AgentManager {
+  private agents: Map<string, MockAgentRecord> = new Map();
+  private scenarioOverrides: Map<string, MockAgentScenario> = new Map();
+  private defaultScenario: MockAgentScenario;
+  private eventBus?: EventBus;
+ 
+  constructor(options?: { eventBus?: EventBus; defaultScenario?: MockAgentScenario }) {
+    this.eventBus = options?.eventBus;
+    this.defaultScenario = options?.defaultScenario ?? DEFAULT_SCENARIO;
+  }
+ 
+  /**
+   * Set scenario override for a specific agent name.
+   * When spawn() is called with this name, the override takes precedence.
+   */
+  setScenario(agentName: string, scenario: MockAgentScenario): void {
+    this.scenarioOverrides.set(agentName, scenario);
+  }
+ 
+  /**
+   * Clear scenario override for a specific agent name.
+   */
+  clearScenario(agentName: string): void {
+    this.scenarioOverrides.delete(agentName);
+  }
+ 
+  /**
+   * Spawn a new mock agent.
+   *
+   * Creates agent record in internal Map, schedules completion based on scenario.
+   * Completion happens async via setTimeout (even if delay=0).
+   */
+  async spawn(options: SpawnAgentOptions): Promise<AgentInfo> {
+    const { taskId, prompt } = options;
+    const name = options.name ?? `agent-${taskId?.slice(0, 6) ?? 'noTask'}`;
+ 
+    // Check name uniqueness
+    for (const record of this.agents.values()) {
+      if (record.info.name === name) {
+        throw new Error(`Agent with name '${name}' already exists`);
+      }
+    }
+ 
+    const agentId = randomUUID();
+    const sessionId = randomUUID();
+    const worktreeId = randomUUID();
+    const now = new Date();
+ 
+    // Determine scenario (override takes precedence — use original name or generated)
+    const scenario = this.scenarioOverrides.get(name) ?? this.defaultScenario;
+ 
+    const info: AgentInfo = {
+      id: agentId,
+      name: name ?? `mock-${agentId.slice(0, 6)}`,
+      taskId: taskId ?? null,
+      initiativeId: options.initiativeId ?? null,
+      sessionId,
+      worktreeId,
+      status: 'running',
+      mode: options.mode ?? 'execute',
+      provider: options.provider ?? 'claude',
+      accountId: null,
+      createdAt: now,
+      updatedAt: now,
+    };
+ 
+    const record: MockAgentRecord = {
+      info,
+      scenario,
+    };
+ 
+    this.agents.set(agentId, record);
+ 
+    // Emit spawned event
+    if (this.eventBus) {
+      const event: AgentSpawnedEvent = {
+        type: 'agent:spawned',
+        timestamp: new Date(),
+        payload: {
+          agentId,
+          name,
+          taskId: taskId ?? null,
+          worktreeId,
+          provider: options.provider ?? 'claude',
+        },
+      };
+      this.eventBus.emit(event);
+    }
+ 
+    // Schedule completion async (even with delay=0, uses setTimeout for async behavior)
+    this.scheduleCompletion(agentId, scenario);
+ 
+    return info;
+  }
+ 
+  /**
+   * Schedule agent completion based on scenario.
+   */
+  private scheduleCompletion(agentId: string, scenario: MockAgentScenario): void {
+    const delay = scenario.delay ?? 0;
+ 
+    const timer = setTimeout(() => {
+      this.completeAgent(agentId, scenario);
+    }, delay);
+ 
+    const record = this.agents.get(agentId);
+    Eif (record) {
+      record.completionTimer = timer;
+    }
+  }
+ 
+  /**
+   * Map agent mode to stopped event reason.
+   */
+  private getStoppedReason(mode: AgentMode): AgentStoppedEvent['payload']['reason'] {
+    switch (mode) {
+      case 'discuss': return 'context_complete';
+      case 'plan': return 'plan_complete';
+      case 'detail': return 'detail_complete';
+      case 'refine': return 'refine_complete';
+      default: return 'task_complete';
+    }
+  }
+ 
+  /**
+   * Complete agent based on scenario status.
+   */
+  private completeAgent(agentId: string, scenario: MockAgentScenario): void {
+    const record = this.agents.get(agentId);
+    Iif (!record) return;
+ 
+    const { info } = record;
+ 
+    switch (scenario.status) {
+      case 'done':
+        record.result = {
+          success: true,
+          message: scenario.result ?? 'Task completed successfully',
+          filesModified: scenario.filesModified,
+        };
+        record.info.status = 'idle';
+        record.info.updatedAt = new Date();
+ 
+        Eif (this.eventBus) {
+          const reason = this.getStoppedReason(info.mode);
+          const event: AgentStoppedEvent = {
+            type: 'agent:stopped',
+            timestamp: new Date(),
+            payload: {
+              agentId,
+              name: info.name,
+              taskId: info.taskId,
+              reason,
+            },
+          };
+          this.eventBus.emit(event);
+        }
+        break;
+ 
+      case 'error':
+        record.result = {
+          success: false,
+          message: scenario.error,
+        };
+        record.info.status = 'crashed';
+        record.info.updatedAt = new Date();
+ 
+        Eif (this.eventBus) {
+          const event: AgentCrashedEvent = {
+            type: 'agent:crashed',
+            timestamp: new Date(),
+            payload: {
+              agentId,
+              name: info.name,
+              taskId: info.taskId,
+              error: scenario.error,
+            },
+          };
+          this.eventBus.emit(event);
+        }
+        break;
+ 
+      case 'questions':
+        record.info.status = 'waiting_for_input';
+        record.info.updatedAt = new Date();
+        record.pendingQuestions = {
+          questions: scenario.questions,
+        };
+ 
+        Eif (this.eventBus) {
+          const event: AgentWaitingEvent = {
+            type: 'agent:waiting',
+            timestamp: new Date(),
+            payload: {
+              agentId,
+              name: info.name,
+              taskId: info.taskId,
+              sessionId: info.sessionId ?? '',
+              questions: scenario.questions,
+            },
+          };
+          this.eventBus.emit(event);
+        }
+        break;
+    }
+  }
+ 
+  /**
+   * Stop a running agent.
+   *
+   * Cancels scheduled completion, marks agent stopped, emits agent:stopped event.
+   */
+  async stop(agentId: string): Promise<void> {
+    const record = this.agents.get(agentId);
+    if (!record) {
+      throw new Error(`Agent '${agentId}' not found`);
+    }
+ 
+    // Cancel any pending completion
+    Eif (record.completionTimer) {
+      clearTimeout(record.completionTimer);
+      record.completionTimer = undefined;
+    }
+ 
+    record.info.status = 'stopped';
+    record.info.updatedAt = new Date();
+ 
+    Eif (this.eventBus) {
+      const event: AgentStoppedEvent = {
+        type: 'agent:stopped',
+        timestamp: new Date(),
+        payload: {
+          agentId,
+          name: record.info.name,
+          taskId: record.info.taskId,
+          reason: 'user_requested',
+        },
+      };
+      this.eventBus.emit(event);
+    }
+  }
+ 
+  /**
+   * Delete an agent and clean up.
+   * Removes from internal map and emits agent:deleted event.
+   */
+  async delete(agentId: string): Promise<void> {
+    const record = this.agents.get(agentId);
+    if (!record) {
+      throw new Error(`Agent '${agentId}' not found`);
+    }
+ 
+    // Cancel any pending completion
+    if (record.completionTimer) {
+      clearTimeout(record.completionTimer);
+      record.completionTimer = undefined;
+    }
+ 
+    const name = record.info.name;
+    this.agents.delete(agentId);
+ 
+    if (this.eventBus) {
+      const event: AgentDeletedEvent = {
+        type: 'agent:deleted',
+        timestamp: new Date(),
+        payload: {
+          agentId,
+          name,
+        },
+      };
+      this.eventBus.emit(event);
+    }
+  }
+ 
+  /**
+   * List all agents with their current status.
+   */
+  async list(): Promise<AgentInfo[]> {
+    return Array.from(this.agents.values()).map((record) => record.info);
+  }
+ 
+  /**
+   * Get a specific agent by ID.
+   */
+  async get(agentId: string): Promise<AgentInfo | null> {
+    const record = this.agents.get(agentId);
+    return record ? record.info : null;
+  }
+ 
+  /**
+   * Get a specific agent by name.
+   */
+  async getByName(name: string): Promise<AgentInfo | null> {
+    for (const record of this.agents.values()) {
+      Eif (record.info.name === name) {
+        return record.info;
+      }
+    }
+    return null;
+  }
+ 
+  /**
+   * Resume an agent that's waiting for input.
+   *
+   * Re-runs the scenario for the resumed agent. Emits agent:resumed event.
+   * Agent must be in 'waiting_for_input' status.
+   *
+   * @param agentId - Agent to resume
+   * @param answers - Map of question ID to user's answer
+   */
+  async resume(agentId: string, answers: Record<string, string>): Promise<void> {
+    const record = this.agents.get(agentId);
+    if (!record) {
+      throw new Error(`Agent '${agentId}' not found`);
+    }
+ 
+    if (record.info.status !== 'waiting_for_input') {
+      throw new Error(
+        `Agent '${record.info.name}' is not waiting for input (status: ${record.info.status})`
+      );
+    }
+ 
+    Iif (!record.info.sessionId) {
+      throw new Error(`Agent '${record.info.name}' has no session to resume`);
+    }
+ 
+    // Update status to running, clear pending questions
+    record.info.status = 'running';
+    record.info.updatedAt = new Date();
+    record.pendingQuestions = undefined;
+ 
+    // Emit resumed event
+    Eif (this.eventBus) {
+      const event: AgentResumedEvent = {
+        type: 'agent:resumed',
+        timestamp: new Date(),
+        payload: {
+          agentId,
+          name: record.info.name,
+          taskId: record.info.taskId,
+          sessionId: record.info.sessionId,
+        },
+      };
+      this.eventBus.emit(event);
+    }
+ 
+    // Re-run scenario (after resume, typically completes successfully)
+    // For testing, we use a new scenario that defaults to success
+    // Extract filesModified from original scenario if it was a 'done' type
+    const originalFilesModified =
+      record.scenario.status === 'done' ? record.scenario.filesModified : undefined;
+    const resumeScenario: MockAgentScenario = {
+      status: 'done',
+      delay: record.scenario.delay ?? 0,
+      result: 'Resumed and completed successfully',
+      filesModified: originalFilesModified,
+    };
+ 
+    this.scheduleCompletion(agentId, resumeScenario);
+  }
+ 
+  /**
+   * Get the result of an agent's work.
+   *
+   * Only available after agent completes or crashes.
+   */
+  async getResult(agentId: string): Promise<AgentResult | null> {
+    const record = this.agents.get(agentId);
+    return record?.result ?? null;
+  }
+ 
+  /**
+   * Get pending questions for an agent waiting for input.
+   */
+  async getPendingQuestions(agentId: string): Promise<PendingQuestions | null> {
+    const record = this.agents.get(agentId);
+    return record?.pendingQuestions ?? null;
+  }
+ 
+  /**
+   * Dismiss an agent.
+   * Mock implementation just marks the agent as dismissed.
+   */
+  async dismiss(agentId: string): Promise<void> {
+    const record = this.agents.get(agentId);
+    Iif (!record) {
+      throw new Error(`Agent '${agentId}' not found`);
+    }
+    const now = new Date();
+    record.info.userDismissedAt = now;
+    record.info.updatedAt = now;
+  }
+ 
+  /**
+   * Clear all agents and pending timers.
+   * Useful for test cleanup.
+   */
+  clear(): void {
+    for (const record of this.agents.values()) {
+      if (record.completionTimer) {
+        clearTimeout(record.completionTimer);
+      }
+    }
+    this.agents.clear();
+    this.scenarioOverrides.clear();
+  }
+}
+ 
+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/coverage/src/agent/output-handler.ts.html b/coverage/src/agent/output-handler.ts.html new file mode 100644 index 0000000..7bdf31d --- /dev/null +++ b/coverage/src/agent/output-handler.ts.html @@ -0,0 +1,2869 @@ + + + + + + Code coverage report for src/agent/output-handler.ts + + + + + + + + + +
+
+

All files / src/agent output-handler.ts

+
+ +
+ 49.56% + Statements + 169/341 +
+ + +
+ 30.85% + Branches + 79/256 +
+ + +
+ 75% + Functions + 15/20 +
+ + +
+ 50.76% + Lines + 166/327 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+

+
1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 +30 +31 +32 +33 +34 +35 +36 +37 +38 +39 +40 +41 +42 +43 +44 +45 +46 +47 +48 +49 +50 +51 +52 +53 +54 +55 +56 +57 +58 +59 +60 +61 +62 +63 +64 +65 +66 +67 +68 +69 +70 +71 +72 +73 +74 +75 +76 +77 +78 +79 +80 +81 +82 +83 +84 +85 +86 +87 +88 +89 +90 +91 +92 +93 +94 +95 +96 +97 +98 +99 +100 +101 +102 +103 +104 +105 +106 +107 +108 +109 +110 +111 +112 +113 +114 +115 +116 +117 +118 +119 +120 +121 +122 +123 +124 +125 +126 +127 +128 +129 +130 +131 +132 +133 +134 +135 +136 +137 +138 +139 +140 +141 +142 +143 +144 +145 +146 +147 +148 +149 +150 +151 +152 +153 +154 +155 +156 +157 +158 +159 +160 +161 +162 +163 +164 +165 +166 +167 +168 +169 +170 +171 +172 +173 +174 +175 +176 +177 +178 +179 +180 +181 +182 +183 +184 +185 +186 +187 +188 +189 +190 +191 +192 +193 +194 +195 +196 +197 +198 +199 +200 +201 +202 +203 +204 +205 +206 +207 +208 +209 +210 +211 +212 +213 +214 +215 +216 +217 +218 +219 +220 +221 +222 +223 +224 +225 +226 +227 +228 +229 +230 +231 +232 +233 +234 +235 +236 +237 +238 +239 +240 +241 +242 +243 +244 +245 +246 +247 +248 +249 +250 +251 +252 +253 +254 +255 +256 +257 +258 +259 +260 +261 +262 +263 +264 +265 +266 +267 +268 +269 +270 +271 +272 +273 +274 +275 +276 +277 +278 +279 +280 +281 +282 +283 +284 +285 +286 +287 +288 +289 +290 +291 +292 +293 +294 +295 +296 +297 +298 +299 +300 +301 +302 +303 +304 +305 +306 +307 +308 +309 +310 +311 +312 +313 +314 +315 +316 +317 +318 +319 +320 +321 +322 +323 +324 +325 +326 +327 +328 +329 +330 +331 +332 +333 +334 +335 +336 +337 +338 +339 +340 +341 +342 +343 +344 +345 +346 +347 +348 +349 +350 +351 +352 +353 +354 +355 +356 +357 +358 +359 +360 +361 +362 +363 +364 +365 +366 +367 +368 +369 +370 +371 +372 +373 +374 +375 +376 +377 +378 +379 +380 +381 +382 +383 +384 +385 +386 +387 +388 +389 +390 +391 +392 +393 +394 +395 +396 +397 +398 +399 +400 +401 +402 +403 +404 +405 +406 +407 +408 +409 +410 +411 +412 +413 +414 +415 +416 +417 +418 +419 +420 +421 +422 +423 +424 +425 +426 +427 +428 +429 +430 +431 +432 +433 +434 +435 +436 +437 +438 +439 +440 +441 +442 +443 +444 +445 +446 +447 +448 +449 +450 +451 +452 +453 +454 +455 +456 +457 +458 +459 +460 +461 +462 +463 +464 +465 +466 +467 +468 +469 +470 +471 +472 +473 +474 +475 +476 +477 +478 +479 +480 +481 +482 +483 +484 +485 +486 +487 +488 +489 +490 +491 +492 +493 +494 +495 +496 +497 +498 +499 +500 +501 +502 +503 +504 +505 +506 +507 +508 +509 +510 +511 +512 +513 +514 +515 +516 +517 +518 +519 +520 +521 +522 +523 +524 +525 +526 +527 +528 +529 +530 +531 +532 +533 +534 +535 +536 +537 +538 +539 +540 +541 +542 +543 +544 +545 +546 +547 +548 +549 +550 +551 +552 +553 +554 +555 +556 +557 +558 +559 +560 +561 +562 +563 +564 +565 +566 +567 +568 +569 +570 +571 +572 +573 +574 +575 +576 +577 +578 +579 +580 +581 +582 +583 +584 +585 +586 +587 +588 +589 +590 +591 +592 +593 +594 +595 +596 +597 +598 +599 +600 +601 +602 +603 +604 +605 +606 +607 +608 +609 +610 +611 +612 +613 +614 +615 +616 +617 +618 +619 +620 +621 +622 +623 +624 +625 +626 +627 +628 +629 +630 +631 +632 +633 +634 +635 +636 +637 +638 +639 +640 +641 +642 +643 +644 +645 +646 +647 +648 +649 +650 +651 +652 +653 +654 +655 +656 +657 +658 +659 +660 +661 +662 +663 +664 +665 +666 +667 +668 +669 +670 +671 +672 +673 +674 +675 +676 +677 +678 +679 +680 +681 +682 +683 +684 +685 +686 +687 +688 +689 +690 +691 +692 +693 +694 +695 +696 +697 +698 +699 +700 +701 +702 +703 +704 +705 +706 +707 +708 +709 +710 +711 +712 +713 +714 +715 +716 +717 +718 +719 +720 +721 +722 +723 +724 +725 +726 +727 +728 +729 +730 +731 +732 +733 +734 +735 +736 +737 +738 +739 +740 +741 +742 +743 +744 +745 +746 +747 +748 +749 +750 +751 +752 +753 +754 +755 +756 +757 +758 +759 +760 +761 +762 +763 +764 +765 +766 +767 +768 +769 +770 +771 +772 +773 +774 +775 +776 +777 +778 +779 +780 +781 +782 +783 +784 +785 +786 +787 +788 +789 +790 +791 +792 +793 +794 +795 +796 +797 +798 +799 +800 +801 +802 +803 +804 +805 +806 +807 +808 +809 +810 +811 +812 +813 +814 +815 +816 +817 +818 +819 +820 +821 +822 +823 +824 +825 +826 +827 +828 +829 +830 +831 +832 +833 +834 +835 +836 +837 +838 +839 +840 +841 +842 +843 +844 +845 +846 +847 +848 +849 +850 +851 +852 +853 +854 +855 +856 +857 +858 +859 +860 +861 +862 +863 +864 +865 +866 +867 +868 +869 +870 +871 +872 +873 +874 +875 +876 +877 +878 +879 +880 +881 +882 +883 +884 +885 +886 +887 +888 +889 +890 +891 +892 +893 +894 +895 +896 +897 +898 +899 +900 +901 +902 +903 +904 +905 +906 +907 +908 +909 +910 +911 +912 +913 +914 +915 +916 +917 +918 +919 +920 +921 +922 +923 +924 +925 +926 +927 +928 +929  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +20x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +51x +51x +  +  +51x +51x +51x +51x +51x +51x +51x +  +  +  +  +  +  +2x +2x +2x +2x +  +  +  +2x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +2x +2x +  +2x +2x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +2x +2x +  +2x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +18x +2x +2x +  +  +16x +  +16x +16x +14x +  +8x +8x +  +8x +  +  +  +  +8x +18x +18x +18x +  +18x +18x +18x +  +18x +  +  +  +  +  +  +  +  +18x +  +  +  +  +  +  +8x +  +  +  +18x +  +  +  +  +  +8x +8x +8x +8x +  +8x +  +8x +8x +  +8x +6x +6x +6x +6x +6x +  +2x +  +  +  +2x +8x +  +2x +  +  +  +  +  +  +2x +  +  +  +  +  +  +  +  +  +  +2x +2x +2x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +16x +16x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +8x +8x +  +  +  +  +  +8x +8x +8x +  +  +  +  +  +  +  +  +  +  +  +  +  +8x +8x +8x +  +  +  +  +  +  +  +  +  +  +  +  +  +8x +  +3x +3x +  +5x +5x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +3x +3x +3x +3x +  +3x +3x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +3x +3x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +3x +  +3x +  +  +  +3x +  +  +  +  +3x +  +3x +3x +1x +  +  +  +  +  +  +  +  +  +1x +  +  +3x +  +  +  +  +  +  +  +  +  +  +  +5x +  +5x +  +5x +1x +  +  +  +  +  +  +  +  +  +  +1x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +3x +  +  +  +3x +  +  +  +  +  +  +  +  +  +  +  +  +  +3x +3x +  +  +3x +3x +3x +3x +  +  +  +  +  +  +  +  +  +  +3x +3x +3x +3x +3x +  +  +  +  +  +  +  +3x +  +  +3x +  +3x +  +3x +3x +3x +3x +3x +3x +3x +  +  +  +  +3x +  +  +  +  +  +  +3x +  +  +  +  +  +  +3x +3x +3x +  +1x +1x +1x +  +  +2x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +3x +3x +3x +  +3x +  +3x +  +  +  +  +3x +  +  +  +  +3x +1x +  +  +  +  +  +  +  +  +  +1x +  +  +  +  +  +  +  +  +7x +7x +7x +  +7x +7x +  +7x +  +7x +  +  +  +  +  +  +1x +1x +1x +  +  +  +  +  +  +2x +2x +2x +  +  +  +  +  +  +  +  +  +  +  +  +  +14x +  +  +  +  +  +14x +14x +14x +  +11x +11x +  +11x +9x +  +1x +  +1x +1x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  + 
/**
+ * OutputHandler — Stream event processing, signal parsing, file reading, result capture.
+ *
+ * Extracted from MultiProviderAgentManager. Processes all output from agent
+ * subprocesses: stream events, agent signals, output files, and result/question
+ * retrieval.
+ */
+ 
+import { readFile } from 'node:fs/promises';
+import { existsSync } from 'node:fs';
+import { join } from 'node:path';
+import type { AgentRepository } from '../db/repositories/agent-repository.js';
+import type { ChangeSetRepository, CreateChangeSetEntryData } from '../db/repositories/change-set-repository.js';
+import type { PhaseRepository } from '../db/repositories/phase-repository.js';
+import type { TaskRepository } from '../db/repositories/task-repository.js';
+import type { PageRepository } from '../db/repositories/page-repository.js';
+import type {
+  EventBus,
+  AgentStoppedEvent,
+  AgentCrashedEvent,
+  AgentWaitingEvent,
+} from '../events/index.js';
+import type {
+  AgentResult,
+  AgentMode,
+  PendingQuestions,
+  QuestionItem,
+} from './types.js';
+import type { StreamEvent } from './providers/parsers/index.js';
+import type { AgentProviderConfig } from './providers/types.js';
+import { agentSignalSchema } from './schema.js';
+import {
+  readSummary,
+  readPhaseFiles,
+  readTaskFiles,
+  readDecisionFiles,
+  readPageFiles,
+  readFrontmatterFile,
+} from './file-io.js';
+import { getProvider } from './providers/registry.js';
+import { markdownToTiptapJson } from './markdown-to-tiptap.js';
+import type { SignalManager } from './lifecycle/signal-manager.js';
+import { createModuleLogger } from '../logger/index.js';
+ 
+const log = createModuleLogger('output-handler');
+ 
+/**
+ * Tracks an active agent with its PID and file tailer.
+ */
+export interface ActiveAgent {
+  agentId: string;
+  pid: number;
+  tailer: import('./file-tailer.js').FileTailer;
+  outputFilePath: string;
+  /** Actual working directory the agent process runs in (may differ from getAgentWorkdir for standalone agents) */
+  agentCwd?: string;
+  result?: AgentResult;
+  pendingQuestions?: PendingQuestions;
+  streamResultText?: string;
+  streamSessionId?: string;
+  streamCostUsd?: number;
+  /** True when the stream result indicated an error (e.g. auth failure) */
+  streamIsError?: boolean;
+  /** Cancel handle for polling timer — call to stop polling on cleanup */
+  cancelPoll?: () => void;
+}
+ 
+/**
+ * Result structure from Claude CLI with --output-format json.
+ */
+interface ClaudeCliResult {
+  type: 'result';
+  subtype: 'success' | 'error';
+  is_error: boolean;
+  session_id: string;
+  result: string;
+  structured_output?: unknown;
+  total_cost_usd?: number;
+}
+ 
+export class OutputHandler {
+  private filePositions = new Map<string, number>();
+  private completionLocks = new Set<string>(); // Track agents currently being processed
+ 
+  constructor(
+    private repository: AgentRepository,
+    private eventBus?: EventBus,
+    private changeSetRepository?: ChangeSetRepository,
+    private phaseRepository?: PhaseRepository,
+    private taskRepository?: TaskRepository,
+    private pageRepository?: PageRepository,
+    private signalManager?: SignalManager,
+  ) {}
+ 
+  /**
+   * Validate that a signal file is complete and properly formatted.
+   */
+  private async validateSignalFile(filePath: string): Promise<boolean> {
+    try {
+      const content = await readFile(filePath, 'utf-8');
+      const trimmed = content.trim();
+      Eif (!trimmed) return false;
+ 
+      // Check if JSON is complete (ends with } or ])
+      const endsCorrectly = trimmed.endsWith('}') || trimmed.endsWith(']');
+      Iif (!endsCorrectly) return false;
+ 
+      // Try to parse as JSON to ensure it's valid
+      JSON.parse(trimmed);
+      return true;
+    } catch {
+      return false;
+    }
+  }
+ 
+  /**
+   * Read complete lines from a file, avoiding partial lines that might still be writing.
+   * This eliminates race conditions when agents are still writing output.
+   */
+  private async readCompleteLines(filePath: string, fromPosition: number = 0): Promise<{ content: string; lastPosition: number }> {
+    try {
+      const content = await readFile(filePath, 'utf-8');
+ 
+      Eif (fromPosition >= content.length) {
+        return { content: '', lastPosition: fromPosition };
+      }
+ 
+      // Get content from our last read position
+      const newContent = content.slice(fromPosition);
+ 
+      // Split into lines
+      const lines = newContent.split('\n');
+ 
+      // If file doesn't end with newline, last element is potentially incomplete
+      // Only process complete lines (all but the last, unless file ends with \n)
+      const hasTrailingNewline = newContent.endsWith('\n');
+      const completeLines = hasTrailingNewline ? lines : lines.slice(0, -1);
+ 
+      // Calculate new position (only count complete lines)
+      const completeLinesContent = completeLines.join('\n') + (completeLines.length > 0 && hasTrailingNewline ? '\n' : '');
+      const newPosition = fromPosition + Buffer.byteLength(completeLinesContent, 'utf-8');
+ 
+      return {
+        content: completeLinesContent,
+        lastPosition: newPosition
+      };
+    } catch (err) {
+      log.debug({ filePath, err: err instanceof Error ? err.message : String(err) }, 'failed to read output file lines');
+      return { content: '', lastPosition: fromPosition };
+    }
+  }
+ 
+  /**
+   * Handle a standardized stream event from a parser.
+   */
+  handleStreamEvent(
+    agentId: string,
+    event: StreamEvent,
+    active: ActiveAgent | undefined,
+  ): void {
+    switch (event.type) {
+      case 'init':
+        if (active && event.sessionId) {
+          active.streamSessionId = event.sessionId;
+          this.repository.update(agentId, { sessionId: event.sessionId }).catch((err) => {
+            log.warn({ agentId, err: err instanceof Error ? err.message : String(err) }, 'failed to update session ID');
+          });
+        }
+        break;
+ 
+      case 'text_delta':
+        // Text deltas are now streamed via DB log chunks + EventBus in manager.createLogChunkCallback
+        break;
+ 
+      case 'tool_use_start':
+        log.debug({ agentId, tool: event.name, toolId: event.id }, 'tool use started');
+        break;
+ 
+      case 'result':
+        if (active) {
+          active.streamResultText = event.text;
+          active.streamCostUsd = event.costUsd;
+          active.streamIsError = event.isError === true;
+          if (!active.streamSessionId && event.sessionId) {
+            active.streamSessionId = event.sessionId;
+          }
+        }
+        break;
+ 
+      case 'error':
+        log.error({ agentId, error: event.message }, 'stream error event');
+        break;
+ 
+      case 'turn_end':
+        log.debug({ agentId, stopReason: event.stopReason }, 'turn ended');
+        break;
+    }
+  }
+ 
+  /**
+   * Handle completion of a detached agent.
+   * Processes the final result from the stream data captured by the tailer.
+   *
+   * RACE CONDITION FIX: Uses a completion lock to prevent duplicate processing.
+   * Both the polling handler (handleDetachedAgentCompletion) and crash handler
+   * (handleProcessCrashed) can call this method when a process exits with non-zero code.
+   * The mutex ensures only one handler processes the completion per agent.
+   */
+  async handleCompletion(
+    agentId: string,
+    active: ActiveAgent | undefined,
+    getAgentWorkdir: (alias: string) => string,
+  ): Promise<void> {
+    // CRITICAL: Prevent race condition - only one completion handler per agent
+    if (this.completionLocks.has(agentId)) {
+      log.debug({ agentId }, 'completion already being processed - skipping duplicate');
+      return;
+    }
+ 
+    this.completionLocks.add(agentId);
+ 
+    try {
+      const agent = await this.repository.findById(agentId);
+      if (!agent) return;
+ 
+      const provider = getProvider(agent.provider);
+      Iif (!provider) return;
+ 
+      log.debug({ agentId }, 'detached agent completed');
+ 
+      // Resolve actual agent working directory — standalone agents run in a
+      // "workspace/" subdirectory inside getAgentWorkdir, so prefer agentCwd
+      // recorded at spawn time when available.
+      const agentWorkdir = active?.agentCwd ?? getAgentWorkdir(agent.worktreeId);
+      const outputDir = join(agentWorkdir, '.cw', 'output');
+      const expectedPwdFile = join(agentWorkdir, '.cw', 'expected-pwd.txt');
+      const diagnosticFile = join(agentWorkdir, '.cw', 'spawn-diagnostic.json');
+ 
+      const outputDirExists = existsSync(outputDir);
+      const expectedPwdExists = existsSync(expectedPwdFile);
+      const diagnosticExists = existsSync(diagnosticFile);
+ 
+      log.info({
+        agentId,
+        agentWorkdir,
+        outputDirExists,
+        expectedPwdExists,
+        diagnosticExists,
+        verification: outputDirExists ? 'PASS' : 'FAIL'
+      }, 'agent workdir verification completed');
+ 
+      Iif (!outputDirExists) {
+        log.warn({
+          agentId,
+          agentWorkdir
+        }, 'No output files found in agent workdir! Agent may have run in wrong location.');
+      }
+ 
+      let signalText = active?.streamResultText;
+ 
+      // If the stream result indicated an error (e.g. auth failure, usage limit),
+      // route directly to error handling instead of trying to parse as signal JSON
+      Iif (signalText && active?.streamIsError) {
+        log.warn({ agentId, error: signalText }, 'agent returned error result');
+        await this.handleAgentError(agentId, new Error(signalText), provider, getAgentWorkdir);
+        return;
+      }
+ 
+      Eif (!signalText) {
+        try {
+          const outputFilePath = active?.outputFilePath ?? '';
+          Eif (outputFilePath) {
+            // First, check for robust signal.json completion before attempting incremental reading
+            log.debug({ agentId, worktreeId: agent.worktreeId, agentWorkdir }, 'checking signal completion');
+ 
+            const hasSignalCompletion = await this.readSignalCompletion(agentWorkdir);
+            log.debug({ agentId, agentWorkdir, hasSignalCompletion }, 'signal completion check result');
+ 
+            if (hasSignalCompletion) {
+              const signalPath = join(agentWorkdir, '.cw/output/signal.json');
+              const signalContent = await readFile(signalPath, 'utf-8');
+              log.debug({ agentId, signalPath }, 'detected completion via signal.json, processing');
+              await this.processSignalAndFiles(agentId, signalContent, agent.mode as AgentMode, getAgentWorkdir, active?.streamSessionId);
+              return;
+            } else {
+              log.debug({ agentId, agentWorkdir }, 'no signal completion found, proceeding with raw output');
+            }
+ 
+            // Read only complete lines from the file, avoiding race conditions
+            const lastPosition = this.filePositions.get(agentId) || 0;
+            const { content: fileContent, lastPosition: newPosition } = await this.readCompleteLines(outputFilePath, lastPosition);
+ 
+            Iif (fileContent.trim()) {
+              this.filePositions.set(agentId, newPosition);
+              await this.processAgentOutput(agentId, fileContent, provider, getAgentWorkdir);
+              return;
+            }
+ 
+            // If no new complete lines, but file might still be writing, try again with validation
+            Iif (await this.validateSignalFile(outputFilePath)) {
+              const fullContent = await readFile(outputFilePath, 'utf-8');
+              if (fullContent.trim() && fullContent.length > newPosition) {
+                // File is complete and has content beyond what we've read
+                await this.processAgentOutput(agentId, fullContent, provider, getAgentWorkdir);
+                return;
+              }
+            }
+          }
+        } catch { /* file empty or missing */ }
+ 
+        log.debug({ agentId }, 'no result from stream or file, marking as error');
+        await this.handleAgentError(agentId, new Error('No output received'), provider, getAgentWorkdir);
+        return;
+      }
+ 
+      // Check for signal.json file first, then fall back to stream text
+      if (await this.readSignalCompletion(agentWorkdir)) {
+        const signalPath = join(agentWorkdir, '.cw/output/signal.json');
+        const signalContent = await readFile(signalPath, 'utf-8');
+        log.debug({ agentId, signalPath }, 'using signal.json content for completion');
+        await this.processSignalAndFiles(agentId, signalContent, agent.mode as AgentMode, getAgentWorkdir, active?.streamSessionId);
+      } else {
+        log.debug({ agentId }, 'using stream text for completion (no signal.json found)');
+        await this.processSignalAndFiles(
+          agentId,
+          signalText,
+          agent.mode as AgentMode,
+          getAgentWorkdir,
+          active?.streamSessionId,
+        );
+      }
+    } finally {
+      this.completionLocks.delete(agentId);
+      this.filePositions.delete(agentId);
+    }
+  }
+ 
+  /**
+   * Process agent signal JSON and read output files.
+   * Universal handler for all providers and modes.
+   */
+  async processSignalAndFiles(
+    agentId: string,
+    signalText: string,
+    mode: AgentMode,
+    getAgentWorkdir: (alias: string) => string,
+    sessionId?: string,
+  ): Promise<void> {
+    const agent = await this.repository.findById(agentId);
+    Iif (!agent) return;
+ 
+    let signal;
+    let parsed;
+ 
+    // Step 1: JSON parsing
+    try {
+      parsed = JSON.parse(signalText.trim());
+      log.debug({ agentId }, 'signal JSON parsing successful');
+    } catch (jsonError) {
+      log.error({
+        agentId,
+        signalText: signalText.trim(),
+        error: jsonError instanceof Error ? jsonError.message : String(jsonError),
+        stack: jsonError instanceof Error ? jsonError.stack : undefined
+      }, 'signal JSON parsing failed');
+      await this.repository.update(agentId, { status: 'crashed' });
+      this.emitCrashed(agent, 'Failed to parse agent signal JSON');
+      return;
+    }
+ 
+    // Step 2: Schema validation
+    try {
+      signal = agentSignalSchema.parse(parsed);
+      log.debug({ agentId, signalStatus: signal.status }, 'signal schema validation passed');
+    } catch (schemaError) {
+      log.error({
+        agentId,
+        signalText: signalText.trim(),
+        parsed,
+        error: schemaError instanceof Error ? schemaError.message : String(schemaError),
+        stack: schemaError instanceof Error ? schemaError.stack : undefined
+      }, 'signal schema validation failed');
+      await this.repository.update(agentId, { status: 'crashed' });
+      this.emitCrashed(agent, 'Failed to validate agent signal schema');
+      return;
+    }
+ 
+    switch (signal.status) {
+      case 'done':
+        await this.processOutputFiles(agentId, agent, mode, getAgentWorkdir);
+        break;
+      case 'questions':
+        await this.handleQuestions(agentId, agent, signal.questions, sessionId);
+        break;
+      case 'error':
+        await this.handleSignalError(agentId, agent, signal.error);
+        break;
+    }
+  }
+ 
+  /**
+   * Process output files from agent workdir after successful completion.
+   * Performs direct writes to entities and records change sets.
+   */
+  private async processOutputFiles(
+    agentId: string,
+    agent: { id: string; name: string; taskId: string | null; worktreeId: string; mode: string; initiativeId?: string | null },
+    mode: AgentMode,
+    getAgentWorkdir: (alias: string) => string,
+  ): Promise<void> {
+    const agentWorkdir = getAgentWorkdir(agent.worktreeId);
+    const summary = readSummary(agentWorkdir);
+    const initiativeId = agent.initiativeId;
+    const canWriteChangeSets = this.changeSetRepository && initiativeId;
+ 
+    let resultMessage = summary?.body ?? 'Task completed';
+    switch (mode) {
+      case 'plan': {
+        const phases = readPhaseFiles(agentWorkdir);
+        if (canWriteChangeSets && this.phaseRepository && phases.length > 0) {
+          const entries: CreateChangeSetEntryData[] = [];
+ 
+          // First pass: create phases
+          for (const [i, p] of phases.entries()) {
+            try {
+              const tiptapContent = p.body ? JSON.stringify(markdownToTiptapJson(p.body)) : undefined;
+              const created = await this.phaseRepository.create({
+                id: p.id ?? undefined,
+                initiativeId,
+                name: p.title,
+                content: tiptapContent,
+              });
+              entries.push({
+                entityType: 'phase',
+                entityId: created.id,
+                action: 'create',
+                newState: JSON.stringify(created),
+                sortOrder: i,
+              });
+              this.eventBus?.emit({
+                type: 'phase:started' as const,
+                timestamp: new Date(),
+                payload: { phaseId: created.id, initiativeId },
+              });
+            } catch (err) {
+              log.warn({ agentId, phase: p.title, err: err instanceof Error ? err.message : String(err) }, 'failed to create phase');
+            }
+          }
+ 
+          // Second pass: create phase dependencies
+          let depSortOrder = entries.length;
+          for (const p of phases) {
+            const phaseId = p.id;
+            if (!phaseId || !Array.isArray(p.dependencies)) continue;
+            for (const depFileId of p.dependencies) {
+              try {
+                await this.phaseRepository.createDependency(phaseId, depFileId);
+                entries.push({
+                  entityType: 'phase_dependency',
+                  entityId: `${phaseId}:${depFileId}`,
+                  action: 'create',
+                  newState: JSON.stringify({ phaseId, dependsOnPhaseId: depFileId }),
+                  sortOrder: depSortOrder++,
+                });
+              } catch (err) {
+                log.warn({ agentId, phaseId, depFileId, err: err instanceof Error ? err.message : String(err) }, 'failed to create phase dependency');
+              }
+            }
+          }
+ 
+          if (entries.length > 0) {
+            try {
+              const cs = await this.changeSetRepository!.createWithEntries({
+                agentId,
+                agentName: agent.name,
+                initiativeId,
+                mode: 'plan',
+                summary: summary?.body ?? `Created ${phases.length} phases`,
+              }, entries);
+              this.eventBus?.emit({
+                type: 'changeset:created' as const,
+                timestamp: new Date(),
+                payload: { changeSetId: cs.id, initiativeId, agentId, mode: 'plan', entryCount: entries.length },
+              });
+            } catch (err) {
+              log.warn({ agentId, err: err instanceof Error ? err.message : String(err) }, 'failed to record change set after successful writes');
+            }
+          }
+          resultMessage = summary?.body ?? `${phases.length} phases created`;
+        } else {
+          resultMessage = JSON.stringify({ summary: summary?.body, phases });
+        }
+        break;
+      }
+      case 'detail': {
+        const tasks = readTaskFiles(agentWorkdir);
+        if (canWriteChangeSets && this.taskRepository && tasks.length > 0) {
+          const phaseInput = readFrontmatterFile(join(agentWorkdir, '.cw', 'input', 'phase.md'));
+          const phaseId = (phaseInput?.data?.id as string) ?? null;
+          const entries: CreateChangeSetEntryData[] = [];
+ 
+          // Load existing tasks for dedup — prevents duplicates when multiple agents finish concurrently
+          const existingTasks = phaseId ? await this.taskRepository.findByPhaseId(phaseId) : [];
+          const existingNames = new Set(existingTasks.map(t => t.name));
+ 
+          for (const [i, t] of tasks.entries()) {
+            if (existingNames.has(t.title)) {
+              log.info({ agentId, task: t.title, phaseId }, 'skipped duplicate task');
+              continue;
+            }
+            try {
+              const created = await this.taskRepository.create({
+                initiativeId,
+                phaseId,
+                parentTaskId: agent.taskId ?? null,
+                name: t.title,
+                description: t.body ?? undefined,
+                category: (t.category as any) ?? 'execute',
+                type: (t.type as any) ?? 'auto',
+              });
+              existingNames.add(t.title); // prevent dupes within same agent output
+              entries.push({
+                entityType: 'task',
+                entityId: created.id,
+                action: 'create',
+                newState: JSON.stringify(created),
+                sortOrder: i,
+              });
+              this.eventBus?.emit({
+                type: 'task:completed' as const,
+                timestamp: new Date(),
+                payload: { taskId: created.id, agentId, success: true, message: 'Task created by detail' },
+              });
+            } catch (err) {
+              log.warn({ agentId, task: t.title, err: err instanceof Error ? err.message : String(err) }, 'failed to create task');
+            }
+          }
+ 
+          if (entries.length > 0) {
+            try {
+              const cs = await this.changeSetRepository!.createWithEntries({
+                agentId,
+                agentName: agent.name,
+                initiativeId,
+                mode: 'detail',
+                summary: summary?.body ?? `Created ${tasks.length} tasks`,
+              }, entries);
+              this.eventBus?.emit({
+                type: 'changeset:created' as const,
+                timestamp: new Date(),
+                payload: { changeSetId: cs.id, initiativeId, agentId, mode: 'detail', entryCount: entries.length },
+              });
+            } catch (err) {
+              log.warn({ agentId, err: err instanceof Error ? err.message : String(err) }, 'failed to record change set after successful writes');
+            }
+          }
+          resultMessage = summary?.body ?? `${tasks.length} tasks created`;
+        } else {
+          resultMessage = JSON.stringify({ summary: summary?.body, tasks });
+        }
+        break;
+      }
+      case 'discuss': {
+        const decisions = readDecisionFiles(agentWorkdir);
+        resultMessage = JSON.stringify({ summary: summary?.body, decisions });
+        break;
+      }
+      case 'refine': {
+        const pages = readPageFiles(agentWorkdir);
+        Iif (canWriteChangeSets && this.pageRepository && pages.length > 0) {
+          const entries: CreateChangeSetEntryData[] = [];
+ 
+          for (const [i, p] of pages.entries()) {
+            try {
+              if (!p.pageId) continue;
+              const existing = await this.pageRepository.findById(p.pageId);
+              if (!existing) {
+                log.warn({ agentId, pageId: p.pageId }, 'page not found for refine update');
+                continue;
+              }
+              const previousState = JSON.stringify(existing);
+              const tiptapJson = markdownToTiptapJson(p.body || '');
+              await this.pageRepository.update(p.pageId, {
+                content: JSON.stringify(tiptapJson),
+                title: p.title,
+              });
+              const updated = await this.pageRepository.findById(p.pageId);
+              entries.push({
+                entityType: 'page',
+                entityId: p.pageId,
+                action: 'update',
+                previousState,
+                newState: JSON.stringify(updated),
+                sortOrder: i,
+              });
+              this.eventBus?.emit({
+                type: 'page:updated' as const,
+                timestamp: new Date(),
+                payload: { pageId: p.pageId, initiativeId, title: p.title },
+              });
+            } catch (err) {
+              log.warn({ agentId, pageId: p.pageId, err: err instanceof Error ? err.message : String(err) }, 'failed to update page');
+            }
+          }
+ 
+          if (entries.length > 0) {
+            try {
+              const cs = await this.changeSetRepository!.createWithEntries({
+                agentId,
+                agentName: agent.name,
+                initiativeId,
+                mode: 'refine',
+                summary: summary?.body ?? `Updated ${entries.length} pages`,
+              }, entries);
+              this.eventBus?.emit({
+                type: 'changeset:created' as const,
+                timestamp: new Date(),
+                payload: { changeSetId: cs.id, initiativeId, agentId, mode: 'refine', entryCount: entries.length },
+              });
+            } catch (err) {
+              log.warn({ agentId, err: err instanceof Error ? err.message : String(err) }, 'failed to record change set after successful writes');
+            }
+          }
+          resultMessage = summary?.body ?? `${entries.length} pages updated`;
+        } else {
+          resultMessage = JSON.stringify({ summary: summary?.body, pages });
+        }
+        break;
+      }
+    }
+ 
+    const resultPayload: AgentResult = {
+      success: true,
+      message: resultMessage,
+      filesModified: summary?.filesModified,
+    };
+    await this.repository.update(agentId, { result: JSON.stringify(resultPayload), status: 'idle' });
+ 
+    const reason = this.getStoppedReason(mode);
+    if (this.eventBus) {
+      const event: AgentStoppedEvent = {
+        type: 'agent:stopped',
+        timestamp: new Date(),
+        payload: {
+          agentId,
+          name: agent.name,
+          taskId: agent.taskId ?? '',
+          reason,
+        },
+      };
+      this.eventBus.emit(event);
+    }
+ 
+    return;
+  }
+ 
+  /**
+   * Handle questions signal from agent.
+   */
+  async handleQuestions(
+    agentId: string,
+    agent: { id: string; name: string; taskId: string | null; sessionId: string | null },
+    questions: QuestionItem[],
+    sessionId?: string,
+  ): Promise<void> {
+    const questionsPayload: PendingQuestions = { questions };
+ 
+    await this.repository.update(agentId, { pendingQuestions: JSON.stringify(questionsPayload), status: 'waiting_for_input' });
+ 
+    if (this.eventBus) {
+      const event: AgentWaitingEvent = {
+        type: 'agent:waiting',
+        timestamp: new Date(),
+        payload: {
+          agentId,
+          name: agent.name,
+          taskId: agent.taskId ?? '',
+          sessionId: sessionId ?? agent.sessionId ?? '',
+          questions,
+        },
+      };
+      this.eventBus.emit(event);
+    }
+  }
+ 
+  /**
+   * Handle error signal from agent.
+   */
+  async handleSignalError(
+    agentId: string,
+    agent: { id: string; name: string; taskId: string | null },
+    error: string,
+  ): Promise<void> {
+    const errorResult: AgentResult = { success: false, message: error };
+ 
+    await this.repository.update(agentId, {
+      result: JSON.stringify(errorResult),
+      status: 'crashed'
+    });
+ 
+    this.emitCrashed(agent, error);
+  }
+ 
+  /**
+   * Map agent mode to stopped event reason.
+   */
+  getStoppedReason(mode: AgentMode): AgentStoppedEvent['payload']['reason'] {
+    switch (mode) {
+      case 'discuss': return 'context_complete';
+      case 'plan': return 'plan_complete';
+      case 'detail': return 'detail_complete';
+      case 'refine': return 'refine_complete';
+      default: return 'task_complete';
+    }
+  }
+ 
+  /**
+   * Process raw output from an agent (from file or direct).
+   */
+  async processAgentOutput(
+    agentId: string,
+    rawOutput: string,
+    provider: AgentProviderConfig,
+    getAgentWorkdir: (alias: string) => string,
+  ): Promise<void> {
+    const agent = await this.repository.findById(agentId);
+    Iif (!agent) return;
+ 
+    // Extract session ID using provider's extraction config
+    let sessionId: string | null = null;
+    Eif (provider.sessionId) {
+      const outputLines = rawOutput.trim().split('\n');
+      Iif (provider.sessionId.extractFrom === 'result') {
+        // Find the result line in JSONL output
+        for (const line of outputLines) {
+          try {
+            const parsed = JSON.parse(line);
+            if (parsed.type === 'result' || parsed[provider.sessionId.field]) {
+              sessionId = parsed[provider.sessionId.field] ?? null;
+              if (sessionId) break;
+            }
+          } catch { /* intentional: skip non-JSON JSONL lines */ }
+        }
+      E} else if (provider.sessionId.extractFrom === 'event') {
+        for (const line of outputLines) {
+          try {
+            const event = JSON.parse(line);
+            Iif (event.type === provider.sessionId.eventType) {
+              sessionId = event[provider.sessionId.field] ?? null;
+            }
+          } catch { /* intentional: skip non-JSON JSONL lines */ }
+        }
+      }
+    }
+ 
+    Iif (sessionId) {
+      await this.repository.update(agentId, { sessionId });
+    }
+    log.debug({ agentId, provider: provider.name, hasSessionId: !!sessionId }, 'processing agent output');
+ 
+    if (provider.name === 'claude') {
+      // rawOutput may be a single JSON object or multi-line JSONL — find the result line
+      let cliResult: ClaudeCliResult | null = null;
+      const lines = rawOutput.trim().split('\n');
+      for (const line of lines) {
+        try {
+          const parsed = JSON.parse(line);
+          Eif (parsed.type === 'result') {
+            cliResult = parsed;
+          }
+        } catch { /* intentional: skip non-JSON JSONL lines */ }
+      }
+ 
+      Iif (!cliResult) {
+        log.error({ agentId }, 'no result event found in agent output');
+        await this.handleAgentError(agentId, new Error('No result event in output'), provider, getAgentWorkdir);
+        return;
+      }
+ 
+      // Handle error results (auth failure, usage limits, etc.)
+      Iif (cliResult.is_error) {
+        log.warn({ agentId, error: cliResult.result }, 'agent returned error result from file');
+        await this.handleAgentError(agentId, new Error(cliResult.result), provider, getAgentWorkdir);
+        return;
+      }
+ 
+      let signalText: string;
+      try {
+        const signal = cliResult.structured_output ?? JSON.parse(cliResult.result);
+        signalText = JSON.stringify(signal);
+      } catch (parseErr) {
+        log.error({ agentId, err: parseErr instanceof Error ? parseErr.message : String(parseErr) }, 'failed to parse agent signal from result');
+        await this.handleAgentError(agentId, new Error('Failed to parse agent signal'), provider, getAgentWorkdir);
+        return;
+      }
+ 
+      await this.processSignalAndFiles(agentId, signalText, agent.mode as AgentMode, getAgentWorkdir, sessionId ?? undefined);
+    } else E{
+      await this.processSignalAndFiles(agentId, rawOutput, agent.mode as AgentMode, getAgentWorkdir, sessionId ?? undefined);
+    }
+  }
+ 
+  /**
+   * Handle agent errors. Detects usage limit exhaustion patterns.
+   * Returns true if error was an exhaustion error (caller should attempt failover).
+   */
+  async handleAgentError(
+    agentId: string,
+    error: unknown,
+    provider: AgentProviderConfig,
+    _getAgentWorkdir: (alias: string) => string,
+  ): Promise<void> {
+    const errorMessage = error instanceof Error ? error.message : String(error);
+    const agent = await this.repository.findById(agentId);
+    Iif (!agent) return;
+ 
+    log.error({ agentId, err: errorMessage }, 'agent error');
+ 
+    const errorResult: AgentResult = {
+      success: false,
+      message: errorMessage,
+    };
+ 
+    await this.repository.update(agentId, {
+      status: 'crashed',
+      result: JSON.stringify(errorResult)
+    });
+ 
+    if (this.eventBus) {
+      const event: AgentCrashedEvent = {
+        type: 'agent:crashed',
+        timestamp: new Date(),
+        payload: {
+          agentId,
+          name: agent.name,
+          taskId: agent.taskId ?? '',
+          error: errorMessage,
+        },
+      };
+      this.eventBus.emit(event);
+    }
+  }
+ 
+  /**
+   * Format answers map as structured prompt.
+   * Handles special __instruction__ key for retry scenarios.
+   */
+  formatAnswersAsPrompt(answers: Record<string, string>): string {
+    const instruction = answers['__instruction__'];
+    const realAnswers = { ...answers };
+    delete realAnswers['__instruction__'];
+ 
+    const lines = Object.entries(realAnswers).map(
+      ([questionId, answer]) => `[${questionId}]: ${answer}`,
+    );
+    const basePrompt = `Here are my answers to your questions:\n${lines.join('\n')}`;
+ 
+    return instruction ? `${instruction.trim()}\n\n${basePrompt}` : basePrompt;
+  }
+ 
+  /**
+   * Get the result of an agent's work.
+   */
+  async getResult(agentId: string, active?: ActiveAgent): Promise<AgentResult | null> {
+    Iif (active?.result) return active.result;
+    const agent = await this.repository.findById(agentId);
+    return agent?.result ? JSON.parse(agent.result) : null;
+  }
+ 
+  /**
+   * Get pending questions for an agent waiting for input.
+   */
+  async getPendingQuestions(agentId: string, active?: ActiveAgent): Promise<PendingQuestions | null> {
+    Iif (active?.pendingQuestions) return active.pendingQuestions;
+    const agent = await this.repository.findById(agentId);
+    return agent?.pendingQuestions ? JSON.parse(agent.pendingQuestions) : null;
+  }
+ 
+  // =========================================================================
+  // Private Helpers
+  // =========================================================================
+ 
+  /**
+   * Read signal.json and return its content if the agent completed successfully.
+   * Uses SignalManager for atomic read-and-validate when available.
+   * Returns the raw JSON string on success, null if missing/invalid.
+   */
+  private async readSignalCompletion(agentWorkdir: string): Promise<string | null> {
+    // Prefer SignalManager (unified implementation with proper validation)
+    Iif (this.signalManager) {
+      const signal = await this.signalManager.readSignal(agentWorkdir);
+      return signal ? JSON.stringify(signal) : null;
+    }
+ 
+    // Fallback: inline read (for tests that don't inject SignalManager)
+    try {
+      const signalPath = join(agentWorkdir, '.cw/output/signal.json');
+      if (!existsSync(signalPath)) return null;
+ 
+      const signalContent = await readFile(signalPath, 'utf-8');
+      const signal = JSON.parse(signalContent);
+ 
+      if (signal.status === 'done' || signal.status === 'questions' || signal.status === 'error') {
+        return signalContent;
+      }
+      return null;
+    } catch (err) {
+      log.debug({ agentWorkdir, err: err instanceof Error ? err.message : String(err) }, 'failed to read or parse signal.json');
+      return null;
+    }
+  }
+ 
+  private emitCrashed(agent: { id: string; name: string; taskId: string | null }, error: string): void {
+    if (this.eventBus) {
+      const event: AgentCrashedEvent = {
+        type: 'agent:crashed',
+        timestamp: new Date(),
+        payload: {
+          agentId: agent.id,
+          name: agent.name,
+          taskId: agent.taskId ?? '',
+          error,
+        },
+      };
+      this.eventBus.emit(event);
+    }
+  }
+}
+ 
+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/coverage/src/agent/process-manager.ts.html b/coverage/src/agent/process-manager.ts.html new file mode 100644 index 0000000..45e6a36 --- /dev/null +++ b/coverage/src/agent/process-manager.ts.html @@ -0,0 +1,1267 @@ + + + + + + Code coverage report for src/agent/process-manager.ts + + + + + + + + + +
+
+

All files / src/agent process-manager.ts

+
+ +
+ 68.88% + Statements + 93/135 +
+ + +
+ 42.64% + Branches + 29/68 +
+ + +
+ 63.15% + Functions + 12/19 +
+ + +
+ 70.54% + Lines + 91/129 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+

+
1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 +30 +31 +32 +33 +34 +35 +36 +37 +38 +39 +40 +41 +42 +43 +44 +45 +46 +47 +48 +49 +50 +51 +52 +53 +54 +55 +56 +57 +58 +59 +60 +61 +62 +63 +64 +65 +66 +67 +68 +69 +70 +71 +72 +73 +74 +75 +76 +77 +78 +79 +80 +81 +82 +83 +84 +85 +86 +87 +88 +89 +90 +91 +92 +93 +94 +95 +96 +97 +98 +99 +100 +101 +102 +103 +104 +105 +106 +107 +108 +109 +110 +111 +112 +113 +114 +115 +116 +117 +118 +119 +120 +121 +122 +123 +124 +125 +126 +127 +128 +129 +130 +131 +132 +133 +134 +135 +136 +137 +138 +139 +140 +141 +142 +143 +144 +145 +146 +147 +148 +149 +150 +151 +152 +153 +154 +155 +156 +157 +158 +159 +160 +161 +162 +163 +164 +165 +166 +167 +168 +169 +170 +171 +172 +173 +174 +175 +176 +177 +178 +179 +180 +181 +182 +183 +184 +185 +186 +187 +188 +189 +190 +191 +192 +193 +194 +195 +196 +197 +198 +199 +200 +201 +202 +203 +204 +205 +206 +207 +208 +209 +210 +211 +212 +213 +214 +215 +216 +217 +218 +219 +220 +221 +222 +223 +224 +225 +226 +227 +228 +229 +230 +231 +232 +233 +234 +235 +236 +237 +238 +239 +240 +241 +242 +243 +244 +245 +246 +247 +248 +249 +250 +251 +252 +253 +254 +255 +256 +257 +258 +259 +260 +261 +262 +263 +264 +265 +266 +267 +268 +269 +270 +271 +272 +273 +274 +275 +276 +277 +278 +279 +280 +281 +282 +283 +284 +285 +286 +287 +288 +289 +290 +291 +292 +293 +294 +295 +296 +297 +298 +299 +300 +301 +302 +303 +304 +305 +306 +307 +308 +309 +310 +311 +312 +313 +314 +315 +316 +317 +318 +319 +320 +321 +322 +323 +324 +325 +326 +327 +328 +329 +330 +331 +332 +333 +334 +335 +336 +337 +338 +339 +340 +341 +342 +343 +344 +345 +346 +347 +348 +349 +350 +351 +352 +353 +354 +355 +356 +357 +358 +359 +360 +361 +362 +363 +364 +365 +366 +367 +368 +369 +370 +371 +372 +373 +374 +375 +376 +377 +378 +379 +380 +381 +382 +383 +384 +385 +386 +387 +388 +389 +390 +391 +392 +393 +394 +395  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +16x +  +  +  +  +  +10x +10x +10x +  +10x +  +  +  +  +  +38x +38x +  +  +  +  +  +  +16x +  +  +  +  +  +  +  +  +  +  +  +  +3x +3x +  +3x +  +  +  +  +  +  +  +  +  +3x +  +  +  +  +3x +3x +3x +3x +3x +3x +3x +  +3x +  +  +  +  +  +  +  +3x +1x +1x +  +  +  +2x +  +  +  +  +  +  +10x +10x +  +10x +  +10x +10x +10x +  +10x +  +  +  +  +  +  +10x +1x +1x +  +  +9x +  +  +  +  +  +  +  +  +  +10x +10x +  +10x +2x +  +  +10x +9x +1x +1x +  +  +10x +10x +  +  +10x +  +  +  +  +  +  +  +  +  +  +4x +4x +  +4x +  +3x +3x +  +  +  +  +  +  +  +1x +  +  +3x +3x +  +  +  +  +3x +3x +  +  +3x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +15x +15x +  +  +15x +  +  +  +  +  +  +15x +  +  +  +  +  +  +  +  +15x +1x +1x +  +  +14x +14x +14x +14x +  +14x +11x +  +  +14x +14x +  +14x +  +  +  +  +  +  +14x +14x +  +14x +  +14x +14x +  +  +  +  +  +  +  +  +14x +14x +  +  +  +  +  +  +  +  +15x +  +  +  +15x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +10x +10x +10x +10x +10x +10x +10x +  +  +  +  +  +  +  +10x +10x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  + 
/**
+ * ProcessManager — Subprocess lifecycle, worktree creation, command building.
+ *
+ * Extracted from MultiProviderAgentManager. Manages the spawning of detached
+ * subprocesses, worktree creation per project, and provider-specific command
+ * construction.
+ */
+ 
+import { spawn } from 'node:child_process';
+import { writeFileSync, mkdirSync, openSync, closeSync, existsSync } from 'node:fs';
+import { join } from 'node:path';
+import type { ProjectRepository } from '../db/repositories/project-repository.js';
+import type { AgentProviderConfig } from './providers/types.js';
+import type { StreamEvent } from './providers/parsers/index.js';
+import { getStreamParser } from './providers/parsers/index.js';
+import { SimpleGitWorktreeManager } from '../git/manager.js';
+import { ensureProjectClone, getProjectCloneDir } from '../git/project-clones.js';
+import { FileTailer } from './file-tailer.js';
+import { createModuleLogger } from '../logger/index.js';
+ 
+const log = createModuleLogger('process-manager');
+ 
+/**
+ * Check if a process with the given PID is still alive.
+ */
+export function isPidAlive(pid: number): boolean {
+  try {
+    process.kill(pid, 0);
+    return true;
+  } catch {
+    return false;
+  }
+}
+ 
+export class ProcessManager {
+  constructor(
+    private workspaceRoot: string,
+    private projectRepository: ProjectRepository,
+  ) {}
+ 
+  /**
+   * Resolve the agent's working directory path.
+   */
+  getAgentWorkdir(alias: string): string {
+    return join(this.workspaceRoot, 'agent-workdirs', alias);
+  }
+ 
+  /**
+   * Create worktrees for all projects linked to an initiative.
+   * Returns the base agent workdir path.
+   */
+  async createProjectWorktrees(
+    alias: string,
+    initiativeId: string,
+    baseBranch?: string,
+    branchName?: string,
+  ): Promise<string> {
+    const projects = await this.projectRepository.findProjectsByInitiativeId(initiativeId);
+    const agentWorkdir = this.getAgentWorkdir(alias);
+ 
+    log.debug({
+      alias,
+      initiativeId,
+      projectCount: projects.length,
+      agentWorkdir,
+      baseBranch
+    }, 'creating project worktrees');
+ 
+    // No linked projects — fall back to standalone worktree so the agent
+    // always has a git-backed working directory.
+    Iif (projects.length === 0) {
+      log.info({ alias, initiativeId }, 'initiative has no linked projects, falling back to standalone worktree');
+      return this.createStandaloneWorktree(alias);
+    }
+ 
+    for (const project of projects) {
+      const clonePath = await ensureProjectClone(project, this.workspaceRoot);
+      const worktreeManager = new SimpleGitWorktreeManager(clonePath, undefined, agentWorkdir);
+      const effectiveBaseBranch = baseBranch ?? project.defaultBranch;
+      const worktree = await worktreeManager.create(project.name, branchName ?? `agent/${alias}`, effectiveBaseBranch);
+      const worktreePath = worktree.path;
+      const pathExists = existsSync(worktreePath);
+ 
+      log.debug({
+        alias,
+        agentWorkdir,
+        projectName: project.name,
+        worktreePath,
+        pathExists
+      }, 'worktree created');
+ 
+      if (!pathExists) {
+        log.error({ worktreePath }, 'Worktree path does not exist after creation!');
+        throw new Error(`Worktree creation failed: ${worktreePath}`);
+      }
+    }
+ 
+    return agentWorkdir;
+  }
+ 
+  /**
+   * Fallback: create a single "workspace" worktree for standalone agents.
+   */
+  async createStandaloneWorktree(alias: string): Promise<string> {
+    const agentWorkdir = this.getAgentWorkdir(alias);
+    const worktreeManager = new SimpleGitWorktreeManager(this.workspaceRoot, undefined, agentWorkdir);
+ 
+    log.debug({ alias, agentWorkdir }, 'creating standalone worktree');
+ 
+    const worktree = await worktreeManager.create('workspace', `agent/${alias}`);
+    const worktreePath = worktree.path;
+    const pathExists = existsSync(worktreePath);
+ 
+    log.debug({
+      alias,
+      agentWorkdir,
+      worktreePath,
+      pathExists
+    }, 'standalone worktree created');
+ 
+    if (!pathExists) {
+      log.error({ worktreePath }, 'Standalone worktree path does not exist after creation!');
+      throw new Error(`Standalone worktree creation failed: ${worktreePath}`);
+    }
+ 
+    return worktree.path;
+  }
+ 
+  /**
+   * Build the spawn command for a given provider configuration.
+   */
+  buildSpawnCommand(
+    provider: AgentProviderConfig,
+    prompt: string,
+  ): { command: string; args: string[]; env: Record<string, string> } {
+    const args = [...provider.args];
+    const env: Record<string, string> = { ...provider.env };
+ 
+    if (provider.nonInteractive?.subcommand) {
+      args.unshift(provider.nonInteractive.subcommand);
+    }
+ 
+    if (provider.promptMode === 'native') {
+      args.push('-p', prompt);
+    E} else if (provider.promptMode === 'flag' && provider.nonInteractive?.promptFlag) {
+      args.push(provider.nonInteractive.promptFlag, prompt);
+    }
+ 
+    Eif (provider.nonInteractive?.outputFlag) {
+      args.push(...provider.nonInteractive.outputFlag.split(' '));
+    }
+ 
+    return { command: provider.command, args, env };
+  }
+ 
+  /**
+   * Build the resume command for a given provider configuration.
+   */
+  buildResumeCommand(
+    provider: AgentProviderConfig,
+    sessionId: string,
+    prompt: string,
+  ): { command: string; args: string[]; env: Record<string, string> } {
+    const args = [...provider.args];
+    const env: Record<string, string> = { ...provider.env };
+ 
+    switch (provider.resumeStyle) {
+      case 'flag':
+        args.push(provider.resumeFlag!, sessionId);
+        break;
+      case 'subcommand':
+        if (provider.nonInteractive?.subcommand) {
+          args.unshift(provider.nonInteractive.subcommand);
+        }
+        args.push(provider.resumeFlag!, sessionId);
+        break;
+      case 'none':
+        throw new Error(`Provider '${provider.name}' does not support resume`);
+    }
+ 
+    if (provider.promptMode === 'native') {
+      args.push('-p', prompt);
+    E} else if (provider.promptMode === 'flag' && provider.nonInteractive?.promptFlag) {
+      args.push(provider.nonInteractive.promptFlag, prompt);
+    }
+ 
+    Eif (provider.nonInteractive?.outputFlag) {
+      args.push(...provider.nonInteractive.outputFlag.split(' '));
+    }
+ 
+    return { command: provider.command, args, env };
+  }
+ 
+  /**
+   * Extract session ID from CLI output based on provider config.
+   */
+  extractSessionId(
+    provider: AgentProviderConfig,
+    output: string,
+  ): string | null {
+    if (!provider.sessionId) return null;
+ 
+    try {
+      if (provider.sessionId.extractFrom === 'result') {
+        const parsed = JSON.parse(output);
+        return parsed[provider.sessionId.field] ?? null;
+      }
+ 
+      if (provider.sessionId.extractFrom === 'event') {
+        const lines = output.trim().split('\n');
+        for (const line of lines) {
+          try {
+            const event = JSON.parse(line);
+            if (event.type === provider.sessionId.eventType) {
+              return event[provider.sessionId.field] ?? null;
+            }
+          } catch {
+            // Skip non-JSON lines
+          }
+        }
+      }
+    } catch {
+      // Parse failure
+    }
+ 
+    return null;
+  }
+ 
+  /**
+   * Spawn a detached subprocess with file redirection for crash resilience.
+   * The subprocess writes directly to files and survives server crashes.
+   * A FileTailer watches the output file and emits events in real-time.
+   *
+   * @param onEvent - Callback for stream events from the tailer
+   */
+  spawnDetached(
+    agentId: string,
+    agentName: string,
+    command: string,
+    args: string[],
+    cwd: string,
+    env: Record<string, string>,
+    providerName: string,
+    prompt?: string,
+    onEvent?: (event: StreamEvent) => void,
+    onRawContent?: (content: string) => void,
+  ): { pid: number; outputFilePath: string; tailer: FileTailer } {
+    // Pre-spawn validation and logging
+    const cwdExists = existsSync(cwd);
+    const commandWithArgs = [command, ...args].join(' ');
+ 
+    // Log environment variables that might affect working directory
+    const environmentInfo = {
+      PWD: process.env.PWD,
+      HOME: process.env.HOME,
+      CLAUDE_CONFIG_DIR: env.CLAUDE_CONFIG_DIR,
+      CW_CONFIG_DIR: env.CW_CONFIG_DIR
+    };
+ 
+    log.info({
+      agentId,
+      cwd,
+      cwdExists,
+      commandWithArgs,
+      providerName,
+      environmentInfo
+    }, 'spawning detached process with workdir validation');
+ 
+    if (!cwdExists) {
+      log.error({ cwd }, 'CWD does not exist before spawn!');
+      throw new Error(`Agent working directory does not exist: ${cwd}`);
+    }
+ 
+    const logDir = join(this.workspaceRoot, '.cw', 'agent-logs', agentName);
+    mkdirSync(logDir, { recursive: true });
+    const outputFilePath = join(logDir, 'output.jsonl');
+    const stderrFilePath = join(logDir, 'stderr.log');
+ 
+    if (prompt) {
+      writeFileSync(join(logDir, 'PROMPT.md'), prompt, 'utf-8');
+    }
+ 
+    const stdoutFd = openSync(outputFilePath, 'w');
+    const stderrFd = openSync(stderrFilePath, 'w');
+ 
+    const child = spawn(command, args, {
+      cwd,
+      env: { ...process.env, ...env },
+      detached: true,
+      stdio: ['ignore', stdoutFd, stderrFd],
+    });
+ 
+    closeSync(stdoutFd);
+    closeSync(stderrFd);
+ 
+    child.unref();
+ 
+    const pid = child.pid!;
+    log.info({
+      agentId,
+      pid,
+      command,
+      args: args.join(' '),
+      cwd,
+      spawnSuccess: true
+    }, 'spawned detached process successfully');
+ 
+    const parser = getStreamParser(providerName);
+    const tailer = new FileTailer({
+      filePath: outputFilePath,
+      agentId,
+      parser,
+      onEvent: onEvent ?? (() => {}),
+      startFromBeginning: true,
+      onRawContent,
+    });
+ 
+    tailer.start().catch((err) => {
+      log.warn({ agentId, err: err instanceof Error ? err.message : String(err) }, 'failed to start tailer');
+    });
+ 
+    return { pid, outputFilePath, tailer };
+  }
+ 
+  /**
+   * Poll for process completion by checking if PID is still alive.
+   * When the process exits, calls onComplete callback.
+   * Returns a cancel handle to stop polling (e.g. on agent cleanup or re-resume).
+   *
+   * @param onComplete - Called when the process is no longer alive
+   * @param getTailer - Function to get the current tailer for final flush
+   */
+  pollForCompletion(
+    agentId: string,
+    pid: number,
+    onComplete: () => Promise<void>,
+    getTailer: () => FileTailer | undefined,
+  ): { cancel: () => void } {
+    let cancelled = false;
+    const check = async () => {
+      Iif (cancelled) return;
+      Eif (!isPidAlive(pid)) {
+        const tailer = getTailer();
+        Eif (tailer) {
+          await new Promise((resolve) => setTimeout(resolve, 500));
+          await tailer.stop();
+        }
+        if (!cancelled) await onComplete();
+        return;
+      }
+      if (!cancelled) setTimeout(check, 1000);
+    };
+    check();
+    return { cancel: () => { cancelled = true; } };
+  }
+ 
+  /**
+   * Wait for a process to complete with Promise-based API.
+   * Returns when the process is no longer alive.
+   */
+  async waitForProcessCompletion(pid: number, timeoutMs: number = 300000): Promise<{ exitCode: number | null }> {
+    return new Promise((resolve, reject) => {
+      const startTime = Date.now();
+ 
+      const check = () => {
+        if (!isPidAlive(pid)) {
+          // Process has exited, try to get exit code
+          // Note: Getting exact exit code from detached process is limited
+          resolve({ exitCode: null });
+          return;
+        }
+ 
+        if (Date.now() - startTime > timeoutMs) {
+          reject(new Error(`Process ${pid} did not complete within ${timeoutMs}ms`));
+          return;
+        }
+ 
+        setTimeout(check, 1000);
+      };
+ 
+      check();
+    });
+  }
+ 
+  /**
+   * Get the exit code of a completed process.
+   * Limited implementation since we use detached processes.
+   */
+  async getExitCode(pid: number): Promise<number | null> {
+    // For detached processes, we can't easily get the exit code
+    // This would need to be enhanced with process tracking
+    return null;
+  }
+}
+ 
+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/coverage/src/agent/prompts/detail.ts.html b/coverage/src/agent/prompts/detail.ts.html new file mode 100644 index 0000000..d8cda6a --- /dev/null +++ b/coverage/src/agent/prompts/detail.ts.html @@ -0,0 +1,367 @@ + + + + + + Code coverage report for src/agent/prompts/detail.ts + + + + + + + + + +
+
+

All files / src/agent/prompts detail.ts

+
+ +
+ 100% + Statements + 1/1 +
+ + +
+ 100% + Branches + 0/0 +
+ + +
+ 100% + Functions + 1/1 +
+ + +
+ 100% + Lines + 1/1 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+

+
1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 +30 +31 +32 +33 +34 +35 +36 +37 +38 +39 +40 +41 +42 +43 +44 +45 +46 +47 +48 +49 +50 +51 +52 +53 +54 +55 +56 +57 +58 +59 +60 +61 +62 +63 +64 +65 +66 +67 +68 +69 +70 +71 +72 +73 +74 +75 +76 +77 +78 +79 +80 +81 +82 +83 +84 +85 +86 +87 +88 +89 +90 +91 +92 +93 +94 +95  +  +  +  +  +  +  +9x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  + 
/**
+ * Detail mode prompt — break a phase into executable tasks.
+ */
+ 
+import { CONTEXT_MANAGEMENT, ID_GENERATION, INPUT_FILES, SIGNAL_FORMAT } from './shared.js';
+ 
+export function buildDetailPrompt(): string {
+  return `You are an Architect agent in DETAIL mode. Break the phase into executable tasks. You do NOT write code.
+${INPUT_FILES}
+${SIGNAL_FORMAT}
+ 
+## Output Files
+ 
+Write one file per task to \`.cw/output/tasks/{id}.md\`:
+- Frontmatter: \`title\`, \`category\` (execute|research|discuss|plan|detail|refine|verify|merge|review), \`type\` (auto|checkpoint:human-verify|checkpoint:decision|checkpoint:human-action), \`dependencies\` (list of task IDs)
+- Body: Detailed task description
+ 
+${ID_GENERATION}
+ 
+## Task Body Requirements
+ 
+Every task body must include:
+1. **Files to create or modify** — specific paths (e.g., \`src/db/schema.ts\`, \`src/api/routes/users.ts\`)
+2. **Expected behavior** — concrete examples, inputs/outputs, edge cases
+3. **Test specification** — for every execute-category task:
+   - Test file path (e.g., \`src/api/validators/user.test.ts\`)
+   - Test scenarios (happy path, error cases, edge cases)
+   - Run command (e.g., \`npm test -- src/api/validators/user.test.ts\`)
+   Non-execute tasks may omit this.
+4. **Verification command** — exact command to confirm completion
+ 
+**Bad task:**
+\`\`\`
+Title: Add user validation
+Body: Add validation to the user model. Make sure all fields are validated properly.
+\`\`\`
+ 
+**Good task:**
+\`\`\`
+Title: Add Zod validation schema for user creation
+Body: Create \`src/api/validators/user.ts\` — Zod schema for CreateUserInput:
+- email: valid format, lowercase, max 255 chars
+- name: 1-100 chars, trimmed
+- password: min 8 chars, uppercase + number required
+ 
+Test file: \`src/api/validators/user.test.ts\`
+Tests: valid input passes, missing fields rejected, invalid email rejected,
+  weak password rejected, whitespace-only name rejected
+ 
+Files: src/api/validators/user.ts (create), user.test.ts (create)
+Verify: \`npm test -- src/api/validators/user.test.ts\`
+\`\`\`
+ 
+## File Ownership
+ 
+Parallel tasks must not modify the same files. Include a file list per task:
+\`\`\`
+Files: src/db/schema/users.ts (create), src/db/migrations/001_users.sql (create)
+\`\`\`
+If two tasks touch the same file or one needs the other's output, add a dependency.
+ 
+## Task Sizing (by lines changed)
+ 
+- **<150 lines, 1-3 files**: Sweet spot
+- **150-300 lines, 4-5 files**: Only for mechanical/boilerplate work with precise specs
+- **300+ lines or 5+ files**: Split it
+- **<20 lines**: Merge with a related task
+- **1 sentence description**: Too vague — add detail or merge
+ 
+## Checkpoint Tasks
+ 
+- \`checkpoint:human-verify\`: Visual changes, migrations, API contracts
+- \`checkpoint:decision\`: Architecture choices affecting multiple phases
+- \`checkpoint:human-action\`: External setup (DNS, credentials, third-party config)
+ 
+~90% of tasks should be \`auto\`.
+ 
+## Existing Context
+- Read ALL \`context/tasks/\` files before generating output
+- Only create tasks for THIS phase (\`phase.md\`)
+- Do not duplicate work that exists in context/tasks/ (even under different names)
+- Use pages as requirements source
+${CONTEXT_MANAGEMENT}
+ 
+## Done Checklist
+ 
+Before signal.json "done":
+- [ ] Every execute task has test file path + run command
+- [ ] Every task has a file ownership list
+- [ ] No parallel tasks share files
+- [ ] Every task is executable without clarifying questions
+- [ ] Tasks sized within ~20-300 lines changed
+- [ ] No duplicates with existing context tasks`;
+}
+ 
+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/coverage/src/agent/prompts/discuss.ts.html b/coverage/src/agent/prompts/discuss.ts.html new file mode 100644 index 0000000..ce97cb3 --- /dev/null +++ b/coverage/src/agent/prompts/discuss.ts.html @@ -0,0 +1,277 @@ + + + + + + Code coverage report for src/agent/prompts/discuss.ts + + + + + + + + + +
+
+

All files / src/agent/prompts discuss.ts

+
+ +
+ 100% + Statements + 1/1 +
+ + +
+ 100% + Branches + 0/0 +
+ + +
+ 100% + Functions + 1/1 +
+ + +
+ 100% + Lines + 1/1 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+

+
1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 +30 +31 +32 +33 +34 +35 +36 +37 +38 +39 +40 +41 +42 +43 +44 +45 +46 +47 +48 +49 +50 +51 +52 +53 +54 +55 +56 +57 +58 +59 +60 +61 +62 +63 +64 +65  +  +  +  +  +  +  +3x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  + 
/**
+ * Discuss mode prompt — clarifying questions and decision capture.
+ */
+ 
+import { ID_GENERATION, INPUT_FILES, SIGNAL_FORMAT } from './shared.js';
+ 
+export function buildDiscussPrompt(): string {
+  return `You are an Architect agent in the Codewalk multi-agent system operating in DISCUSS mode.
+ 
+## Your Role
+Transform user intent into clear, documented decisions. You do NOT write code — you capture decisions.
+${INPUT_FILES}
+${SIGNAL_FORMAT}
+ 
+## Output Files
+ 
+Write decisions to \`.cw/output/decisions/{id}.md\`:
+- Frontmatter: \`topic\`, \`decision\`, \`reason\`
+- Body: Additional context or rationale
+ 
+${ID_GENERATION}
+ 
+## Goal-Backward Analysis
+ 
+Work backward from the goal before asking anything:
+1. **Observable outcome**: What will the user see/do when this is done?
+2. **Artifacts needed**: What code, config, or infra produces that outcome?
+3. **Wiring**: How do the artifacts connect (data flow, API contracts, events)?
+4. **Failure points**: What can go wrong? Edge cases?
+ 
+Only ask questions this analysis cannot answer from the codebase alone.
+ 
+## Question Quality
+ 
+**Bad**: "How should we handle errors?"
+**Good**: "The current API returns HTTP 500 for all errors. Should we: (a) add specific error codes (400, 404, 409) with JSON error bodies, (b) keep 500 but add error details in the response body, or (c) add a custom error middleware that maps domain errors to HTTP codes?"
+ 
+Every question must explain what depends on the answer.
+ 
+## Decision Quality
+ 
+**Bad**: "We'll use a database for storage"
+**Good**: "Use SQLite via better-sqlite3 with drizzle-orm. Schema in src/db/schema.ts, migrations via drizzle-kit. Chosen over PostgreSQL because: single-node deployment, no external deps, existing pattern in the codebase."
+ 
+Include: what, why, rejected alternatives. For behavioral decisions, add verification criteria.
+ 
+## Codebase First
+Don't ask what the codebase already answers. If the project uses a framework, don't ask which framework to use.
+ 
+## Question Categories
+- **User Journeys**: Workflows, success/failure paths, edge cases
+- **Technical Constraints**: Patterns to follow, things to avoid
+- **Data & Validation**: Structures, rules, constraints
+- **Integration Points**: External systems, APIs, error handling
+- **Testability**: Acceptance criteria, test strategies
+ 
+## Rules
+- Ask 2-4 questions at a time, not more
+ 
+## Definition of Done
+- Every decision includes what, why, and rejected alternatives
+- Behavioral decisions include verification criteria
+- No questions the codebase already answers`;
+}
+ 
+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/coverage/src/agent/prompts/execute.ts.html b/coverage/src/agent/prompts/execute.ts.html new file mode 100644 index 0000000..c9e366e --- /dev/null +++ b/coverage/src/agent/prompts/execute.ts.html @@ -0,0 +1,307 @@ + + + + + + Code coverage report for src/agent/prompts/execute.ts + + + + + + + + + +
+
+

All files / src/agent/prompts execute.ts

+
+ +
+ 100% + Statements + 2/2 +
+ + +
+ 50% + Branches + 1/2 +
+ + +
+ 100% + Functions + 1/1 +
+ + +
+ 100% + Lines + 2/2 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+

+
1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 +30 +31 +32 +33 +34 +35 +36 +37 +38 +39 +40 +41 +42 +43 +44 +45 +46 +47 +48 +49 +50 +51 +52 +53 +54 +55 +56 +57 +58 +59 +60 +61 +62 +63 +64 +65 +66 +67 +68 +69 +70 +71 +72 +73 +74 +75  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +35x +  +  +  +35x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  + 
/**
+ * Execute mode prompt — standard worker agent.
+ */
+ 
+import {
+  CONTEXT_MANAGEMENT,
+  DEVIATION_RULES,
+  GIT_WORKFLOW,
+  INPUT_FILES,
+  PROGRESS_TRACKING,
+  SESSION_STARTUP,
+  SIGNAL_FORMAT,
+  TEST_INTEGRITY,
+} from './shared.js';
+ 
+export function buildExecutePrompt(taskDescription?: string): string {
+  const taskSection = taskDescription
+    ? `\n## Task (inline summary)\n\n${taskDescription}\n\nRead \`.cw/input/task.md\` for the full structured task with metadata, priority, and dependencies.`
+    : '';
+ 
+  return `You are a Worker agent in the Codewalk multi-agent system. Execute the assigned coding task using RED-GREEN-REFACTOR.
+${taskSection}
+${INPUT_FILES}
+${SIGNAL_FORMAT}
+${SESSION_STARTUP}
+ 
+## Execution Protocol
+ 
+Follow these steps in order. Signal done only after the Definition of Done checklist passes.
+ 
+1. **Startup**: Verify environment per Session Startup. If baseline tests fail, signal error.
+ 
+2. **Read & orient**: Read all input files. Run \`git log --oneline -10\` to check recent changes.
+ 
+3. **Write failing tests (RED)**: Write tests for the expected behavior. Run them — they must fail. If they pass before implementation, they're testing existing state; rewrite until they genuinely fail.
+ 
+4. **Implement (GREEN)**: Minimum code to pass tests. Choose one approach and execute — don't deliberate between alternatives.
+ 
+5. **Verify green**: Run the full relevant test suite. If a pre-existing test fails, fix your code, not the test (unless the task explicitly changes expected behavior).
+ 
+6. **Commit**: Stage specific files, commit with a descriptive message, update progress file.
+ 
+7. **Iterate**: For multi-part tasks, repeat 3-6 per part. Each cycle produces a commit.
+ 
+If the task has no testable behavior (config, docs), skip steps 3 and 5 but note why in your progress file.
+${TEST_INTEGRITY}
+ 
+## Anti-Patterns
+ 
+- **Mega-commits**: Commit after each logical unit, not one giant commit at the end.
+- **Silent reinterpretation**: Task says X, do X. Don't substitute Y because you think it's better.
+- **Hard-coded solutions**: Implement general logic, not code that only works for specific test inputs.
+ 
+## Scope Rules
+ 
+- Do exactly what the task says — no unrelated fixes, refactors, or improvements. Other agents may own those files.
+- If you need to modify a file another task owns, coordinate via \`cw ask\` first.
+- Touching 7+ files? You're probably overscoping. Re-read the task.
+${DEVIATION_RULES}
+${GIT_WORKFLOW}
+${PROGRESS_TRACKING}
+${CONTEXT_MANAGEMENT}
+ 
+## Definition of Done
+ 
+Before writing signal.json with status "done":
+ 
+- [ ] All tests pass (full relevant suite)
+- [ ] No uncommitted changes
+- [ ] Progress file updated
+- [ ] Implemented exactly what the task asked — no more, no less
+ 
+If any item fails, fix it. If unfixable, signal "error" explaining what's wrong.`;
+}
+ 
+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/coverage/src/agent/prompts/index.html b/coverage/src/agent/prompts/index.html new file mode 100644 index 0000000..e22c316 --- /dev/null +++ b/coverage/src/agent/prompts/index.html @@ -0,0 +1,221 @@ + + + + + + Code coverage report for src/agent/prompts + + + + + + + + + +
+
+

All files src/agent/prompts

+
+ +
+ 69.23% + Statements + 18/26 +
+ + +
+ 16.66% + Branches + 1/6 +
+ + +
+ 60% + Functions + 6/10 +
+ + +
+ 69.23% + Lines + 18/26 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
FileStatementsBranchesFunctionsLines
detail.ts +
+
100%1/1100%0/0100%1/1100%1/1
discuss.ts +
+
100%1/1100%0/0100%1/1100%1/1
execute.ts +
+
100%2/250%1/2100%1/1100%2/2
index.ts +
+
0%0/00%0/00%0/00%0/0
plan.ts +
+
100%1/1100%0/0100%1/1100%1/1
refine.ts +
+
0%0/1100%0/00%0/10%0/1
shared.ts +
+
100%10/10100%0/0100%1/1100%10/10
workspace.ts +
+
30%3/100%0/425%1/430%3/10
+
+
+
+ + + + + + + + \ No newline at end of file diff --git a/coverage/src/agent/prompts/index.ts.html b/coverage/src/agent/prompts/index.ts.html new file mode 100644 index 0000000..a10e72c --- /dev/null +++ b/coverage/src/agent/prompts/index.ts.html @@ -0,0 +1,127 @@ + + + + + + Code coverage report for src/agent/prompts/index.ts + + + + + + + + + +
+
+

All files / src/agent/prompts index.ts

+
+ +
+ 0% + Statements + 0/0 +
+ + +
+ 0% + Branches + 0/0 +
+ + +
+ 0% + Functions + 0/0 +
+ + +
+ 0% + Lines + 0/0 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+

+
1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15  +  +  +  +  +  +  +  +  +  +  +  +  +  + 
/**
+ * Agent Prompts — per-mode prompt builders and shared instructions.
+ *
+ * Each agent type lives in its own file. Shared instructions (signal format,
+ * input files, ID generation) are in shared.ts.
+ */
+ 
+export { SIGNAL_FORMAT, INPUT_FILES, ID_GENERATION, CONTEXT_MANAGEMENT, DEVIATION_RULES, GIT_WORKFLOW, TEST_INTEGRITY, SESSION_STARTUP, PROGRESS_TRACKING, buildInterAgentCommunication } from './shared.js';
+export { buildExecutePrompt } from './execute.js';
+export { buildDiscussPrompt } from './discuss.js';
+export { buildPlanPrompt } from './plan.js';
+export { buildDetailPrompt } from './detail.js';
+export { buildRefinePrompt } from './refine.js';
+export { buildWorkspaceLayout } from './workspace.js';
+ 
+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/coverage/src/agent/prompts/plan.ts.html b/coverage/src/agent/prompts/plan.ts.html new file mode 100644 index 0000000..732210c --- /dev/null +++ b/coverage/src/agent/prompts/plan.ts.html @@ -0,0 +1,295 @@ + + + + + + Code coverage report for src/agent/prompts/plan.ts + + + + + + + + + +
+
+

All files / src/agent/prompts plan.ts

+
+ +
+ 100% + Statements + 1/1 +
+ + +
+ 100% + Branches + 0/0 +
+ + +
+ 100% + Functions + 1/1 +
+ + +
+ 100% + Lines + 1/1 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+

+
1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 +30 +31 +32 +33 +34 +35 +36 +37 +38 +39 +40 +41 +42 +43 +44 +45 +46 +47 +48 +49 +50 +51 +52 +53 +54 +55 +56 +57 +58 +59 +60 +61 +62 +63 +64 +65 +66 +67 +68 +69 +70 +71  +  +  +  +  +  +  +7x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  + 
/**
+ * Plan mode prompt — plan initiative into phases.
+ */
+ 
+import { CONTEXT_MANAGEMENT, ID_GENERATION, INPUT_FILES, SIGNAL_FORMAT } from './shared.js';
+ 
+export function buildPlanPrompt(): string {
+  return `You are an Architect agent in PLAN mode. Plan the initiative into phases. You do NOT write code.
+${INPUT_FILES}
+${SIGNAL_FORMAT}
+ 
+## Output
+ 
+Write one file per phase to \`.cw/output/phases/{id}.md\`:
+- Frontmatter: \`title\`, \`dependencies\` (list of phase IDs this depends on)
+- Body: what gets built, specific enough for a detail agent to break into tasks without clarifying questions
+ 
+${ID_GENERATION}
+ 
+## Phase Design
+- Single concern, independently deliverable, testable
+- Foundation phases first; minimize cross-phase dependencies
+- 2-5 tasks each. Action-oriented names (what gets built, not how)
+- Tests are part of every phase, not a separate phase
+ 
+**Bad**: Phase 1: Database → Phase 2: API → Phase 3: Frontend → Phase 4: Tests
+**Good**: Phase 1: Database + schema tests → Phase 2: API + endpoint tests → Phase 3: Frontend + component tests
+ 
+## Dependencies
+ 
+Maximize parallelism. If your plan is fully serial, reconsider.
+ 
+**Good:**
+\`\`\`
+Wave 1 (parallel): "Database schema", "API skeleton"
+Wave 2 (parallel): "User endpoints" (depends: API skeleton, DB schema), "Auth middleware" (depends: API skeleton)
+Wave 3: "Integration tests" (depends: User endpoints, Auth middleware)
+\`\`\`
+ 
+**Bad:**
+\`\`\`
+Phase 1 → Phase 2 → Phase 3 → Phase 4 (fully serial, no parallelism)
+\`\`\`
+ 
+## File Ownership
+ 
+Parallel phases MUST NOT modify the same files.
+ 
+**Bad**: Phase A "Add user model" and Phase B "Add product model" both modify \`schema.ts\` and \`index.ts\`
+**Good**: Phase A creates \`user-schema.ts\`, Phase B creates \`product-schema.ts\`, Phase C "Wire models into index" depends on both
+ 
+## Specificity
+ 
+Each phase must pass: **"Could a detail agent break this into tasks without clarifying questions?"**
+ 
+**Bad**: "Set up the backend" — what backend? What framework? What endpoints?
+**Good**: "Create Express API server with health check endpoint at /api/health, CORS configured for localhost:3000, error handling middleware returning JSON errors"
+ 
+## Existing Context
+- Account for existing phases/tasks — don't plan work already covered
+- Always generate new phase IDs — never reuse existing ones
+${CONTEXT_MANAGEMENT}
+ 
+## Definition of Done
+- [ ] Every phase has explicit dependencies (or explicitly none)
+- [ ] Parallel phases do not modify the same files
+- [ ] Each phase specific enough for detail agent — no clarifying questions needed
+- [ ] Tests included in each phase, not trailing
+- [ ] Existing work accounted for`;
+}
+ 
+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/coverage/src/agent/prompts/refine.ts.html b/coverage/src/agent/prompts/refine.ts.html new file mode 100644 index 0000000..0871a30 --- /dev/null +++ b/coverage/src/agent/prompts/refine.ts.html @@ -0,0 +1,202 @@ + + + + + + Code coverage report for src/agent/prompts/refine.ts + + + + + + + + + +
+
+

All files / src/agent/prompts refine.ts

+
+ +
+ 0% + Statements + 0/1 +
+ + +
+ 100% + Branches + 0/0 +
+ + +
+ 0% + Functions + 0/1 +
+ + +
+ 0% + Lines + 0/1 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+

+
1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 +30 +31 +32 +33 +34 +35 +36 +37 +38 +39 +40  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  + 
/**
+ * Refine mode prompt — review and propose edits to initiative pages.
+ */
+ 
+import { INPUT_FILES, SIGNAL_FORMAT } from './shared.js';
+ 
+export function buildRefinePrompt(): string {
+  return `You are an Architect agent reviewing initiative pages. You do NOT write code.
+${INPUT_FILES}
+${SIGNAL_FORMAT}
+ 
+## Output Files
+ 
+Write one file per modified page to \`.cw/output/pages/{pageId}.md\`:
+- Frontmatter: \`title\`, \`summary\` (what changed and why)
+- Body: Full replacement markdown content for the page
+ 
+## What to Improve (priority order)
+ 
+1. **Ambiguity**: Requirements interpretable multiple ways → make specific
+2. **Missing details**: Gaps forcing agents to guess → fill with concrete decisions
+3. **Contradictions**: Conflicting statements → resolve
+4. **Unverifiable requirements**: "Make it fast" → add testable criteria. Better: "Response time under 200ms". Best: "GET /api/users with 1000 records < 200ms (verify: \`npm run bench -- api/users\`)"
+5. **Missing edge cases**: Happy path only → add error/empty/boundary scenarios. E.g. "When cart is empty and user clicks checkout → show 'Your cart is empty', disable payment button"
+ 
+Ignore style, grammar, formatting unless they cause genuine ambiguity. Rough but precise beats polished but vague.
+ 
+If all pages are already clear, signal done with no output files.
+ 
+## Rules
+- Ask 2-4 questions if you need clarification
+- Preserve [[page:\$id|title]] cross-references
+- Only reference page IDs that exist in .cw/input/pages/
+ 
+## Definition of Done
+ 
+- [ ] Every modified requirement has specific, testable acceptance criteria
+- [ ] No style-only changes — every edit fixes a real clarity problem`;
+}
+ 
+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/coverage/src/agent/prompts/shared.ts.html b/coverage/src/agent/prompts/shared.ts.html new file mode 100644 index 0000000..1c4db61 --- /dev/null +++ b/coverage/src/agent/prompts/shared.ts.html @@ -0,0 +1,451 @@ + + + + + + Code coverage report for src/agent/prompts/shared.ts + + + + + + + + + +
+
+

All files / src/agent/prompts shared.ts

+
+ +
+ 100% + Statements + 10/10 +
+ + +
+ 100% + Branches + 0/0 +
+ + +
+ 100% + Functions + 1/1 +
+ + +
+ 100% + Lines + 10/10 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+

+
1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 +30 +31 +32 +33 +34 +35 +36 +37 +38 +39 +40 +41 +42 +43 +44 +45 +46 +47 +48 +49 +50 +51 +52 +53 +54 +55 +56 +57 +58 +59 +60 +61 +62 +63 +64 +65 +66 +67 +68 +69 +70 +71 +72 +73 +74 +75 +76 +77 +78 +79 +80 +81 +82 +83 +84 +85 +86 +87 +88 +89 +90 +91 +92 +93 +94 +95 +96 +97 +98 +99 +100 +101 +102 +103 +104 +105 +106 +107 +108 +109 +110 +111 +112 +113 +114 +115 +116 +117 +118 +119 +120 +121 +122 +123  +  +  +  +19x +  +  +  +  +  +  +  +19x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +19x +  +  +  +  +  +  +  +  +19x +  +  +  +  +  +  +  +  +  +  +  +19x +  +  +  +  +  +  +  +  +19x +  +  +  +  +19x +  +  +  +  +  +  +  +  +19x +  +  +  +  +  +  +  +19x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +8x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  + 
/**
+ * Shared prompt instructions reused across agent types.
+ */
+ 
+export const SIGNAL_FORMAT = `
+## Signal Output
+ 
+As your final action, write \`.cw/output/signal.json\`:
+- Done: \`{ "status": "done" }\`
+- Need clarification: \`{ "status": "questions", "questions": [{ "id": "q1", "question": "..." }] }\`
+- Unrecoverable error: \`{ "status": "error", "error": "..." }\``;
+ 
+export const INPUT_FILES = `
+## Input Files
+ 
+Read \`.cw/input/manifest.json\` first, then read listed files from \`.cw/input/\`.
+ 
+### Assignment Files
+- \`initiative.md\` — frontmatter: id, name, status
+- \`phase.md\` — frontmatter: id, name, status; body: description
+- \`task.md\` — frontmatter: id, name, category, type, priority, status; body: description
+- \`pages/\` — one per page; frontmatter: title, parentPageId, sortOrder; body: markdown
+ 
+### Context Files (read-only)
+Present when \`contextFiles\` exists in manifest:
+- \`context/phases/\` — frontmatter: id, name, status, dependsOn; body: description
+- \`context/tasks/\` — frontmatter: id, name, phaseId, parentTaskId, category, type, priority, status; body: description
+ 
+Do not duplicate or contradict context file content in your output.`;
+ 
+export const ID_GENERATION = `
+## ID Generation
+ 
+When creating new entities (phases, tasks, decisions), generate a unique ID by running:
+\`\`\`
+cw id
+\`\`\`
+Use the output as the filename (e.g., \`{id}.md\`).`;
+ 
+export const DEVIATION_RULES = `
+## Deviation Decision Tree
+ 
+1. **Typo in assigned files** → Fix silently
+2. **Bug in files you're modifying** → Fix if < 10 lines, otherwise note and move on
+3. **Missing dependency** → Check context files for another agent's work; \`cw ask\` if yes, create if within scope
+4. **Architectural mismatch** → STOP. Signal "questions" with what you found vs. what the task assumes
+5. **Ambiguous requirement** → STOP. Signal "questions" with the ambiguity and 2-3 concrete options
+6. **Task wrong or impossible** → STOP. Signal "error" explaining why
+ 
+Never silently reinterpret a task.`;
+ 
+export const GIT_WORKFLOW = `
+## Git Workflow
+ 
+You are in an isolated git worktree. Other agents work in parallel on separate branches.
+ 
+- Stage specific files with \`git add <file>\`, not \`git add .\`
+- Never force-push
+- Run \`git status\` before committing`;
+ 
+export const CONTEXT_MANAGEMENT = `
+## Context Management
+ 
+When reading multiple files or running independent commands, execute them in parallel rather than sequentially. After each commit, update your progress file (see Progress Tracking).`;
+ 
+export const TEST_INTEGRITY = `
+## Test Integrity Rules
+ 
+1. **Never mirror implementation logic in assertions.** Hardcode expected values from requirements, don't recalculate them.
+2. **Never modify existing test assertions to make them pass.** If a test expects X and your code produces Y, fix your code. Exception: your task explicitly changes expected behavior.
+3. **Never skip or disable tests.** No \`it.skip()\`, \`.todo()\`, or commenting out. If unfixable, signal error.
+4. **Each test must be independent.** No shared mutable state, no order dependence.
+5. **Run the full relevant test suite**, not just your new tests.`;
+ 
+export const SESSION_STARTUP = `
+## Session Startup
+ 
+1. \`pwd\` — confirm working directory
+2. \`git status\` — check for unexpected state
+3. Run test suite — establish green baseline. If already failing, signal "error". Don't build on a broken foundation.
+4. Read \`.cw/input/manifest.json\` and all listed input files`;
+ 
+export const PROGRESS_TRACKING = `
+## Progress Tracking
+ 
+Update \`.cw/output/progress.md\` after each commit:
+ 
+\`\`\`markdown
+## Current Status
+[What you just completed]
+ 
+## Next Steps
+[What you're working on next]
+ 
+## Blockers
+[Any issues or questions — empty if none]
+\`\`\`
+ 
+Survives context compaction — read this first if your context is refreshed.`;
+ 
+export function buildInterAgentCommunication(agentId: string): string {
+  return `
+## Inter-Agent Communication
+ 
+Your agent ID: **${agentId}**
+ 
+### CLI Commands
+ 
+- \`cw listen --agent-id ${agentId}\` — Waits for incoming question. Prints JSON (\`{ conversationId, fromAgentId, question, phaseId, taskId }\`) and exits.
+- \`cw ask "<question>" --from ${agentId} --agent-id <TARGET>\` — Blocks until answered. Target with one of: \`--agent-id <id>\`, \`--task-id <id>\`, \`--phase-id <id>\`.
+- \`cw answer "<answer>" --conversation-id <ID>\` — Answer a pending question.
+ 
+### Usage Pattern
+ 
+Run \`cw listen > "$file" &\` at session start. Check periodically. On question: answer, restart listener. Before signal.json: kill listener, clean up.
+ 
+### When to Communicate
+- Need interface/schema/API contract info from another agent
+- About to modify a shared resource
+- Have a dependency on another agent's work
+- Don't ask questions you can answer by reading the codebase`;
+}
+ 
+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/coverage/src/agent/prompts/workspace.ts.html b/coverage/src/agent/prompts/workspace.ts.html new file mode 100644 index 0000000..fe3d173 --- /dev/null +++ b/coverage/src/agent/prompts/workspace.ts.html @@ -0,0 +1,184 @@ + + + + + + Code coverage report for src/agent/prompts/workspace.ts + + + + + + + + + +
+
+

All files / src/agent/prompts workspace.ts

+
+ +
+ 30% + Statements + 3/10 +
+ + +
+ 0% + Branches + 0/4 +
+ + +
+ 25% + Functions + 1/4 +
+ + +
+ 30% + Lines + 3/10 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+

+
1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 +30 +31 +32 +33 +34  +  +  +  +  +  +  +  +  +8x +8x +  +  +  +8x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  + 
/**
+ * Workspace layout section describing the agent's working directory.
+ */
+ 
+import { readdirSync } from 'node:fs';
+import { join } from 'node:path';
+ 
+export function buildWorkspaceLayout(agentCwd: string): string {
+  let entries: string[];
+  try {
+    entries = readdirSync(agentCwd, { withFileTypes: true })
+      .filter(d => d.isDirectory() && d.name !== '.cw')
+      .map(d => d.name);
+  } catch {
+    return '';
+  }
+ 
+  if (entries.length === 0) {
+    return `\n\n## Workspace Layout\n\nYour working directory is: ${agentCwd}\nThis is an isolated git worktree. Other agents may be working in parallel on separate branches — do not assume you have exclusive access to the repository.`;
+  }
+ 
+  const lines = entries.map(
+    name => `- \`${name}/\` — ${join(agentCwd, name)}`
+  );
+ 
+  return `\n\n## Workspace Layout
+ 
+Your working directory is: ${agentCwd}
+This is an isolated git worktree. Other agents may be working in parallel on separate branches — do not assume you have exclusive access to the repository.
+The following project directories contain the source code (git worktrees):
+ 
+${lines.join('\n')}`;
+}
+ 
+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/coverage/src/agent/providers/index.html b/coverage/src/agent/providers/index.html new file mode 100644 index 0000000..568af4f --- /dev/null +++ b/coverage/src/agent/providers/index.html @@ -0,0 +1,146 @@ + + + + + + Code coverage report for src/agent/providers + + + + + + + + + +
+
+

All files src/agent/providers

+
+ +
+ 33.33% + Statements + 3/9 +
+ + +
+ 50% + Branches + 1/2 +
+ + +
+ 25% + Functions + 1/4 +
+ + +
+ 33.33% + Lines + 3/9 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
FileStatementsBranchesFunctionsLines
index.ts +
+
0%0/00%0/00%0/00%0/0
presets.ts +
+
100%1/1100%0/0100%0/0100%1/1
registry.ts +
+
25%2/850%1/225%1/425%2/8
+
+
+
+ + + + + + + + \ No newline at end of file diff --git a/coverage/src/agent/providers/index.ts.html b/coverage/src/agent/providers/index.ts.html new file mode 100644 index 0000000..00931a9 --- /dev/null +++ b/coverage/src/agent/providers/index.ts.html @@ -0,0 +1,205 @@ + + + + + + Code coverage report for src/agent/providers/index.ts + + + + + + + + + +
+
+

All files / src/agent/providers index.ts

+
+ +
+ 0% + Statements + 0/0 +
+ + +
+ 0% + Branches + 0/0 +
+ + +
+ 0% + Functions + 0/0 +
+ + +
+ 0% + Lines + 0/0 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+

+
1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 +30 +31 +32 +33 +34 +35 +36 +37 +38 +39 +40 +41  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  + 
/**
+ * Agent Providers Module - Public API
+ *
+ * Re-exports provider types, presets, and registry functions.
+ */
+ 
+export type {
+  AgentProviderConfig,
+  StructuredOutputConfig,
+  SessionIdConfig,
+  NonInteractiveConfig,
+} from './types.js';
+ 
+export { PROVIDER_PRESETS } from './presets.js';
+ 
+export {
+  getProvider,
+  listProviders,
+  registerProvider,
+  loadProvidersFromFile,
+} from './registry.js';
+ 
+// Stream parsing
+export type {
+  StreamEvent,
+  StreamParser,
+  StreamInitEvent,
+  StreamTextDeltaEvent,
+  StreamToolUseStartEvent,
+  StreamToolResultEvent,
+  StreamTurnEndEvent,
+  StreamResultEvent,
+  StreamErrorEvent,
+} from './stream-types.js';
+ 
+export {
+  getStreamParser,
+  ClaudeStreamParser,
+  GenericStreamParser,
+} from './parsers/index.js';
+ 
+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/coverage/src/agent/providers/parsers/claude.ts.html b/coverage/src/agent/providers/parsers/claude.ts.html new file mode 100644 index 0000000..7f030ff --- /dev/null +++ b/coverage/src/agent/providers/parsers/claude.ts.html @@ -0,0 +1,586 @@ + + + + + + Code coverage report for src/agent/providers/parsers/claude.ts + + + + + + + + + +
+
+

All files / src/agent/providers/parsers claude.ts

+
+ +
+ 2.17% + Statements + 1/46 +
+ + +
+ 0% + Branches + 0/47 +
+ + +
+ 0% + Functions + 0/2 +
+ + +
+ 2.27% + Lines + 1/44 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+

+
1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 +30 +31 +32 +33 +34 +35 +36 +37 +38 +39 +40 +41 +42 +43 +44 +45 +46 +47 +48 +49 +50 +51 +52 +53 +54 +55 +56 +57 +58 +59 +60 +61 +62 +63 +64 +65 +66 +67 +68 +69 +70 +71 +72 +73 +74 +75 +76 +77 +78 +79 +80 +81 +82 +83 +84 +85 +86 +87 +88 +89 +90 +91 +92 +93 +94 +95 +96 +97 +98 +99 +100 +101 +102 +103 +104 +105 +106 +107 +108 +109 +110 +111 +112 +113 +114 +115 +116 +117 +118 +119 +120 +121 +122 +123 +124 +125 +126 +127 +128 +129 +130 +131 +132 +133 +134 +135 +136 +137 +138 +139 +140 +141 +142 +143 +144 +145 +146 +147 +148 +149 +150 +151 +152 +153 +154 +155 +156 +157 +158 +159 +160 +161 +162 +163 +164 +165 +166 +167 +168  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +10x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  + 
/**
+ * Claude Code Stream Parser
+ *
+ * Parses Claude Code CLI `--output-format stream-json` NDJSON output
+ * into standardized StreamEvents.
+ *
+ * Key line types handled:
+ * - system (subtype=init): session_id
+ * - stream_event (content_block_delta, text_delta): delta.text
+ * - stream_event (content_block_start, tool_use): content_block.name, .id
+ * - stream_event (message_delta): delta.stop_reason
+ * - result: result, session_id, total_cost_usd
+ * - any with is_error: true: error message
+ */
+ 
+import type { StreamEvent, StreamParser } from '../stream-types.js';
+ 
+interface ClaudeSystemEvent {
+  type: 'system';
+  subtype?: string;
+  session_id?: string;
+}
+ 
+interface ClaudeStreamEvent {
+  type: 'stream_event';
+  event?: {
+    type: string;
+    index?: number;
+    delta?: {
+      type?: string;
+      text?: string;
+      stop_reason?: string;
+    };
+    content_block?: {
+      type?: string;
+      id?: string;
+      name?: string;
+    };
+  };
+}
+ 
+interface ClaudeAssistantEvent {
+  type: 'assistant';
+  message?: {
+    content?: Array<{
+      type: string;
+      text?: string;
+      id?: string;
+      name?: string;
+    }>;
+  };
+}
+ 
+interface ClaudeResultEvent {
+  type: 'result';
+  result?: string;
+  session_id?: string;
+  total_cost_usd?: number;
+  is_error?: boolean;
+}
+ 
+type ClaudeEvent = ClaudeSystemEvent | ClaudeStreamEvent | ClaudeAssistantEvent | ClaudeResultEvent | { type: string; is_error?: boolean; result?: string };
+ 
+export class ClaudeStreamParser implements StreamParser {
+  readonly provider = 'claude';
+ 
+  parseLine(line: string): StreamEvent[] {
+    const trimmed = line.trim();
+    if (!trimmed) return [];
+ 
+    let parsed: ClaudeEvent;
+    try {
+      parsed = JSON.parse(trimmed);
+    } catch {
+      // Not valid JSON, ignore
+      return [];
+    }
+ 
+    // Check for error on non-result events (e.g. stream errors)
+    // Result events with is_error are handled in the 'result' case below
+    if ('is_error' in parsed && parsed.is_error && 'result' in parsed && parsed.type !== 'result') {
+      return [{ type: 'error', message: String(parsed.result) }];
+    }
+ 
+    const events: StreamEvent[] = [];
+ 
+    switch (parsed.type) {
+      case 'system': {
+        const sysEvent = parsed as ClaudeSystemEvent;
+        if (sysEvent.subtype === 'init' && sysEvent.session_id) {
+          events.push({ type: 'init', sessionId: sysEvent.session_id });
+        }
+        break;
+      }
+ 
+      case 'stream_event': {
+        const streamEvent = parsed as ClaudeStreamEvent;
+        const inner = streamEvent.event;
+        if (!inner) break;
+ 
+        switch (inner.type) {
+          case 'content_block_delta': {
+            if (inner.delta?.type === 'text_delta' && inner.delta.text) {
+              events.push({ type: 'text_delta', text: inner.delta.text });
+            }
+            break;
+          }
+ 
+          case 'content_block_start': {
+            if (inner.content_block?.type === 'tool_use') {
+              const name = inner.content_block.name || 'unknown';
+              const id = inner.content_block.id || '';
+              events.push({ type: 'tool_use_start', name, id });
+            }
+            break;
+          }
+ 
+          case 'message_delta': {
+            if (inner.delta?.stop_reason) {
+              events.push({ type: 'turn_end', stopReason: inner.delta.stop_reason });
+            }
+            break;
+          }
+        }
+        break;
+      }
+ 
+      case 'assistant': {
+        // Claude CLI stream-json now emits complete assistant messages
+        // instead of granular stream_event deltas
+        const assistantEvent = parsed as ClaudeAssistantEvent;
+        const content = assistantEvent.message?.content;
+        if (Array.isArray(content)) {
+          for (const block of content) {
+            if (block.type === 'text' && block.text) {
+              events.push({ type: 'text_delta', text: block.text });
+            } else if (block.type === 'tool_use' && block.name) {
+              events.push({ type: 'tool_use_start', name: block.name, id: block.id || '' });
+            }
+          }
+        }
+        break;
+      }
+ 
+      case 'result': {
+        const resultEvent = parsed as ClaudeResultEvent;
+        events.push({
+          type: 'result',
+          text: resultEvent.result || '',
+          sessionId: resultEvent.session_id,
+          costUsd: resultEvent.total_cost_usd,
+          isError: resultEvent.is_error === true,
+        });
+        break;
+      }
+ 
+      // Ignore: message_start, content_block_stop, message_stop, user
+    }
+ 
+    return events;
+  }
+ 
+  end(): StreamEvent[] {
+    // Claude emits a result event, so nothing needed at end
+    return [];
+  }
+}
+ 
+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/coverage/src/agent/providers/parsers/generic.ts.html b/coverage/src/agent/providers/parsers/generic.ts.html new file mode 100644 index 0000000..a3ed1d5 --- /dev/null +++ b/coverage/src/agent/providers/parsers/generic.ts.html @@ -0,0 +1,181 @@ + + + + + + Code coverage report for src/agent/providers/parsers/generic.ts + + + + + + + + + +
+
+

All files / src/agent/providers/parsers generic.ts

+
+ +
+ 0% + Statements + 0/11 +
+ + +
+ 0% + Branches + 0/4 +
+ + +
+ 0% + Functions + 0/2 +
+ + +
+ 0% + Lines + 0/9 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+

+
1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 +30 +31 +32 +33  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  + 
/**
+ * Generic Fallback Stream Parser
+ *
+ * For providers without a dedicated parser. Treats each line as text output.
+ * Accumulates all output and emits a final result event on stream end.
+ */
+ 
+import type { StreamEvent, StreamParser } from '../stream-types.js';
+ 
+export class GenericStreamParser implements StreamParser {
+  readonly provider = 'generic';
+  private accumulated: string[] = [];
+ 
+  parseLine(line: string): StreamEvent[] {
+    if (!line) return [];
+ 
+    this.accumulated.push(line);
+ 
+    // Emit each line as a text delta
+    return [{ type: 'text_delta', text: line + '\n' }];
+  }
+ 
+  end(): StreamEvent[] {
+    // Emit the accumulated output as the result
+    const fullText = this.accumulated.join('\n');
+    this.accumulated = [];
+ 
+    if (!fullText) return [];
+ 
+    return [{ type: 'result', text: fullText }];
+  }
+}
+ 
+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/coverage/src/agent/providers/parsers/index.html b/coverage/src/agent/providers/parsers/index.html new file mode 100644 index 0000000..fff6cb7 --- /dev/null +++ b/coverage/src/agent/providers/parsers/index.html @@ -0,0 +1,146 @@ + + + + + + Code coverage report for src/agent/providers/parsers + + + + + + + + + +
+
+

All files src/agent/providers/parsers

+
+ +
+ 8.06% + Statements + 5/62 +
+ + +
+ 1.88% + Branches + 1/53 +
+ + +
+ 20% + Functions + 1/5 +
+ + +
+ 8.62% + Lines + 5/58 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
FileStatementsBranchesFunctionsLines
claude.ts +
+
2.17%1/460%0/470%0/22.27%1/44
generic.ts +
+
0%0/110%0/40%0/20%0/9
index.ts +
+
80%4/550%1/2100%1/180%4/5
+
+
+
+ + + + + + + + \ No newline at end of file diff --git a/coverage/src/agent/providers/parsers/index.ts.html b/coverage/src/agent/providers/parsers/index.ts.html new file mode 100644 index 0000000..4bdd454 --- /dev/null +++ b/coverage/src/agent/providers/parsers/index.ts.html @@ -0,0 +1,178 @@ + + + + + + Code coverage report for src/agent/providers/parsers/index.ts + + + + + + + + + +
+
+

All files / src/agent/providers/parsers index.ts

+
+ +
+ 80% + Statements + 4/5 +
+ + +
+ 50% + Branches + 1/2 +
+ + +
+ 100% + Functions + 1/1 +
+ + +
+ 80% + Lines + 4/5 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+

+
1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 +30 +31 +32  +  +  +  +  +  +  +  +  +  +  +15x +  +  +  +  +  +  +  +  +10x +10x +10x +  +  +  +  +  +  +  +  + 
/**
+ * Stream Parser Registry
+ *
+ * Factory function to get the appropriate stream parser for a provider.
+ */
+ 
+import type { StreamParser } from '../stream-types.js';
+import { ClaudeStreamParser } from './claude.js';
+import { GenericStreamParser } from './generic.js';
+ 
+/** Map of provider names to parser constructors */
+const parserRegistry: Record<string, new () => StreamParser> = {
+  claude: ClaudeStreamParser,
+};
+ 
+/**
+ * Get a stream parser for the given provider.
+ * Returns a provider-specific parser if available, otherwise the generic fallback.
+ */
+export function getStreamParser(providerName: string): StreamParser {
+  const ParserClass = parserRegistry[providerName];
+  Eif (ParserClass) {
+    return new ParserClass();
+  }
+  return new GenericStreamParser();
+}
+ 
+// Re-export types and parsers for direct access
+export type { StreamParser, StreamEvent } from '../stream-types.js';
+export { ClaudeStreamParser } from './claude.js';
+export { GenericStreamParser } from './generic.js';
+ 
+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/coverage/src/agent/providers/presets.ts.html b/coverage/src/agent/providers/presets.ts.html new file mode 100644 index 0000000..50aa2fa --- /dev/null +++ b/coverage/src/agent/providers/presets.ts.html @@ -0,0 +1,520 @@ + + + + + + Code coverage report for src/agent/providers/presets.ts + + + + + + + + + +
+
+

All files / src/agent/providers presets.ts

+
+ +
+ 100% + Statements + 1/1 +
+ + +
+ 100% + Branches + 0/0 +
+ + +
+ 100% + Functions + 0/0 +
+ + +
+ 100% + Lines + 1/1 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+

+
1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 +30 +31 +32 +33 +34 +35 +36 +37 +38 +39 +40 +41 +42 +43 +44 +45 +46 +47 +48 +49 +50 +51 +52 +53 +54 +55 +56 +57 +58 +59 +60 +61 +62 +63 +64 +65 +66 +67 +68 +69 +70 +71 +72 +73 +74 +75 +76 +77 +78 +79 +80 +81 +82 +83 +84 +85 +86 +87 +88 +89 +90 +91 +92 +93 +94 +95 +96 +97 +98 +99 +100 +101 +102 +103 +104 +105 +106 +107 +108 +109 +110 +111 +112 +113 +114 +115 +116 +117 +118 +119 +120 +121 +122 +123 +124 +125 +126 +127 +128 +129 +130 +131 +132 +133 +134 +135 +136 +137 +138 +139 +140 +141 +142 +143 +144 +145 +146  +  +  +  +  +  +  +  +  +23x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  + 
/**
+ * Built-in Agent Provider Presets
+ *
+ * Data-driven configuration for all supported agent CLI providers.
+ * Ported from reference/gastown/internal/config/agents.go builtinPresets.
+ */
+ 
+import type { AgentProviderConfig } from './types.js';
+ 
+export const PROVIDER_PRESETS: Record<string, AgentProviderConfig> = {
+  claude: {
+    name: 'claude',
+    command: 'claude',
+    args: ['--dangerously-skip-permissions', '--verbose'],
+    processNames: ['node', 'claude'],
+    configDirEnv: 'CLAUDE_CONFIG_DIR',
+    resumeFlag: '--resume',
+    resumeStyle: 'flag',
+    promptMode: 'native',
+    // No structuredOutput - schema enforcement via prompt text + validation
+    sessionId: {
+      extractFrom: 'event',
+      field: 'session_id',
+      eventType: 'system',
+    },
+    nonInteractive: {
+      outputFlag: '--output-format stream-json',
+    },
+  },
+ 
+  codex: {
+    name: 'codex',
+    command: 'codex',
+    args: ['--full-auto'],
+    processNames: ['codex'],
+    resumeFlag: 'resume',
+    resumeStyle: 'subcommand',
+    promptMode: 'native',
+    structuredOutput: {
+      flag: '--output-schema',
+      schemaMode: 'file',
+      outputFormat: 'jsonl',
+    },
+    sessionId: {
+      extractFrom: 'event',
+      field: 'thread_id',
+      eventType: 'thread.started',
+    },
+    nonInteractive: {
+      subcommand: 'exec',
+      outputFlag: '--json',
+    },
+  },
+ 
+  gemini: {
+    name: 'gemini',
+    command: 'gemini',
+    args: ['--sandbox=off'],
+    processNames: ['gemini'],
+    resumeFlag: '--resume',
+    resumeStyle: 'flag',
+    promptMode: 'flag',
+    structuredOutput: {
+      flag: '--output-format',
+      schemaMode: 'none',
+      outputFormat: 'json',
+    },
+    sessionId: {
+      extractFrom: 'result',
+      field: 'session_id',
+    },
+    nonInteractive: {
+      promptFlag: '-p',
+      outputFlag: '--output-format json',
+    },
+  },
+ 
+  cursor: {
+    name: 'cursor',
+    command: 'cursor-agent',
+    args: ['-f'],
+    processNames: ['cursor-agent'],
+    resumeStyle: 'none',
+    promptMode: 'flag',
+    structuredOutput: {
+      flag: '--output-format',
+      schemaMode: 'none',
+      outputFormat: 'json',
+    },
+    nonInteractive: {
+      promptFlag: '-p',
+      outputFlag: '--output-format json',
+    },
+  },
+ 
+  auggie: {
+    name: 'auggie',
+    command: 'aug',
+    args: ['--allow-indexing'],
+    processNames: ['aug'],
+    resumeStyle: 'none',
+    promptMode: 'flag',
+    nonInteractive: {
+      promptFlag: '-p',
+    },
+  },
+ 
+  amp: {
+    name: 'amp',
+    command: 'amp',
+    args: ['--allow-all'],
+    processNames: ['amp'],
+    resumeFlag: '--thread',
+    resumeStyle: 'flag',
+    promptMode: 'flag',
+    sessionId: {
+      extractFrom: 'result',
+      field: 'thread_id',
+    },
+    nonInteractive: {
+      promptFlag: '-p',
+      outputFlag: '--json',
+    },
+  },
+ 
+  opencode: {
+    name: 'opencode',
+    command: 'opencode',
+    args: [],
+    env: { OPENCODE_PERMISSION: '{"*":"allow"}' },
+    processNames: ['opencode', 'node', 'bun'],
+    resumeStyle: 'none',
+    promptMode: 'flag',
+    structuredOutput: {
+      flag: '--format',
+      schemaMode: 'none',
+      outputFormat: 'json',
+    },
+    nonInteractive: {
+      subcommand: 'run',
+      promptFlag: '-p',
+      outputFlag: '--format json',
+    },
+  },
+};
+ 
+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/coverage/src/agent/providers/registry.ts.html b/coverage/src/agent/providers/registry.ts.html new file mode 100644 index 0000000..4f9da96 --- /dev/null +++ b/coverage/src/agent/providers/registry.ts.html @@ -0,0 +1,235 @@ + + + + + + Code coverage report for src/agent/providers/registry.ts + + + + + + + + + +
+
+

All files / src/agent/providers registry.ts

+
+ +
+ 25% + Statements + 2/8 +
+ + +
+ 50% + Branches + 1/2 +
+ + +
+ 25% + Functions + 1/4 +
+ + +
+ 25% + Lines + 2/8 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+

+
1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 +30 +31 +32 +33 +34 +35 +36 +37 +38 +39 +40 +41 +42 +43 +44 +45 +46 +47 +48 +49 +50 +51  +  +  +  +  +  +  +  +  +  +  +  +23x +  +  +  +  +  +  +  +  +22x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  + 
/**
+ * Agent Provider Registry
+ *
+ * In-memory registry of agent provider configurations.
+ * Pre-populated with built-in presets, extensible via registerProvider()
+ * or loadProvidersFromFile() for custom/override configs.
+ */
+ 
+import { readFileSync } from 'node:fs';
+import type { AgentProviderConfig } from './types.js';
+import { PROVIDER_PRESETS } from './presets.js';
+ 
+const providers = new Map<string, AgentProviderConfig>(
+  Object.entries(PROVIDER_PRESETS),
+);
+ 
+/**
+ * Get a provider configuration by name.
+ * Returns null if the provider is not registered.
+ */
+export function getProvider(name: string): AgentProviderConfig | null {
+  return providers.get(name) ?? null;
+}
+ 
+/**
+ * List all registered provider names.
+ */
+export function listProviders(): string[] {
+  return Array.from(providers.keys());
+}
+ 
+/**
+ * Register or override a provider configuration.
+ */
+export function registerProvider(config: AgentProviderConfig): void {
+  providers.set(config.name, config);
+}
+ 
+/**
+ * Load provider configurations from a JSON file and merge into the registry.
+ * File should contain a JSON object mapping provider names to AgentProviderConfig objects.
+ * Existing providers with matching names will be overridden.
+ */
+export function loadProvidersFromFile(path: string): void {
+  const raw = readFileSync(path, 'utf-8');
+  const parsed = JSON.parse(raw) as Record<string, AgentProviderConfig>;
+  for (const [name, config] of Object.entries(parsed)) {
+    providers.set(name, { ...config, name });
+  }
+}
+ 
+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/coverage/src/agent/schema.ts.html b/coverage/src/agent/schema.ts.html new file mode 100644 index 0000000..1ba6bc6 --- /dev/null +++ b/coverage/src/agent/schema.ts.html @@ -0,0 +1,376 @@ + + + + + + Code coverage report for src/agent/schema.ts + + + + + + + + + +
+
+

All files / src/agent schema.ts

+
+ +
+ 100% + Statements + 6/6 +
+ + +
+ 100% + Branches + 0/0 +
+ + +
+ 100% + Functions + 0/0 +
+ + +
+ 100% + Lines + 6/6 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+

+
1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 +30 +31 +32 +33 +34 +35 +36 +37 +38 +39 +40 +41 +42 +43 +44 +45 +46 +47 +48 +49 +50 +51 +52 +53 +54 +55 +56 +57 +58 +59 +60 +61 +62 +63 +64 +65 +66 +67 +68 +69 +70 +71 +72 +73 +74 +75 +76 +77 +78 +79 +80 +81 +82 +83 +84 +85 +86 +87 +88 +89 +90 +91 +92 +93 +94 +95 +96 +97 +98  +  +  +  +  +  +  +  +  +  +  +  +  +21x +  +  +  +  +21x +  +  +  +  +  +  +  +  +  +  +  +  +21x +  +  +  +  +  +  +  +21x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +21x +  +  +  +21x + 
/**
+ * Agent Signal Schema
+ *
+ * Agents communicate via a trivial JSON signal: done, questions, or error.
+ * All structured output is file-based (see file-io.ts).
+ */
+ 
+import { z } from 'zod';
+ 
+// =============================================================================
+// SHARED SCHEMAS
+// =============================================================================
+ 
+const optionSchema = z.object({
+  label: z.string(),
+  description: z.string().optional(),
+});
+ 
+export const questionItemSchema = z.object({
+  id: z.string(),
+  question: z.string(),
+  options: z.array(optionSchema).optional(),
+  multiSelect: z.boolean().optional(),
+});
+ 
+export type QuestionItem = z.infer<typeof questionItemSchema>;
+ 
+// =============================================================================
+// UNIVERSAL SIGNAL SCHEMA
+// =============================================================================
+ 
+export const agentSignalSchema = z.discriminatedUnion('status', [
+  z.object({ status: z.literal('done') }),
+  z.object({ status: z.literal('questions'), questions: z.array(questionItemSchema) }),
+  z.object({ status: z.literal('error'), error: z.string() }),
+]);
+ 
+export type AgentSignal = z.infer<typeof agentSignalSchema>;
+ 
+export const agentSignalJsonSchema = {
+  type: 'object',
+  oneOf: [
+    {
+      properties: {
+        status: { const: 'done' },
+      },
+      required: ['status'],
+    },
+    {
+      properties: {
+        status: { const: 'questions' },
+        questions: {
+          type: 'array',
+          items: {
+            type: 'object',
+            properties: {
+              id: { type: 'string' },
+              question: { type: 'string' },
+              options: {
+                type: 'array',
+                items: {
+                  type: 'object',
+                  properties: {
+                    label: { type: 'string' },
+                    description: { type: 'string' },
+                  },
+                  required: ['label'],
+                },
+              },
+              multiSelect: { type: 'boolean' },
+            },
+            required: ['id', 'question'],
+          },
+        },
+      },
+      required: ['status', 'questions'],
+    },
+    {
+      properties: {
+        status: { const: 'error' },
+        error: { type: 'string' },
+      },
+      required: ['status', 'error'],
+    },
+  ],
+};
+ 
+// =============================================================================
+// BACKWARD COMPATIBILITY
+// =============================================================================
+ 
+/** @deprecated Use agentSignalSchema */
+export const agentOutputSchema = agentSignalSchema;
+/** @deprecated Use AgentSignal */
+export type AgentOutput = AgentSignal;
+/** @deprecated Use agentSignalJsonSchema */
+export const agentOutputJsonSchema = agentSignalJsonSchema;
+ 
+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/coverage/src/cli/index.html b/coverage/src/cli/index.html new file mode 100644 index 0000000..686aaf5 --- /dev/null +++ b/coverage/src/cli/index.html @@ -0,0 +1,116 @@ + + + + + + Code coverage report for src/cli + + + + + + + + + +
+
+

All files src/cli

+
+ +
+ 62.5% + Statements + 5/8 +
+ + +
+ 33.33% + Branches + 2/6 +
+ + +
+ 66.66% + Functions + 2/3 +
+ + +
+ 62.5% + Lines + 5/8 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
FileStatementsBranchesFunctionsLines
trpc-client.ts +
+
62.5%5/833.33%2/666.66%2/362.5%5/8
+
+
+
+ + + + + + + + \ No newline at end of file diff --git a/coverage/src/cli/trpc-client.ts.html b/coverage/src/cli/trpc-client.ts.html new file mode 100644 index 0000000..90e419e --- /dev/null +++ b/coverage/src/cli/trpc-client.ts.html @@ -0,0 +1,256 @@ + + + + + + Code coverage report for src/cli/trpc-client.ts + + + + + + + + + +
+
+

All files / src/cli trpc-client.ts

+
+ +
+ 62.5% + Statements + 5/8 +
+ + +
+ 33.33% + Branches + 2/6 +
+ + +
+ 66.66% + Functions + 2/3 +
+ + +
+ 62.5% + Lines + 5/8 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+

+
1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 +30 +31 +32 +33 +34 +35 +36 +37 +38 +39 +40 +41 +42 +43 +44 +45 +46 +47 +48 +49 +50 +51 +52 +53 +54 +55 +56 +57 +58  +  +  +  +  +  +  +  +  +  +  +1x +  +  +1x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +2x +2x +  +  +8x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  + 
/**
+ * tRPC Client for CLI
+ *
+ * Type-safe client for communicating with the coordination server.
+ * Uses splitLink to route subscriptions to SSE and queries/mutations to HTTP batch.
+ */
+ 
+import { createTRPCClient, httpBatchLink, splitLink, httpSubscriptionLink } from '@trpc/client';
+import type { AppRouter } from '../trpc/index.js';
+ 
+/** Default server port */
+const DEFAULT_PORT = 3847;
+ 
+/** Default server host */
+const DEFAULT_HOST = '127.0.0.1';
+ 
+/**
+ * Type-safe tRPC client for the coordination server.
+ */
+export type TrpcClient = ReturnType<typeof createTRPCClient<AppRouter>>;
+ 
+/**
+ * Creates a tRPC client for the coordination server.
+ *
+ * @param port - Server port (default: 3847)
+ * @param host - Server host (default: 127.0.0.1)
+ * @returns Type-safe tRPC client
+ */
+export function createTrpcClient(
+  port: number = DEFAULT_PORT,
+  host: string = DEFAULT_HOST
+): TrpcClient {
+  const url = `http://${host}:${port}/trpc`;
+  return createTRPCClient<AppRouter>({
+    links: [
+      splitLink({
+        condition: (op) => op.type === 'subscription',
+        true: httpSubscriptionLink({ url }),
+        false: httpBatchLink({ url }),
+      }),
+    ],
+  });
+}
+ 
+/**
+ * Creates a tRPC client using environment variables or defaults.
+ *
+ * Uses CW_PORT and CW_HOST environment variables if available,
+ * falling back to defaults (127.0.0.1:3847).
+ *
+ * @returns Type-safe tRPC client
+ */
+export function createDefaultTrpcClient(): TrpcClient {
+  const port = process.env.CW_PORT ? parseInt(process.env.CW_PORT, 10) : DEFAULT_PORT;
+  const host = process.env.CW_HOST ?? DEFAULT_HOST;
+  return createTrpcClient(port, host);
+}
+ 
+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/coverage/src/config/cwrc.ts.html b/coverage/src/config/cwrc.ts.html new file mode 100644 index 0000000..739565f --- /dev/null +++ b/coverage/src/config/cwrc.ts.html @@ -0,0 +1,283 @@ + + + + + + Code coverage report for src/config/cwrc.ts + + + + + + + + + +
+
+

All files / src/config cwrc.ts

+
+ +
+ 5.55% + Statements + 1/18 +
+ + +
+ 0% + Branches + 0/7 +
+ + +
+ 0% + Functions + 0/4 +
+ + +
+ 5.55% + Lines + 1/18 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+

+
1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 +30 +31 +32 +33 +34 +35 +36 +37 +38 +39 +40 +41 +42 +43 +44 +45 +46 +47 +48 +49 +50 +51 +52 +53 +54 +55 +56 +57 +58 +59 +60 +61 +62 +63 +64 +65 +66 +67  +  +  +  +  +  +  +  +  +  +  +  +8x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  + 
/**
+ * .cwrc File Operations
+ *
+ * Find, read, and write the .cwrc configuration file.
+ * The file's presence marks the workspace root directory.
+ */
+ 
+import { readFileSync, writeFileSync, existsSync } from 'node:fs';
+import { join, dirname, parse } from 'node:path';
+import type { CwConfig } from './types.js';
+ 
+/** Default filename */
+const CWRC_FILENAME = '.cwrc';
+ 
+/**
+ * Walk up from `startDir` looking for a .cwrc file.
+ * Returns the absolute path to the directory containing it,
+ * or null if the filesystem root is reached.
+ */
+export function findWorkspaceRoot(startDir: string = process.cwd()): string | null {
+  let dir = startDir;
+ 
+  while (true) {
+    const candidate = join(dir, CWRC_FILENAME);
+    if (existsSync(candidate)) {
+      return dir;
+    }
+ 
+    const parent = dirname(dir);
+    if (parent === dir) {
+      // Reached filesystem root
+      return null;
+    }
+    dir = parent;
+  }
+}
+ 
+/**
+ * Read and parse the .cwrc file in the given directory.
+ * Returns null if the file doesn't exist.
+ * Throws on malformed JSON.
+ */
+export function readCwrc(dir: string): CwConfig | null {
+  const filePath = join(dir, CWRC_FILENAME);
+  if (!existsSync(filePath)) {
+    return null;
+  }
+ 
+  const raw = readFileSync(filePath, 'utf-8');
+  return JSON.parse(raw) as CwConfig;
+}
+ 
+/**
+ * Write a .cwrc file to the given directory.
+ */
+export function writeCwrc(dir: string, config: CwConfig): void {
+  const filePath = join(dir, CWRC_FILENAME);
+  writeFileSync(filePath, JSON.stringify(config, null, 2) + '\n', 'utf-8');
+}
+ 
+/**
+ * Create a default .cwrc config.
+ */
+export function defaultCwConfig(): CwConfig {
+  return { version: 1 };
+}
+ 
+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/coverage/src/config/index.html b/coverage/src/config/index.html new file mode 100644 index 0000000..bbbd3ac --- /dev/null +++ b/coverage/src/config/index.html @@ -0,0 +1,131 @@ + + + + + + Code coverage report for src/config + + + + + + + + + +
+
+

All files src/config

+
+ +
+ 5.55% + Statements + 1/18 +
+ + +
+ 0% + Branches + 0/7 +
+ + +
+ 0% + Functions + 0/4 +
+ + +
+ 5.55% + Lines + 1/18 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
FileStatementsBranchesFunctionsLines
cwrc.ts +
+
5.55%1/180%0/70%0/45.55%1/18
index.ts +
+
0%0/00%0/00%0/00%0/0
+
+
+
+ + + + + + + + \ No newline at end of file diff --git a/coverage/src/config/index.ts.html b/coverage/src/config/index.ts.html new file mode 100644 index 0000000..b22e88b --- /dev/null +++ b/coverage/src/config/index.ts.html @@ -0,0 +1,124 @@ + + + + + + Code coverage report for src/config/index.ts + + + + + + + + + +
+
+

All files / src/config index.ts

+
+ +
+ 0% + Statements + 0/0 +
+ + +
+ 0% + Branches + 0/0 +
+ + +
+ 0% + Functions + 0/0 +
+ + +
+ 0% + Lines + 0/0 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+

+
1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14  +  +  +  +  +  +  +  +  +  +  +  +  + 
/**
+ * Configuration Module
+ *
+ * Handles .cwrc workspace configuration.
+ */
+ 
+export type { CwConfig } from './types.js';
+export {
+  findWorkspaceRoot,
+  readCwrc,
+  writeCwrc,
+  defaultCwConfig,
+} from './cwrc.js';
+ 
+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/coverage/src/container.ts.html b/coverage/src/container.ts.html new file mode 100644 index 0000000..6639420 --- /dev/null +++ b/coverage/src/container.ts.html @@ -0,0 +1,883 @@ + + + + + + Code coverage report for src/container.ts + + + + + + + + + +
+
+

All files / src container.ts

+
+ +
+ 3.12% + Statements + 1/32 +
+ + +
+ 0% + Branches + 0/4 +
+ + +
+ 33.33% + Functions + 1/3 +
+ + +
+ 3.12% + Lines + 1/32 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+

+
1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 +30 +31 +32 +33 +34 +35 +36 +37 +38 +39 +40 +41 +42 +43 +44 +45 +46 +47 +48 +49 +50 +51 +52 +53 +54 +55 +56 +57 +58 +59 +60 +61 +62 +63 +64 +65 +66 +67 +68 +69 +70 +71 +72 +73 +74 +75 +76 +77 +78 +79 +80 +81 +82 +83 +84 +85 +86 +87 +88 +89 +90 +91 +92 +93 +94 +95 +96 +97 +98 +99 +100 +101 +102 +103 +104 +105 +106 +107 +108 +109 +110 +111 +112 +113 +114 +115 +116 +117 +118 +119 +120 +121 +122 +123 +124 +125 +126 +127 +128 +129 +130 +131 +132 +133 +134 +135 +136 +137 +138 +139 +140 +141 +142 +143 +144 +145 +146 +147 +148 +149 +150 +151 +152 +153 +154 +155 +156 +157 +158 +159 +160 +161 +162 +163 +164 +165 +166 +167 +168 +169 +170 +171 +172 +173 +174 +175 +176 +177 +178 +179 +180 +181 +182 +183 +184 +185 +186 +187 +188 +189 +190 +191 +192 +193 +194 +195 +196 +197 +198 +199 +200 +201 +202 +203 +204 +205 +206 +207 +208 +209 +210 +211 +212 +213 +214 +215 +216 +217 +218 +219 +220 +221 +222 +223 +224 +225 +226 +227 +228 +229 +230 +231 +232 +233 +234 +235 +236 +237 +238 +239 +240 +241 +242 +243 +244 +245 +246 +247 +248 +249 +250 +251 +252 +253 +254 +255 +256 +257 +258 +259 +260 +261 +262 +263 +264 +265 +266 +267  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +80x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  + 
/**
+ * Dependency Container
+ *
+ * Factory functions for creating the full dependency graph.
+ * Keeps startServer() thin and makes repo wiring reusable by the test harness.
+ */
+ 
+import type { DrizzleDatabase } from './db/index.js';
+import {
+  createDatabase,
+  ensureSchema,
+  DrizzleInitiativeRepository,
+  DrizzlePhaseRepository,
+  DrizzleTaskRepository,
+  DrizzleMessageRepository,
+  DrizzleAgentRepository,
+  DrizzlePageRepository,
+  DrizzleProjectRepository,
+  DrizzleAccountRepository,
+  DrizzleChangeSetRepository,
+  DrizzleLogChunkRepository,
+  DrizzleConversationRepository,
+} from './db/index.js';
+import type { InitiativeRepository } from './db/repositories/initiative-repository.js';
+import type { PhaseRepository } from './db/repositories/phase-repository.js';
+import type { TaskRepository } from './db/repositories/task-repository.js';
+import type { MessageRepository } from './db/repositories/message-repository.js';
+import type { AgentRepository } from './db/repositories/agent-repository.js';
+import type { PageRepository } from './db/repositories/page-repository.js';
+import type { ProjectRepository } from './db/repositories/project-repository.js';
+import type { AccountRepository } from './db/repositories/account-repository.js';
+import type { ChangeSetRepository } from './db/repositories/change-set-repository.js';
+import type { LogChunkRepository } from './db/repositories/log-chunk-repository.js';
+import type { ConversationRepository } from './db/repositories/conversation-repository.js';
+import type { EventBus } from './events/index.js';
+import { createEventBus } from './events/index.js';
+import { ProcessManager, ProcessRegistry } from './process/index.js';
+import { LogManager } from './logging/index.js';
+import { MultiProviderAgentManager } from './agent/index.js';
+import { DefaultAccountCredentialManager } from './agent/credentials/index.js';
+import type { AccountCredentialManager } from './agent/credentials/types.js';
+import { DefaultDispatchManager } from './dispatch/manager.js';
+import { DefaultPhaseDispatchManager } from './dispatch/phase-manager.js';
+import type { DispatchManager, PhaseDispatchManager } from './dispatch/types.js';
+import { SimpleGitBranchManager } from './git/simple-git-branch-manager.js';
+import type { BranchManager } from './git/branch-manager.js';
+import { ExecutionOrchestrator } from './execution/orchestrator.js';
+import { DefaultConflictResolutionService } from './coordination/conflict-resolution-service.js';
+import { PreviewManager } from './preview/index.js';
+import { findWorkspaceRoot } from './config/index.js';
+import { createModuleLogger } from './logger/index.js';
+import type { ServerContextDeps } from './server/index.js';
+ 
+// =============================================================================
+// Repositories
+// =============================================================================
+ 
+/**
+ * All 11 repository ports.
+ */
+export interface Repositories {
+  initiativeRepository: InitiativeRepository;
+  phaseRepository: PhaseRepository;
+  taskRepository: TaskRepository;
+  messageRepository: MessageRepository;
+  agentRepository: AgentRepository;
+  pageRepository: PageRepository;
+  projectRepository: ProjectRepository;
+  accountRepository: AccountRepository;
+  changeSetRepository: ChangeSetRepository;
+  logChunkRepository: LogChunkRepository;
+  conversationRepository: ConversationRepository;
+}
+ 
+/**
+ * Create all 11 Drizzle repository adapters from a database instance.
+ * Reusable by both the production server and the test harness.
+ */
+export function createRepositories(db: DrizzleDatabase): Repositories {
+  return {
+    initiativeRepository: new DrizzleInitiativeRepository(db),
+    phaseRepository: new DrizzlePhaseRepository(db),
+    taskRepository: new DrizzleTaskRepository(db),
+    messageRepository: new DrizzleMessageRepository(db),
+    agentRepository: new DrizzleAgentRepository(db),
+    pageRepository: new DrizzlePageRepository(db),
+    projectRepository: new DrizzleProjectRepository(db),
+    accountRepository: new DrizzleAccountRepository(db),
+    changeSetRepository: new DrizzleChangeSetRepository(db),
+    logChunkRepository: new DrizzleLogChunkRepository(db),
+    conversationRepository: new DrizzleConversationRepository(db),
+  };
+}
+ 
+// =============================================================================
+// Container
+// =============================================================================
+ 
+/**
+ * Full dependency graph for the coordination server.
+ */
+export interface Container extends Repositories {
+  db: DrizzleDatabase;
+  eventBus: EventBus;
+  processManager: ProcessManager;
+  logManager: LogManager;
+  workspaceRoot: string;
+  credentialManager: AccountCredentialManager;
+  agentManager: MultiProviderAgentManager;
+  dispatchManager: DispatchManager;
+  phaseDispatchManager: PhaseDispatchManager;
+  branchManager: BranchManager;
+  executionOrchestrator: ExecutionOrchestrator;
+  previewManager: PreviewManager;
+ 
+  /** Extract the subset of deps that CoordinationServer needs. */
+  toContextDeps(): ServerContextDeps;
+}
+ 
+/**
+ * Options for container creation.
+ */
+export interface ContainerOptions {
+  debug?: boolean;
+}
+ 
+/**
+ * Create the full dependency container.
+ *
+ * Wires: ProcessRegistry → EventBus → ProcessManager → LogManager →
+ *        Database → Repositories → CredentialManager → AgentManager.
+ * Runs ensureSchema() and reconcileAfterRestart() before returning.
+ */
+export async function createContainer(options?: ContainerOptions): Promise<Container> {
+  const log = createModuleLogger('container');
+ 
+  // Infrastructure
+  const registry = new ProcessRegistry();
+  const eventBus = createEventBus();
+  const processManager = new ProcessManager(registry, eventBus);
+  const logManager = new LogManager();
+ 
+  // Database
+  const db = createDatabase();
+  ensureSchema(db);
+  log.info('database initialized');
+ 
+  // Repositories
+  const repos = createRepositories(db);
+  log.info('repositories created');
+ 
+  // Workspace root
+  const workspaceRoot = findWorkspaceRoot(process.cwd()) ?? process.cwd();
+  log.info({ workspaceRoot }, 'workspace root resolved');
+ 
+  // Credential manager
+  const credentialManager = new DefaultAccountCredentialManager(eventBus);
+  log.info('credential manager created');
+ 
+  // Agent manager
+  const agentManager = new MultiProviderAgentManager(
+    repos.agentRepository,
+    workspaceRoot,
+    repos.projectRepository,
+    repos.accountRepository,
+    eventBus,
+    credentialManager,
+    repos.changeSetRepository,
+    repos.phaseRepository,
+    repos.taskRepository,
+    repos.pageRepository,
+    repos.logChunkRepository,
+    options?.debug ?? false,
+  );
+  log.info('agent manager created');
+ 
+  // Reconcile agent state from any previous server session
+  await agentManager.reconcileAfterRestart();
+  log.info('agent reconciliation complete');
+ 
+  // Branch manager
+  const branchManager = new SimpleGitBranchManager();
+  log.info('branch manager created');
+ 
+  // Dispatch managers
+  const dispatchManager = new DefaultDispatchManager(
+    repos.taskRepository,
+    repos.messageRepository,
+    agentManager,
+    eventBus,
+    repos.initiativeRepository,
+    repos.phaseRepository,
+  );
+  const phaseDispatchManager = new DefaultPhaseDispatchManager(
+    repos.phaseRepository,
+    repos.taskRepository,
+    dispatchManager,
+    eventBus,
+    repos.initiativeRepository,
+    repos.projectRepository,
+    branchManager,
+    workspaceRoot,
+  );
+  log.info('dispatch managers created');
+ 
+  // Conflict resolution service (for orchestrator)
+  const conflictResolutionService = new DefaultConflictResolutionService(
+    repos.taskRepository,
+    repos.agentRepository,
+    repos.messageRepository,
+    eventBus,
+  );
+ 
+  // Execution orchestrator
+  const executionOrchestrator = new ExecutionOrchestrator(
+    branchManager,
+    repos.phaseRepository,
+    repos.taskRepository,
+    repos.initiativeRepository,
+    repos.projectRepository,
+    phaseDispatchManager,
+    conflictResolutionService,
+    eventBus,
+    workspaceRoot,
+  );
+  executionOrchestrator.start();
+  log.info('execution orchestrator started');
+ 
+  // Preview manager
+  const previewManager = new PreviewManager(
+    repos.projectRepository,
+    eventBus,
+    workspaceRoot,
+  );
+  log.info('preview manager created');
+ 
+  return {
+    db,
+    eventBus,
+    processManager,
+    logManager,
+    workspaceRoot,
+    credentialManager,
+    agentManager,
+    dispatchManager,
+    phaseDispatchManager,
+    branchManager,
+    executionOrchestrator,
+    previewManager,
+    ...repos,
+ 
+    toContextDeps(): ServerContextDeps {
+      return {
+        agentManager,
+        credentialManager,
+        dispatchManager,
+        phaseDispatchManager,
+        branchManager,
+        executionOrchestrator,
+        previewManager,
+        workspaceRoot,
+        ...repos,
+      };
+    },
+  };
+}
+ 
+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/coverage/src/coordination/conflict-resolution-service.ts.html b/coverage/src/coordination/conflict-resolution-service.ts.html new file mode 100644 index 0000000..d53c1ba --- /dev/null +++ b/coverage/src/coordination/conflict-resolution-service.ts.html @@ -0,0 +1,559 @@ + + + + + + Code coverage report for src/coordination/conflict-resolution-service.ts + + + + + + + + + +
+
+

All files / src/coordination conflict-resolution-service.ts

+
+ +
+ 96% + Statements + 24/25 +
+ + +
+ 83.33% + Branches + 10/12 +
+ + +
+ 100% + Functions + 4/4 +
+ + +
+ 96% + Lines + 24/25 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+

+
1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 +30 +31 +32 +33 +34 +35 +36 +37 +38 +39 +40 +41 +42 +43 +44 +45 +46 +47 +48 +49 +50 +51 +52 +53 +54 +55 +56 +57 +58 +59 +60 +61 +62 +63 +64 +65 +66 +67 +68 +69 +70 +71 +72 +73 +74 +75 +76 +77 +78 +79 +80 +81 +82 +83 +84 +85 +86 +87 +88 +89 +90 +91 +92 +93 +94 +95 +96 +97 +98 +99 +100 +101 +102 +103 +104 +105 +106 +107 +108 +109 +110 +111 +112 +113 +114 +115 +116 +117 +118 +119 +120 +121 +122 +123 +124 +125 +126 +127 +128 +129 +130 +131 +132 +133 +134 +135 +136 +137 +138 +139 +140 +141 +142 +143 +144 +145 +146 +147 +148 +149 +150 +151 +152 +153 +154 +155 +156 +157 +158 +159  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +115x +115x +115x +115x +  +  +  +  +  +  +  +  +24x +24x +2x +  +  +  +22x +22x +2x +  +  +  +20x +  +  +28x +  +  +  +  +  +20x +  +  +  +  +  +  +20x +  +  +  +  +20x +  +  +20x +  +  +  +  +  +  +  +  +  +  +  +  +  +20x +  +  +20x +19x +  +  +  +27x +  +  +  +  +  +  +19x +  +  +  +  +  +  +  +  +  +  +  +20x +19x +  +  +  +  +  +  +  +  +19x +  +  + 
/**
+ * ConflictResolutionService
+ *
+ * Service responsible for handling merge conflicts by:
+ * - Creating conflict resolution tasks
+ * - Updating original task status
+ * - Notifying agents via messages
+ * - Emitting appropriate events
+ *
+ * This service is used by the CoordinationManager when merge conflicts occur.
+ */
+ 
+import type { EventBus, TaskQueuedEvent } from '../events/index.js';
+import type { TaskRepository } from '../db/repositories/task-repository.js';
+import type { AgentRepository } from '../db/repositories/agent-repository.js';
+import type { MessageRepository } from '../db/repositories/message-repository.js';
+ 
+// =============================================================================
+// ConflictResolutionService Interface (Port)
+// =============================================================================
+ 
+/**
+ * Service interface for handling merge conflicts.
+ * This is the PORT - implementations are ADAPTERS.
+ */
+/**
+ * Branch context for merge conflicts from the branch hierarchy.
+ */
+export interface MergeContext {
+  sourceBranch: string;
+  targetBranch: string;
+}
+ 
+export interface ConflictResolutionService {
+  /**
+   * Handle a merge conflict by creating resolution task and notifying agent.
+   *
+   * @param taskId - ID of the task that conflicted
+   * @param conflicts - List of conflicting file paths
+   * @param mergeContext - Optional branch context for branch hierarchy merges
+   */
+  handleConflict(taskId: string, conflicts: string[], mergeContext?: MergeContext): Promise<void>;
+}
+ 
+// =============================================================================
+// DefaultConflictResolutionService Implementation (Adapter)
+// =============================================================================
+ 
+/**
+ * Default implementation of ConflictResolutionService.
+ *
+ * Creates conflict resolution tasks, updates task statuses, sends messages
+ * to agents, and emits events when merge conflicts occur.
+ */
+export class DefaultConflictResolutionService implements ConflictResolutionService {
+  constructor(
+    private taskRepository: TaskRepository,
+    private agentRepository: AgentRepository,
+    private messageRepository?: MessageRepository,
+    private eventBus?: EventBus
+  ) {}
+ 
+  /**
+   * Handle a merge conflict.
+   * Creates a conflict-resolution task and notifies the agent via message.
+   */
+  async handleConflict(taskId: string, conflicts: string[], mergeContext?: MergeContext): Promise<void> {
+    // Get original task for context
+    const originalTask = await this.taskRepository.findById(taskId);
+    if (!originalTask) {
+      throw new Error(`Original task not found: ${taskId}`);
+    }
+ 
+    // Get agent that was working on the task
+    const agent = await this.agentRepository.findByTaskId(taskId);
+    if (!agent) {
+      throw new Error(`No agent found for task: ${taskId}`);
+    }
+ 
+    // Build conflict description
+    const descriptionLines = [
+      'Merge conflicts detected. Resolve conflicts in the following files:',
+      '',
+      ...conflicts.map((f) => `- ${f}`),
+      '',
+      `Original task: ${originalTask.name}`,
+      '',
+    ];
+ 
+    Iif (mergeContext) {
+      descriptionLines.push(
+        `Resolve merge conflicts between branch "${mergeContext.sourceBranch}" and "${mergeContext.targetBranch}".`,
+        `Run: git merge ${mergeContext.sourceBranch} --no-edit`,
+        'Resolve all conflicts, then: git add . && git commit',
+      );
+    } else {
+      descriptionLines.push(
+        'Instructions: Resolve merge conflicts in the listed files, then mark task complete.',
+      );
+    }
+ 
+    const conflictDescription = descriptionLines.join('\n');
+ 
+    // Create new conflict-resolution task
+    const conflictTask = await this.taskRepository.create({
+      parentTaskId: originalTask.parentTaskId,
+      phaseId: originalTask.phaseId,
+      initiativeId: originalTask.initiativeId,
+      name: `Resolve conflicts: ${originalTask.name}`,
+      description: conflictDescription,
+      category: mergeContext ? 'merge' : 'execute',
+      type: 'auto',
+      priority: 'high',
+      status: 'pending',
+      order: originalTask.order + 1,
+    });
+ 
+    // Update original task status to blocked
+    await this.taskRepository.update(taskId, { status: 'blocked' });
+ 
+    // Create message to agent if messageRepository is configured
+    if (this.messageRepository) {
+      const messageContent = [
+        `Merge conflict detected for task: ${originalTask.name}`,
+        '',
+        'Conflicting files:',
+        ...conflicts.map((f) => `- ${f}`),
+        '',
+        `A new task has been created to resolve these conflicts: ${conflictTask.name}`,
+        '',
+        'Please resolve the merge conflicts in the listed files and mark the resolution task as complete.',
+      ].join('\n');
+ 
+      await this.messageRepository.create({
+        senderType: 'user', // System-generated messages appear as from user
+        senderId: null,
+        recipientType: 'agent',
+        recipientId: agent.id,
+        type: 'info',
+        content: messageContent,
+        requiresResponse: false,
+      });
+    }
+ 
+    // Emit TaskQueuedEvent for the new conflict-resolution task
+    if (this.eventBus) {
+      const event: TaskQueuedEvent = {
+        type: 'task:queued',
+        timestamp: new Date(),
+        payload: {
+          taskId: conflictTask.id,
+          priority: 'high',
+          dependsOn: [],
+        },
+      };
+      this.eventBus.emit(event);
+    }
+  }
+}
+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/coverage/src/coordination/index.html b/coverage/src/coordination/index.html new file mode 100644 index 0000000..7248e0b --- /dev/null +++ b/coverage/src/coordination/index.html @@ -0,0 +1,131 @@ + + + + + + Code coverage report for src/coordination + + + + + + + + + +
+
+

All files src/coordination

+
+ +
+ 94.44% + Statements + 102/108 +
+ + +
+ 85% + Branches + 34/40 +
+ + +
+ 89.47% + Functions + 17/19 +
+ + +
+ 95.28% + Lines + 101/106 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
FileStatementsBranchesFunctionsLines
conflict-resolution-service.ts +
+
96%24/2583.33%10/12100%4/496%24/25
manager.ts +
+
93.97%78/8385.71%24/2886.66%13/1595.06%77/81
+
+
+
+ + + + + + + + \ No newline at end of file diff --git a/coverage/src/coordination/manager.ts.html b/coverage/src/coordination/manager.ts.html new file mode 100644 index 0000000..d04153a --- /dev/null +++ b/coverage/src/coordination/manager.ts.html @@ -0,0 +1,1081 @@ + + + + + + Code coverage report for src/coordination/manager.ts + + + + + + + + + +
+
+

All files / src/coordination manager.ts

+
+ +
+ 93.97% + Statements + 78/83 +
+ + +
+ 85.71% + Branches + 24/28 +
+ + +
+ 86.66% + Functions + 13/15 +
+ + +
+ 95.06% + Lines + 77/81 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+

+
1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 +30 +31 +32 +33 +34 +35 +36 +37 +38 +39 +40 +41 +42 +43 +44 +45 +46 +47 +48 +49 +50 +51 +52 +53 +54 +55 +56 +57 +58 +59 +60 +61 +62 +63 +64 +65 +66 +67 +68 +69 +70 +71 +72 +73 +74 +75 +76 +77 +78 +79 +80 +81 +82 +83 +84 +85 +86 +87 +88 +89 +90 +91 +92 +93 +94 +95 +96 +97 +98 +99 +100 +101 +102 +103 +104 +105 +106 +107 +108 +109 +110 +111 +112 +113 +114 +115 +116 +117 +118 +119 +120 +121 +122 +123 +124 +125 +126 +127 +128 +129 +130 +131 +132 +133 +134 +135 +136 +137 +138 +139 +140 +141 +142 +143 +144 +145 +146 +147 +148 +149 +150 +151 +152 +153 +154 +155 +156 +157 +158 +159 +160 +161 +162 +163 +164 +165 +166 +167 +168 +169 +170 +171 +172 +173 +174 +175 +176 +177 +178 +179 +180 +181 +182 +183 +184 +185 +186 +187 +188 +189 +190 +191 +192 +193 +194 +195 +196 +197 +198 +199 +200 +201 +202 +203 +204 +205 +206 +207 +208 +209 +210 +211 +212 +213 +214 +215 +216 +217 +218 +219 +220 +221 +222 +223 +224 +225 +226 +227 +228 +229 +230 +231 +232 +233 +234 +235 +236 +237 +238 +239 +240 +241 +242 +243 +244 +245 +246 +247 +248 +249 +250 +251 +252 +253 +254 +255 +256 +257 +258 +259 +260 +261 +262 +263 +264 +265 +266 +267 +268 +269 +270 +271 +272 +273 +274 +275 +276 +277 +278 +279 +280 +281 +282 +283 +284 +285 +286 +287 +288 +289 +290 +291 +292 +293 +294 +295 +296 +297 +298 +299 +300 +301 +302 +303 +304 +305 +306 +307 +308 +309 +310 +311 +312 +313 +314 +315 +316 +317 +318 +319 +320 +321 +322 +323 +324 +325 +326 +327 +328 +329 +330 +331 +332 +333  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +105x +  +  +105x +  +  +105x +  +  +  +  +  +105x +105x +105x +105x +105x +  +  +  +105x +  +105x +103x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +40x +1x +  +  +39x +39x +1x +  +  +  +38x +1x +  +  +37x +37x +1x +  +  +  +  +36x +  +36x +  +  +  +  +  +  +  +  +  +36x +  +  +36x +  +  +  +  +  +  +  +  +  +36x +  +  +  +  +  +  +  +54x +37x +  +  +54x +24x +  +  +  +30x +37x +  +  +30x +  +  +  +  +30x +  +30x +9x +9x +7x +  +2x +  +  +  +30x +30x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +24x +1x +  +  +23x +  +  +23x +  +23x +27x +  +  +27x +  +  +27x +  +  +  +  +  +  +  +  +  +27x +  +  +27x +  +27x +  +15x +15x +  +  +15x +  +  +  +  +  +  +  +  +  +15x +  +15x +  +  +  +  +  +  +12x +12x +12x +  +  +12x +  +  +  +  +  +  +  +  +  +  +12x +  +  +12x +  +12x +  +  +  +  +  +  +  +  +27x +  +  +23x +  +  +  +  +  +  +  +14x +  +  +  +14x +  +  +  +  +  +  +  +  +  +  +  +11x +  +  +11x +3x +3x +  +  +  +  +  +  +  +  +11x +3x +  +  +  +  +  +  +  +  +  +11x +  +11x +  +  +  +  +11x +  +  + 
/**
+ * Default Coordination Manager - Adapter Implementation
+ *
+ * Implements CoordinationManager interface with in-memory merge queue
+ * and dependency-ordered merging.
+ *
+ * This is the ADAPTER for the CoordinationManager PORT.
+ */
+ 
+import type {
+  EventBus,
+  MergeQueuedEvent,
+  MergeStartedEvent,
+  MergeCompletedEvent,
+  MergeConflictedEvent,
+} from '../events/index.js';
+import type { WorktreeManager } from '../git/types.js';
+import type { TaskRepository } from '../db/repositories/task-repository.js';
+import type { AgentRepository } from '../db/repositories/agent-repository.js';
+import type { MessageRepository } from '../db/repositories/message-repository.js';
+import type { CoordinationManager, MergeQueueItem, MergeResult } from './types.js';
+import type { ConflictResolutionService } from './conflict-resolution-service.js';
+import { DefaultConflictResolutionService } from './conflict-resolution-service.js';
+ 
+// =============================================================================
+// Internal Types
+// =============================================================================
+ 
+/**
+ * Internal representation of a merge queue item with status.
+ */
+interface InternalMergeQueueItem extends MergeQueueItem {
+  status: 'queued' | 'in_progress';
+}
+ 
+// =============================================================================
+// DefaultCoordinationManager Implementation
+// =============================================================================
+ 
+/**
+ * In-memory implementation of CoordinationManager.
+ *
+ * Uses Map for queue management and processes merges in dependency order.
+ * Handles conflicts by creating resolution tasks.
+ */
+export class DefaultCoordinationManager implements CoordinationManager {
+  /** Internal merge queue */
+  private mergeQueue: Map<string, InternalMergeQueueItem> = new Map();
+ 
+  /** Task IDs that have been successfully merged */
+  private mergedTasks: Set<string> = new Set();
+ 
+  /** Tasks with conflicts awaiting resolution */
+  private conflictedTasks: Map<string, string[]> = new Map();
+ 
+  /** Service for handling merge conflicts */
+  private conflictResolutionService?: ConflictResolutionService;
+ 
+  constructor(
+    private worktreeManager?: WorktreeManager,
+    private taskRepository?: TaskRepository,
+    private agentRepository?: AgentRepository,
+    private messageRepository?: MessageRepository,
+    private eventBus?: EventBus,
+    conflictResolutionService?: ConflictResolutionService
+  ) {
+    // Create default conflict resolution service if none provided
+    Iif (conflictResolutionService) {
+      this.conflictResolutionService = conflictResolutionService;
+    } else if (taskRepository && agentRepository) {
+      this.conflictResolutionService = new DefaultConflictResolutionService(
+        taskRepository,
+        agentRepository,
+        messageRepository,
+        eventBus
+      );
+    }
+  }
+ 
+  /**
+   * Queue a completed task for merge.
+   * Extracts agent/worktree information from the task.
+   */
+  async queueMerge(taskId: string): Promise<void> {
+    // Look up task to get dependencies
+    if (!this.taskRepository) {
+      throw new Error('TaskRepository not configured');
+    }
+ 
+    const task = await this.taskRepository.findById(taskId);
+    if (!task) {
+      throw new Error(`Task not found: ${taskId}`);
+    }
+ 
+    // Look up agent assigned to task to get worktreeId
+    if (!this.agentRepository) {
+      throw new Error('AgentRepository not configured');
+    }
+ 
+    const agent = await this.agentRepository.findByTaskId(taskId);
+    if (!agent) {
+      throw new Error(`No agent found for task: ${taskId}`);
+    }
+ 
+    // For now, dependsOn is empty - would need to query task_dependencies table
+    // to get actual dependencies
+    const dependsOn: string[] = [];
+ 
+    const queueItem: InternalMergeQueueItem = {
+      taskId,
+      agentId: agent.id,
+      worktreeId: agent.worktreeId,
+      priority: task.priority,
+      queuedAt: new Date(),
+      dependsOn,
+      status: 'queued',
+    };
+ 
+    this.mergeQueue.set(taskId, queueItem);
+ 
+    // Emit MergeQueuedEvent
+    const event: MergeQueuedEvent = {
+      type: 'merge:queued',
+      timestamp: new Date(),
+      payload: {
+        taskId,
+        agentId: agent.id,
+        worktreeId: agent.worktreeId,
+        priority: task.priority,
+      },
+    };
+    this.eventBus?.emit(event);
+  }
+ 
+  /**
+   * Get next task ready to merge.
+   * Returns task with all dependency tasks already merged.
+   */
+  async getNextMergeable(): Promise<MergeQueueItem | null> {
+    const queuedItems = Array.from(this.mergeQueue.values()).filter(
+      (item) => item.status === 'queued'
+    );
+ 
+    if (queuedItems.length === 0) {
+      return null;
+    }
+ 
+    // Filter to only items where ALL dependsOn tasks are in mergedTasks
+    const readyItems = queuedItems.filter((item) =>
+      item.dependsOn.every((depTaskId) => this.mergedTasks.has(depTaskId))
+    );
+ 
+    Iif (readyItems.length === 0) {
+      return null;
+    }
+ 
+    // Sort by priority (high > medium > low), then by queuedAt (oldest first)
+    const priorityOrder: Record<string, number> = { high: 0, medium: 1, low: 2 };
+ 
+    readyItems.sort((a, b) => {
+      const priorityDiff = priorityOrder[a.priority] - priorityOrder[b.priority];
+      if (priorityDiff !== 0) {
+        return priorityDiff;
+      }
+      return a.queuedAt.getTime() - b.queuedAt.getTime();
+    });
+ 
+    // Return as MergeQueueItem (without internal status)
+    const item = readyItems[0];
+    return {
+      taskId: item.taskId,
+      agentId: item.agentId,
+      worktreeId: item.worktreeId,
+      priority: item.priority,
+      queuedAt: item.queuedAt,
+      dependsOn: item.dependsOn,
+    };
+  }
+ 
+  /**
+   * Process all ready merges in dependency order.
+   * Merges each ready task into the target branch.
+   */
+  async processMerges(targetBranch: string): Promise<MergeResult[]> {
+    if (!this.worktreeManager) {
+      throw new Error('WorktreeManager not configured');
+    }
+ 
+    const results: MergeResult[] = [];
+ 
+    // Loop while there are mergeable items
+    let nextItem = await this.getNextMergeable();
+ 
+    while (nextItem) {
+      const queueItem = this.mergeQueue.get(nextItem.taskId)!;
+ 
+      // Mark as in_progress
+      queueItem.status = 'in_progress';
+ 
+      // Emit MergeStartedEvent
+      const startEvent: MergeStartedEvent = {
+        type: 'merge:started',
+        timestamp: new Date(),
+        payload: {
+          taskId: nextItem.taskId,
+          agentId: nextItem.agentId,
+          worktreeId: nextItem.worktreeId,
+          targetBranch,
+        },
+      };
+      this.eventBus?.emit(startEvent);
+ 
+      // Attempt merge via worktreeManager
+      const mergeResult = await this.worktreeManager.merge(nextItem.worktreeId, targetBranch);
+ 
+      if (mergeResult.success) {
+        // Success - add to mergedTasks and remove from queue
+        this.mergedTasks.add(nextItem.taskId);
+        this.mergeQueue.delete(nextItem.taskId);
+ 
+        // Emit MergeCompletedEvent
+        const completedEvent: MergeCompletedEvent = {
+          type: 'merge:completed',
+          timestamp: new Date(),
+          payload: {
+            taskId: nextItem.taskId,
+            agentId: nextItem.agentId,
+            worktreeId: nextItem.worktreeId,
+            targetBranch,
+          },
+        };
+        this.eventBus?.emit(completedEvent);
+ 
+        results.push({
+          taskId: nextItem.taskId,
+          success: true,
+          message: mergeResult.message,
+        });
+      } else {
+        // Conflict - add to conflictedTasks and remove from queue
+        const conflicts = mergeResult.conflicts || [];
+        this.conflictedTasks.set(nextItem.taskId, conflicts);
+        this.mergeQueue.delete(nextItem.taskId);
+ 
+        // Emit MergeConflictedEvent
+        const conflictEvent: MergeConflictedEvent = {
+          type: 'merge:conflicted',
+          timestamp: new Date(),
+          payload: {
+            taskId: nextItem.taskId,
+            agentId: nextItem.agentId,
+            worktreeId: nextItem.worktreeId,
+            targetBranch,
+            conflictingFiles: conflicts,
+          },
+        };
+        this.eventBus?.emit(conflictEvent);
+ 
+        // Handle conflict - create resolution task
+        await this.handleConflict(nextItem.taskId, conflicts);
+ 
+        results.push({
+          taskId: nextItem.taskId,
+          success: false,
+          conflicts,
+          message: mergeResult.message,
+        });
+      }
+ 
+      // Get next item
+      nextItem = await this.getNextMergeable();
+    }
+ 
+    return results;
+  }
+ 
+  /**
+   * Handle a merge conflict.
+   * Delegates to the ConflictResolutionService.
+   */
+  async handleConflict(taskId: string, conflicts: string[]): Promise<void> {
+    Iif (!this.conflictResolutionService) {
+      throw new Error('ConflictResolutionService not configured');
+    }
+ 
+    await this.conflictResolutionService.handleConflict(taskId, conflicts);
+  }
+ 
+  /**
+   * Get current state of the merge queue.
+   */
+  async getQueueState(): Promise<{
+    queued: MergeQueueItem[];
+    inProgress: MergeQueueItem[];
+    merged: string[];
+    conflicted: Array<{ taskId: string; conflicts: string[] }>;
+  }> {
+    const allItems = Array.from(this.mergeQueue.values());
+ 
+    // Filter by status
+    const queued = allItems
+      .filter((item) => item.status === 'queued')
+      .map((item) => ({
+        taskId: item.taskId,
+        agentId: item.agentId,
+        worktreeId: item.worktreeId,
+        priority: item.priority,
+        queuedAt: item.queuedAt,
+        dependsOn: item.dependsOn,
+      }));
+ 
+    const inProgress = allItems
+      .filter((item) => item.status === 'in_progress')
+      .map((item) => ({
+        taskId: item.taskId,
+        agentId: item.agentId,
+        worktreeId: item.worktreeId,
+        priority: item.priority,
+        queuedAt: item.queuedAt,
+        dependsOn: item.dependsOn,
+      }));
+ 
+    const merged = Array.from(this.mergedTasks);
+ 
+    const conflicted = Array.from(this.conflictedTasks.entries()).map(([taskId, conflicts]) => ({
+      taskId,
+      conflicts,
+    }));
+ 
+    return { queued, inProgress, merged, conflicted };
+  }
+}
+ 
+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/coverage/src/db/config.ts.html b/coverage/src/db/config.ts.html new file mode 100644 index 0000000..71ffb6f --- /dev/null +++ b/coverage/src/db/config.ts.html @@ -0,0 +1,205 @@ + + + + + + Code coverage report for src/db/config.ts + + + + + + + + + +
+
+

All files / src/db config.ts

+
+ +
+ 0% + Statements + 0/11 +
+ + +
+ 0% + Branches + 0/6 +
+ + +
+ 0% + Functions + 0/2 +
+ + +
+ 0% + Lines + 0/11 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+

+
1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 +30 +31 +32 +33 +34 +35 +36 +37 +38 +39 +40 +41  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  + 
import { mkdirSync } from 'node:fs';
+import { dirname, join } from 'node:path';
+import { findWorkspaceRoot } from '../config/cwrc.js';
+ 
+/**
+ * Get the database path.
+ *
+ * - Default: <workspace-root>/.cw/cw.db
+ * - Throws if no .cwrc workspace is found
+ * - Override via CW_DB_PATH environment variable
+ * - For testing, pass ':memory:' as CW_DB_PATH
+ */
+export function getDbPath(): string {
+  const envPath = process.env.CW_DB_PATH;
+  if (envPath) {
+    return envPath;
+  }
+ 
+  const root = findWorkspaceRoot();
+  if (!root) {
+    throw new Error(
+      'No .cwrc workspace found. Run `cw init` to initialize a workspace.',
+    );
+  }
+  return join(root, '.cw', 'cw.db');
+}
+ 
+/**
+ * Ensure the parent directory for the database file exists.
+ * No-op for in-memory databases.
+ */
+export function ensureDbDirectory(dbPath: string): void {
+  // Skip for in-memory database
+  if (dbPath === ':memory:') {
+    return;
+  }
+ 
+  const dir = dirname(dbPath);
+  mkdirSync(dir, { recursive: true });
+}
+ 
+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/coverage/src/db/ensure-schema.ts.html b/coverage/src/db/ensure-schema.ts.html new file mode 100644 index 0000000..67d03ac --- /dev/null +++ b/coverage/src/db/ensure-schema.ts.html @@ -0,0 +1,199 @@ + + + + + + Code coverage report for src/db/ensure-schema.ts + + + + + + + + + +
+
+

All files / src/db ensure-schema.ts

+
+ +
+ 100% + Statements + 6/6 +
+ + +
+ 100% + Branches + 0/0 +
+ + +
+ 100% + Functions + 2/2 +
+ + +
+ 100% + Lines + 6/6 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+

+
1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 +30 +31 +32 +33 +34 +35 +36 +37 +38 +39  +  +  +  +  +  +  +  +  +  +  +  +  +24x +  +  +  +  +  +  +239x +  +239x +  +  +  +  +  +  +  +  +  +  +  +239x +239x +239x +  + 
/**
+ * Database Migration
+ *
+ * Runs drizzle-kit migrations from the drizzle/ directory.
+ * Safe to call on every startup - only applies pending migrations.
+ */
+ 
+import { migrate } from 'drizzle-orm/better-sqlite3/migrator';
+import { join, dirname } from 'node:path';
+import { fileURLToPath } from 'node:url';
+import type { DrizzleDatabase } from './index.js';
+import { createModuleLogger } from '../logger/index.js';
+ 
+const log = createModuleLogger('db');
+ 
+/**
+ * Resolve the migrations directory relative to the package root.
+ * Works both in development (src/) and after build (dist/).
+ */
+function getMigrationsPath(): string {
+  const currentDir = dirname(fileURLToPath(import.meta.url));
+  // From src/db/ or dist/db/, go up two levels to package root, then into drizzle/
+  return join(currentDir, '..', '..', 'drizzle');
+}
+ 
+/**
+ * Run all pending database migrations.
+ *
+ * Uses drizzle-kit's migration system which tracks applied migrations
+ * in a __drizzle_migrations table. Safe to call on every startup.
+ *
+ * @param db - Drizzle database instance
+ */
+export function ensureSchema(db: DrizzleDatabase): void {
+  log.info('applying database migrations');
+  migrate(db, { migrationsFolder: getMigrationsPath() });
+  log.info('database migrations complete');
+}
+ 
+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/coverage/src/db/index.html b/coverage/src/db/index.html new file mode 100644 index 0000000..fecd50e --- /dev/null +++ b/coverage/src/db/index.html @@ -0,0 +1,161 @@ + + + + + + Code coverage report for src/db + + + + + + + + + +
+
+

All files src/db

+
+ +
+ 55.2% + Statements + 53/96 +
+ + +
+ 0% + Branches + 0/8 +
+ + +
+ 40.81% + Functions + 20/49 +
+ + +
+ 48.19% + Lines + 40/83 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
FileStatementsBranchesFunctionsLines
config.ts +
+
0%0/110%0/60%0/20%0/11
ensure-schema.ts +
+
100%6/6100%0/0100%2/2100%6/6
index.ts +
+
0%0/60%0/20%0/10%0/6
schema.ts +
+
64.38%47/73100%0/040.9%18/4456.66%34/60
+
+
+
+ + + + + + + + \ No newline at end of file diff --git a/coverage/src/db/index.ts.html b/coverage/src/db/index.ts.html new file mode 100644 index 0000000..db9e615 --- /dev/null +++ b/coverage/src/db/index.ts.html @@ -0,0 +1,241 @@ + + + + + + Code coverage report for src/db/index.ts + + + + + + + + + +
+
+

All files / src/db index.ts

+
+ +
+ 0% + Statements + 0/6 +
+ + +
+ 0% + Branches + 0/2 +
+ + +
+ 0% + Functions + 0/1 +
+ + +
+ 0% + Lines + 0/6 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+

+
1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 +30 +31 +32 +33 +34 +35 +36 +37 +38 +39 +40 +41 +42 +43 +44 +45 +46 +47 +48 +49 +50 +51 +52 +53  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  + 
import Database from 'better-sqlite3';
+import { drizzle } from 'drizzle-orm/better-sqlite3';
+import type { BetterSQLite3Database } from 'drizzle-orm/better-sqlite3';
+ 
+import { getDbPath, ensureDbDirectory } from './config.js';
+import * as schema from './schema.js';
+ 
+export type DrizzleDatabase = BetterSQLite3Database<typeof schema>;
+ 
+/**
+ * Create a new database connection.
+ *
+ * This is a factory function (not a singleton) to allow multiple instances
+ * for testing with isolated databases.
+ *
+ * @param path - Optional path override. Defaults to getDbPath().
+ *               Use ':memory:' for in-memory testing database.
+ * @returns Drizzle database instance with schema
+ */
+export function createDatabase(path?: string): DrizzleDatabase {
+  const dbPath = path ?? getDbPath();
+ 
+  // Ensure directory exists for file-based databases
+  ensureDbDirectory(dbPath);
+ 
+  // Create SQLite connection
+  const sqlite = new Database(dbPath);
+ 
+  // Enable WAL mode for better concurrent read performance
+  sqlite.pragma('journal_mode = WAL');
+ 
+  // Enable foreign keys (SQLite has them disabled by default)
+  sqlite.pragma('foreign_keys = ON');
+ 
+  // Create Drizzle instance with schema
+  return drizzle(sqlite, { schema });
+}
+ 
+// Re-export config utilities
+export { getDbPath, ensureDbDirectory } from './config.js';
+ 
+// Re-export schema initialization
+export { ensureSchema } from './ensure-schema.js';
+ 
+// Re-export schema and types
+export * from './schema.js';
+ 
+// Re-export repository interfaces (ports)
+export * from './repositories/index.js';
+ 
+// Re-export Drizzle adapters
+export * from './repositories/drizzle/index.js';
+ 
+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/coverage/src/db/repositories/drizzle/account.ts.html b/coverage/src/db/repositories/drizzle/account.ts.html new file mode 100644 index 0000000..a09dce7 --- /dev/null +++ b/coverage/src/db/repositories/drizzle/account.ts.html @@ -0,0 +1,694 @@ + + + + + + Code coverage report for src/db/repositories/drizzle/account.ts + + + + + + + + + +
+
+

All files / src/db/repositories/drizzle account.ts

+
+ +
+ 2.17% + Statements + 1/46 +
+ + +
+ 0% + Branches + 0/24 +
+ + +
+ 7.14% + Functions + 1/14 +
+ + +
+ 2.17% + Lines + 1/46 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+

+
1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 +30 +31 +32 +33 +34 +35 +36 +37 +38 +39 +40 +41 +42 +43 +44 +45 +46 +47 +48 +49 +50 +51 +52 +53 +54 +55 +56 +57 +58 +59 +60 +61 +62 +63 +64 +65 +66 +67 +68 +69 +70 +71 +72 +73 +74 +75 +76 +77 +78 +79 +80 +81 +82 +83 +84 +85 +86 +87 +88 +89 +90 +91 +92 +93 +94 +95 +96 +97 +98 +99 +100 +101 +102 +103 +104 +105 +106 +107 +108 +109 +110 +111 +112 +113 +114 +115 +116 +117 +118 +119 +120 +121 +122 +123 +124 +125 +126 +127 +128 +129 +130 +131 +132 +133 +134 +135 +136 +137 +138 +139 +140 +141 +142 +143 +144 +145 +146 +147 +148 +149 +150 +151 +152 +153 +154 +155 +156 +157 +158 +159 +160 +161 +162 +163 +164 +165 +166 +167 +168 +169 +170 +171 +172 +173 +174 +175 +176 +177 +178 +179 +180 +181 +182 +183 +184 +185 +186 +187 +188 +189 +190 +191 +192 +193 +194 +195 +196 +197 +198 +199 +200 +201 +202 +203 +204  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +80x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  + 
/**
+ * Drizzle Account Repository Adapter
+ *
+ * Implements AccountRepository interface using Drizzle ORM.
+ * Handles round-robin selection via lastUsedAt ordering
+ * and automatic exhaustion expiry.
+ */
+ 
+import { eq, and, asc, lte } from 'drizzle-orm';
+import { nanoid } from 'nanoid';
+import type { DrizzleDatabase } from '../../index.js';
+import { accounts, agents, type Account } from '../../schema.js';
+import type { AccountRepository, CreateAccountData } from '../account-repository.js';
+ 
+export class DrizzleAccountRepository implements AccountRepository {
+  constructor(private db: DrizzleDatabase) {}
+ 
+  async create(data: CreateAccountData): Promise<Account> {
+    const id = nanoid();
+    const now = new Date();
+ 
+    const [created] = await this.db.insert(accounts).values({
+      id,
+      email: data.email,
+      provider: data.provider ?? 'claude',
+      configJson: data.configJson ?? null,
+      credentials: data.credentials ?? null,
+      isExhausted: false,
+      exhaustedUntil: null,
+      lastUsedAt: null,
+      sortOrder: 0,
+      createdAt: now,
+      updatedAt: now,
+    }).returning();
+ 
+    return created;
+  }
+ 
+  async findById(id: string): Promise<Account | null> {
+    const result = await this.db
+      .select()
+      .from(accounts)
+      .where(eq(accounts.id, id))
+      .limit(1);
+    return result[0] ?? null;
+  }
+ 
+  async findByEmail(email: string): Promise<Account | null> {
+    const result = await this.db
+      .select()
+      .from(accounts)
+      .where(eq(accounts.email, email))
+      .limit(1);
+    return result[0] ?? null;
+  }
+ 
+  async findByProvider(provider: string): Promise<Account[]> {
+    return this.db
+      .select()
+      .from(accounts)
+      .where(eq(accounts.provider, provider));
+  }
+ 
+  async findNextAvailable(provider: string): Promise<Account | null> {
+    await this.clearExpiredExhaustion();
+ 
+    const result = await this.db
+      .select()
+      .from(accounts)
+      .where(
+        and(
+          eq(accounts.provider, provider),
+          eq(accounts.isExhausted, false),
+        ),
+      )
+      .orderBy(asc(accounts.lastUsedAt))
+      .limit(1);
+ 
+    return result[0] ?? null;
+  }
+ 
+  async markExhausted(id: string, until: Date): Promise<Account> {
+    const now = new Date();
+    const [updated] = await this.db
+      .update(accounts)
+      .set({
+        isExhausted: true,
+        exhaustedUntil: until,
+        updatedAt: now,
+      })
+      .where(eq(accounts.id, id))
+      .returning();
+ 
+    if (!updated) {
+      throw new Error(`Account not found: ${id}`);
+    }
+ 
+    return updated;
+  }
+ 
+  async markAvailable(id: string): Promise<Account> {
+    const now = new Date();
+    const [updated] = await this.db
+      .update(accounts)
+      .set({
+        isExhausted: false,
+        exhaustedUntil: null,
+        updatedAt: now,
+      })
+      .where(eq(accounts.id, id))
+      .returning();
+ 
+    if (!updated) {
+      throw new Error(`Account not found: ${id}`);
+    }
+ 
+    return updated;
+  }
+ 
+  async updateLastUsed(id: string): Promise<Account> {
+    const now = new Date();
+    const [updated] = await this.db
+      .update(accounts)
+      .set({ lastUsedAt: now, updatedAt: now })
+      .where(eq(accounts.id, id))
+      .returning();
+ 
+    if (!updated) {
+      throw new Error(`Account not found: ${id}`);
+    }
+ 
+    return updated;
+  }
+ 
+  async clearExpiredExhaustion(): Promise<number> {
+    const now = new Date();
+ 
+    const cleared = await this.db
+      .update(accounts)
+      .set({
+        isExhausted: false,
+        exhaustedUntil: null,
+        updatedAt: now,
+      })
+      .where(
+        and(
+          eq(accounts.isExhausted, true),
+          lte(accounts.exhaustedUntil, now),
+        ),
+      )
+      .returning({ id: accounts.id });
+ 
+    return cleared.length;
+  }
+ 
+  async findAll(): Promise<Account[]> {
+    return this.db.select().from(accounts);
+  }
+ 
+  async updateCredentials(id: string, credentials: string): Promise<Account> {
+    const now = new Date();
+    const [updated] = await this.db
+      .update(accounts)
+      .set({ credentials, updatedAt: now })
+      .where(eq(accounts.id, id))
+      .returning();
+ 
+    if (!updated) {
+      throw new Error(`Account not found: ${id}`);
+    }
+ 
+    return updated;
+  }
+ 
+  async updateAccountAuth(id: string, configJson: string, credentials: string): Promise<Account> {
+    const now = new Date();
+    const [updated] = await this.db
+      .update(accounts)
+      .set({ configJson, credentials, updatedAt: now })
+      .where(eq(accounts.id, id))
+      .returning();
+ 
+    if (!updated) {
+      throw new Error(`Account not found: ${id}`);
+    }
+ 
+    return updated;
+  }
+ 
+  async delete(id: string): Promise<void> {
+    // Manually nullify agent FK — the migration lacks ON DELETE SET NULL
+    await this.db
+      .update(agents)
+      .set({ accountId: null })
+      .where(eq(agents.accountId, id));
+ 
+    const [deleted] = await this.db.delete(accounts).where(eq(accounts.id, id)).returning();
+ 
+    if (!deleted) {
+      throw new Error(`Account not found: ${id}`);
+    }
+  }
+}
+ 
+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/coverage/src/db/repositories/drizzle/agent.ts.html b/coverage/src/db/repositories/drizzle/agent.ts.html new file mode 100644 index 0000000..62857c7 --- /dev/null +++ b/coverage/src/db/repositories/drizzle/agent.ts.html @@ -0,0 +1,442 @@ + + + + + + Code coverage report for src/db/repositories/drizzle/agent.ts + + + + + + + + + +
+
+

All files / src/db/repositories/drizzle agent.ts

+
+ +
+ 100% + Statements + 23/23 +
+ + +
+ 100% + Branches + 26/26 +
+ + +
+ 100% + Functions + 10/10 +
+ + +
+ 100% + Lines + 23/23 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+

+
1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 +30 +31 +32 +33 +34 +35 +36 +37 +38 +39 +40 +41 +42 +43 +44 +45 +46 +47 +48 +49 +50 +51 +52 +53 +54 +55 +56 +57 +58 +59 +60 +61 +62 +63 +64 +65 +66 +67 +68 +69 +70 +71 +72 +73 +74 +75 +76 +77 +78 +79 +80 +81 +82 +83 +84 +85 +86 +87 +88 +89 +90 +91 +92 +93 +94 +95 +96 +97 +98 +99 +100 +101 +102 +103 +104 +105 +106 +107 +108 +109 +110 +111 +112 +113 +114 +115 +116 +117 +118 +119 +120  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +156x +  +  +89x +89x +  +89x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +88x +  +  +  +6x +  +  +  +  +  +6x +  +  +  +2x +  +  +  +  +  +2x +  +  +  +61x +  +  +  +  +  +61x +  +  +  +2x +  +  +  +  +  +2x +  +  +  +2x +  +  +  +4x +  +  +  +6x +6x +  +  +  +  +  +6x +1x +  +  +5x +  +  +  +2x +  +2x +1x +  +  +  + 
/**
+ * Drizzle Agent Repository Adapter
+ *
+ * Implements AgentRepository interface using Drizzle ORM.
+ */
+ 
+import { eq } from 'drizzle-orm';
+import { nanoid } from 'nanoid';
+import type { DrizzleDatabase } from '../../index.js';
+import { agents, type Agent } from '../../schema.js';
+import type {
+  AgentRepository,
+  AgentStatus,
+  CreateAgentData,
+  UpdateAgentData,
+} from '../agent-repository.js';
+ 
+/**
+ * Drizzle adapter for AgentRepository.
+ *
+ * Uses dependency injection for database instance,
+ * enabling isolated test databases.
+ */
+export class DrizzleAgentRepository implements AgentRepository {
+  constructor(private db: DrizzleDatabase) {}
+ 
+  async create(data: CreateAgentData): Promise<Agent> {
+    const id = nanoid();
+    const now = new Date();
+ 
+    const [created] = await this.db.insert(agents).values({
+      id,
+      name: data.name,
+      taskId: data.taskId ?? null,
+      initiativeId: data.initiativeId ?? null,
+      sessionId: data.sessionId ?? null,
+      worktreeId: data.worktreeId,
+      provider: data.provider ?? 'claude',
+      accountId: data.accountId ?? null,
+      status: data.status ?? 'idle',
+      mode: data.mode ?? 'execute',
+      createdAt: now,
+      updatedAt: now,
+    }).returning();
+ 
+    return created;
+  }
+ 
+  async findById(id: string): Promise<Agent | null> {
+    const result = await this.db
+      .select()
+      .from(agents)
+      .where(eq(agents.id, id))
+      .limit(1);
+ 
+    return result[0] ?? null;
+  }
+ 
+  async findByName(name: string): Promise<Agent | null> {
+    const result = await this.db
+      .select()
+      .from(agents)
+      .where(eq(agents.name, name))
+      .limit(1);
+ 
+    return result[0] ?? null;
+  }
+ 
+  async findByTaskId(taskId: string): Promise<Agent | null> {
+    const result = await this.db
+      .select()
+      .from(agents)
+      .where(eq(agents.taskId, taskId))
+      .limit(1);
+ 
+    return result[0] ?? null;
+  }
+ 
+  async findBySessionId(sessionId: string): Promise<Agent | null> {
+    const result = await this.db
+      .select()
+      .from(agents)
+      .where(eq(agents.sessionId, sessionId))
+      .limit(1);
+ 
+    return result[0] ?? null;
+  }
+ 
+  async findAll(): Promise<Agent[]> {
+    return this.db.select().from(agents);
+  }
+ 
+  async findByStatus(status: AgentStatus): Promise<Agent[]> {
+    return this.db.select().from(agents).where(eq(agents.status, status));
+  }
+ 
+  async update(id: string, data: UpdateAgentData): Promise<Agent> {
+    const now = new Date();
+    const [updated] = await this.db
+      .update(agents)
+      .set({ ...data, updatedAt: now })
+      .where(eq(agents.id, id))
+      .returning();
+ 
+    if (!updated) {
+      throw new Error(`Agent not found: ${id}`);
+    }
+ 
+    return updated;
+  }
+ 
+  async delete(id: string): Promise<void> {
+    const [deleted] = await this.db.delete(agents).where(eq(agents.id, id)).returning();
+ 
+    if (!deleted) {
+      throw new Error(`Agent not found: ${id}`);
+    }
+  }
+}
+ 
+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/coverage/src/db/repositories/drizzle/change-set.ts.html b/coverage/src/db/repositories/drizzle/change-set.ts.html new file mode 100644 index 0000000..6776e22 --- /dev/null +++ b/coverage/src/db/repositories/drizzle/change-set.ts.html @@ -0,0 +1,415 @@ + + + + + + Code coverage report for src/db/repositories/drizzle/change-set.ts + + + + + + + + + +
+
+

All files / src/db/repositories/drizzle change-set.ts

+
+ +
+ 13.04% + Statements + 3/23 +
+ + +
+ 12.5% + Branches + 2/16 +
+ + +
+ 22.22% + Functions + 2/9 +
+ + +
+ 14.28% + Lines + 3/21 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+

+
1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 +30 +31 +32 +33 +34 +35 +36 +37 +38 +39 +40 +41 +42 +43 +44 +45 +46 +47 +48 +49 +50 +51 +52 +53 +54 +55 +56 +57 +58 +59 +60 +61 +62 +63 +64 +65 +66 +67 +68 +69 +70 +71 +72 +73 +74 +75 +76 +77 +78 +79 +80 +81 +82 +83 +84 +85 +86 +87 +88 +89 +90 +91 +92 +93 +94 +95 +96 +97 +98 +99 +100 +101 +102 +103 +104 +105 +106 +107 +108 +109 +110 +111  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +84x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +6x +  +  +  +  +  +6x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  + 
/**
+ * Drizzle Change Set Repository Adapter
+ *
+ * Implements ChangeSetRepository interface using Drizzle ORM.
+ */
+ 
+import { eq, desc, asc } from 'drizzle-orm';
+import { nanoid } from 'nanoid';
+import type { DrizzleDatabase } from '../../index.js';
+import { changeSets, changeSetEntries, type ChangeSet } from '../../schema.js';
+import type {
+  ChangeSetRepository,
+  CreateChangeSetData,
+  CreateChangeSetEntryData,
+  ChangeSetWithEntries,
+} from '../change-set-repository.js';
+ 
+export class DrizzleChangeSetRepository implements ChangeSetRepository {
+  constructor(private db: DrizzleDatabase) {}
+ 
+  async createWithEntries(data: CreateChangeSetData, entries: CreateChangeSetEntryData[]): Promise<ChangeSet> {
+    const id = nanoid();
+    const now = new Date();
+ 
+    // Use transaction for atomicity
+    return this.db.transaction(async (tx) => {
+      const [created] = await tx.insert(changeSets).values({
+        id,
+        agentId: data.agentId,
+        agentName: data.agentName,
+        initiativeId: data.initiativeId,
+        mode: data.mode,
+        summary: data.summary ?? null,
+        status: 'applied',
+        createdAt: now,
+      }).returning();
+ 
+      if (entries.length > 0) {
+        const entryRows = entries.map((e, i) => ({
+          id: nanoid(),
+          changeSetId: id,
+          entityType: e.entityType,
+          entityId: e.entityId,
+          action: e.action,
+          previousState: e.previousState ?? null,
+          newState: e.newState ?? null,
+          sortOrder: e.sortOrder ?? i,
+          createdAt: now,
+        }));
+ 
+        await tx.insert(changeSetEntries).values(entryRows);
+      }
+ 
+      return created;
+    });
+  }
+ 
+  async findById(id: string): Promise<ChangeSet | null> {
+    const result = await this.db
+      .select()
+      .from(changeSets)
+      .where(eq(changeSets.id, id))
+      .limit(1);
+ 
+    return result[0] ?? null;
+  }
+ 
+  async findByIdWithEntries(id: string): Promise<ChangeSetWithEntries | null> {
+    const cs = await this.findById(id);
+    if (!cs) return null;
+ 
+    const entries = await this.db
+      .select()
+      .from(changeSetEntries)
+      .where(eq(changeSetEntries.changeSetId, id))
+      .orderBy(asc(changeSetEntries.sortOrder));
+ 
+    return { ...cs, entries };
+  }
+ 
+  async findByInitiativeId(initiativeId: string): Promise<ChangeSet[]> {
+    return this.db
+      .select()
+      .from(changeSets)
+      .where(eq(changeSets.initiativeId, initiativeId))
+      .orderBy(desc(changeSets.createdAt));
+  }
+ 
+  async findByAgentId(agentId: string): Promise<ChangeSet[]> {
+    return this.db
+      .select()
+      .from(changeSets)
+      .where(eq(changeSets.agentId, agentId))
+      .orderBy(desc(changeSets.createdAt));
+  }
+ 
+  async markReverted(id: string): Promise<ChangeSet> {
+    const [updated] = await this.db
+      .update(changeSets)
+      .set({ status: 'reverted', revertedAt: new Date() })
+      .where(eq(changeSets.id, id))
+      .returning();
+ 
+    if (!updated) {
+      throw new Error(`ChangeSet not found: ${id}`);
+    }
+ 
+    return updated;
+  }
+}
+ 
+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/coverage/src/db/repositories/drizzle/conversation.ts.html b/coverage/src/db/repositories/drizzle/conversation.ts.html new file mode 100644 index 0000000..2068f78 --- /dev/null +++ b/coverage/src/db/repositories/drizzle/conversation.ts.html @@ -0,0 +1,286 @@ + + + + + + Code coverage report for src/db/repositories/drizzle/conversation.ts + + + + + + + + + +
+
+

All files / src/db/repositories/drizzle conversation.ts

+
+ +
+ 70% + Statements + 7/10 +
+ + +
+ 75% + Branches + 6/8 +
+ + +
+ 60% + Functions + 3/5 +
+ + +
+ 70% + Lines + 7/10 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+

+
1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 +30 +31 +32 +33 +34 +35 +36 +37 +38 +39 +40 +41 +42 +43 +44 +45 +46 +47 +48 +49 +50 +51 +52 +53 +54 +55 +56 +57 +58 +59 +60 +61 +62 +63 +64 +65 +66 +67 +68  +  +  +  +  +  +  +  +  +  +  +  +  +84x +  +  +4x +4x +4x +  +  +  +  +  +  +  +  +  +  +  +4x +  +  +  +5x +  +  +  +  +5x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  + 
/**
+ * Drizzle Conversation Repository Adapter
+ *
+ * Implements ConversationRepository interface using Drizzle ORM.
+ */
+ 
+import { eq, and, asc } from 'drizzle-orm';
+import { nanoid } from 'nanoid';
+import type { DrizzleDatabase } from '../../index.js';
+import { conversations, type Conversation } from '../../schema.js';
+import type { ConversationRepository, CreateConversationData } from '../conversation-repository.js';
+ 
+export class DrizzleConversationRepository implements ConversationRepository {
+  constructor(private db: DrizzleDatabase) {}
+ 
+  async create(data: CreateConversationData): Promise<Conversation> {
+    const now = new Date();
+    const id = nanoid();
+    await this.db.insert(conversations).values({
+      id,
+      fromAgentId: data.fromAgentId,
+      toAgentId: data.toAgentId,
+      initiativeId: data.initiativeId ?? null,
+      phaseId: data.phaseId ?? null,
+      taskId: data.taskId ?? null,
+      question: data.question,
+      status: 'pending',
+      createdAt: now,
+      updatedAt: now,
+    });
+    return this.findById(id) as Promise<Conversation>;
+  }
+ 
+  async findById(id: string): Promise<Conversation | null> {
+    const rows = await this.db
+      .select()
+      .from(conversations)
+      .where(eq(conversations.id, id))
+      .limit(1);
+    return rows[0] ?? null;
+  }
+ 
+  async findPendingForAgent(toAgentId: string): Promise<Conversation[]> {
+    return this.db
+      .select()
+      .from(conversations)
+      .where(
+        and(
+          eq(conversations.toAgentId, toAgentId),
+          eq(conversations.status, 'pending' as 'pending' | 'answered'),
+        ),
+      )
+      .orderBy(asc(conversations.createdAt));
+  }
+ 
+  async answer(id: string, answer: string): Promise<Conversation | null> {
+    await this.db
+      .update(conversations)
+      .set({
+        answer,
+        status: 'answered' as 'pending' | 'answered',
+        updatedAt: new Date(),
+      })
+      .where(eq(conversations.id, id));
+    return this.findById(id);
+  }
+}
+ 
+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/coverage/src/db/repositories/drizzle/index.html b/coverage/src/db/repositories/drizzle/index.html new file mode 100644 index 0000000..3c06623 --- /dev/null +++ b/coverage/src/db/repositories/drizzle/index.html @@ -0,0 +1,296 @@ + + + + + + Code coverage report for src/db/repositories/drizzle + + + + + + + + + +
+
+

All files src/db/repositories/drizzle

+
+ +
+ 57.29% + Statements + 157/274 +
+ + +
+ 58.64% + Branches + 95/162 +
+ + +
+ 61.6% + Functions + 69/112 +
+ + +
+ 57.79% + Lines + 152/263 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
FileStatementsBranchesFunctionsLines
account.ts +
+
2.17%1/460%0/247.14%1/142.17%1/46
agent.ts +
+
100%23/23100%26/26100%10/10100%23/23
change-set.ts +
+
13.04%3/2312.5%2/1622.22%2/914.28%3/21
conversation.ts +
+
70%7/1075%6/860%3/570%7/10
index.ts +
+
0%0/00%0/00%0/00%0/0
initiative.ts +
+
100%17/17100%8/8100%7/7100%17/17
log-chunk.ts +
+
16.66%1/60%0/220%1/516.66%1/6
message.ts +
+
100%23/23100%22/22100%10/10100%23/23
page.ts +
+
28%7/2516.66%2/1230%3/1030.43%7/23
phase.ts +
+
96.29%26/27100%10/1092.3%12/1396%24/25
project.ts +
+
55.26%21/3825%3/1250%8/1655.88%19/34
task.ts +
+
74.19%23/3172.72%16/2291.66%11/1273.33%22/30
test-helpers.ts +
+
100%5/5100%0/0100%1/1100%5/5
+
+
+
+ + + + + + + + \ No newline at end of file diff --git a/coverage/src/db/repositories/drizzle/index.ts.html b/coverage/src/db/repositories/drizzle/index.ts.html new file mode 100644 index 0000000..46d9e1f --- /dev/null +++ b/coverage/src/db/repositories/drizzle/index.ts.html @@ -0,0 +1,139 @@ + + + + + + Code coverage report for src/db/repositories/drizzle/index.ts + + + + + + + + + +
+
+

All files / src/db/repositories/drizzle index.ts

+
+ +
+ 0% + Statements + 0/0 +
+ + +
+ 0% + Branches + 0/0 +
+ + +
+ 0% + Functions + 0/0 +
+ + +
+ 0% + Lines + 0/0 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+

+
1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  + 
/**
+ * Drizzle Repository Adapters
+ *
+ * Re-exports all Drizzle implementations of repository interfaces.
+ * These are the ADAPTERS for the repository PORTS.
+ */
+ 
+export { DrizzleInitiativeRepository } from './initiative.js';
+export { DrizzlePhaseRepository } from './phase.js';
+export { DrizzleTaskRepository } from './task.js';
+export { DrizzleAgentRepository } from './agent.js';
+export { DrizzleMessageRepository } from './message.js';
+export { DrizzlePageRepository } from './page.js';
+export { DrizzleProjectRepository } from './project.js';
+export { DrizzleAccountRepository } from './account.js';
+export { DrizzleChangeSetRepository } from './change-set.js';
+export { DrizzleLogChunkRepository } from './log-chunk.js';
+export { DrizzleConversationRepository } from './conversation.js';
+ 
+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/coverage/src/db/repositories/drizzle/initiative.ts.html b/coverage/src/db/repositories/drizzle/initiative.ts.html new file mode 100644 index 0000000..904efe7 --- /dev/null +++ b/coverage/src/db/repositories/drizzle/initiative.ts.html @@ -0,0 +1,346 @@ + + + + + + Code coverage report for src/db/repositories/drizzle/initiative.ts + + + + + + + + + +
+
+

All files / src/db/repositories/drizzle initiative.ts

+
+ +
+ 100% + Statements + 17/17 +
+ + +
+ 100% + Branches + 8/8 +
+ + +
+ 100% + Functions + 7/7 +
+ + +
+ 100% + Lines + 17/17 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+

+
1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 +30 +31 +32 +33 +34 +35 +36 +37 +38 +39 +40 +41 +42 +43 +44 +45 +46 +47 +48 +49 +50 +51 +52 +53 +54 +55 +56 +57 +58 +59 +60 +61 +62 +63 +64 +65 +66 +67 +68 +69 +70 +71 +72 +73 +74 +75 +76 +77 +78 +79 +80 +81 +82 +83 +84 +85 +86 +87 +88  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +287x +  +  +236x +236x +  +236x +  +  +  +  +  +  +  +236x +  +  +  +27x +  +  +  +  +  +27x +  +  +  +2x +  +  +  +4x +  +  +  +  +  +  +2x +  +  +  +  +  +2x +1x +  +  +1x +  +  +  +  +  +4x +  +4x +  +4x +1x +  +  +  + 
/**
+ * Drizzle Initiative Repository Adapter
+ *
+ * Implements InitiativeRepository interface using Drizzle ORM.
+ */
+ 
+import { eq } from 'drizzle-orm';
+import { nanoid } from 'nanoid';
+import type { DrizzleDatabase } from '../../index.js';
+import { agents, initiatives, type Initiative } from '../../schema.js';
+import type {
+  InitiativeRepository,
+  CreateInitiativeData,
+  UpdateInitiativeData,
+} from '../initiative-repository.js';
+ 
+/**
+ * Drizzle adapter for InitiativeRepository.
+ *
+ * Uses dependency injection for database instance,
+ * enabling isolated test databases.
+ */
+export class DrizzleInitiativeRepository implements InitiativeRepository {
+  constructor(private db: DrizzleDatabase) {}
+ 
+  async create(data: CreateInitiativeData): Promise<Initiative> {
+    const id = nanoid();
+    const now = new Date();
+ 
+    const [created] = await this.db.insert(initiatives).values({
+      id,
+      ...data,
+      status: data.status ?? 'active',
+      createdAt: now,
+      updatedAt: now,
+    }).returning();
+ 
+    return created;
+  }
+ 
+  async findById(id: string): Promise<Initiative | null> {
+    const result = await this.db
+      .select()
+      .from(initiatives)
+      .where(eq(initiatives.id, id))
+      .limit(1);
+ 
+    return result[0] ?? null;
+  }
+ 
+  async findAll(): Promise<Initiative[]> {
+    return this.db.select().from(initiatives);
+  }
+ 
+  async findByStatus(status: 'active' | 'completed' | 'archived'): Promise<Initiative[]> {
+    return this.db
+      .select()
+      .from(initiatives)
+      .where(eq(initiatives.status, status));
+  }
+ 
+  async update(id: string, data: UpdateInitiativeData): Promise<Initiative> {
+    const [updated] = await this.db
+      .update(initiatives)
+      .set({ ...data, updatedAt: new Date() })
+      .where(eq(initiatives.id, id))
+      .returning();
+ 
+    if (!updated) {
+      throw new Error(`Initiative not found: ${id}`);
+    }
+ 
+    return updated;
+  }
+ 
+  async delete(id: string): Promise<void> {
+    // Detach agents before deleting — agents.initiative_id FK may lack ON DELETE SET NULL
+    // in databases that haven't applied migration 0025 yet.
+    await this.db.update(agents).set({ initiativeId: null }).where(eq(agents.initiativeId, id));
+ 
+    const [deleted] = await this.db.delete(initiatives).where(eq(initiatives.id, id)).returning();
+ 
+    if (!deleted) {
+      throw new Error(`Initiative not found: ${id}`);
+    }
+  }
+}
+ 
+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/coverage/src/db/repositories/drizzle/log-chunk.ts.html b/coverage/src/db/repositories/drizzle/log-chunk.ts.html new file mode 100644 index 0000000..bb5e03f --- /dev/null +++ b/coverage/src/db/repositories/drizzle/log-chunk.ts.html @@ -0,0 +1,259 @@ + + + + + + Code coverage report for src/db/repositories/drizzle/log-chunk.ts + + + + + + + + + +
+
+

All files / src/db/repositories/drizzle log-chunk.ts

+
+ +
+ 16.66% + Statements + 1/6 +
+ + +
+ 0% + Branches + 0/2 +
+ + +
+ 20% + Functions + 1/5 +
+ + +
+ 16.66% + Lines + 1/6 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+

+
1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 +30 +31 +32 +33 +34 +35 +36 +37 +38 +39 +40 +41 +42 +43 +44 +45 +46 +47 +48 +49 +50 +51 +52 +53 +54 +55 +56 +57 +58 +59  +  +  +  +  +  +  +  +  +  +  +  +  +80x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  + 
/**
+ * Drizzle Log Chunk Repository Adapter
+ *
+ * Implements LogChunkRepository interface using Drizzle ORM.
+ */
+ 
+import { eq, asc, max } from 'drizzle-orm';
+import { nanoid } from 'nanoid';
+import type { DrizzleDatabase } from '../../index.js';
+import { agentLogChunks } from '../../schema.js';
+import type { LogChunkRepository } from '../log-chunk-repository.js';
+ 
+export class DrizzleLogChunkRepository implements LogChunkRepository {
+  constructor(private db: DrizzleDatabase) {}
+ 
+  async insertChunk(data: {
+    agentId: string;
+    agentName: string;
+    sessionNumber: number;
+    content: string;
+  }): Promise<void> {
+    await this.db.insert(agentLogChunks).values({
+      id: nanoid(),
+      agentId: data.agentId,
+      agentName: data.agentName,
+      sessionNumber: data.sessionNumber,
+      content: data.content,
+      createdAt: new Date(),
+    });
+  }
+ 
+  async findByAgentId(agentId: string): Promise<{ content: string; sessionNumber: number; createdAt: Date }[]> {
+    return this.db
+      .select({
+        content: agentLogChunks.content,
+        sessionNumber: agentLogChunks.sessionNumber,
+        createdAt: agentLogChunks.createdAt,
+      })
+      .from(agentLogChunks)
+      .where(eq(agentLogChunks.agentId, agentId))
+      .orderBy(asc(agentLogChunks.createdAt));
+  }
+ 
+  async deleteByAgentId(agentId: string): Promise<void> {
+    await this.db
+      .delete(agentLogChunks)
+      .where(eq(agentLogChunks.agentId, agentId));
+  }
+ 
+  async getSessionCount(agentId: string): Promise<number> {
+    const result = await this.db
+      .select({ maxSession: max(agentLogChunks.sessionNumber) })
+      .from(agentLogChunks)
+      .where(eq(agentLogChunks.agentId, agentId));
+ 
+    return result[0]?.maxSession ?? 0;
+  }
+}
+ 
+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/coverage/src/db/repositories/drizzle/message.ts.html b/coverage/src/db/repositories/drizzle/message.ts.html new file mode 100644 index 0000000..be238d5 --- /dev/null +++ b/coverage/src/db/repositories/drizzle/message.ts.html @@ -0,0 +1,499 @@ + + + + + + Code coverage report for src/db/repositories/drizzle/message.ts + + + + + + + + + +
+
+

All files / src/db/repositories/drizzle message.ts

+
+ +
+ 100% + Statements + 23/23 +
+ + +
+ 100% + Branches + 22/22 +
+ + +
+ 100% + Functions + 10/10 +
+ + +
+ 100% + Lines + 23/23 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+

+
1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 +30 +31 +32 +33 +34 +35 +36 +37 +38 +39 +40 +41 +42 +43 +44 +45 +46 +47 +48 +49 +50 +51 +52 +53 +54 +55 +56 +57 +58 +59 +60 +61 +62 +63 +64 +65 +66 +67 +68 +69 +70 +71 +72 +73 +74 +75 +76 +77 +78 +79 +80 +81 +82 +83 +84 +85 +86 +87 +88 +89 +90 +91 +92 +93 +94 +95 +96 +97 +98 +99 +100 +101 +102 +103 +104 +105 +106 +107 +108 +109 +110 +111 +112 +113 +114 +115 +116 +117 +118 +119 +120 +121 +122 +123 +124 +125 +126 +127 +128 +129 +130 +131 +132 +133 +134 +135 +136 +137 +138 +139  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +145x +  +  +46x +46x +  +46x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +46x +  +  +  +3x +  +  +  +  +  +3x +  +  +  +3x +2x +  +  +  +  +  +  +  +1x +  +  +  +  +  +  +  +5x +4x +  +  +  +  +  +  +  +1x +  +  +  +  +  +  +  +2x +  +  +  +  +  +  +  +2x +  +  +  +  +  +  +  +2x +  +  +  +  +  +  +  +6x +  +  +  +  +  +6x +1x +  +  +5x +  +  +  +2x +  +2x +1x +  +  +  + 
/**
+ * Drizzle Message Repository Adapter
+ *
+ * Implements MessageRepository interface using Drizzle ORM.
+ */
+ 
+import { eq, and, desc } from 'drizzle-orm';
+import { nanoid } from 'nanoid';
+import type { DrizzleDatabase } from '../../index.js';
+import { messages, type Message } from '../../schema.js';
+import type {
+  MessageRepository,
+  CreateMessageData,
+  UpdateMessageData,
+  MessageParticipantType,
+} from '../message-repository.js';
+ 
+/**
+ * Drizzle adapter for MessageRepository.
+ *
+ * Uses dependency injection for database instance,
+ * enabling isolated test databases.
+ */
+export class DrizzleMessageRepository implements MessageRepository {
+  constructor(private db: DrizzleDatabase) {}
+ 
+  async create(data: CreateMessageData): Promise<Message> {
+    const id = nanoid();
+    const now = new Date();
+ 
+    const [created] = await this.db.insert(messages).values({
+      id,
+      senderType: data.senderType,
+      senderId: data.senderId ?? null,
+      recipientType: data.recipientType,
+      recipientId: data.recipientId ?? null,
+      type: data.type ?? 'info',
+      content: data.content,
+      requiresResponse: data.requiresResponse ?? false,
+      status: data.status ?? 'pending',
+      parentMessageId: data.parentMessageId ?? null,
+      createdAt: now,
+      updatedAt: now,
+    }).returning();
+ 
+    return created;
+  }
+ 
+  async findById(id: string): Promise<Message | null> {
+    const result = await this.db
+      .select()
+      .from(messages)
+      .where(eq(messages.id, id))
+      .limit(1);
+ 
+    return result[0] ?? null;
+  }
+ 
+  async findBySender(type: MessageParticipantType, id?: string): Promise<Message[]> {
+    if (id) {
+      return this.db
+        .select()
+        .from(messages)
+        .where(and(eq(messages.senderType, type), eq(messages.senderId, id)))
+        .orderBy(desc(messages.createdAt));
+    }
+ 
+    // For user sender (no id), find where senderType='user' and senderId is null
+    return this.db
+      .select()
+      .from(messages)
+      .where(eq(messages.senderType, type))
+      .orderBy(desc(messages.createdAt));
+  }
+ 
+  async findByRecipient(type: MessageParticipantType, id?: string): Promise<Message[]> {
+    if (id) {
+      return this.db
+        .select()
+        .from(messages)
+        .where(and(eq(messages.recipientType, type), eq(messages.recipientId, id)))
+        .orderBy(desc(messages.createdAt));
+    }
+ 
+    // For user recipient (no id), find where recipientType='user' and recipientId is null
+    return this.db
+      .select()
+      .from(messages)
+      .where(eq(messages.recipientType, type))
+      .orderBy(desc(messages.createdAt));
+  }
+ 
+  async findPendingForUser(): Promise<Message[]> {
+    return this.db
+      .select()
+      .from(messages)
+      .where(and(eq(messages.recipientType, 'user'), eq(messages.status, 'pending')))
+      .orderBy(desc(messages.createdAt));
+  }
+ 
+  async findRequiringResponse(): Promise<Message[]> {
+    return this.db
+      .select()
+      .from(messages)
+      .where(and(eq(messages.requiresResponse, true), eq(messages.status, 'pending')))
+      .orderBy(desc(messages.createdAt));
+  }
+ 
+  async findReplies(parentMessageId: string): Promise<Message[]> {
+    return this.db
+      .select()
+      .from(messages)
+      .where(eq(messages.parentMessageId, parentMessageId))
+      .orderBy(desc(messages.createdAt));
+  }
+ 
+  async update(id: string, data: UpdateMessageData): Promise<Message> {
+    const [updated] = await this.db
+      .update(messages)
+      .set({ ...data, updatedAt: new Date() })
+      .where(eq(messages.id, id))
+      .returning();
+ 
+    if (!updated) {
+      throw new Error(`Message not found: ${id}`);
+    }
+ 
+    return updated;
+  }
+ 
+  async delete(id: string): Promise<void> {
+    const [deleted] = await this.db.delete(messages).where(eq(messages.id, id)).returning();
+ 
+    if (!deleted) {
+      throw new Error(`Message not found: ${id}`);
+    }
+  }
+}
+ 
+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/coverage/src/db/repositories/drizzle/page.ts.html b/coverage/src/db/repositories/drizzle/page.ts.html new file mode 100644 index 0000000..fd11901 --- /dev/null +++ b/coverage/src/db/repositories/drizzle/page.ts.html @@ -0,0 +1,436 @@ + + + + + + Code coverage report for src/db/repositories/drizzle/page.ts + + + + + + + + + +
+
+

All files / src/db/repositories/drizzle page.ts

+
+ +
+ 28% + Statements + 7/25 +
+ + +
+ 16.66% + Branches + 2/12 +
+ + +
+ 30% + Functions + 3/10 +
+ + +
+ 30.43% + Lines + 7/23 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+

+
1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 +30 +31 +32 +33 +34 +35 +36 +37 +38 +39 +40 +41 +42 +43 +44 +45 +46 +47 +48 +49 +50 +51 +52 +53 +54 +55 +56 +57 +58 +59 +60 +61 +62 +63 +64 +65 +66 +67 +68 +69 +70 +71 +72 +73 +74 +75 +76 +77 +78 +79 +80 +81 +82 +83 +84 +85 +86 +87 +88 +89 +90 +91 +92 +93 +94 +95 +96 +97 +98 +99 +100 +101 +102 +103 +104 +105 +106 +107 +108 +109 +110 +111 +112 +113 +114 +115 +116 +117 +118  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +84x +  +  +4x +4x +  +4x +  +  +  +  +  +  +4x +  +  +  +2x +  +  +  +  +  +2x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  + 
/**
+ * Drizzle Page Repository Adapter
+ *
+ * Implements PageRepository interface using Drizzle ORM.
+ */
+ 
+import { eq, isNull, and, asc, inArray } from 'drizzle-orm';
+import { nanoid } from 'nanoid';
+import type { DrizzleDatabase } from '../../index.js';
+import { pages, type Page } from '../../schema.js';
+import type {
+  PageRepository,
+  CreatePageData,
+  UpdatePageData,
+} from '../page-repository.js';
+ 
+export class DrizzlePageRepository implements PageRepository {
+  constructor(private db: DrizzleDatabase) {}
+ 
+  async create(data: CreatePageData): Promise<Page> {
+    const id = nanoid();
+    const now = new Date();
+ 
+    const [created] = await this.db.insert(pages).values({
+      id,
+      ...data,
+      createdAt: now,
+      updatedAt: now,
+    }).returning();
+ 
+    return created;
+  }
+ 
+  async findById(id: string): Promise<Page | null> {
+    const result = await this.db
+      .select()
+      .from(pages)
+      .where(eq(pages.id, id))
+      .limit(1);
+ 
+    return result[0] ?? null;
+  }
+ 
+  async findByIds(ids: string[]): Promise<Page[]> {
+    if (ids.length === 0) return [];
+    return this.db
+      .select()
+      .from(pages)
+      .where(inArray(pages.id, ids));
+  }
+ 
+  async findByInitiativeId(initiativeId: string): Promise<Page[]> {
+    return this.db
+      .select()
+      .from(pages)
+      .where(eq(pages.initiativeId, initiativeId))
+      .orderBy(asc(pages.sortOrder));
+  }
+ 
+  async findByParentPageId(parentPageId: string): Promise<Page[]> {
+    return this.db
+      .select()
+      .from(pages)
+      .where(eq(pages.parentPageId, parentPageId))
+      .orderBy(asc(pages.sortOrder));
+  }
+ 
+  async findRootPage(initiativeId: string): Promise<Page | null> {
+    const result = await this.db
+      .select()
+      .from(pages)
+      .where(
+        and(
+          eq(pages.initiativeId, initiativeId),
+          isNull(pages.parentPageId),
+        ),
+      )
+      .limit(1);
+ 
+    return result[0] ?? null;
+  }
+ 
+  async getOrCreateRootPage(initiativeId: string): Promise<Page> {
+    const existing = await this.findRootPage(initiativeId);
+    if (existing) return existing;
+ 
+    return this.create({
+      initiativeId,
+      parentPageId: null,
+      title: 'Untitled',
+      content: null,
+      sortOrder: 0,
+    });
+  }
+ 
+  async update(id: string, data: UpdatePageData): Promise<Page> {
+    const [updated] = await this.db
+      .update(pages)
+      .set({ ...data, updatedAt: new Date() })
+      .where(eq(pages.id, id))
+      .returning();
+ 
+    if (!updated) {
+      throw new Error(`Page not found: ${id}`);
+    }
+ 
+    return updated;
+  }
+ 
+  async delete(id: string): Promise<void> {
+    const [deleted] = await this.db.delete(pages).where(eq(pages.id, id)).returning();
+ 
+    if (!deleted) {
+      throw new Error(`Page not found: ${id}`);
+    }
+  }
+}
+ 
+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/coverage/src/db/repositories/drizzle/phase.ts.html b/coverage/src/db/repositories/drizzle/phase.ts.html new file mode 100644 index 0000000..faf7b81 --- /dev/null +++ b/coverage/src/db/repositories/drizzle/phase.ts.html @@ -0,0 +1,475 @@ + + + + + + Code coverage report for src/db/repositories/drizzle/phase.ts + + + + + + + + + +
+
+

All files / src/db/repositories/drizzle phase.ts

+
+ +
+ 96.29% + Statements + 26/27 +
+ + +
+ 100% + Branches + 10/10 +
+ + +
+ 92.3% + Functions + 12/13 +
+ + +
+ 96% + Lines + 24/25 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+

+
1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 +30 +31 +32 +33 +34 +35 +36 +37 +38 +39 +40 +41 +42 +43 +44 +45 +46 +47 +48 +49 +50 +51 +52 +53 +54 +55 +56 +57 +58 +59 +60 +61 +62 +63 +64 +65 +66 +67 +68 +69 +70 +71 +72 +73 +74 +75 +76 +77 +78 +79 +80 +81 +82 +83 +84 +85 +86 +87 +88 +89 +90 +91 +92 +93 +94 +95 +96 +97 +98 +99 +100 +101 +102 +103 +104 +105 +106 +107 +108 +109 +110 +111 +112 +113 +114 +115 +116 +117 +118 +119 +120 +121 +122 +123 +124 +125 +126 +127 +128 +129 +130 +131  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +275x +  +  +252x +252x +252x +  +252x +  +  +  +  +  +  +  +251x +  +  +  +154x +  +  +  +  +  +154x +  +  +  +20x +  +  +  +  +  +  +  +19x +  +  +  +  +  +  +  +65x +  +  +  +  +  +65x +1x +  +  +64x +  +  +  +3x +  +3x +1x +  +  +  +  +32x +32x +  +32x +  +  +  +  +  +  +  +  +38x +  +  +  +  +38x +  +  +  +3x +  +  +  +  +3x +  +  +  +  +  +  +  +  +  +  +  +  +  + 
/**
+ * Drizzle Phase Repository Adapter
+ *
+ * Implements PhaseRepository interface using Drizzle ORM.
+ */
+ 
+import { eq, asc, and } from 'drizzle-orm';
+import { nanoid } from 'nanoid';
+import type { DrizzleDatabase } from '../../index.js';
+import { phases, phaseDependencies, type Phase } from '../../schema.js';
+import type {
+  PhaseRepository,
+  CreatePhaseData,
+  UpdatePhaseData,
+} from '../phase-repository.js';
+ 
+/**
+ * Drizzle adapter for PhaseRepository.
+ *
+ * Uses dependency injection for database instance,
+ * enabling isolated test databases.
+ */
+export class DrizzlePhaseRepository implements PhaseRepository {
+  constructor(private db: DrizzleDatabase) {}
+ 
+  async create(data: CreatePhaseData): Promise<Phase> {
+    const { id: providedId, ...rest } = data;
+    const id = providedId ?? nanoid();
+    const now = new Date();
+ 
+    const [created] = await this.db.insert(phases).values({
+      id,
+      ...rest,
+      status: data.status ?? 'pending',
+      createdAt: now,
+      updatedAt: now,
+    }).returning();
+ 
+    return created;
+  }
+ 
+  async findById(id: string): Promise<Phase | null> {
+    const result = await this.db
+      .select()
+      .from(phases)
+      .where(eq(phases.id, id))
+      .limit(1);
+ 
+    return result[0] ?? null;
+  }
+ 
+  async findByInitiativeId(initiativeId: string): Promise<Phase[]> {
+    return this.db
+      .select()
+      .from(phases)
+      .where(eq(phases.initiativeId, initiativeId))
+      .orderBy(asc(phases.createdAt));
+  }
+ 
+  async findDependenciesByInitiativeId(initiativeId: string): Promise<Array<{ phaseId: string; dependsOnPhaseId: string }>> {
+    return this.db
+      .select({ phaseId: phaseDependencies.phaseId, dependsOnPhaseId: phaseDependencies.dependsOnPhaseId })
+      .from(phaseDependencies)
+      .innerJoin(phases, eq(phaseDependencies.phaseId, phases.id))
+      .where(eq(phases.initiativeId, initiativeId));
+  }
+ 
+  async update(id: string, data: UpdatePhaseData): Promise<Phase> {
+    const [updated] = await this.db
+      .update(phases)
+      .set({ ...data, updatedAt: new Date() })
+      .where(eq(phases.id, id))
+      .returning();
+ 
+    if (!updated) {
+      throw new Error(`Phase not found: ${id}`);
+    }
+ 
+    return updated;
+  }
+ 
+  async delete(id: string): Promise<void> {
+    const [deleted] = await this.db.delete(phases).where(eq(phases.id, id)).returning();
+ 
+    if (!deleted) {
+      throw new Error(`Phase not found: ${id}`);
+    }
+  }
+ 
+  async createDependency(phaseId: string, dependsOnPhaseId: string): Promise<void> {
+    const id = nanoid();
+    const now = new Date();
+ 
+    await this.db.insert(phaseDependencies).values({
+      id,
+      phaseId,
+      dependsOnPhaseId,
+      createdAt: now,
+    });
+  }
+ 
+  async getDependencies(phaseId: string): Promise<string[]> {
+    const result = await this.db
+      .select({ dependsOnPhaseId: phaseDependencies.dependsOnPhaseId })
+      .from(phaseDependencies)
+      .where(eq(phaseDependencies.phaseId, phaseId));
+ 
+    return result.map((row) => row.dependsOnPhaseId);
+  }
+ 
+  async getDependents(phaseId: string): Promise<string[]> {
+    const result = await this.db
+      .select({ phaseId: phaseDependencies.phaseId })
+      .from(phaseDependencies)
+      .where(eq(phaseDependencies.dependsOnPhaseId, phaseId));
+ 
+    return result.map((row) => row.phaseId);
+  }
+ 
+  async removeDependency(phaseId: string, dependsOnPhaseId: string): Promise<void> {
+    await this.db
+      .delete(phaseDependencies)
+      .where(
+        and(
+          eq(phaseDependencies.phaseId, phaseId),
+          eq(phaseDependencies.dependsOnPhaseId, dependsOnPhaseId),
+        ),
+      );
+  }
+}
+ 
+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/coverage/src/db/repositories/drizzle/project.ts.html b/coverage/src/db/repositories/drizzle/project.ts.html new file mode 100644 index 0000000..3a7f072 --- /dev/null +++ b/coverage/src/db/repositories/drizzle/project.ts.html @@ -0,0 +1,547 @@ + + + + + + Code coverage report for src/db/repositories/drizzle/project.ts + + + + + + + + + +
+
+

All files / src/db/repositories/drizzle project.ts

+
+ +
+ 55.26% + Statements + 21/38 +
+ + +
+ 25% + Branches + 3/12 +
+ + +
+ 50% + Functions + 8/16 +
+ + +
+ 55.88% + Lines + 19/34 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+

+
1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 +30 +31 +32 +33 +34 +35 +36 +37 +38 +39 +40 +41 +42 +43 +44 +45 +46 +47 +48 +49 +50 +51 +52 +53 +54 +55 +56 +57 +58 +59 +60 +61 +62 +63 +64 +65 +66 +67 +68 +69 +70 +71 +72 +73 +74 +75 +76 +77 +78 +79 +80 +81 +82 +83 +84 +85 +86 +87 +88 +89 +90 +91 +92 +93 +94 +95 +96 +97 +98 +99 +100 +101 +102 +103 +104 +105 +106 +107 +108 +109 +110 +111 +112 +113 +114 +115 +116 +117 +118 +119 +120 +121 +122 +123 +124 +125 +126 +127 +128 +129 +130 +131 +132 +133 +134 +135 +136 +137 +138 +139 +140 +141 +142 +143 +144 +145 +146 +147 +148 +149 +150 +151 +152 +153 +154 +155  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +84x +  +  +4x +4x +  +4x +  +  +  +  +  +  +4x +  +  +  +1x +  +  +  +  +  +1x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +2x +  +  +  +  +  +2x +  +  +  +  +4x +  +  +  +  +4x +4x +  +  +4x +4x +  +  +4x +  +  +  +  +  +  +  +  +  +  +  +4x +4x +4x +4x +  +  +  +  +  +  +  +  +  + 
/**
+ * Drizzle Project Repository Adapter
+ *
+ * Implements ProjectRepository interface using Drizzle ORM.
+ */
+ 
+import { eq, and, inArray } from 'drizzle-orm';
+import { nanoid } from 'nanoid';
+import type { DrizzleDatabase } from '../../index.js';
+import { projects, initiativeProjects, type Project } from '../../schema.js';
+import type {
+  ProjectRepository,
+  CreateProjectData,
+  UpdateProjectData,
+} from '../project-repository.js';
+ 
+export class DrizzleProjectRepository implements ProjectRepository {
+  constructor(private db: DrizzleDatabase) {}
+ 
+  async create(data: CreateProjectData): Promise<Project> {
+    const id = nanoid();
+    const now = new Date();
+ 
+    const [created] = await this.db.insert(projects).values({
+      id,
+      ...data,
+      createdAt: now,
+      updatedAt: now,
+    }).returning();
+ 
+    return created;
+  }
+ 
+  async findById(id: string): Promise<Project | null> {
+    const result = await this.db
+      .select()
+      .from(projects)
+      .where(eq(projects.id, id))
+      .limit(1);
+ 
+    return result[0] ?? null;
+  }
+ 
+  async findByName(name: string): Promise<Project | null> {
+    const result = await this.db
+      .select()
+      .from(projects)
+      .where(eq(projects.name, name))
+      .limit(1);
+ 
+    return result[0] ?? null;
+  }
+ 
+  async findAll(): Promise<Project[]> {
+    return this.db.select().from(projects);
+  }
+ 
+  async update(id: string, data: UpdateProjectData): Promise<Project> {
+    const [updated] = await this.db
+      .update(projects)
+      .set({ ...data, updatedAt: new Date() })
+      .where(eq(projects.id, id))
+      .returning();
+ 
+    if (!updated) {
+      throw new Error(`Project not found: ${id}`);
+    }
+ 
+    return updated;
+  }
+ 
+  async delete(id: string): Promise<void> {
+    const [deleted] = await this.db.delete(projects).where(eq(projects.id, id)).returning();
+ 
+    if (!deleted) {
+      throw new Error(`Project not found: ${id}`);
+    }
+  }
+ 
+  // Junction ops
+ 
+  async addProjectToInitiative(initiativeId: string, projectId: string): Promise<void> {
+    const id = nanoid();
+    const now = new Date();
+ 
+    await this.db.insert(initiativeProjects).values({
+      id,
+      initiativeId,
+      projectId,
+      createdAt: now,
+    });
+  }
+ 
+  async removeProjectFromInitiative(initiativeId: string, projectId: string): Promise<void> {
+    await this.db
+      .delete(initiativeProjects)
+      .where(
+        and(
+          eq(initiativeProjects.initiativeId, initiativeId),
+          eq(initiativeProjects.projectId, projectId),
+        ),
+      );
+  }
+ 
+  async findProjectsByInitiativeId(initiativeId: string): Promise<Project[]> {
+    const rows = await this.db
+      .select({ project: projects })
+      .from(initiativeProjects)
+      .innerJoin(projects, eq(initiativeProjects.projectId, projects.id))
+      .where(eq(initiativeProjects.initiativeId, initiativeId));
+ 
+    return rows.map((r) => r.project);
+  }
+ 
+  async setInitiativeProjects(initiativeId: string, projectIds: string[]): Promise<void> {
+    // Get current associations
+    const currentRows = await this.db
+      .select({ projectId: initiativeProjects.projectId })
+      .from(initiativeProjects)
+      .where(eq(initiativeProjects.initiativeId, initiativeId));
+ 
+    const currentIds = new Set(currentRows.map((r) => r.projectId));
+    const desiredIds = new Set(projectIds);
+ 
+    // Compute diff
+    const toRemove = [...currentIds].filter((id) => !desiredIds.has(id));
+    const toAdd = [...desiredIds].filter((id) => !currentIds.has(id));
+ 
+    // Remove
+    Iif (toRemove.length > 0) {
+      await this.db
+        .delete(initiativeProjects)
+        .where(
+          and(
+            eq(initiativeProjects.initiativeId, initiativeId),
+            inArray(initiativeProjects.projectId, toRemove),
+          ),
+        );
+    }
+ 
+    // Add
+    Eif (toAdd.length > 0) {
+      const now = new Date();
+      await this.db.insert(initiativeProjects).values(
+        toAdd.map((projectId) => ({
+          id: nanoid(),
+          initiativeId,
+          projectId,
+          createdAt: now,
+        })),
+      );
+    }
+  }
+}
+ 
+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/coverage/src/db/repositories/drizzle/task.ts.html b/coverage/src/db/repositories/drizzle/task.ts.html new file mode 100644 index 0000000..72dcf56 --- /dev/null +++ b/coverage/src/db/repositories/drizzle/task.ts.html @@ -0,0 +1,511 @@ + + + + + + Code coverage report for src/db/repositories/drizzle/task.ts + + + + + + + + + +
+
+

All files / src/db/repositories/drizzle task.ts

+
+ +
+ 74.19% + Statements + 23/31 +
+ + +
+ 72.72% + Branches + 16/22 +
+ + +
+ 91.66% + Functions + 11/12 +
+ + +
+ 73.33% + Lines + 22/30 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+

+
1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 +30 +31 +32 +33 +34 +35 +36 +37 +38 +39 +40 +41 +42 +43 +44 +45 +46 +47 +48 +49 +50 +51 +52 +53 +54 +55 +56 +57 +58 +59 +60 +61 +62 +63 +64 +65 +66 +67 +68 +69 +70 +71 +72 +73 +74 +75 +76 +77 +78 +79 +80 +81 +82 +83 +84 +85 +86 +87 +88 +89 +90 +91 +92 +93 +94 +95 +96 +97 +98 +99 +100 +101 +102 +103 +104 +105 +106 +107 +108 +109 +110 +111 +112 +113 +114 +115 +116 +117 +118 +119 +120 +121 +122 +123 +124 +125 +126 +127 +128 +129 +130 +131 +132 +133 +134 +135 +136 +137 +138 +139 +140 +141 +142 +143  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +253x +  +  +415x +415x +  +415x +  +  +  +  +  +  +  +  +  +  +  +414x +  +  +  +343x +  +  +  +  +  +343x +  +  +  +5x +  +  +  +  +  +  +  +16x +  +  +  +  +  +  +  +34x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +100x +  +  +  +  +  +100x +1x +  +  +99x +  +  +  +3x +  +3x +1x +  +  +  +  +12x +12x +  +12x +  +  +  +  +  +  +  +  +66x +  +  +  +  +66x +  +  + 
/**
+ * Drizzle Task Repository Adapter
+ *
+ * Implements TaskRepository interface using Drizzle ORM.
+ */
+ 
+import { eq, asc, and } from 'drizzle-orm';
+import { nanoid } from 'nanoid';
+import type { DrizzleDatabase } from '../../index.js';
+import { tasks, taskDependencies, type Task } from '../../schema.js';
+import type {
+  TaskRepository,
+  CreateTaskData,
+  UpdateTaskData,
+  PendingApprovalFilters,
+} from '../task-repository.js';
+ 
+/**
+ * Drizzle adapter for TaskRepository.
+ *
+ * Uses dependency injection for database instance,
+ * enabling isolated test databases.
+ */
+export class DrizzleTaskRepository implements TaskRepository {
+  constructor(private db: DrizzleDatabase) {}
+ 
+  async create(data: CreateTaskData): Promise<Task> {
+    const id = nanoid();
+    const now = new Date();
+ 
+    const [created] = await this.db.insert(tasks).values({
+      id,
+      ...data,
+      type: data.type ?? 'auto',
+      category: data.category ?? 'execute',
+      priority: data.priority ?? 'medium',
+      status: data.status ?? 'pending',
+      order: data.order ?? 0,
+      createdAt: now,
+      updatedAt: now,
+    }).returning();
+ 
+    return created;
+  }
+ 
+  async findById(id: string): Promise<Task | null> {
+    const result = await this.db
+      .select()
+      .from(tasks)
+      .where(eq(tasks.id, id))
+      .limit(1);
+ 
+    return result[0] ?? null;
+  }
+ 
+  async findByParentTaskId(parentTaskId: string): Promise<Task[]> {
+    return this.db
+      .select()
+      .from(tasks)
+      .where(eq(tasks.parentTaskId, parentTaskId))
+      .orderBy(asc(tasks.order));
+  }
+ 
+  async findByInitiativeId(initiativeId: string): Promise<Task[]> {
+    return this.db
+      .select()
+      .from(tasks)
+      .where(eq(tasks.initiativeId, initiativeId))
+      .orderBy(asc(tasks.order));
+  }
+ 
+  async findByPhaseId(phaseId: string): Promise<Task[]> {
+    return this.db
+      .select()
+      .from(tasks)
+      .where(eq(tasks.phaseId, phaseId))
+      .orderBy(asc(tasks.order));
+  }
+ 
+  async findPendingApproval(filters?: PendingApprovalFilters): Promise<Task[]> {
+    const conditions = [eq(tasks.status, 'pending_approval')];
+ 
+    if (filters?.initiativeId) {
+      conditions.push(eq(tasks.initiativeId, filters.initiativeId));
+    }
+    if (filters?.phaseId) {
+      conditions.push(eq(tasks.phaseId, filters.phaseId));
+    }
+    if (filters?.category) {
+      conditions.push(eq(tasks.category, filters.category));
+    }
+ 
+    return this.db
+      .select()
+      .from(tasks)
+      .where(and(...conditions))
+      .orderBy(asc(tasks.createdAt));
+  }
+ 
+  async update(id: string, data: UpdateTaskData): Promise<Task> {
+    const [updated] = await this.db
+      .update(tasks)
+      .set({ ...data, updatedAt: new Date() })
+      .where(eq(tasks.id, id))
+      .returning();
+ 
+    if (!updated) {
+      throw new Error(`Task not found: ${id}`);
+    }
+ 
+    return updated;
+  }
+ 
+  async delete(id: string): Promise<void> {
+    const [deleted] = await this.db.delete(tasks).where(eq(tasks.id, id)).returning();
+ 
+    if (!deleted) {
+      throw new Error(`Task not found: ${id}`);
+    }
+  }
+ 
+  async createDependency(taskId: string, dependsOnTaskId: string): Promise<void> {
+    const id = nanoid();
+    const now = new Date();
+ 
+    await this.db.insert(taskDependencies).values({
+      id,
+      taskId,
+      dependsOnTaskId,
+      createdAt: now,
+    });
+  }
+ 
+  async getDependencies(taskId: string): Promise<string[]> {
+    const deps = await this.db
+      .select({ dependsOnTaskId: taskDependencies.dependsOnTaskId })
+      .from(taskDependencies)
+      .where(eq(taskDependencies.taskId, taskId));
+ 
+    return deps.map((d) => d.dependsOnTaskId);
+  }
+}
+ 
+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/coverage/src/db/repositories/drizzle/test-helpers.ts.html b/coverage/src/db/repositories/drizzle/test-helpers.ts.html new file mode 100644 index 0000000..e5f851a --- /dev/null +++ b/coverage/src/db/repositories/drizzle/test-helpers.ts.html @@ -0,0 +1,175 @@ + + + + + + Code coverage report for src/db/repositories/drizzle/test-helpers.ts + + + + + + + + + +
+
+

All files / src/db/repositories/drizzle test-helpers.ts

+
+ +
+ 100% + Statements + 5/5 +
+ + +
+ 100% + Branches + 0/0 +
+ + +
+ 100% + Functions + 1/1 +
+ + +
+ 100% + Lines + 5/5 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+

+
1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 +30 +31  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +239x +  +  +239x +  +239x +  +  +239x +  +239x +  + 
/**
+ * Test helpers for repository tests.
+ *
+ * Provides utilities for setting up in-memory test databases
+ * with schema applied.
+ */
+ 
+import Database from 'better-sqlite3';
+import { drizzle } from 'drizzle-orm/better-sqlite3';
+import type { DrizzleDatabase } from '../../index.js';
+import { ensureSchema } from '../../ensure-schema.js';
+import * as schema from '../../schema.js';
+ 
+/**
+ * Create an in-memory test database with schema applied.
+ * Returns a fresh Drizzle instance for each call.
+ */
+export function createTestDatabase(): DrizzleDatabase {
+  const sqlite = new Database(':memory:');
+ 
+  // Enable foreign keys
+  sqlite.pragma('foreign_keys = ON');
+ 
+  const db = drizzle(sqlite, { schema });
+ 
+  // Create all tables
+  ensureSchema(db);
+ 
+  return db;
+}
+ 
+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/coverage/src/db/repositories/index.html b/coverage/src/db/repositories/index.html new file mode 100644 index 0000000..d275c11 --- /dev/null +++ b/coverage/src/db/repositories/index.html @@ -0,0 +1,116 @@ + + + + + + Code coverage report for src/db/repositories + + + + + + + + + +
+
+

All files src/db/repositories

+
+ +
+ 0% + Statements + 0/0 +
+ + +
+ 0% + Branches + 0/0 +
+ + +
+ 0% + Functions + 0/0 +
+ + +
+ 0% + Lines + 0/0 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
FileStatementsBranchesFunctionsLines
index.ts +
+
0%0/00%0/00%0/00%0/0
+
+
+
+ + + + + + + + \ No newline at end of file diff --git a/coverage/src/db/repositories/index.ts.html b/coverage/src/db/repositories/index.ts.html new file mode 100644 index 0000000..dca65ba --- /dev/null +++ b/coverage/src/db/repositories/index.ts.html @@ -0,0 +1,307 @@ + + + + + + Code coverage report for src/db/repositories/index.ts + + + + + + + + + +
+
+

All files / src/db/repositories index.ts

+
+ +
+ 0% + Statements + 0/0 +
+ + +
+ 0% + Branches + 0/0 +
+ + +
+ 0% + Functions + 0/0 +
+ + +
+ 0% + Lines + 0/0 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+

+
1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 +30 +31 +32 +33 +34 +35 +36 +37 +38 +39 +40 +41 +42 +43 +44 +45 +46 +47 +48 +49 +50 +51 +52 +53 +54 +55 +56 +57 +58 +59 +60 +61 +62 +63 +64 +65 +66 +67 +68 +69 +70 +71 +72 +73 +74 +75  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  + 
/**
+ * Repository Port Interfaces
+ *
+ * Re-exports all repository port interfaces.
+ * These are the PORTS in hexagonal architecture.
+ * Implementations in ./drizzle/ are ADAPTERS.
+ */
+ 
+export type {
+  InitiativeRepository,
+  CreateInitiativeData,
+  UpdateInitiativeData,
+} from './initiative-repository.js';
+ 
+export type {
+  PhaseRepository,
+  CreatePhaseData,
+  UpdatePhaseData,
+} from './phase-repository.js';
+ 
+export type {
+  TaskRepository,
+  CreateTaskData,
+  UpdateTaskData,
+  PendingApprovalFilters,
+} from './task-repository.js';
+ 
+export type {
+  AgentRepository,
+  AgentStatus,
+  CreateAgentData,
+} from './agent-repository.js';
+ 
+export type {
+  MessageRepository,
+  MessageParticipantType,
+  MessageType,
+  MessageStatus,
+  CreateMessageData,
+  UpdateMessageData,
+} from './message-repository.js';
+ 
+export type {
+  PageRepository,
+  CreatePageData,
+  UpdatePageData,
+} from './page-repository.js';
+ 
+export type {
+  ProjectRepository,
+  CreateProjectData,
+  UpdateProjectData,
+} from './project-repository.js';
+ 
+export type {
+  AccountRepository,
+  CreateAccountData,
+} from './account-repository.js';
+ 
+export type {
+  ChangeSetRepository,
+  CreateChangeSetData,
+  CreateChangeSetEntryData,
+  ChangeSetWithEntries,
+} from './change-set-repository.js';
+ 
+export type {
+  LogChunkRepository,
+} from './log-chunk-repository.js';
+ 
+export type {
+  ConversationRepository,
+  CreateConversationData,
+} from './conversation-repository.js';
+ 
+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/coverage/src/db/schema.ts.html b/coverage/src/db/schema.ts.html new file mode 100644 index 0000000..0c5e8db --- /dev/null +++ b/coverage/src/db/schema.ts.html @@ -0,0 +1,1696 @@ + + + + + + Code coverage report for src/db/schema.ts + + + + + + + + + +
+
+

All files / src/db schema.ts

+
+ +
+ 64.38% + Statements + 47/73 +
+ + +
+ 100% + Branches + 0/0 +
+ + +
+ 40.9% + Functions + 18/44 +
+ + +
+ 56.66% + Lines + 34/60 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+

+
1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 +30 +31 +32 +33 +34 +35 +36 +37 +38 +39 +40 +41 +42 +43 +44 +45 +46 +47 +48 +49 +50 +51 +52 +53 +54 +55 +56 +57 +58 +59 +60 +61 +62 +63 +64 +65 +66 +67 +68 +69 +70 +71 +72 +73 +74 +75 +76 +77 +78 +79 +80 +81 +82 +83 +84 +85 +86 +87 +88 +89 +90 +91 +92 +93 +94 +95 +96 +97 +98 +99 +100 +101 +102 +103 +104 +105 +106 +107 +108 +109 +110 +111 +112 +113 +114 +115 +116 +117 +118 +119 +120 +121 +122 +123 +124 +125 +126 +127 +128 +129 +130 +131 +132 +133 +134 +135 +136 +137 +138 +139 +140 +141 +142 +143 +144 +145 +146 +147 +148 +149 +150 +151 +152 +153 +154 +155 +156 +157 +158 +159 +160 +161 +162 +163 +164 +165 +166 +167 +168 +169 +170 +171 +172 +173 +174 +175 +176 +177 +178 +179 +180 +181 +182 +183 +184 +185 +186 +187 +188 +189 +190 +191 +192 +193 +194 +195 +196 +197 +198 +199 +200 +201 +202 +203 +204 +205 +206 +207 +208 +209 +210 +211 +212 +213 +214 +215 +216 +217 +218 +219 +220 +221 +222 +223 +224 +225 +226 +227 +228 +229 +230 +231 +232 +233 +234 +235 +236 +237 +238 +239 +240 +241 +242 +243 +244 +245 +246 +247 +248 +249 +250 +251 +252 +253 +254 +255 +256 +257 +258 +259 +260 +261 +262 +263 +264 +265 +266 +267 +268 +269 +270 +271 +272 +273 +274 +275 +276 +277 +278 +279 +280 +281 +282 +283 +284 +285 +286 +287 +288 +289 +290 +291 +292 +293 +294 +295 +296 +297 +298 +299 +300 +301 +302 +303 +304 +305 +306 +307 +308 +309 +310 +311 +312 +313 +314 +315 +316 +317 +318 +319 +320 +321 +322 +323 +324 +325 +326 +327 +328 +329 +330 +331 +332 +333 +334 +335 +336 +337 +338 +339 +340 +341 +342 +343 +344 +345 +346 +347 +348 +349 +350 +351 +352 +353 +354 +355 +356 +357 +358 +359 +360 +361 +362 +363 +364 +365 +366 +367 +368 +369 +370 +371 +372 +373 +374 +375 +376 +377 +378 +379 +380 +381 +382 +383 +384 +385 +386 +387 +388 +389 +390 +391 +392 +393 +394 +395 +396 +397 +398 +399 +400 +401 +402 +403 +404 +405 +406 +407 +408 +409 +410 +411 +412 +413 +414 +415 +416 +417 +418 +419 +420 +421 +422 +423 +424 +425 +426 +427 +428 +429 +430 +431 +432 +433 +434 +435 +436 +437 +438 +439 +440 +441 +442 +443 +444 +445 +446 +447 +448 +449 +450 +451 +452 +453 +454 +455 +456 +457 +458 +459 +460 +461 +462 +463 +464 +465 +466 +467 +468 +469 +470 +471 +472 +473 +474 +475 +476 +477 +478 +479 +480 +481 +482 +483 +484 +485 +486 +487 +488 +489 +490 +491 +492 +493 +494 +495 +496 +497 +498 +499 +500 +501 +502 +503 +504 +505 +506 +507 +508 +509 +510 +511 +512 +513 +514 +515 +516 +517 +518 +519 +520 +521 +522 +523 +524 +525 +526 +527 +528 +529 +530 +531 +532 +533 +534 +535 +536 +537 +538  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +24x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +239x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +24x +  +  +  +  +  +  +  +  +  +  +  +  +  +239x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +24x +  +  +  +  +  +  +  +  +  +  +239x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +24x +  +  +  +  +  +  +  +  +  +  +  +  +  +24x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +239x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +24x +  +  +  +  +  +  +  +  +  +  +239x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +24x +  +  +  +  +  +  +  +  +  +  +  +  +  +239x +  +  +  +  +  +  +  +  +  +  +24x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +239x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +24x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +239x +  +  +  +239x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +24x +  +  +  +  +  +  +  +  +  +  +  +239x +  +  +  +239x +  +  +  +  +  +  +  +  +  +  +  +  +  +24x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +239x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +24x +  +  +  +  +  +  +  +  +  +  +  +  +239x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +24x +  +  +  +  +  +  +  +  +239x +  +  +  +  +  +  +  +  +  +  +24x +  +  +  +  +  +  +  +  +239x +  +  +  +239x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +24x +  +  +  +  +  +  +239x +  +  +  +  +  +  +  +  +  +  +24x +  +  +  +  +  +  +  +  +  +  +  +239x +  +  +  +  +  +  + 
/**
+ * Database schema for Codewalk District.
+ *
+ * Defines the three-level task hierarchy:
+ * - Initiative: Top-level project
+ * - Phase: Major milestone within initiative
+ * - Task: Individual work item (can have parentTaskId for decomposition relationships)
+ *
+ * Plus a task_dependencies table for task dependency relationships.
+ */
+ 
+import { sqliteTable, text, integer, uniqueIndex, index } from 'drizzle-orm/sqlite-core';
+import { relations, type InferInsertModel, type InferSelectModel } from 'drizzle-orm';
+ 
+// ============================================================================
+// INITIATIVES
+// ============================================================================
+ 
+export const initiatives = sqliteTable('initiatives', {
+  id: text('id').primaryKey(),
+  name: text('name').notNull(),
+  status: text('status', { enum: ['active', 'completed', 'archived'] })
+    .notNull()
+    .default('active'),
+  mergeRequiresApproval: integer('merge_requires_approval', { mode: 'boolean' })
+    .notNull()
+    .default(true),
+  branch: text('branch'), // Auto-generated initiative branch (e.g., 'cw/user-auth')
+  executionMode: text('execution_mode', { enum: ['yolo', 'review_per_phase'] })
+    .notNull()
+    .default('review_per_phase'),
+  createdAt: integer('created_at', { mode: 'timestamp' }).notNull(),
+  updatedAt: integer('updated_at', { mode: 'timestamp' }).notNull(),
+});
+ 
+export const initiativesRelations = relations(initiatives, ({ many }) => ({
+  phases: many(phases),
+  pages: many(pages),
+  initiativeProjects: many(initiativeProjects),
+  tasks: many(tasks),
+  changeSets: many(changeSets),
+}));
+ 
+export type Initiative = InferSelectModel<typeof initiatives>;
+export type NewInitiative = InferInsertModel<typeof initiatives>;
+ 
+// ============================================================================
+// PHASES
+// ============================================================================
+ 
+export const phases = sqliteTable('phases', {
+  id: text('id').primaryKey(),
+  initiativeId: text('initiative_id')
+    .notNull()
+    .references(() => initiatives.id, { onDelete: 'cascade' }),
+  name: text('name').notNull(),
+  content: text('content'),
+  status: text('status', { enum: ['pending', 'approved', 'in_progress', 'completed', 'blocked', 'pending_review'] })
+    .notNull()
+    .default('pending'),
+  createdAt: integer('created_at', { mode: 'timestamp' }).notNull(),
+  updatedAt: integer('updated_at', { mode: 'timestamp' }).notNull(),
+});
+ 
+export const phasesRelations = relations(phases, ({ one, many }) => ({
+  initiative: one(initiatives, {
+    fields: [phases.initiativeId],
+    references: [initiatives.id],
+  }),
+  tasks: many(tasks),
+  // Dependencies: phases this phase depends on
+  dependsOn: many(phaseDependencies, { relationName: 'dependentPhase' }),
+  // Dependents: phases that depend on this phase
+  dependents: many(phaseDependencies, { relationName: 'dependencyPhase' }),
+}));
+ 
+export type Phase = InferSelectModel<typeof phases>;
+export type NewPhase = InferInsertModel<typeof phases>;
+ 
+// ============================================================================
+// PHASE DEPENDENCIES
+// ============================================================================
+ 
+export const phaseDependencies = sqliteTable('phase_dependencies', {
+  id: text('id').primaryKey(),
+  phaseId: text('phase_id')
+    .notNull()
+    .references(() => phases.id, { onDelete: 'cascade' }),
+  dependsOnPhaseId: text('depends_on_phase_id')
+    .notNull()
+    .references(() => phases.id, { onDelete: 'cascade' }),
+  createdAt: integer('created_at', { mode: 'timestamp' }).notNull(),
+});
+ 
+export const phaseDependenciesRelations = relations(phaseDependencies, ({ one }) => ({
+  phase: one(phases, {
+    fields: [phaseDependencies.phaseId],
+    references: [phases.id],
+    relationName: 'dependentPhase',
+  }),
+  dependsOnPhase: one(phases, {
+    fields: [phaseDependencies.dependsOnPhaseId],
+    references: [phases.id],
+    relationName: 'dependencyPhase',
+  }),
+}));
+ 
+export type PhaseDependency = InferSelectModel<typeof phaseDependencies>;
+export type NewPhaseDependency = InferInsertModel<typeof phaseDependencies>;
+ 
+// ============================================================================
+// TASKS
+// ============================================================================
+ 
+/**
+ * Task category enum values.
+ * Defines what kind of work a task represents.
+ */
+export const TASK_CATEGORIES = [
+  'execute',    // Standard execution task
+  'research',   // Research/exploration task
+  'discuss',    // Discussion/context gathering
+  'plan',       // Plan initiative into phases
+  'detail',     // Detail phase into tasks
+  'refine',     // Refine/edit content
+  'verify',     // Verification task
+  'merge',      // Merge task
+  'review',     // Review/approval task
+] as const;
+ 
+export type TaskCategory = (typeof TASK_CATEGORIES)[number];
+ 
+export const tasks = sqliteTable('tasks', {
+  id: text('id').primaryKey(),
+  // Parent context - at least one should be set
+  phaseId: text('phase_id').references(() => phases.id, { onDelete: 'cascade' }),
+  initiativeId: text('initiative_id').references(() => initiatives.id, { onDelete: 'cascade' }),
+  // Parent task for detail hierarchy (child tasks link to parent detail task)
+  parentTaskId: text('parent_task_id').references((): ReturnType<typeof text> => tasks.id, { onDelete: 'cascade' }),
+  name: text('name').notNull(),
+  description: text('description'),
+  type: text('type', {
+    enum: ['auto', 'checkpoint:human-verify', 'checkpoint:decision', 'checkpoint:human-action'],
+  })
+    .notNull()
+    .default('auto'),
+  category: text('category', {
+    enum: TASK_CATEGORIES,
+  })
+    .notNull()
+    .default('execute'),
+  priority: text('priority', { enum: ['low', 'medium', 'high'] })
+    .notNull()
+    .default('medium'),
+  status: text('status', {
+    enum: ['pending_approval', 'pending', 'in_progress', 'completed', 'blocked'],
+  })
+    .notNull()
+    .default('pending'),
+  requiresApproval: integer('requires_approval', { mode: 'boolean' }), // null = inherit from initiative
+  order: integer('order').notNull().default(0),
+  createdAt: integer('created_at', { mode: 'timestamp' }).notNull(),
+  updatedAt: integer('updated_at', { mode: 'timestamp' }).notNull(),
+});
+ 
+export const tasksRelations = relations(tasks, ({ one, many }) => ({
+  phase: one(phases, {
+    fields: [tasks.phaseId],
+    references: [phases.id],
+  }),
+  initiative: one(initiatives, {
+    fields: [tasks.initiativeId],
+    references: [initiatives.id],
+  }),
+  // Parent task (for detail hierarchy - child links to parent detail task)
+  parentTask: one(tasks, {
+    fields: [tasks.parentTaskId],
+    references: [tasks.id],
+    relationName: 'parentTask',
+  }),
+  // Child tasks (tasks created from decomposition of this task)
+  childTasks: many(tasks, { relationName: 'parentTask' }),
+  // Dependencies: tasks this task depends on
+  dependsOn: many(taskDependencies, { relationName: 'dependentTask' }),
+  // Dependents: tasks that depend on this task
+  dependents: many(taskDependencies, { relationName: 'dependencyTask' }),
+}));
+ 
+export type Task = InferSelectModel<typeof tasks>;
+export type NewTask = InferInsertModel<typeof tasks>;
+ 
+// ============================================================================
+// TASK DEPENDENCIES
+// ============================================================================
+ 
+export const taskDependencies = sqliteTable('task_dependencies', {
+  id: text('id').primaryKey(),
+  taskId: text('task_id')
+    .notNull()
+    .references(() => tasks.id, { onDelete: 'cascade' }),
+  dependsOnTaskId: text('depends_on_task_id')
+    .notNull()
+    .references(() => tasks.id, { onDelete: 'cascade' }),
+  createdAt: integer('created_at', { mode: 'timestamp' }).notNull(),
+});
+ 
+export const taskDependenciesRelations = relations(taskDependencies, ({ one }) => ({
+  task: one(tasks, {
+    fields: [taskDependencies.taskId],
+    references: [tasks.id],
+    relationName: 'dependentTask',
+  }),
+  dependsOnTask: one(tasks, {
+    fields: [taskDependencies.dependsOnTaskId],
+    references: [tasks.id],
+    relationName: 'dependencyTask',
+  }),
+}));
+ 
+export type TaskDependency = InferSelectModel<typeof taskDependencies>;
+export type NewTaskDependency = InferInsertModel<typeof taskDependencies>;
+ 
+// ============================================================================
+// ACCOUNTS
+// ============================================================================
+ 
+export const accounts = sqliteTable('accounts', {
+  id: text('id').primaryKey(),
+  email: text('email').notNull(),
+  provider: text('provider').notNull().default('claude'),
+  configJson: text('config_json'),    // .claude.json content (JSON string)
+  credentials: text('credentials'),    // .credentials.json content (JSON string)
+  isExhausted: integer('is_exhausted', { mode: 'boolean' }).notNull().default(false),
+  exhaustedUntil: integer('exhausted_until', { mode: 'timestamp' }),
+  lastUsedAt: integer('last_used_at', { mode: 'timestamp' }),
+  sortOrder: integer('sort_order').notNull().default(0),
+  createdAt: integer('created_at', { mode: 'timestamp' }).notNull(),
+  updatedAt: integer('updated_at', { mode: 'timestamp' }).notNull(),
+});
+ 
+export const accountsRelations = relations(accounts, ({ many }) => ({
+  agents: many(agents),
+}));
+ 
+export type Account = InferSelectModel<typeof accounts>;
+export type NewAccount = InferInsertModel<typeof accounts>;
+ 
+// ============================================================================
+// AGENTS
+// ============================================================================
+ 
+export const agents = sqliteTable('agents', {
+  id: text('id').primaryKey(),
+  name: text('name').notNull().unique(), // Human-readable alias (e.g., 'jolly-penguin')
+  taskId: text('task_id').references(() => tasks.id, { onDelete: 'set null' }), // Task may be deleted
+  initiativeId: text('initiative_id').references(() => initiatives.id, { onDelete: 'set null' }),
+  sessionId: text('session_id'), // Claude CLI session ID for resumption (null until first run completes)
+  worktreeId: text('worktree_id').notNull(), // Agent alias (deterministic path: agent-workdirs/<alias>/)
+  provider: text('provider').notNull().default('claude'),
+  accountId: text('account_id').references(() => accounts.id, { onDelete: 'set null' }),
+  status: text('status', {
+    enum: ['idle', 'running', 'waiting_for_input', 'stopped', 'crashed'],
+  })
+    .notNull()
+    .default('idle'),
+  mode: text('mode', { enum: ['execute', 'discuss', 'plan', 'detail', 'refine'] })
+    .notNull()
+    .default('execute'),
+  pid: integer('pid'),
+  exitCode: integer('exit_code'), // Process exit code for debugging crashes
+  outputFilePath: text('output_file_path'),
+  result: text('result'),
+  pendingQuestions: text('pending_questions'),
+  createdAt: integer('created_at', { mode: 'timestamp' }).notNull(),
+  updatedAt: integer('updated_at', { mode: 'timestamp' }).notNull(),
+  userDismissedAt: integer('user_dismissed_at', { mode: 'timestamp' }),
+});
+ 
+export const agentsRelations = relations(agents, ({ one, many }) => ({
+  task: one(tasks, {
+    fields: [agents.taskId],
+    references: [tasks.id],
+  }),
+  initiative: one(initiatives, {
+    fields: [agents.initiativeId],
+    references: [initiatives.id],
+  }),
+  account: one(accounts, {
+    fields: [agents.accountId],
+    references: [accounts.id],
+  }),
+  changeSets: many(changeSets),
+}));
+ 
+export type Agent = InferSelectModel<typeof agents>;
+export type NewAgent = InferInsertModel<typeof agents>;
+ 
+// ============================================================================
+// CHANGE SETS
+// ============================================================================
+ 
+export const changeSets = sqliteTable('change_sets', {
+  id: text('id').primaryKey(),
+  agentId: text('agent_id')
+    .references(() => agents.id, { onDelete: 'set null' }),
+  agentName: text('agent_name').notNull(),
+  initiativeId: text('initiative_id')
+    .notNull()
+    .references(() => initiatives.id, { onDelete: 'cascade' }),
+  mode: text('mode', { enum: ['plan', 'detail', 'refine'] }).notNull(),
+  summary: text('summary'),
+  status: text('status', { enum: ['applied', 'reverted'] })
+    .notNull()
+    .default('applied'),
+  revertedAt: integer('reverted_at', { mode: 'timestamp' }),
+  createdAt: integer('created_at', { mode: 'timestamp' }).notNull(),
+}, (table) => [
+  index('change_sets_initiative_id_idx').on(table.initiativeId),
+]);
+ 
+export const changeSetsRelations = relations(changeSets, ({ one, many }) => ({
+  agent: one(agents, {
+    fields: [changeSets.agentId],
+    references: [agents.id],
+  }),
+  initiative: one(initiatives, {
+    fields: [changeSets.initiativeId],
+    references: [initiatives.id],
+  }),
+  entries: many(changeSetEntries),
+}));
+ 
+export type ChangeSet = InferSelectModel<typeof changeSets>;
+export type NewChangeSet = InferInsertModel<typeof changeSets>;
+ 
+export const changeSetEntries = sqliteTable('change_set_entries', {
+  id: text('id').primaryKey(),
+  changeSetId: text('change_set_id')
+    .notNull()
+    .references(() => changeSets.id, { onDelete: 'cascade' }),
+  entityType: text('entity_type', { enum: ['page', 'phase', 'task', 'phase_dependency'] }).notNull(),
+  entityId: text('entity_id').notNull(),
+  action: text('action', { enum: ['create', 'update', 'delete'] }).notNull(),
+  previousState: text('previous_state'), // JSON snapshot, null for creates
+  newState: text('new_state'), // JSON snapshot, null for deletes
+  sortOrder: integer('sort_order').notNull().default(0),
+  createdAt: integer('created_at', { mode: 'timestamp' }).notNull(),
+}, (table) => [
+  index('change_set_entries_change_set_id_idx').on(table.changeSetId),
+]);
+ 
+export const changeSetEntriesRelations = relations(changeSetEntries, ({ one }) => ({
+  changeSet: one(changeSets, {
+    fields: [changeSetEntries.changeSetId],
+    references: [changeSets.id],
+  }),
+}));
+ 
+export type ChangeSetEntry = InferSelectModel<typeof changeSetEntries>;
+export type NewChangeSetEntry = InferInsertModel<typeof changeSetEntries>;
+ 
+// ============================================================================
+// MESSAGES
+// ============================================================================
+ 
+export const messages = sqliteTable('messages', {
+  id: text('id').primaryKey(),
+  senderType: text('sender_type', { enum: ['agent', 'user'] }).notNull(),
+  senderId: text('sender_id').references(() => agents.id, { onDelete: 'set null' }), // Agent ID if senderType='agent', null for user
+  recipientType: text('recipient_type', { enum: ['agent', 'user'] }).notNull(),
+  recipientId: text('recipient_id').references(() => agents.id, { onDelete: 'set null' }), // Agent ID if recipientType='agent', null for user
+  type: text('type', { enum: ['question', 'info', 'error', 'response'] })
+    .notNull()
+    .default('info'),
+  content: text('content').notNull(),
+  requiresResponse: integer('requires_response', { mode: 'boolean' })
+    .notNull()
+    .default(false),
+  status: text('status', { enum: ['pending', 'read', 'responded'] })
+    .notNull()
+    .default('pending'),
+  parentMessageId: text('parent_message_id').references((): ReturnType<typeof text> => messages.id, { onDelete: 'set null' }), // Links response to original question
+  createdAt: integer('created_at', { mode: 'timestamp' }).notNull(),
+  updatedAt: integer('updated_at', { mode: 'timestamp' }).notNull(),
+});
+ 
+export const messagesRelations = relations(messages, ({ one, many }) => ({
+  // Sender agent (optional - null for user senders)
+  senderAgent: one(agents, {
+    fields: [messages.senderId],
+    references: [agents.id],
+    relationName: 'senderAgent',
+  }),
+  // Recipient agent (optional - null for user recipients)
+  recipientAgent: one(agents, {
+    fields: [messages.recipientId],
+    references: [agents.id],
+    relationName: 'recipientAgent',
+  }),
+  // Parent message (for threading responses)
+  parentMessage: one(messages, {
+    fields: [messages.parentMessageId],
+    references: [messages.id],
+    relationName: 'parentMessage',
+  }),
+  // Child messages (replies to this message)
+  childMessages: many(messages, { relationName: 'parentMessage' }),
+}));
+ 
+export type Message = InferSelectModel<typeof messages>;
+export type NewMessage = InferInsertModel<typeof messages>;
+ 
+// ============================================================================
+// PAGES
+// ============================================================================
+ 
+export const pages = sqliteTable('pages', {
+  id: text('id').primaryKey(),
+  initiativeId: text('initiative_id')
+    .notNull()
+    .references(() => initiatives.id, { onDelete: 'cascade' }),
+  parentPageId: text('parent_page_id').references((): ReturnType<typeof text> => pages.id, { onDelete: 'cascade' }),
+  title: text('title').notNull(),
+  content: text('content'), // JSON string from Tiptap
+  sortOrder: integer('sort_order').notNull().default(0),
+  createdAt: integer('created_at', { mode: 'timestamp' }).notNull(),
+  updatedAt: integer('updated_at', { mode: 'timestamp' }).notNull(),
+});
+ 
+export const pagesRelations = relations(pages, ({ one, many }) => ({
+  initiative: one(initiatives, {
+    fields: [pages.initiativeId],
+    references: [initiatives.id],
+  }),
+  parentPage: one(pages, {
+    fields: [pages.parentPageId],
+    references: [pages.id],
+    relationName: 'parentPage',
+  }),
+  childPages: many(pages, { relationName: 'parentPage' }),
+}));
+ 
+export type Page = InferSelectModel<typeof pages>;
+export type NewPage = InferInsertModel<typeof pages>;
+ 
+// ============================================================================
+// PROJECTS
+// ============================================================================
+ 
+export const projects = sqliteTable('projects', {
+  id: text('id').primaryKey(),
+  name: text('name').notNull().unique(),
+  url: text('url').notNull().unique(),
+  defaultBranch: text('default_branch').notNull().default('main'),
+  createdAt: integer('created_at', { mode: 'timestamp' }).notNull(),
+  updatedAt: integer('updated_at', { mode: 'timestamp' }).notNull(),
+});
+ 
+export const projectsRelations = relations(projects, ({ many }) => ({
+  initiativeProjects: many(initiativeProjects),
+}));
+ 
+export type Project = InferSelectModel<typeof projects>;
+export type NewProject = InferInsertModel<typeof projects>;
+ 
+// ============================================================================
+// INITIATIVE PROJECTS (junction)
+// ============================================================================
+ 
+export const initiativeProjects = sqliteTable('initiative_projects', {
+  id: text('id').primaryKey(),
+  initiativeId: text('initiative_id')
+    .notNull()
+    .references(() => initiatives.id, { onDelete: 'cascade' }),
+  projectId: text('project_id')
+    .notNull()
+    .references(() => projects.id, { onDelete: 'cascade' }),
+  createdAt: integer('created_at', { mode: 'timestamp' }).notNull(),
+}, (table) => [
+  uniqueIndex('initiative_project_unique').on(table.initiativeId, table.projectId),
+]);
+ 
+export const initiativeProjectsRelations = relations(initiativeProjects, ({ one }) => ({
+  initiative: one(initiatives, {
+    fields: [initiativeProjects.initiativeId],
+    references: [initiatives.id],
+  }),
+  project: one(projects, {
+    fields: [initiativeProjects.projectId],
+    references: [projects.id],
+  }),
+}));
+ 
+export type InitiativeProject = InferSelectModel<typeof initiativeProjects>;
+export type NewInitiativeProject = InferInsertModel<typeof initiativeProjects>;
+ 
+// ============================================================================
+// AGENT LOG CHUNKS
+// ============================================================================
+ 
+export const agentLogChunks = sqliteTable('agent_log_chunks', {
+  id: text('id').primaryKey(),
+  agentId: text('agent_id').notNull(),            // NO FK — survives agent deletion
+  agentName: text('agent_name').notNull(),         // Snapshot for display after deletion
+  sessionNumber: integer('session_number').notNull().default(1),
+  content: text('content').notNull(),              // Raw JSONL chunk from file
+  createdAt: integer('created_at', { mode: 'timestamp' }).notNull(),
+}, (table) => [
+  index('agent_log_chunks_agent_id_idx').on(table.agentId),
+]);
+ 
+export type AgentLogChunk = InferSelectModel<typeof agentLogChunks>;
+export type NewAgentLogChunk = InferInsertModel<typeof agentLogChunks>;
+ 
+// ============================================================================
+// CONVERSATIONS (inter-agent communication)
+// ============================================================================
+ 
+export const conversations = sqliteTable('conversations', {
+  id: text('id').primaryKey(),
+  fromAgentId: text('from_agent_id').notNull().references(() => agents.id, { onDelete: 'cascade' }),
+  toAgentId: text('to_agent_id').notNull().references(() => agents.id, { onDelete: 'cascade' }),
+  initiativeId: text('initiative_id').references(() => initiatives.id, { onDelete: 'set null' }),
+  phaseId: text('phase_id').references(() => phases.id, { onDelete: 'set null' }),
+  taskId: text('task_id').references(() => tasks.id, { onDelete: 'set null' }),
+  question: text('question').notNull(),
+  answer: text('answer'),
+  status: text('status', { enum: ['pending', 'answered'] }).notNull().default('pending'),
+  createdAt: integer('created_at', { mode: 'timestamp' }).notNull(),
+  updatedAt: integer('updated_at', { mode: 'timestamp' }).notNull(),
+}, (table) => [
+  index('conversations_to_agent_status_idx').on(table.toAgentId, table.status),
+  index('conversations_from_agent_idx').on(table.fromAgentId),
+]);
+ 
+export type Conversation = InferSelectModel<typeof conversations>;
+export type NewConversation = InferInsertModel<typeof conversations>;
+ 
+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/coverage/src/dispatch/index.html b/coverage/src/dispatch/index.html new file mode 100644 index 0000000..077fd81 --- /dev/null +++ b/coverage/src/dispatch/index.html @@ -0,0 +1,131 @@ + + + + + + Code coverage report for src/dispatch + + + + + + + + + +
+
+

All files src/dispatch

+
+ +
+ 75% + Statements + 168/224 +
+ + +
+ 59.64% + Branches + 68/114 +
+ + +
+ 95.45% + Functions + 21/22 +
+ + +
+ 74.77% + Lines + 166/222 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
FileStatementsBranchesFunctionsLines
manager.ts +
+
69.62%94/13556.57%43/7692.3%12/1369.4%93/134
phase-manager.ts +
+
83.14%74/8965.78%25/38100%9/982.95%73/88
+
+
+
+ + + + + + + + \ No newline at end of file diff --git a/coverage/src/dispatch/manager.ts.html b/coverage/src/dispatch/manager.ts.html new file mode 100644 index 0000000..937e758 --- /dev/null +++ b/coverage/src/dispatch/manager.ts.html @@ -0,0 +1,1540 @@ + + + + + + Code coverage report for src/dispatch/manager.ts + + + + + + + + + +
+
+

All files / src/dispatch manager.ts

+
+ +
+ 69.62% + Statements + 94/135 +
+ + +
+ 56.57% + Branches + 43/76 +
+ + +
+ 92.3% + Functions + 12/13 +
+ + +
+ 69.4% + Lines + 93/134 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+

+
1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 +30 +31 +32 +33 +34 +35 +36 +37 +38 +39 +40 +41 +42 +43 +44 +45 +46 +47 +48 +49 +50 +51 +52 +53 +54 +55 +56 +57 +58 +59 +60 +61 +62 +63 +64 +65 +66 +67 +68 +69 +70 +71 +72 +73 +74 +75 +76 +77 +78 +79 +80 +81 +82 +83 +84 +85 +86 +87 +88 +89 +90 +91 +92 +93 +94 +95 +96 +97 +98 +99 +100 +101 +102 +103 +104 +105 +106 +107 +108 +109 +110 +111 +112 +113 +114 +115 +116 +117 +118 +119 +120 +121 +122 +123 +124 +125 +126 +127 +128 +129 +130 +131 +132 +133 +134 +135 +136 +137 +138 +139 +140 +141 +142 +143 +144 +145 +146 +147 +148 +149 +150 +151 +152 +153 +154 +155 +156 +157 +158 +159 +160 +161 +162 +163 +164 +165 +166 +167 +168 +169 +170 +171 +172 +173 +174 +175 +176 +177 +178 +179 +180 +181 +182 +183 +184 +185 +186 +187 +188 +189 +190 +191 +192 +193 +194 +195 +196 +197 +198 +199 +200 +201 +202 +203 +204 +205 +206 +207 +208 +209 +210 +211 +212 +213 +214 +215 +216 +217 +218 +219 +220 +221 +222 +223 +224 +225 +226 +227 +228 +229 +230 +231 +232 +233 +234 +235 +236 +237 +238 +239 +240 +241 +242 +243 +244 +245 +246 +247 +248 +249 +250 +251 +252 +253 +254 +255 +256 +257 +258 +259 +260 +261 +262 +263 +264 +265 +266 +267 +268 +269 +270 +271 +272 +273 +274 +275 +276 +277 +278 +279 +280 +281 +282 +283 +284 +285 +286 +287 +288 +289 +290 +291 +292 +293 +294 +295 +296 +297 +298 +299 +300 +301 +302 +303 +304 +305 +306 +307 +308 +309 +310 +311 +312 +313 +314 +315 +316 +317 +318 +319 +320 +321 +322 +323 +324 +325 +326 +327 +328 +329 +330 +331 +332 +333 +334 +335 +336 +337 +338 +339 +340 +341 +342 +343 +344 +345 +346 +347 +348 +349 +350 +351 +352 +353 +354 +355 +356 +357 +358 +359 +360 +361 +362 +363 +364 +365 +366 +367 +368 +369 +370 +371 +372 +373 +374 +375 +376 +377 +378 +379 +380 +381 +382 +383 +384 +385 +386 +387 +388 +389 +390 +391 +392 +393 +394 +395 +396 +397 +398 +399 +400 +401 +402 +403 +404 +405 +406 +407 +408 +409 +410 +411 +412 +413 +414 +415 +416 +417 +418 +419 +420 +421 +422 +423 +424 +425 +426 +427 +428 +429 +430 +431 +432 +433 +434 +435 +436 +437 +438 +439 +440 +441 +442 +443 +444 +445 +446 +447 +448 +449 +450 +451 +452 +453 +454 +455 +456 +457 +458 +459 +460 +461 +462 +463 +464 +465 +466 +467 +468 +469 +470 +471 +472 +473 +474 +475 +476 +477 +478 +479 +480 +481 +482 +483 +484 +485 +486  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +9x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +96x +  +  +96x +  +  +96x +96x +96x +96x +96x +96x +  +  +  +  +  +  +  +  +  +67x +67x +1x +  +  +  +66x +  +66x +  +  +  +  +  +  +66x +  +66x +  +  +66x +  +  +  +  +  +  +  +  +66x +  +  +  +  +  +  +  +  +47x +  +47x +4x +  +  +  +43x +  +43x +  +43x +  +75x +75x +12x +  +  +  +63x +63x +  +  +  +  +  +63x +  +  +  +  +63x +  +  +43x +  +43x +  +  +  +  +43x +  +43x +30x +30x +25x +  +5x +  +  +43x +  +  +  +  +  +  +  +  +  +  +  +16x +16x +  +  +  +  +16x +  +16x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +16x +  +  +16x +  +16x +  +  +16x +  +  +  +  +  +  +  +  +  +16x +  +  +  +16x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +7x +  +  +7x +  +7x +  +  +7x +  +  +7x +  +  +  +  +  +  +  +7x +  +  +  +  +  +  +  +39x +  +39x +2x +2x +  +  +  +  +  +  +  +37x +37x +  +37x +2x +2x +  +  +  +  +  +  +  +35x +35x +  +  +  +  +  +  +  +  +  +  +  +35x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +35x +  +  +  +  +  +  +  +  +35x +  +  +35x +  +  +35x +  +  +35x +  +  +  +  +  +  +  +  +35x +  +35x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +17x +  +  +17x +17x +31x +31x +22x +  +  +  +17x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +106x +79x +  +  +27x +31x +31x +21x +  +  +  +6x +  +  +  +  +  +  +  +129x +  +  +  +  +  +  +  +  +16x +  +  +  +  +16x +  +  +  +  +  +  +  +  +16x +  +  + 
/**
+ * Default Dispatch Manager - Adapter Implementation
+ *
+ * Implements DispatchManager interface with in-memory queue
+ * and dependency-ordered dispatch.
+ *
+ * This is the ADAPTER for the DispatchManager PORT.
+ */
+ 
+import type {
+  EventBus,
+  TaskQueuedEvent,
+  TaskCompletedEvent,
+  TaskBlockedEvent,
+  TaskDispatchedEvent,
+  TaskPendingApprovalEvent,
+} from '../events/index.js';
+import type { AgentManager } from '../agent/types.js';
+import type { TaskRepository } from '../db/repositories/task-repository.js';
+import type { MessageRepository } from '../db/repositories/message-repository.js';
+import type { InitiativeRepository } from '../db/repositories/initiative-repository.js';
+import type { PhaseRepository } from '../db/repositories/phase-repository.js';
+import type { Task } from '../db/schema.js';
+import type { DispatchManager, QueuedTask, DispatchResult } from './types.js';
+import { phaseBranchName, taskBranchName, isPlanningCategory, generateInitiativeBranch } from '../git/branch-naming.js';
+import { buildExecutePrompt } from '../agent/prompts/index.js';
+import { createModuleLogger } from '../logger/index.js';
+ 
+const log = createModuleLogger('dispatch');
+ 
+// =============================================================================
+// Internal Types
+// =============================================================================
+ 
+/**
+ * Internal representation of a blocked task.
+ */
+interface BlockedTask {
+  taskId: string;
+  reason: string;
+}
+ 
+// =============================================================================
+// DefaultDispatchManager Implementation
+// =============================================================================
+ 
+/**
+ * In-memory implementation of DispatchManager.
+ *
+ * Uses Map for queue management and checks task_dependencies table
+ * for dependency resolution.
+ */
+export class DefaultDispatchManager implements DispatchManager {
+  /** Internal queue of tasks pending dispatch */
+  private taskQueue: Map<string, QueuedTask> = new Map();
+ 
+  /** Blocked tasks with their reasons */
+  private blockedTasks: Map<string, BlockedTask> = new Map();
+ 
+  constructor(
+    private taskRepository: TaskRepository,
+    private messageRepository: MessageRepository,
+    private agentManager: AgentManager,
+    private eventBus: EventBus,
+    private initiativeRepository?: InitiativeRepository,
+    private phaseRepository?: PhaseRepository,
+  ) {}
+ 
+  /**
+   * Queue a task for dispatch.
+   * Fetches task dependencies and adds to internal queue.
+   * Checkpoint tasks are queued but won't auto-dispatch.
+   */
+  async queue(taskId: string): Promise<void> {
+    // Fetch task to verify it exists and get priority
+    const task = await this.taskRepository.findById(taskId);
+    if (!task) {
+      throw new Error(`Task not found: ${taskId}`);
+    }
+ 
+    // Get dependencies for this task from the repository
+    const dependsOn = await this.taskRepository.getDependencies(taskId);
+ 
+    const queuedTask: QueuedTask = {
+      taskId,
+      priority: task.priority,
+      queuedAt: new Date(),
+      dependsOn,
+    };
+ 
+    this.taskQueue.set(taskId, queuedTask);
+ 
+    log.info({ taskId, priority: task.priority, isCheckpoint: this.isCheckpointTask(task) }, 'task queued');
+ 
+    // Emit TaskQueuedEvent
+    const event: TaskQueuedEvent = {
+      type: 'task:queued',
+      timestamp: new Date(),
+      payload: {
+        taskId,
+        priority: task.priority,
+        dependsOn,
+      },
+    };
+    this.eventBus.emit(event);
+  }
+ 
+  /**
+   * Get next dispatchable task.
+   * Returns task with all dependencies complete, highest priority first.
+   * Checkpoint tasks are excluded (require human action).
+   */
+  async getNextDispatchable(): Promise<QueuedTask | null> {
+    const queuedTasks = Array.from(this.taskQueue.values());
+ 
+    if (queuedTasks.length === 0) {
+      return null;
+    }
+ 
+    // Filter to only tasks with all dependencies complete and not checkpoint tasks
+    const readyTasks: QueuedTask[] = [];
+ 
+    log.debug({ queueSize: queuedTasks.length }, 'evaluating dispatchable tasks');
+ 
+    for (const qt of queuedTasks) {
+      // Check dependencies
+      const allDepsComplete = await this.areAllDependenciesComplete(qt.dependsOn);
+      if (!allDepsComplete) {
+        continue;
+      }
+ 
+      // Check if this is a checkpoint task (requires human action)
+      const task = await this.taskRepository.findById(qt.taskId);
+      Iif (task && this.isCheckpointTask(task)) {
+        log.debug({ taskId: qt.taskId, type: task.type }, 'skipping checkpoint task');
+        continue;
+      }
+ 
+      // Skip planning-category tasks (handled by architect flow)
+      Iif (task && isPlanningCategory(task.category)) {
+        log.debug({ taskId: qt.taskId, category: task.category }, 'skipping planning-category task');
+        continue;
+      }
+ 
+      readyTasks.push(qt);
+    }
+ 
+    log.debug({ queueSize: queuedTasks.length, readyCount: readyTasks.length }, 'dispatchable evaluation complete');
+ 
+    Iif (readyTasks.length === 0) {
+      return null;
+    }
+ 
+    // Sort by priority (high > medium > low), then by queuedAt (oldest first)
+    const priorityOrder: Record<string, number> = { high: 0, medium: 1, low: 2 };
+ 
+    readyTasks.sort((a, b) => {
+      const priorityDiff = priorityOrder[a.priority] - priorityOrder[b.priority];
+      if (priorityDiff !== 0) {
+        return priorityDiff;
+      }
+      return a.queuedAt.getTime() - b.queuedAt.getTime();
+    });
+ 
+    return readyTasks[0];
+  }
+ 
+  /**
+   * Mark a task as complete.
+   * If the task requires approval, sets status to 'pending_approval' instead.
+   * Updates task status and removes from queue.
+   *
+   * @param taskId - ID of the task to complete
+   * @param agentId - Optional ID of the agent that completed the task
+   */
+  async completeTask(taskId: string, agentId?: string): Promise<void> {
+    const task = await this.taskRepository.findById(taskId);
+    Iif (!task) {
+      throw new Error(`Task not found: ${taskId}`);
+    }
+ 
+    // Determine if approval is required
+    const requiresApproval = await this.taskRequiresApproval(task);
+ 
+    Iif (requiresApproval) {
+      // Set to pending_approval instead of completed
+      await this.taskRepository.update(taskId, { status: 'pending_approval' });
+ 
+      // Remove from queue
+      this.taskQueue.delete(taskId);
+ 
+      log.info({ taskId, category: task.category }, 'task pending approval');
+ 
+      // Emit TaskPendingApprovalEvent
+      const event: TaskPendingApprovalEvent = {
+        type: 'task:pending_approval',
+        timestamp: new Date(),
+        payload: {
+          taskId,
+          agentId: agentId ?? '',
+          category: task.category,
+          name: task.name,
+        },
+      };
+      this.eventBus.emit(event);
+    } else {
+      // Complete directly
+      await this.taskRepository.update(taskId, { status: 'completed' });
+ 
+      // Remove from queue
+      this.taskQueue.delete(taskId);
+ 
+      log.info({ taskId }, 'task completed');
+ 
+      // Emit TaskCompletedEvent
+      const event: TaskCompletedEvent = {
+        type: 'task:completed',
+        timestamp: new Date(),
+        payload: {
+          taskId,
+          agentId: agentId ?? '',
+          success: true,
+          message: 'Task completed',
+        },
+      };
+      this.eventBus.emit(event);
+    }
+ 
+    // Also remove from blocked if it was there
+    this.blockedTasks.delete(taskId);
+  }
+ 
+  /**
+   * Approve a task that is pending approval.
+   * Sets status to 'completed' and emits completion event.
+   */
+  async approveTask(taskId: string): Promise<void> {
+    const task = await this.taskRepository.findById(taskId);
+    if (!task) {
+      throw new Error(`Task not found: ${taskId}`);
+    }
+ 
+    if (task.status !== 'pending_approval') {
+      throw new Error(`Task ${taskId} is not pending approval (status: ${task.status})`);
+    }
+ 
+    // Complete the task
+    await this.taskRepository.update(taskId, { status: 'completed' });
+ 
+    log.info({ taskId }, 'task approved and completed');
+ 
+    // Emit TaskCompletedEvent
+    const event: TaskCompletedEvent = {
+      type: 'task:completed',
+      timestamp: new Date(),
+      payload: {
+        taskId,
+        agentId: '',
+        success: true,
+        message: 'Task approved',
+      },
+    };
+    this.eventBus.emit(event);
+  }
+ 
+  /**
+   * Mark a task as blocked.
+   * Updates task status and records block reason.
+   */
+  async blockTask(taskId: string, reason: string): Promise<void> {
+    // Update task status to 'blocked'
+    await this.taskRepository.update(taskId, { status: 'blocked' });
+ 
+    // Record in blocked map
+    this.blockedTasks.set(taskId, { taskId, reason });
+ 
+    log.warn({ taskId, reason }, 'task blocked');
+ 
+    // Remove from queue (blocked tasks aren't dispatchable)
+    this.taskQueue.delete(taskId);
+ 
+    // Emit TaskBlockedEvent
+    const event: TaskBlockedEvent = {
+      type: 'task:blocked',
+      timestamp: new Date(),
+      payload: {
+        taskId,
+        reason,
+      },
+    };
+    this.eventBus.emit(event);
+  }
+ 
+  /**
+   * Dispatch next available task to an agent.
+   */
+  async dispatchNext(): Promise<DispatchResult> {
+    // Get next dispatchable task
+    const nextTask = await this.getNextDispatchable();
+ 
+    if (!nextTask) {
+      log.debug('no dispatchable tasks');
+      return {
+        success: false,
+        taskId: '',
+        reason: 'No dispatchable tasks',
+      };
+    }
+ 
+    // Find available agent (status='idle')
+    const agents = await this.agentManager.list();
+    const idleAgent = agents.find((a) => a.status === 'idle');
+ 
+    if (!idleAgent) {
+      log.debug('no available agents');
+      return {
+        success: false,
+        taskId: nextTask.taskId,
+        reason: 'No available agents',
+      };
+    }
+ 
+    // Get task details
+    const task = await this.taskRepository.findById(nextTask.taskId);
+    Iif (!task) {
+      return {
+        success: false,
+        taskId: nextTask.taskId,
+        reason: 'Task not found',
+      };
+    }
+ 
+    // Compute branch info for branch-aware spawning
+    let baseBranch: string | undefined;
+    let branchName: string | undefined;
+ 
+    Iif (task.initiativeId && this.initiativeRepository) {
+      try {
+        if (isPlanningCategory(task.category)) {
+          // Planning tasks run on project default branches — no initiative branch needed.
+          // baseBranch and branchName remain undefined; ProcessManager uses per-project defaults.
+        } else if (task.phaseId && this.phaseRepository) {
+          // Execution task — ensure initiative has a branch
+          const initiative = await this.initiativeRepository.findById(task.initiativeId);
+          if (initiative) {
+            let initBranch = initiative.branch;
+            if (!initBranch) {
+              initBranch = generateInitiativeBranch(initiative.name);
+              await this.initiativeRepository.update(initiative.id, { branch: initBranch });
+            }
+ 
+            const phase = await this.phaseRepository.findById(task.phaseId);
+            if (phase) {
+              if (task.category === 'merge') {
+                // Merge tasks work directly on the phase branch
+                baseBranch = initBranch;
+                branchName = phaseBranchName(initBranch, phase.name);
+              } else {
+                baseBranch = phaseBranchName(initBranch, phase.name);
+                branchName = taskBranchName(initBranch, task.id);
+              }
+            }
+          }
+        }
+      } catch {
+        // Non-fatal: fall back to default branching
+      }
+    }
+ 
+    // Spawn agent with task (alias auto-generated by agent manager)
+    const agent = await this.agentManager.spawn({
+      taskId: nextTask.taskId,
+      initiativeId: task.initiativeId ?? undefined,
+      phaseId: task.phaseId ?? undefined,
+      prompt: buildExecutePrompt(task.description || task.name),
+      baseBranch,
+      branchName,
+    });
+ 
+    log.info({ taskId: nextTask.taskId, agentId: agent.id }, 'task dispatched');
+ 
+    // Update task status to 'in_progress'
+    await this.taskRepository.update(nextTask.taskId, { status: 'in_progress' });
+ 
+    // Remove from queue (now being worked on)
+    this.taskQueue.delete(nextTask.taskId);
+ 
+    // Emit TaskDispatchedEvent
+    const event: TaskDispatchedEvent = {
+      type: 'task:dispatched',
+      timestamp: new Date(),
+      payload: {
+        taskId: nextTask.taskId,
+        agentId: agent.id,
+        agentName: agent.name,
+      },
+    };
+    this.eventBus.emit(event);
+ 
+    return {
+      success: true,
+      taskId: nextTask.taskId,
+      agentId: agent.id,
+    };
+  }
+ 
+  /**
+   * Get current queue state.
+   */
+  async getQueueState(): Promise<{
+    queued: QueuedTask[];
+    ready: QueuedTask[];
+    blocked: Array<{ taskId: string; reason: string }>;
+  }> {
+    const allQueued = Array.from(this.taskQueue.values());
+ 
+    // Determine which are ready
+    const ready: QueuedTask[] = [];
+    for (const qt of allQueued) {
+      const allDepsComplete = await this.areAllDependenciesComplete(qt.dependsOn);
+      if (allDepsComplete) {
+        ready.push(qt);
+      }
+    }
+ 
+    return {
+      queued: allQueued,
+      ready,
+      blocked: Array.from(this.blockedTasks.values()),
+    };
+  }
+ 
+  // =============================================================================
+  // Private Helpers
+  // =============================================================================
+ 
+  /**
+   * Check if all dependencies are complete.
+   */
+  private async areAllDependenciesComplete(dependsOn: string[]): Promise<boolean> {
+    if (dependsOn.length === 0) {
+      return true;
+    }
+ 
+    for (const depTaskId of dependsOn) {
+      const depTask = await this.taskRepository.findById(depTaskId);
+      if (!depTask || depTask.status !== 'completed') {
+        return false;
+      }
+    }
+ 
+    return true;
+  }
+ 
+  /**
+   * Check if a task is a checkpoint task.
+   * Checkpoint tasks require human action and don't auto-dispatch.
+   */
+  private isCheckpointTask(task: Task): boolean {
+    return task.type.startsWith('checkpoint:');
+  }
+ 
+  /**
+   * Determine if a task requires approval before being marked complete.
+   * Checks task-level override first, then falls back to initiative setting.
+   */
+  private async taskRequiresApproval(task: Task): Promise<boolean> {
+    // Task-level override takes precedence
+    Iif (task.requiresApproval !== null) {
+      return task.requiresApproval;
+    }
+ 
+    // Fall back to initiative setting if we have initiative access
+    Iif (this.initiativeRepository && task.initiativeId) {
+      const initiative = await this.initiativeRepository.findById(task.initiativeId);
+      if (initiative) {
+        return initiative.mergeRequiresApproval;
+      }
+    }
+ 
+    // If task has a phaseId but no initiativeId, we could traverse up but for now default to false
+    // Default: no approval required
+    return false;
+  }
+}
+ 
+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/coverage/src/dispatch/phase-manager.ts.html b/coverage/src/dispatch/phase-manager.ts.html new file mode 100644 index 0000000..00ea734 --- /dev/null +++ b/coverage/src/dispatch/phase-manager.ts.html @@ -0,0 +1,1063 @@ + + + + + + Code coverage report for src/dispatch/phase-manager.ts + + + + + + + + + +
+
+

All files / src/dispatch phase-manager.ts

+
+ +
+ 83.14% + Statements + 74/89 +
+ + +
+ 65.78% + Branches + 25/38 +
+ + +
+ 100% + Functions + 9/9 +
+ + +
+ 82.95% + Lines + 73/88 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+

+
1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 +30 +31 +32 +33 +34 +35 +36 +37 +38 +39 +40 +41 +42 +43 +44 +45 +46 +47 +48 +49 +50 +51 +52 +53 +54 +55 +56 +57 +58 +59 +60 +61 +62 +63 +64 +65 +66 +67 +68 +69 +70 +71 +72 +73 +74 +75 +76 +77 +78 +79 +80 +81 +82 +83 +84 +85 +86 +87 +88 +89 +90 +91 +92 +93 +94 +95 +96 +97 +98 +99 +100 +101 +102 +103 +104 +105 +106 +107 +108 +109 +110 +111 +112 +113 +114 +115 +116 +117 +118 +119 +120 +121 +122 +123 +124 +125 +126 +127 +128 +129 +130 +131 +132 +133 +134 +135 +136 +137 +138 +139 +140 +141 +142 +143 +144 +145 +146 +147 +148 +149 +150 +151 +152 +153 +154 +155 +156 +157 +158 +159 +160 +161 +162 +163 +164 +165 +166 +167 +168 +169 +170 +171 +172 +173 +174 +175 +176 +177 +178 +179 +180 +181 +182 +183 +184 +185 +186 +187 +188 +189 +190 +191 +192 +193 +194 +195 +196 +197 +198 +199 +200 +201 +202 +203 +204 +205 +206 +207 +208 +209 +210 +211 +212 +213 +214 +215 +216 +217 +218 +219 +220 +221 +222 +223 +224 +225 +226 +227 +228 +229 +230 +231 +232 +233 +234 +235 +236 +237 +238 +239 +240 +241 +242 +243 +244 +245 +246 +247 +248 +249 +250 +251 +252 +253 +254 +255 +256 +257 +258 +259 +260 +261 +262 +263 +264 +265 +266 +267 +268 +269 +270 +271 +272 +273 +274 +275 +276 +277 +278 +279 +280 +281 +282 +283 +284 +285 +286 +287 +288 +289 +290 +291 +292 +293 +294 +295 +296 +297 +298 +299 +300 +301 +302 +303 +304 +305 +306 +307 +308 +309 +310 +311 +312 +313 +314 +315 +316 +317 +318 +319 +320 +321 +322 +323 +324 +325 +326 +327  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +9x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +103x +  +  +103x +  +  +103x +103x +103x +103x +103x +103x +103x +103x +  +  +  +  +  +  +  +  +  +38x +38x +1x +  +  +  +37x +4x +  +  +  +33x +  +33x +  +  +  +  +  +  +33x +  +  +33x +  +  +  +  +  +  +  +  +33x +  +  +  +  +  +  +  +23x +  +23x +3x +  +  +  +20x +  +20x +37x +37x +20x +  +  +  +20x +4x +  +  +  +16x +  +16x +  +  +  +  +  +  +  +  +19x +  +19x +5x +  +  +  +  +  +  +  +14x +14x +  +  +  +  +  +  +  +  +14x +  +  +14x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +14x +  +  +14x +14x +  +  +  +  +  +  +14x +  +  +  +  +  +  +  +14x +  +14x +  +  +  +  +  +  +  +  +  +  +  +11x +11x +1x +  +  +  +10x +  +  +10x +  +  +10x +  +  +10x +  +  +  +  +  +  +  +  +  +10x +  +  +  +  +  +  +  +  +6x +  +  +6x +  +  +6x +  +  +6x +  +  +  +  +  +  +  +6x +  +  +  +  +  +  +  +  +  +  +22x +  +  +22x +22x +31x +31x +14x +  +  +  +22x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +68x +18x +  +  +50x +56x +56x +34x +  +  +  +16x +  +  + 
/**
+ * Default Phase Dispatch Manager - Adapter Implementation
+ *
+ * Implements PhaseDispatchManager interface with in-memory queue
+ * and dependency-ordered dispatch.
+ *
+ * This is the ADAPTER for the PhaseDispatchManager PORT.
+ */
+ 
+import type {
+  EventBus,
+  PhaseQueuedEvent,
+  PhaseStartedEvent,
+  PhaseCompletedEvent,
+  PhaseBlockedEvent,
+} from '../events/index.js';
+import type { PhaseRepository } from '../db/repositories/phase-repository.js';
+import type { TaskRepository } from '../db/repositories/task-repository.js';
+import type { InitiativeRepository } from '../db/repositories/initiative-repository.js';
+import type { ProjectRepository } from '../db/repositories/project-repository.js';
+import type { BranchManager } from '../git/branch-manager.js';
+import type { PhaseDispatchManager, DispatchManager, QueuedPhase, PhaseDispatchResult } from './types.js';
+import { phaseBranchName, isPlanningCategory } from '../git/branch-naming.js';
+import { ensureProjectClone } from '../git/project-clones.js';
+import { createModuleLogger } from '../logger/index.js';
+ 
+const log = createModuleLogger('phase-dispatch');
+ 
+// =============================================================================
+// Internal Types
+// =============================================================================
+ 
+/**
+ * Internal representation of a blocked phase.
+ */
+interface BlockedPhase {
+  phaseId: string;
+  reason: string;
+}
+ 
+// =============================================================================
+// DefaultPhaseDispatchManager Implementation
+// =============================================================================
+ 
+/**
+ * In-memory implementation of PhaseDispatchManager.
+ *
+ * Uses Map for queue management and checks phase_dependencies table
+ * for dependency resolution.
+ */
+export class DefaultPhaseDispatchManager implements PhaseDispatchManager {
+  /** Internal queue of phases pending dispatch */
+  private phaseQueue: Map<string, QueuedPhase> = new Map();
+ 
+  /** Blocked phases with their reasons */
+  private blockedPhases: Map<string, BlockedPhase> = new Map();
+ 
+  constructor(
+    private phaseRepository: PhaseRepository,
+    private taskRepository: TaskRepository,
+    private dispatchManager: DispatchManager,
+    private eventBus: EventBus,
+    private initiativeRepository?: InitiativeRepository,
+    private projectRepository?: ProjectRepository,
+    private branchManager?: BranchManager,
+    private workspaceRoot?: string,
+  ) {}
+ 
+  /**
+   * Queue a phase for dispatch.
+   * Only approved phases can be queued.
+   * Fetches phase dependencies and adds to internal queue.
+   */
+  async queuePhase(phaseId: string): Promise<void> {
+    // Fetch phase to verify it exists and get initiativeId
+    const phase = await this.phaseRepository.findById(phaseId);
+    if (!phase) {
+      throw new Error(`Phase not found: ${phaseId}`);
+    }
+ 
+    // Approval gate: only approved phases can be queued
+    if (phase.status !== 'approved') {
+      throw new Error(`Phase '${phaseId}' must be approved before queuing (current status: ${phase.status})`);
+    }
+ 
+    // Get dependencies for this phase
+    const dependsOn = await this.phaseRepository.getDependencies(phaseId);
+ 
+    const queuedPhase: QueuedPhase = {
+      phaseId,
+      initiativeId: phase.initiativeId,
+      queuedAt: new Date(),
+      dependsOn,
+    };
+ 
+    this.phaseQueue.set(phaseId, queuedPhase);
+ 
+    // Emit PhaseQueuedEvent
+    const event: PhaseQueuedEvent = {
+      type: 'phase:queued',
+      timestamp: new Date(),
+      payload: {
+        phaseId,
+        initiativeId: phase.initiativeId,
+        dependsOn,
+      },
+    };
+    this.eventBus.emit(event);
+  }
+ 
+  /**
+   * Get next dispatchable phase.
+   * Returns phase with all dependencies complete, sorted by queuedAt (oldest first).
+   */
+  async getNextDispatchablePhase(): Promise<QueuedPhase | null> {
+    const queuedPhases = Array.from(this.phaseQueue.values());
+ 
+    if (queuedPhases.length === 0) {
+      return null;
+    }
+ 
+    // Filter to only phases with all dependencies complete
+    const readyPhases: QueuedPhase[] = [];
+ 
+    for (const qp of queuedPhases) {
+      const allDepsComplete = await this.areAllPhaseDependenciesComplete(qp.dependsOn);
+      if (allDepsComplete) {
+        readyPhases.push(qp);
+      }
+    }
+ 
+    if (readyPhases.length === 0) {
+      return null;
+    }
+ 
+    // Sort by queuedAt (oldest first)
+    readyPhases.sort((a, b) => a.queuedAt.getTime() - b.queuedAt.getTime());
+ 
+    return readyPhases[0];
+  }
+ 
+  /**
+   * Dispatch next available phase.
+   * Updates phase status to 'in_progress', queues its tasks, and emits PhaseStartedEvent.
+   */
+  async dispatchNextPhase(): Promise<PhaseDispatchResult> {
+    // Get next dispatchable phase
+    const nextPhase = await this.getNextDispatchablePhase();
+ 
+    if (!nextPhase) {
+      return {
+        success: false,
+        phaseId: '',
+        reason: 'No dispatchable phases',
+      };
+    }
+ 
+    // Get phase details for event
+    const phase = await this.phaseRepository.findById(nextPhase.phaseId);
+    Iif (!phase) {
+      return {
+        success: false,
+        phaseId: nextPhase.phaseId,
+        reason: 'Phase not found',
+      };
+    }
+ 
+    // Update phase status to 'in_progress'
+    await this.phaseRepository.update(nextPhase.phaseId, { status: 'in_progress' });
+ 
+    // Create phase branch in all linked project clones
+    Iif (this.initiativeRepository && this.projectRepository && this.branchManager && this.workspaceRoot) {
+      try {
+        const initiative = await this.initiativeRepository.findById(phase.initiativeId);
+        if (initiative?.branch) {
+          const initBranch = initiative.branch;
+          const phBranch = phaseBranchName(initBranch, phase.name);
+          const projects = await this.projectRepository.findProjectsByInitiativeId(phase.initiativeId);
+          for (const project of projects) {
+            const clonePath = await ensureProjectClone(project, this.workspaceRoot);
+            await this.branchManager.ensureBranch(clonePath, initBranch, project.defaultBranch);
+            await this.branchManager.ensureBranch(clonePath, phBranch, initBranch);
+          }
+          log.info({ phaseId: nextPhase.phaseId, phBranch, initBranch }, 'phase branch created');
+        }
+      } catch (err) {
+        log.error({ phaseId: nextPhase.phaseId, err: err instanceof Error ? err.message : String(err) }, 'failed to create phase branch');
+      }
+    }
+ 
+    // Remove from queue (now being worked on)
+    this.phaseQueue.delete(nextPhase.phaseId);
+ 
+    // Auto-queue pending execution tasks for this phase (skip planning-category tasks)
+    const phaseTasks = await this.taskRepository.findByPhaseId(nextPhase.phaseId);
+    for (const task of phaseTasks) {
+      if (task.status === 'pending' && !isPlanningCategory(task.category)) {
+        await this.dispatchManager.queue(task.id);
+      }
+    }
+ 
+    // Emit PhaseStartedEvent
+    const event: PhaseStartedEvent = {
+      type: 'phase:started',
+      timestamp: new Date(),
+      payload: {
+        phaseId: nextPhase.phaseId,
+        initiativeId: phase.initiativeId,
+      },
+    };
+    this.eventBus.emit(event);
+ 
+    return {
+      success: true,
+      phaseId: nextPhase.phaseId,
+    };
+  }
+ 
+  /**
+   * Mark a phase as complete.
+   * Updates phase status and removes from queue.
+   */
+  async completePhase(phaseId: string): Promise<void> {
+    // Get phase for event
+    const phase = await this.phaseRepository.findById(phaseId);
+    if (!phase) {
+      throw new Error(`Phase not found: ${phaseId}`);
+    }
+ 
+    // Update phase status to 'completed'
+    await this.phaseRepository.update(phaseId, { status: 'completed' });
+ 
+    // Remove from queue
+    this.phaseQueue.delete(phaseId);
+ 
+    // Also remove from blocked if it was there
+    this.blockedPhases.delete(phaseId);
+ 
+    // Emit PhaseCompletedEvent
+    const event: PhaseCompletedEvent = {
+      type: 'phase:completed',
+      timestamp: new Date(),
+      payload: {
+        phaseId,
+        initiativeId: phase.initiativeId,
+        success: true,
+        message: 'Phase completed',
+      },
+    };
+    this.eventBus.emit(event);
+  }
+ 
+  /**
+   * Mark a phase as blocked.
+   * Updates phase status and records block reason.
+   */
+  async blockPhase(phaseId: string, reason: string): Promise<void> {
+    // Update phase status to 'blocked'
+    await this.phaseRepository.update(phaseId, { status: 'blocked' });
+ 
+    // Record in blocked map
+    this.blockedPhases.set(phaseId, { phaseId, reason });
+ 
+    // Remove from queue (blocked phases aren't dispatchable)
+    this.phaseQueue.delete(phaseId);
+ 
+    // Emit PhaseBlockedEvent
+    const event: PhaseBlockedEvent = {
+      type: 'phase:blocked',
+      timestamp: new Date(),
+      payload: {
+        phaseId,
+        reason,
+      },
+    };
+    this.eventBus.emit(event);
+  }
+ 
+  /**
+   * Get current phase queue state.
+   */
+  async getPhaseQueueState(): Promise<{
+    queued: QueuedPhase[];
+    ready: QueuedPhase[];
+    blocked: Array<{ phaseId: string; reason: string }>;
+  }> {
+    const allQueued = Array.from(this.phaseQueue.values());
+ 
+    // Determine which are ready
+    const ready: QueuedPhase[] = [];
+    for (const qp of allQueued) {
+      const allDepsComplete = await this.areAllPhaseDependenciesComplete(qp.dependsOn);
+      if (allDepsComplete) {
+        ready.push(qp);
+      }
+    }
+ 
+    return {
+      queued: allQueued,
+      ready,
+      blocked: Array.from(this.blockedPhases.values()),
+    };
+  }
+ 
+  // =============================================================================
+  // Private Helpers
+  // =============================================================================
+ 
+  /**
+   * Check if all phase dependencies are complete.
+   */
+  private async areAllPhaseDependenciesComplete(dependsOn: string[]): Promise<boolean> {
+    if (dependsOn.length === 0) {
+      return true;
+    }
+ 
+    for (const depPhaseId of dependsOn) {
+      const depPhase = await this.phaseRepository.findById(depPhaseId);
+      if (!depPhase || depPhase.status !== 'completed') {
+        return false;
+      }
+    }
+ 
+    return true;
+  }
+}
+ 
+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/coverage/src/events/bus.ts.html b/coverage/src/events/bus.ts.html new file mode 100644 index 0000000..1600f1b --- /dev/null +++ b/coverage/src/events/bus.ts.html @@ -0,0 +1,286 @@ + + + + + + Code coverage report for src/events/bus.ts + + + + + + + + + +
+
+

All files / src/events bus.ts

+
+ +
+ 100% + Statements + 6/6 +
+ + +
+ 100% + Branches + 0/0 +
+ + +
+ 100% + Functions + 5/5 +
+ + +
+ 100% + Lines + 6/6 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+

+
1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 +30 +31 +32 +33 +34 +35 +36 +37 +38 +39 +40 +41 +42 +43 +44 +45 +46 +47 +48 +49 +50 +51 +52 +53 +54 +55 +56 +57 +58 +59 +60 +61 +62 +63 +64 +65 +66 +67 +68  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +143x +  +143x +  +  +  +  +  +  +  +429x +  +  +  +  +  +  +  +  +  +246x +  +  +  +  +  +  +  +  +  +1x +  +  +  +  +  +  +  +  +  +  +1x +  +  + 
/**
+ * Event Emitter Bus - Adapter Implementation
+ *
+ * In-process EventBus implementation using Node.js EventEmitter.
+ * This is the ADAPTER for the EventBus PORT.
+ *
+ * Can be swapped for RabbitMQ, Kafka, WebSocket, etc. later
+ * without changing consumers.
+ */
+ 
+import { EventEmitter } from 'node:events';
+import type { DomainEvent, EventBus } from './types.js';
+ 
+/**
+ * EventEmitter-based implementation of the EventBus interface.
+ *
+ * Wraps Node.js EventEmitter to provide type-safe event handling
+ * that conforms to the EventBus port interface.
+ */
+export class EventEmitterBus implements EventBus {
+  private emitter: EventEmitter;
+ 
+  constructor() {
+    this.emitter = new EventEmitter();
+    // Allow more listeners for complex systems
+    this.emitter.setMaxListeners(100);
+  }
+ 
+  /**
+   * Emit an event to all subscribed handlers.
+   * The event's type property determines which handlers receive it.
+   */
+  emit<T extends DomainEvent>(event: T): void {
+    this.emitter.emit(event.type, event);
+  }
+ 
+  /**
+   * Subscribe to events of a specific type.
+   */
+  on<T extends DomainEvent>(
+    eventType: T['type'],
+    handler: (event: T) => void
+  ): void {
+    this.emitter.on(eventType, handler);
+  }
+ 
+  /**
+   * Unsubscribe from events of a specific type.
+   */
+  off<T extends DomainEvent>(
+    eventType: T['type'],
+    handler: (event: T) => void
+  ): void {
+    this.emitter.off(eventType, handler);
+  }
+ 
+  /**
+   * Subscribe to a single occurrence of an event type.
+   * Handler is automatically removed after first invocation.
+   */
+  once<T extends DomainEvent>(
+    eventType: T['type'],
+    handler: (event: T) => void
+  ): void {
+    this.emitter.once(eventType, handler);
+  }
+}
+ 
+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/coverage/src/events/index.html b/coverage/src/events/index.html new file mode 100644 index 0000000..91d92dd --- /dev/null +++ b/coverage/src/events/index.html @@ -0,0 +1,131 @@ + + + + + + Code coverage report for src/events + + + + + + + + + +
+
+

All files src/events

+
+ +
+ 100% + Statements + 7/7 +
+ + +
+ 100% + Branches + 0/0 +
+ + +
+ 100% + Functions + 6/6 +
+ + +
+ 100% + Lines + 7/7 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
FileStatementsBranchesFunctionsLines
bus.ts +
+
100%6/6100%0/0100%5/5100%6/6
index.ts +
+
100%1/1100%0/0100%1/1100%1/1
+
+
+
+ + + + + + + + \ No newline at end of file diff --git a/coverage/src/events/index.ts.html b/coverage/src/events/index.ts.html new file mode 100644 index 0000000..030eb93 --- /dev/null +++ b/coverage/src/events/index.ts.html @@ -0,0 +1,301 @@ + + + + + + Code coverage report for src/events/index.ts + + + + + + + + + +
+
+

All files / src/events index.ts

+
+ +
+ 100% + Statements + 1/1 +
+ + +
+ 100% + Branches + 0/0 +
+ + +
+ 100% + Functions + 1/1 +
+ + +
+ 100% + Lines + 1/1 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+

+
1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 +30 +31 +32 +33 +34 +35 +36 +37 +38 +39 +40 +41 +42 +43 +44 +45 +46 +47 +48 +49 +50 +51 +52 +53 +54 +55 +56 +57 +58 +59 +60 +61 +62 +63 +64 +65 +66 +67 +68 +69 +70 +71 +72 +73  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +9x +  + 
/**
+ * Events Module - Public API
+ *
+ * Exports the EventBus port interface and EventEmitter adapter.
+ * All modules should import from this index file.
+ */
+ 
+// Port interface (what consumers depend on)
+export type { EventBus, DomainEvent } from './types.js';
+ 
+// Domain event types
+export type {
+  ProcessSpawnedEvent,
+  ProcessStoppedEvent,
+  ProcessCrashedEvent,
+  ServerStartedEvent,
+  ServerStoppedEvent,
+  LogEntryEvent,
+  WorktreeCreatedEvent,
+  WorktreeRemovedEvent,
+  WorktreeMergedEvent,
+  WorktreeConflictEvent,
+  AgentSpawnedEvent,
+  AgentStoppedEvent,
+  AgentCrashedEvent,
+  AgentResumedEvent,
+  AgentAccountSwitchedEvent,
+  AgentDeletedEvent,
+  AgentWaitingEvent,
+  AgentOutputEvent,
+  TaskQueuedEvent,
+  TaskDispatchedEvent,
+  TaskCompletedEvent,
+  TaskBlockedEvent,
+  TaskPendingApprovalEvent,
+  PhaseQueuedEvent,
+  PhaseStartedEvent,
+  PhaseCompletedEvent,
+  PhaseBlockedEvent,
+  PhasePendingReviewEvent,
+  PhaseMergedEvent,
+  TaskMergedEvent,
+  MergeQueuedEvent,
+  MergeStartedEvent,
+  MergeCompletedEvent,
+  MergeConflictedEvent,
+  PageCreatedEvent,
+  PageUpdatedEvent,
+  PageDeletedEvent,
+  AccountCredentialsRefreshedEvent,
+  AccountCredentialsExpiredEvent,
+  AccountCredentialsValidatedEvent,
+  DomainEventMap,
+  DomainEventType,
+} from './types.js';
+ 
+// Adapter implementation
+export { EventEmitterBus } from './bus.js';
+ 
+// Factory function for creating event bus instances
+import { EventEmitterBus } from './bus.js';
+import type { EventBus } from './types.js';
+ 
+/**
+ * Create a new EventBus instance.
+ *
+ * Returns the default in-process EventEmitter adapter.
+ * This factory allows swapping implementations without changing call sites.
+ */
+export function createEventBus(): EventBus {
+  return new EventEmitterBus();
+}
+ 
+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/coverage/src/execution/index.html b/coverage/src/execution/index.html new file mode 100644 index 0000000..8c8d6d6 --- /dev/null +++ b/coverage/src/execution/index.html @@ -0,0 +1,116 @@ + + + + + + Code coverage report for src/execution + + + + + + + + + +
+
+

All files src/execution

+
+ +
+ 1.01% + Statements + 1/99 +
+ + +
+ 0% + Branches + 0/40 +
+ + +
+ 0% + Functions + 0/12 +
+ + +
+ 1.13% + Lines + 1/88 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
FileStatementsBranchesFunctionsLines
orchestrator.ts +
+
1.01%1/990%0/400%0/121.13%1/88
+
+
+
+ + + + + + + + \ No newline at end of file diff --git a/coverage/src/execution/orchestrator.ts.html b/coverage/src/execution/orchestrator.ts.html new file mode 100644 index 0000000..5124ad1 --- /dev/null +++ b/coverage/src/execution/orchestrator.ts.html @@ -0,0 +1,763 @@ + + + + + + Code coverage report for src/execution/orchestrator.ts + + + + + + + + + +
+
+

All files / src/execution orchestrator.ts

+
+ +
+ 1.01% + Statements + 1/99 +
+ + +
+ 0% + Branches + 0/40 +
+ + +
+ 0% + Functions + 0/12 +
+ + +
+ 1.13% + Lines + 1/88 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+

+
1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 +30 +31 +32 +33 +34 +35 +36 +37 +38 +39 +40 +41 +42 +43 +44 +45 +46 +47 +48 +49 +50 +51 +52 +53 +54 +55 +56 +57 +58 +59 +60 +61 +62 +63 +64 +65 +66 +67 +68 +69 +70 +71 +72 +73 +74 +75 +76 +77 +78 +79 +80 +81 +82 +83 +84 +85 +86 +87 +88 +89 +90 +91 +92 +93 +94 +95 +96 +97 +98 +99 +100 +101 +102 +103 +104 +105 +106 +107 +108 +109 +110 +111 +112 +113 +114 +115 +116 +117 +118 +119 +120 +121 +122 +123 +124 +125 +126 +127 +128 +129 +130 +131 +132 +133 +134 +135 +136 +137 +138 +139 +140 +141 +142 +143 +144 +145 +146 +147 +148 +149 +150 +151 +152 +153 +154 +155 +156 +157 +158 +159 +160 +161 +162 +163 +164 +165 +166 +167 +168 +169 +170 +171 +172 +173 +174 +175 +176 +177 +178 +179 +180 +181 +182 +183 +184 +185 +186 +187 +188 +189 +190 +191 +192 +193 +194 +195 +196 +197 +198 +199 +200 +201 +202 +203 +204 +205 +206 +207 +208 +209 +210 +211 +212 +213 +214 +215 +216 +217 +218 +219 +220 +221 +222 +223 +224 +225 +226 +227  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +8x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  + 
/**
+ * Execution Orchestrator
+ *
+ * Subscribes to task:completed events and orchestrates the post-completion
+ * merge workflow:
+ * - Task branch → Phase branch (on task completion)
+ * - Phase branch → Initiative branch (when all phase tasks done)
+ *
+ * Supports two execution modes:
+ * - YOLO: auto-merge everything
+ * - Review per-phase: pause after each phase for diff review
+ */
+ 
+import type { EventBus, TaskCompletedEvent, PhasePendingReviewEvent, PhaseMergedEvent, TaskMergedEvent } from '../events/index.js';
+import type { BranchManager } from '../git/branch-manager.js';
+import type { PhaseRepository } from '../db/repositories/phase-repository.js';
+import type { TaskRepository } from '../db/repositories/task-repository.js';
+import type { InitiativeRepository } from '../db/repositories/initiative-repository.js';
+import type { ProjectRepository } from '../db/repositories/project-repository.js';
+import type { PhaseDispatchManager } from '../dispatch/types.js';
+import type { ConflictResolutionService } from '../coordination/conflict-resolution-service.js';
+import { phaseBranchName, taskBranchName } from '../git/branch-naming.js';
+import { ensureProjectClone } from '../git/project-clones.js';
+import { createModuleLogger } from '../logger/index.js';
+ 
+const log = createModuleLogger('execution-orchestrator');
+ 
+export class ExecutionOrchestrator {
+  /** Serialize merges per phase to avoid concurrent merge conflicts */
+  private phaseMergeLocks: Map<string, Promise<void>> = new Map();
+ 
+  constructor(
+    private branchManager: BranchManager,
+    private phaseRepository: PhaseRepository,
+    private taskRepository: TaskRepository,
+    private initiativeRepository: InitiativeRepository,
+    private projectRepository: ProjectRepository,
+    private phaseDispatchManager: PhaseDispatchManager,
+    private conflictResolutionService: ConflictResolutionService,
+    private eventBus: EventBus,
+    private workspaceRoot: string,
+  ) {}
+ 
+  /**
+   * Start listening for task completion events.
+   */
+  start(): void {
+    this.eventBus.on<TaskCompletedEvent>('task:completed', (event) => {
+      this.handleTaskCompleted(event).catch((err) => {
+        log.error({ err: err instanceof Error ? err.message : String(err) }, 'error handling task:completed');
+      });
+    });
+    log.info('execution orchestrator started');
+  }
+ 
+  /**
+   * Handle a task:completed event.
+   * Merges the task branch into the phase branch, then checks if all phase tasks are done.
+   */
+  private async handleTaskCompleted(event: TaskCompletedEvent): Promise<void> {
+    const { taskId } = event.payload;
+ 
+    const task = await this.taskRepository.findById(taskId);
+    if (!task?.phaseId || !task.initiativeId) return;
+ 
+    const initiative = await this.initiativeRepository.findById(task.initiativeId);
+    if (!initiative?.branch) return;
+ 
+    const phase = await this.phaseRepository.findById(task.phaseId);
+    if (!phase) return;
+ 
+    // Skip merge tasks — they already work on the phase branch directly
+    if (task.category === 'merge') return;
+ 
+    const initBranch = initiative.branch;
+    const phBranch = phaseBranchName(initBranch, phase.name);
+    const tBranch = taskBranchName(initBranch, task.id);
+ 
+    // Serialize merges per phase
+    const lock = this.phaseMergeLocks.get(task.phaseId) ?? Promise.resolve();
+    const mergeOp = lock.then(async () => {
+      await this.mergeTaskIntoPhase(taskId, task.phaseId!, tBranch, phBranch);
+    });
+    this.phaseMergeLocks.set(task.phaseId, mergeOp.catch(() => {}));
+    await mergeOp;
+ 
+    // Check if all phase tasks are done
+    const phaseTasks = await this.taskRepository.findByPhaseId(task.phaseId);
+    const allDone = phaseTasks.every((t) => t.status === 'completed');
+    if (allDone) {
+      await this.handlePhaseAllTasksDone(task.phaseId);
+    }
+  }
+ 
+  /**
+   * Merge a task branch into the phase branch for all linked projects.
+   */
+  private async mergeTaskIntoPhase(
+    taskId: string,
+    phaseId: string,
+    taskBranch: string,
+    phaseBranch: string,
+  ): Promise<void> {
+    const phase = await this.phaseRepository.findById(phaseId);
+    if (!phase) return;
+ 
+    const projects = await this.projectRepository.findProjectsByInitiativeId(phase.initiativeId);
+ 
+    for (const project of projects) {
+      const clonePath = await ensureProjectClone(project, this.workspaceRoot);
+ 
+      // Only merge if the task branch actually exists (agents may not have pushed)
+      const exists = await this.branchManager.branchExists(clonePath, taskBranch);
+      if (!exists) {
+        log.debug({ taskId, taskBranch, project: project.name }, 'task branch does not exist, skipping merge');
+        continue;
+      }
+ 
+      const result = await this.branchManager.mergeBranch(clonePath, taskBranch, phaseBranch);
+ 
+      if (!result.success && result.conflicts) {
+        log.warn({ taskId, taskBranch, phaseBranch, conflicts: result.conflicts }, 'task merge conflict');
+        await this.conflictResolutionService.handleConflict(taskId, result.conflicts, {
+          sourceBranch: taskBranch,
+          targetBranch: phaseBranch,
+        });
+        return;
+      }
+ 
+      log.info({ taskId, taskBranch, phaseBranch, project: project.name }, 'task branch merged into phase branch');
+    }
+ 
+    // Emit task:merged event
+    const mergedEvent: TaskMergedEvent = {
+      type: 'task:merged',
+      timestamp: new Date(),
+      payload: { taskId, phaseId, sourceBranch: taskBranch, targetBranch: phaseBranch },
+    };
+    this.eventBus.emit(mergedEvent);
+  }
+ 
+  /**
+   * Handle all tasks in a phase being done.
+   * YOLO mode: auto-merge phase → initiative.
+   * Review mode: set phase to pending_review.
+   */
+  private async handlePhaseAllTasksDone(phaseId: string): Promise<void> {
+    const phase = await this.phaseRepository.findById(phaseId);
+    if (!phase) return;
+ 
+    const initiative = await this.initiativeRepository.findById(phase.initiativeId);
+    if (!initiative?.branch) return;
+ 
+    if (initiative.executionMode === 'yolo') {
+      await this.mergePhaseIntoInitiative(phaseId);
+      await this.phaseDispatchManager.completePhase(phaseId);
+      await this.phaseDispatchManager.dispatchNextPhase();
+    } else {
+      // review_per_phase
+      await this.phaseRepository.update(phaseId, { status: 'pending_review' as any });
+ 
+      const event: PhasePendingReviewEvent = {
+        type: 'phase:pending_review',
+        timestamp: new Date(),
+        payload: { phaseId, initiativeId: phase.initiativeId },
+      };
+      this.eventBus.emit(event);
+ 
+      log.info({ phaseId, initiativeId: phase.initiativeId }, 'phase pending review');
+    }
+  }
+ 
+  /**
+   * Merge phase branch into initiative branch for all linked projects.
+   */
+  private async mergePhaseIntoInitiative(phaseId: string): Promise<void> {
+    const phase = await this.phaseRepository.findById(phaseId);
+    if (!phase) return;
+ 
+    const initiative = await this.initiativeRepository.findById(phase.initiativeId);
+    if (!initiative?.branch) return;
+ 
+    const initBranch = initiative.branch;
+    const phBranch = phaseBranchName(initBranch, phase.name);
+ 
+    const projects = await this.projectRepository.findProjectsByInitiativeId(phase.initiativeId);
+ 
+    for (const project of projects) {
+      const clonePath = await ensureProjectClone(project, this.workspaceRoot);
+      const result = await this.branchManager.mergeBranch(clonePath, phBranch, initBranch);
+ 
+      if (!result.success) {
+        log.error({ phaseId, phBranch, initBranch, conflicts: result.conflicts }, 'phase merge conflict');
+        throw new Error(`Phase merge conflict: ${result.message}`);
+      }
+ 
+      log.info({ phaseId, phBranch, initBranch, project: project.name }, 'phase branch merged into initiative branch');
+    }
+ 
+    // Emit phase:merged event
+    const mergedEvent: PhaseMergedEvent = {
+      type: 'phase:merged',
+      timestamp: new Date(),
+      payload: { phaseId, initiativeId: phase.initiativeId, sourceBranch: phBranch, targetBranch: initBranch },
+    };
+    this.eventBus.emit(mergedEvent);
+  }
+ 
+  /**
+   * Approve and merge a phase that's pending review.
+   * Called from tRPC when user clicks approve in ReviewTab.
+   */
+  async approveAndMergePhase(phaseId: string): Promise<void> {
+    const phase = await this.phaseRepository.findById(phaseId);
+    if (!phase) throw new Error(`Phase not found: ${phaseId}`);
+    if (phase.status !== 'pending_review') {
+      throw new Error(`Phase ${phaseId} is not pending review (status: ${phase.status})`);
+    }
+ 
+    await this.mergePhaseIntoInitiative(phaseId);
+    await this.phaseDispatchManager.completePhase(phaseId);
+    await this.phaseDispatchManager.dispatchNextPhase();
+ 
+    log.info({ phaseId }, 'phase review approved and merged');
+  }
+}
+ 
+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/coverage/src/git/branch-naming.ts.html b/coverage/src/git/branch-naming.ts.html new file mode 100644 index 0000000..0f1321d --- /dev/null +++ b/coverage/src/git/branch-naming.ts.html @@ -0,0 +1,286 @@ + + + + + + Code coverage report for src/git/branch-naming.ts + + + + + + + + + +
+
+

All files / src/git branch-naming.ts

+
+ +
+ 37.5% + Statements + 3/8 +
+ + +
+ 100% + Branches + 0/0 +
+ + +
+ 16.66% + Functions + 1/6 +
+ + +
+ 37.5% + Lines + 3/8 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+

+
1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 +30 +31 +32 +33 +34 +35 +36 +37 +38 +39 +40 +41 +42 +43 +44 +45 +46 +47 +48 +49 +50 +51 +52 +53 +54 +55 +56 +57 +58 +59 +60 +61 +62 +63 +64 +65 +66 +67 +68  +  +  +  +  +  +  +  +  +  +13x +  +  +  +  +13x +  +  +  +  +  +87x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  + 
/**
+ * Branch Naming Utility
+ *
+ * Pure functions for computing deterministic branch names
+ * in the initiative → phase → task branch hierarchy.
+ */
+ 
+/**
+ * Task categories that run on the project's default branch (no initiative branch needed).
+ */
+export const PLANNING_CATEGORIES = ['research', 'discuss', 'plan', 'detail', 'refine'] as const;
+ 
+/**
+ * Task categories that require an initiative branch.
+ */
+export const EXECUTION_CATEGORIES = ['execute', 'verify', 'merge', 'review'] as const;
+ 
+/**
+ * Check if a task category is a planning category (runs on default branch).
+ */
+export function isPlanningCategory(category: string): boolean {
+  return (PLANNING_CATEGORIES as readonly string[]).includes(category);
+}
+ 
+/**
+ * Convert a name to a URL/branch-safe slug.
+ * Lowercase, replace non-alphanumeric runs with single hyphens, trim hyphens.
+ */
+export function slugify(name: string): string {
+  return name
+    .toLowerCase()
+    .replace(/[^a-z0-9]+/g, '-')
+    .replace(/^-|-$/g, '');
+}
+ 
+/**
+ * Generate an initiative branch name from the initiative name.
+ * Format: `cw/<slugified-name>`
+ */
+export function generateInitiativeBranch(name: string): string {
+  return `cw/${slugify(name)}`;
+}
+ 
+/**
+ * Compute the initiative branch name.
+ * Returns the branch as-is if set, or null if unset.
+ */
+export function initiativeBranchName(branch: string | null): string | null {
+  return branch;
+}
+ 
+/**
+ * Compute a phase branch name.
+ * Format: `<initiativeBranch>-phase-<slugified-phase-name>`
+ */
+export function phaseBranchName(initiativeBranch: string, phaseName: string): string {
+  return `${initiativeBranch}-phase-${slugify(phaseName)}`;
+}
+ 
+/**
+ * Compute a task branch name.
+ * Format: `<initiativeBranch>-task-<taskId>`
+ * Uses the raw task ID (already unique) to avoid collisions.
+ */
+export function taskBranchName(initiativeBranch: string, taskId: string): string {
+  return `${initiativeBranch}-task-${taskId}`;
+}
+ 
+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/coverage/src/git/clone.ts.html b/coverage/src/git/clone.ts.html new file mode 100644 index 0000000..5b9f3f9 --- /dev/null +++ b/coverage/src/git/clone.ts.html @@ -0,0 +1,157 @@ + + + + + + Code coverage report for src/git/clone.ts + + + + + + + + + +
+
+

All files / src/git clone.ts

+
+ +
+ 25% + Statements + 1/4 +
+ + +
+ 100% + Branches + 0/0 +
+ + +
+ 0% + Functions + 0/1 +
+ + +
+ 25% + Lines + 1/4 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+

+
1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25  +  +  +  +  +  +  +  +  +  +  +20x +  +  +  +  +  +  +  +  +  +  +  +  + 
/**
+ * Git Clone Utility
+ *
+ * Clones a git repository to a local path.
+ * Used when registering projects to create the base clone
+ * from which worktrees are later created.
+ */
+ 
+import { simpleGit } from 'simple-git';
+import { createModuleLogger } from '../logger/index.js';
+ 
+const log = createModuleLogger('git');
+ 
+/**
+ * Clone a git repository to a destination path.
+ *
+ * @param url - Remote repository URL
+ * @param destPath - Local filesystem path for the clone
+ */
+export async function cloneProject(url: string, destPath: string): Promise<void> {
+  const git = simpleGit();
+  log.info({ url, destPath }, 'cloning project');
+  await git.clone(url, destPath);
+}
+ 
+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/coverage/src/git/index.html b/coverage/src/git/index.html new file mode 100644 index 0000000..98ce643 --- /dev/null +++ b/coverage/src/git/index.html @@ -0,0 +1,176 @@ + + + + + + Code coverage report for src/git + + + + + + + + + +
+
+

All files src/git

+
+ +
+ 64.64% + Statements + 117/181 +
+ + +
+ 70.49% + Branches + 43/61 +
+ + +
+ 57.69% + Functions + 15/26 +
+ + +
+ 65.71% + Lines + 115/175 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
FileStatementsBranchesFunctionsLines
branch-naming.ts +
+
37.5%3/8100%0/016.66%1/637.5%3/8
clone.ts +
+
25%1/4100%0/00%0/125%1/4
manager.ts +
+
94.28%99/10580.39%41/51100%10/1095.09%97/102
project-clones.ts +
+
25%3/12100%0/050%1/225%3/12
simple-git-branch-manager.ts +
+
21.15%11/5220%2/1042.85%3/722.44%11/49
+
+
+
+ + + + + + + + \ No newline at end of file diff --git a/coverage/src/git/manager.ts.html b/coverage/src/git/manager.ts.html new file mode 100644 index 0000000..0ab94e9 --- /dev/null +++ b/coverage/src/git/manager.ts.html @@ -0,0 +1,1225 @@ + + + + + + Code coverage report for src/git/manager.ts + + + + + + + + + +
+
+

All files / src/git manager.ts

+
+ +
+ 94.28% + Statements + 99/105 +
+ + +
+ 80.39% + Branches + 41/51 +
+ + +
+ 100% + Functions + 10/10 +
+ + +
+ 95.09% + Lines + 97/102 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+

+
1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 +30 +31 +32 +33 +34 +35 +36 +37 +38 +39 +40 +41 +42 +43 +44 +45 +46 +47 +48 +49 +50 +51 +52 +53 +54 +55 +56 +57 +58 +59 +60 +61 +62 +63 +64 +65 +66 +67 +68 +69 +70 +71 +72 +73 +74 +75 +76 +77 +78 +79 +80 +81 +82 +83 +84 +85 +86 +87 +88 +89 +90 +91 +92 +93 +94 +95 +96 +97 +98 +99 +100 +101 +102 +103 +104 +105 +106 +107 +108 +109 +110 +111 +112 +113 +114 +115 +116 +117 +118 +119 +120 +121 +122 +123 +124 +125 +126 +127 +128 +129 +130 +131 +132 +133 +134 +135 +136 +137 +138 +139 +140 +141 +142 +143 +144 +145 +146 +147 +148 +149 +150 +151 +152 +153 +154 +155 +156 +157 +158 +159 +160 +161 +162 +163 +164 +165 +166 +167 +168 +169 +170 +171 +172 +173 +174 +175 +176 +177 +178 +179 +180 +181 +182 +183 +184 +185 +186 +187 +188 +189 +190 +191 +192 +193 +194 +195 +196 +197 +198 +199 +200 +201 +202 +203 +204 +205 +206 +207 +208 +209 +210 +211 +212 +213 +214 +215 +216 +217 +218 +219 +220 +221 +222 +223 +224 +225 +226 +227 +228 +229 +230 +231 +232 +233 +234 +235 +236 +237 +238 +239 +240 +241 +242 +243 +244 +245 +246 +247 +248 +249 +250 +251 +252 +253 +254 +255 +256 +257 +258 +259 +260 +261 +262 +263 +264 +265 +266 +267 +268 +269 +270 +271 +272 +273 +274 +275 +276 +277 +278 +279 +280 +281 +282 +283 +284 +285 +286 +287 +288 +289 +290 +291 +292 +293 +294 +295 +296 +297 +298 +299 +300 +301 +302 +303 +304 +305 +306 +307 +308 +309 +310 +311 +312 +313 +314 +315 +316 +317 +318 +319 +320 +321 +322 +323 +324 +325 +326 +327 +328 +329 +330 +331 +332 +333 +334 +335 +336 +337 +338 +339 +340 +341 +342 +343 +344 +345 +346 +347 +348 +349 +350 +351 +352 +353 +354 +355 +356 +357 +358 +359 +360 +361 +362 +363 +364 +365 +366 +367 +368 +369 +370 +371 +372 +373 +374 +375 +376 +377 +378 +379 +380 +381  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +15x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +24x +24x +24x +24x +  +  +  +  +  +  +  +  +  +  +  +  +  +20x +20x +  +  +  +20x +  +  +  +  +  +  +  +  +20x +  +  +  +  +  +  +  +20x +  +  +  +  +  +  +  +  +  +20x +  +  +  +  +  +  +  +  +5x +5x +1x +  +  +4x +4x +  +  +  +4x +  +  +4x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +23x +  +23x +  +  +  +  +  +  +  +  +18x +32x +  +  +  +  +  +  +  +  +5x +5x +1x +  +  +  +4x +  +  +  +  +4x +4x +  +  +  +  +  +  +  +4x +4x +  +  +  +  +  +  +  +  +  +4x +4x +  +  +4x +  +4x +  +5x +  +  +  +  +  +  +  +  +  +6x +6x +1x +  +5x +  +  +5x +  +5x +  +5x +  +  +5x +  +  +2x +  +  +  +  +  +  +  +  +  +6x +  +  +  +  +  +3x +  +3x +3x +3x +  +  +3x +  +  +  +  +  +  +  +  +  +  +  +3x +  +3x +  +  +  +  +  +  +  +  +  +  +5x +5x +5x +  +  +  +  +  +  +  +  +  +  +  +  +23x +23x +  +23x +23x +  +23x +141x +  +41x +  +18x +18x +  +  +  +  +  +18x +  +41x +100x +  +41x +41x +59x +  +18x +  +18x +  +  +  +  +  +23x +23x +23x +  +  +  +  +  +  +  +23x +  +  +  +  +  +  +  +  +4x +1x +  +  +3x +  +  +  +3x +3x +  +3x +5x +  +  +5x +5x +5x +  +  +5x +3x +  +  +3x +  +1x +1x +  +1x +1x +  +1x +1x +  +  +  +  +3x +  +  +  +3x +  +  + 
/**
+ * SimpleGit WorktreeManager Adapter
+ *
+ * Implementation of WorktreeManager port interface using simple-git.
+ * This is the ADAPTER for the WorktreeManager PORT.
+ *
+ * Manages git worktrees for isolated agent workspaces.
+ * Each agent gets its own worktree to avoid file conflicts.
+ */
+ 
+import path from 'node:path';
+import { simpleGit, type SimpleGit } from 'simple-git';
+import type { EventBus } from '../events/types.js';
+import type {
+  WorktreeManager,
+  Worktree,
+  WorktreeDiff,
+  MergeResult,
+} from './types.js';
+import { createModuleLogger } from '../logger/index.js';
+ 
+const log = createModuleLogger('git');
+ 
+/**
+ * SimpleGit-based implementation of the WorktreeManager interface.
+ *
+ * Wraps simple-git to provide git worktree operations
+ * that conform to the WorktreeManager port interface.
+ */
+export class SimpleGitWorktreeManager implements WorktreeManager {
+  private git: SimpleGit;
+  private repoPath: string;
+  private worktreesDir: string;
+  private eventBus?: EventBus;
+ 
+  /**
+   * Create a new SimpleGitWorktreeManager.
+   *
+   * @param repoPath - Absolute path to the git repository
+   * @param eventBus - Optional EventBus for emitting git events
+   * @param worktreesBaseDir - Optional custom base directory for worktrees (defaults to <repoPath>/.cw-worktrees)
+   */
+  constructor(repoPath: string, eventBus?: EventBus, worktreesBaseDir?: string) {
+    this.repoPath = repoPath;
+    this.git = simpleGit(repoPath);
+    this.worktreesDir = worktreesBaseDir ?? path.join(repoPath, '.cw-worktrees');
+    this.eventBus = eventBus;
+  }
+ 
+  /**
+   * Create a new worktree for isolated agent work.
+   *
+   * Creates a new branch and worktree directory.
+   * The worktree will be ready for the agent to start working.
+   */
+  async create(
+    id: string,
+    branch: string,
+    baseBranch: string = 'main'
+  ): Promise<Worktree> {
+    const worktreePath = path.join(this.worktreesDir, id);
+    log.info({ id, branch, baseBranch }, 'creating worktree');
+ 
+    // Create worktree with new branch
+    // git worktree add -b <branch> <path> <base-branch>
+    await this.git.raw([
+      'worktree',
+      'add',
+      '-b',
+      branch,
+      worktreePath,
+      baseBranch,
+    ]);
+ 
+    const worktree: Worktree = {
+      id,
+      branch,
+      path: worktreePath,
+      isMainWorktree: false,
+    };
+ 
+    // Emit event if eventBus provided
+    this.eventBus?.emit({
+      type: 'worktree:created',
+      timestamp: new Date(),
+      payload: {
+        worktreeId: id,
+        branch,
+        path: worktreePath,
+      },
+    });
+ 
+    return worktree;
+  }
+ 
+  /**
+   * Remove a worktree and optionally its branch.
+   *
+   * Cleans up the worktree directory and removes it from git's tracking.
+   */
+  async remove(id: string): Promise<void> {
+    const worktree = await this.get(id);
+    if (!worktree) {
+      throw new Error(`Worktree not found: ${id}`);
+    }
+ 
+    const branch = worktree.branch;
+    log.info({ id, branch }, 'removing worktree');
+ 
+    // Remove worktree with force to handle any uncommitted changes
+    // git worktree remove <path> --force
+    await this.git.raw(['worktree', 'remove', worktree.path, '--force']);
+ 
+    // Emit event if eventBus provided
+    this.eventBus?.emit({
+      type: 'worktree:removed',
+      timestamp: new Date(),
+      payload: {
+        worktreeId: id,
+        branch,
+      },
+    });
+  }
+ 
+  /**
+   * List all worktrees in the repository.
+   *
+   * Returns all worktrees including the main one.
+   */
+  async list(): Promise<Worktree[]> {
+    // git worktree list --porcelain
+    const output = await this.git.raw(['worktree', 'list', '--porcelain']);
+ 
+    return this.parseWorktreeList(output);
+  }
+ 
+  /**
+   * Get a specific worktree by ID.
+   *
+   * Finds worktree by matching path ending with id.
+   */
+  async get(id: string): Promise<Worktree | null> {
+    const worktrees = await this.list();
+    return worktrees.find((wt) => wt.path.endsWith(id)) ?? null;
+  }
+ 
+  /**
+   * Get the diff/changes in a worktree.
+   *
+   * Shows what files have changed compared to HEAD.
+   */
+  async diff(id: string): Promise<WorktreeDiff> {
+    const worktree = await this.get(id);
+    if (!worktree) {
+      throw new Error(`Worktree not found: ${id}`);
+    }
+ 
+    // Create git instance for the worktree directory
+    const worktreeGit = simpleGit(worktree.path);
+ 
+    // Get name-status diff against HEAD
+    // git diff --name-status HEAD
+    let diffOutput: string;
+    try {
+      diffOutput = await worktreeGit.raw(['diff', '--name-status', 'HEAD']);
+    } catch {
+      // If HEAD doesn't exist or other issues, return empty diff
+      diffOutput = '';
+    }
+ 
+    // Also get staged changes
+    let stagedOutput: string;
+    try {
+      stagedOutput = await worktreeGit.raw([
+        'diff',
+        '--name-status',
+        '--cached',
+      ]);
+    } catch {
+      stagedOutput = '';
+    }
+ 
+    // Combine and parse outputs
+    const combined = diffOutput + stagedOutput;
+    const files = this.parseDiffNameStatus(combined);
+ 
+    // Get summary
+    const fileCount = files.length;
+    const summary =
+      fileCount === 0 ? 'No changes' : `${fileCount} file(s) changed`;
+ 
+    return { files, summary };
+  }
+ 
+  /**
+   * Merge worktree changes into target branch.
+   *
+   * Attempts to merge the worktree's branch into the target branch.
+   * Returns conflict information if merge cannot be completed cleanly.
+   */
+  async merge(id: string, targetBranch: string): Promise<MergeResult> {
+    const worktree = await this.get(id);
+    if (!worktree) {
+      throw new Error(`Worktree not found: ${id}`);
+    }
+    log.info({ id, targetBranch }, 'merging worktree');
+ 
+    // Store current branch to restore later
+    const currentBranch = await this.git.revparse(['--abbrev-ref', 'HEAD']);
+ 
+    try {
+      // Checkout target branch in main repo
+      await this.git.checkout(targetBranch);
+ 
+      // Attempt merge with no-edit (no interactive editor)
+      await this.git.merge([worktree.branch, '--no-edit']);
+ 
+      // Emit success event
+      this.eventBus?.emit({
+        type: 'worktree:merged',
+        timestamp: new Date(),
+        payload: {
+          worktreeId: id,
+          sourceBranch: worktree.branch,
+          targetBranch,
+        },
+      });
+ 
+      return {
+        success: true,
+        message: 'Merged successfully',
+      };
+    } catch (error) {
+      // Check if it's a merge conflict
+      const status = await this.git.status();
+ 
+      Eif (status.conflicted.length > 0) {
+        const conflicts = status.conflicted;
+        log.warn({ id, targetBranch, conflictCount: conflicts.length }, 'merge conflicts detected');
+ 
+        // Emit conflict event
+        this.eventBus?.emit({
+          type: 'worktree:conflict',
+          timestamp: new Date(),
+          payload: {
+            worktreeId: id,
+            sourceBranch: worktree.branch,
+            targetBranch,
+            conflictingFiles: conflicts,
+          },
+        });
+ 
+        // Abort merge to clean up
+        await this.git.merge(['--abort']);
+ 
+        return {
+          success: false,
+          conflicts,
+          message: 'Merge conflicts detected',
+        };
+      }
+ 
+      // Some other error occurred, rethrow
+      throw error;
+    } finally {
+      // Restore original branch if different from target
+      try {
+        const nowBranch = await this.git.revparse(['--abbrev-ref', 'HEAD']);
+        Iif (nowBranch.trim() !== currentBranch.trim()) {
+          await this.git.checkout(currentBranch.trim());
+        }
+      } catch {
+        // Ignore errors restoring branch
+      }
+    }
+  }
+ 
+  /**
+   * Parse the porcelain output of git worktree list.
+   */
+  private parseWorktreeList(output: string): Worktree[] {
+    const worktrees: Worktree[] = [];
+    const lines = output.trim().split('\n');
+ 
+    let currentWorktree: Partial<Worktree> = {};
+    let isFirst = true;
+ 
+    for (const line of lines) {
+      if (line.startsWith('worktree ')) {
+        // Start of a new worktree entry
+        if (currentWorktree.path) {
+          // Derive ID from path
+          const id = isFirst ? 'main' : path.basename(currentWorktree.path);
+          worktrees.push({
+            id,
+            branch: currentWorktree.branch || '',
+            path: currentWorktree.path,
+            isMainWorktree: isFirst,
+          });
+          isFirst = false;
+        }
+        currentWorktree = { path: line.substring('worktree '.length) };
+      } else if (line.startsWith('branch ')) {
+        // Branch reference (e.g., "branch refs/heads/main")
+        const branchRef = line.substring('branch '.length);
+        currentWorktree.branch = branchRef.replace('refs/heads/', '');
+      } else if (line.startsWith('HEAD ')) {
+        // Detached HEAD, skip
+      I} else if (line === 'bare') {
+        // Bare worktree, skip
+      E} else if (line === '') {
+        // Empty line between worktrees
+      }
+    }
+ 
+    // Don't forget the last worktree
+    Eif (currentWorktree.path) {
+      const id = isFirst ? 'main' : path.basename(currentWorktree.path);
+      worktrees.push({
+        id,
+        branch: currentWorktree.branch || '',
+        path: currentWorktree.path,
+        isMainWorktree: isFirst,
+      });
+    }
+ 
+    return worktrees;
+  }
+ 
+  /**
+   * Parse the output of git diff --name-status.
+   */
+  private parseDiffNameStatus(
+    output: string
+  ): Array<{ path: string; status: 'added' | 'modified' | 'deleted' }> {
+    if (!output.trim()) {
+      return [];
+    }
+ 
+    const lines = output.trim().split('\n');
+    const files: Array<{
+      path: string;
+      status: 'added' | 'modified' | 'deleted';
+    }> = [];
+    const seen = new Set<string>();
+ 
+    for (const line of lines) {
+      Iif (!line.trim()) continue;
+ 
+      // Format: "M\tpath/to/file" or "A\tpath/to/file" or "D\tpath/to/file"
+      const match = line.match(/^([AMD])\t(.+)$/);
+      Eif (match) {
+        const [, statusLetter, filePath] = match;
+ 
+        // Skip duplicates (can happen when combining diff + cached)
+        if (seen.has(filePath)) continue;
+        seen.add(filePath);
+ 
+        let status: 'added' | 'modified' | 'deleted';
+        switch (statusLetter) {
+          case 'A':
+            status = 'added';
+            break;
+          case 'M':
+            status = 'modified';
+            break;
+          case 'D':
+            status = 'deleted';
+            break;
+          default:
+            continue;
+        }
+ 
+        files.push({ path: filePath, status });
+      }
+    }
+ 
+    return files;
+  }
+}
+ 
+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/coverage/src/git/project-clones.ts.html b/coverage/src/git/project-clones.ts.html new file mode 100644 index 0000000..5f84fd9 --- /dev/null +++ b/coverage/src/git/project-clones.ts.html @@ -0,0 +1,229 @@ + + + + + + Code coverage report for src/git/project-clones.ts + + + + + + + + + +
+
+

All files / src/git project-clones.ts

+
+ +
+ 25% + Statements + 3/12 +
+ + +
+ 100% + Branches + 0/0 +
+ + +
+ 50% + Functions + 1/2 +
+ + +
+ 25% + Lines + 3/12 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+

+
1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 +30 +31 +32 +33 +34 +35 +36 +37 +38 +39 +40 +41 +42 +43 +44 +45 +46 +47 +48 +49  +  +  +  +  +  +  +  +  +  +  +  +20x +  +  +  +  +  +  +5x +5x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  + 
/**
+ * Project Clone Management
+ *
+ * Ensures project repositories are cloned into the repos/ directory.
+ * These base clones are used as the source for git worktrees.
+ */
+ 
+import { join } from 'node:path';
+import { access } from 'node:fs/promises';
+import { cloneProject } from './clone.js';
+import { createModuleLogger } from '../logger/index.js';
+ 
+const log = createModuleLogger('git');
+ 
+/**
+ * Derive the canonical clone directory for a project (relative to workspace root).
+ * Convention: repos/<sanitizedName>-<id>/
+ */
+export function getProjectCloneDir(projectName: string, projectId: string): string {
+  const sanitized = projectName.toLowerCase().replace(/[^a-z0-9]+/g, '-').replace(/^-|-$/g, '');
+  return join('repos', `${sanitized}-${projectId}`);
+}
+ 
+/**
+ * Ensure a project's git repository is cloned to the workspace.
+ * Uses the canonical path: <workspaceRoot>/repos/<sanitizedName>-<id>/
+ *
+ * @param project - Project with id, name, and url
+ * @param workspaceRoot - Absolute path to the workspace root
+ * @returns Absolute path to the clone directory
+ */
+export async function ensureProjectClone(
+  project: { id: string; name: string; url: string },
+  workspaceRoot: string,
+): Promise<string> {
+  const relPath = getProjectCloneDir(project.name, project.id);
+  const clonePath = join(workspaceRoot, relPath);
+ 
+  try {
+    await access(clonePath);
+    log.debug({ project: project.name, clonePath }, 'project clone already exists');
+    return clonePath;
+  } catch {
+    log.info({ project: project.name, url: project.url, clonePath }, 'cloning project for first time');
+    await cloneProject(project.url, clonePath);
+    return clonePath;
+  }
+}
+ 
+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/coverage/src/git/simple-git-branch-manager.ts.html b/coverage/src/git/simple-git-branch-manager.ts.html new file mode 100644 index 0000000..6e93e48 --- /dev/null +++ b/coverage/src/git/simple-git-branch-manager.ts.html @@ -0,0 +1,442 @@ + + + + + + Code coverage report for src/git/simple-git-branch-manager.ts + + + + + + + + + +
+
+

All files / src/git simple-git-branch-manager.ts

+
+ +
+ 21.15% + Statements + 11/52 +
+ + +
+ 20% + Branches + 2/10 +
+ + +
+ 42.85% + Functions + 3/7 +
+ + +
+ 22.44% + Lines + 11/49 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+

+
1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 +30 +31 +32 +33 +34 +35 +36 +37 +38 +39 +40 +41 +42 +43 +44 +45 +46 +47 +48 +49 +50 +51 +52 +53 +54 +55 +56 +57 +58 +59 +60 +61 +62 +63 +64 +65 +66 +67 +68 +69 +70 +71 +72 +73 +74 +75 +76 +77 +78 +79 +80 +81 +82 +83 +84 +85 +86 +87 +88 +89 +90 +91 +92 +93 +94 +95 +96 +97 +98 +99 +100 +101 +102 +103 +104 +105 +106 +107 +108 +109 +110 +111 +112 +113 +114 +115 +116 +117 +118 +119 +120  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +9x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +1x +1x +1x +1x +  +  +  +  +  +  +7x +7x +7x +6x +13x +  +  +1x +  +  +  + 
/**
+ * SimpleGit BranchManager Adapter
+ *
+ * Implementation of BranchManager port using simple-git.
+ * Performs branch-level operations (create, merge, diff, delete)
+ * on project clones without requiring a worktree.
+ */
+ 
+import { join } from 'node:path';
+import { mkdtempSync, rmSync } from 'node:fs';
+import { tmpdir } from 'node:os';
+import { simpleGit } from 'simple-git';
+import type { BranchManager } from './branch-manager.js';
+import type { MergeResult } from './types.js';
+import { createModuleLogger } from '../logger/index.js';
+ 
+const log = createModuleLogger('branch-manager');
+ 
+export class SimpleGitBranchManager implements BranchManager {
+  async ensureBranch(repoPath: string, branch: string, baseBranch: string): Promise<void> {
+    const git = simpleGit(repoPath);
+ 
+    const exists = await this.branchExists(repoPath, branch);
+    if (exists) {
+      log.debug({ repoPath, branch }, 'branch already exists');
+      return;
+    }
+ 
+    await git.branch([branch, baseBranch]);
+    log.info({ repoPath, branch, baseBranch }, 'branch created');
+  }
+ 
+  async mergeBranch(repoPath: string, sourceBranch: string, targetBranch: string): Promise<MergeResult> {
+    // Use an ephemeral worktree for merge safety
+    const tmpPath = mkdtempSync(join(tmpdir(), 'cw-merge-'));
+    const repoGit = simpleGit(repoPath);
+ 
+    try {
+      // Create ephemeral worktree on target branch
+      await repoGit.raw(['worktree', 'add', tmpPath, targetBranch]);
+ 
+      const wtGit = simpleGit(tmpPath);
+ 
+      try {
+        await wtGit.merge([sourceBranch, '--no-edit']);
+ 
+        log.info({ repoPath, sourceBranch, targetBranch }, 'merge completed cleanly');
+        return { success: true, message: `Merged ${sourceBranch} into ${targetBranch}` };
+      } catch (mergeErr) {
+        // Check for merge conflicts
+        const status = await wtGit.status();
+        const conflicts = status.conflicted;
+ 
+        if (conflicts.length > 0) {
+          log.warn({ repoPath, sourceBranch, targetBranch, conflicts }, 'merge conflicts detected');
+          await wtGit.merge(['--abort']);
+          return {
+            success: false,
+            conflicts,
+            message: `Merge conflicts in ${conflicts.length} file(s)`,
+          };
+        }
+ 
+        // Non-conflict merge failure
+        throw mergeErr;
+      }
+    } finally {
+      // Clean up ephemeral worktree
+      try {
+        await repoGit.raw(['worktree', 'remove', tmpPath, '--force']);
+      } catch {
+        // Best-effort cleanup — force-remove the directory if worktree remove fails
+        try { rmSync(tmpPath, { recursive: true, force: true }); } catch { /* ignore */ }
+        try { await repoGit.raw(['worktree', 'prune']); } catch { /* ignore */ }
+      }
+    }
+  }
+ 
+  async diffBranches(repoPath: string, baseBranch: string, headBranch: string): Promise<string> {
+    const git = simpleGit(repoPath);
+    const diff = await git.diff([`${baseBranch}...${headBranch}`]);
+    return diff;
+  }
+ 
+  async deleteBranch(repoPath: string, branch: string): Promise<void> {
+    const git = simpleGit(repoPath);
+    const exists = await this.branchExists(repoPath, branch);
+    if (!exists) return;
+ 
+    try {
+      await git.deleteLocalBranch(branch, true);
+      log.info({ repoPath, branch }, 'branch deleted');
+    } catch (err) {
+      log.warn({ repoPath, branch, err: err instanceof Error ? err.message : String(err) }, 'failed to delete branch');
+    }
+  }
+ 
+  async branchExists(repoPath: string, branch: string): Promise<boolean> {
+    const git = simpleGit(repoPath);
+    try {
+      const branches = await git.branchLocal();
+      return branches.all.includes(branch);
+    } catch {
+      return false;
+    }
+  }
+ 
+  async remoteBranchExists(repoPath: string, branch: string): Promise<boolean> {
+    try {
+      const git = simpleGit(repoPath);
+      const result = await git.branch(['-r']);
+      return result.all.some(
+        (ref) => ref === `origin/${branch}` || ref === `remotes/origin/${branch}`,
+      );
+    } catch {
+      return false;
+    }
+  }
+}
+ 
+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/coverage/src/index.html b/coverage/src/index.html new file mode 100644 index 0000000..71afe44 --- /dev/null +++ b/coverage/src/index.html @@ -0,0 +1,116 @@ + + + + + + Code coverage report for src + + + + + + + + + +
+
+

All files src

+
+ +
+ 3.12% + Statements + 1/32 +
+ + +
+ 0% + Branches + 0/4 +
+ + +
+ 33.33% + Functions + 1/3 +
+ + +
+ 3.12% + Lines + 1/32 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
FileStatementsBranchesFunctionsLines
container.ts +
+
3.12%1/320%0/433.33%1/33.12%1/32
+
+
+
+ + + + + + + + \ No newline at end of file diff --git a/coverage/src/logger/index.html b/coverage/src/logger/index.html new file mode 100644 index 0000000..ebb96d7 --- /dev/null +++ b/coverage/src/logger/index.html @@ -0,0 +1,116 @@ + + + + + + Code coverage report for src/logger + + + + + + + + + +
+
+

All files src/logger

+
+ +
+ 80% + Statements + 4/5 +
+ + +
+ 37.5% + Branches + 3/8 +
+ + +
+ 100% + Functions + 2/2 +
+ + +
+ 75% + Lines + 3/4 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
FileStatementsBranchesFunctionsLines
index.ts +
+
80%4/537.5%3/8100%2/275%3/4
+
+
+
+ + + + + + + + \ No newline at end of file diff --git a/coverage/src/logger/index.ts.html b/coverage/src/logger/index.ts.html new file mode 100644 index 0000000..147b489 --- /dev/null +++ b/coverage/src/logger/index.ts.html @@ -0,0 +1,169 @@ + + + + + + Code coverage report for src/logger/index.ts + + + + + + + + + +
+
+

All files / src/logger index.ts

+
+ +
+ 80% + Statements + 4/5 +
+ + +
+ 37.5% + Branches + 3/8 +
+ + +
+ 100% + Functions + 2/2 +
+ + +
+ 75% + Lines + 3/4 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+

+
1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29  +  +  +42x +  +  +  +42x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +358x +  + 
import pino from 'pino';
+ 
+function resolveLevel(): string {
+  Eif (process.env.CW_LOG_LEVEL) return process.env.CW_LOG_LEVEL;
+  return process.env.NODE_ENV === 'development' ? 'debug' : 'info';
+}
+ 
+export const logger = pino(
+  {
+    name: 'cw',
+    level: resolveLevel(),
+    ...(process.env.CW_LOG_PRETTY === '1' && {
+      transport: {
+        target: 'pino-pretty',
+        options: {
+          colorize: true,
+          ignore: 'pid,hostname',
+          translateTime: 'HH:MM:ss.l',
+        },
+      },
+    }),
+  },
+  process.env.CW_LOG_PRETTY === '1' ? undefined : pino.destination(2),
+);
+ 
+export function createModuleLogger(module: string) {
+  return logger.child({ module });
+}
+ 
+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/coverage/src/logging/index.html b/coverage/src/logging/index.html new file mode 100644 index 0000000..b88bb7e --- /dev/null +++ b/coverage/src/logging/index.html @@ -0,0 +1,146 @@ + + + + + + Code coverage report for src/logging + + + + + + + + + +
+
+

All files src/logging

+
+ +
+ 95.09% + Statements + 97/102 +
+ + +
+ 91.42% + Branches + 32/35 +
+ + +
+ 93.75% + Functions + 30/32 +
+ + +
+ 94.94% + Lines + 94/99 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
FileStatementsBranchesFunctionsLines
index.ts +
+
0%0/2100%0/00%0/10%0/2
manager.ts +
+
96.77%30/3190%9/10100%10/1096.77%30/31
writer.ts +
+
97.1%67/6992%23/2595.23%20/2196.96%64/66
+
+
+
+ + + + + + + + \ No newline at end of file diff --git a/coverage/src/logging/index.ts.html b/coverage/src/logging/index.ts.html new file mode 100644 index 0000000..0bc5c48 --- /dev/null +++ b/coverage/src/logging/index.ts.html @@ -0,0 +1,235 @@ + + + + + + Code coverage report for src/logging/index.ts + + + + + + + + + +
+
+

All files / src/logging index.ts

+
+ +
+ 0% + Statements + 0/2 +
+ + +
+ 100% + Branches + 0/0 +
+ + +
+ 0% + Functions + 0/1 +
+ + +
+ 0% + Lines + 0/2 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+

+
1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 +30 +31 +32 +33 +34 +35 +36 +37 +38 +39 +40 +41 +42 +43 +44 +45 +46 +47 +48 +49 +50 +51  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  + 
/**
+ * Logging Module
+ *
+ * File-based logging infrastructure for per-process stdout/stderr capture.
+ */
+ 
+// Types
+export type { LogLevel, LogEntry, LogConfig, LogStream } from './types.js';
+ 
+// Classes
+export { LogManager } from './manager.js';
+export { ProcessLogWriter } from './writer.js';
+ 
+// Convenience functions
+import { LogManager } from './manager.js';
+import { ProcessLogWriter } from './writer.js';
+import type { EventBus } from '../events/index.js';
+ 
+/**
+ * Creates a new ProcessLogWriter with default configuration.
+ *
+ * Convenience function for common use case of creating a log writer
+ * for a specific process using default log directory (~/.cw/logs).
+ *
+ * @param processId - Unique identifier for the process
+ * @param eventBus - Optional EventBus for emitting log entry events
+ * @returns A new ProcessLogWriter instance (call open() before writing)
+ *
+ * @example
+ * ```typescript
+ * const writer = createLogger('agent-001');
+ * await writer.open();
+ * await writer.writeStdout('Hello from agent\n');
+ * await writer.close();
+ * ```
+ *
+ * @example
+ * ```typescript
+ * // With event bus for real-time streaming
+ * const bus = createEventBus();
+ * const writer = createLogger('agent-001', bus);
+ * bus.on('log:entry', (event) => console.log(event.payload));
+ * await writer.open();
+ * await writer.writeStdout('Hello from agent\n');
+ * ```
+ */
+export function createLogger(processId: string, eventBus?: EventBus): ProcessLogWriter {
+  const manager = new LogManager();
+  return new ProcessLogWriter(processId, manager, eventBus);
+}
+ 
+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/coverage/src/logging/manager.ts.html b/coverage/src/logging/manager.ts.html new file mode 100644 index 0000000..8cf9757 --- /dev/null +++ b/coverage/src/logging/manager.ts.html @@ -0,0 +1,454 @@ + + + + + + Code coverage report for src/logging/manager.ts + + + + + + + + + +
+
+

All files / src/logging manager.ts

+
+ +
+ 96.77% + Statements + 30/31 +
+ + +
+ 90% + Branches + 9/10 +
+ + +
+ 100% + Functions + 10/10 +
+ + +
+ 96.77% + Lines + 30/31 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+

+
1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 +30 +31 +32 +33 +34 +35 +36 +37 +38 +39 +40 +41 +42 +43 +44 +45 +46 +47 +48 +49 +50 +51 +52 +53 +54 +55 +56 +57 +58 +59 +60 +61 +62 +63 +64 +65 +66 +67 +68 +69 +70 +71 +72 +73 +74 +75 +76 +77 +78 +79 +80 +81 +82 +83 +84 +85 +86 +87 +88 +89 +90 +91 +92 +93 +94 +95 +96 +97 +98 +99 +100 +101 +102 +103 +104 +105 +106 +107 +108 +109 +110 +111 +112 +113 +114 +115 +116 +117 +118 +119 +120 +121 +122 +123 +124  +  +  +  +  +  +  +  +  +  +  +  +  +  +11x +  +  +  +  +  +  +  +  +  +  +  +  +  +47x +47x +  +  +  +  +  +  +  +2x +  +  +  +  +  +  +  +24x +24x +  +  +  +  +  +  +  +30x +  +  +  +  +  +  +  +  +58x +  +  +  +  +  +  +  +8x +8x +6x +9x +8x +  +  +2x +2x +  +  +  +  +  +  +  +  +  +  +  +5x +5x +1x +  +  +4x +4x +4x +  +4x +4x +4x +4x +4x +2x +2x +  +  +  +  +  +  +4x +  +  +  +  +  +  +3x +  +  + 
/**
+ * Log Manager
+ *
+ * Manages log directories and file paths for per-process logging.
+ */
+ 
+import { mkdir, readdir, rm, stat } from 'node:fs/promises';
+import { homedir } from 'node:os';
+import { join } from 'node:path';
+import type { LogConfig, LogStream } from './types.js';
+ 
+/**
+ * Default base directory for logs: ~/.cw/logs
+ */
+const DEFAULT_LOG_DIR = join(homedir(), '.cw', 'logs');
+ 
+/**
+ * Manages log directory structure and file paths.
+ *
+ * Log directory structure:
+ * ~/.cw/logs/{processId}/stdout.log
+ * ~/.cw/logs/{processId}/stderr.log
+ */
+export class LogManager {
+  private readonly baseDir: string;
+  private readonly retainDays?: number;
+ 
+  constructor(config?: Partial<LogConfig>) {
+    this.baseDir = config?.baseDir ?? DEFAULT_LOG_DIR;
+    this.retainDays = config?.retainDays;
+  }
+ 
+  /**
+   * Ensures the base log directory exists.
+   * Creates it recursively if it doesn't exist.
+   */
+  async ensureLogDir(): Promise<void> {
+    await mkdir(this.baseDir, { recursive: true });
+  }
+ 
+  /**
+   * Ensures the process-specific log directory exists.
+   * @param processId - The process identifier
+   */
+  async ensureProcessDir(processId: string): Promise<void> {
+    const processDir = this.getProcessDir(processId);
+    await mkdir(processDir, { recursive: true });
+  }
+ 
+  /**
+   * Gets the directory path for a specific process's logs.
+   * @param processId - The process identifier
+   */
+  getProcessDir(processId: string): string {
+    return join(this.baseDir, processId);
+  }
+ 
+  /**
+   * Gets the full path to a log file for a process and stream.
+   * @param processId - The process identifier
+   * @param stream - Either 'stdout' or 'stderr'
+   */
+  getLogPath(processId: string, stream: LogStream): string {
+    return join(this.baseDir, processId, `${stream}.log`);
+  }
+ 
+  /**
+   * Lists all log directories (one per process).
+   * @returns Array of process IDs that have log directories
+   */
+  async listLogs(): Promise<string[]> {
+    try {
+      const entries = await readdir(this.baseDir, { withFileTypes: true });
+      return entries
+        .filter((entry) => entry.isDirectory())
+        .map((entry) => entry.name);
+    } catch (error) {
+      // If directory doesn't exist, return empty list
+      Eif ((error as NodeJS.ErrnoException).code === 'ENOENT') {
+        return [];
+      }
+      throw error;
+    }
+  }
+ 
+  /**
+   * Removes log directories older than the specified number of days.
+   * @param retainDays - Number of days to retain logs (uses config value if not provided)
+   * @returns Number of directories removed
+   */
+  async cleanOldLogs(retainDays?: number): Promise<number> {
+    const days = retainDays ?? this.retainDays;
+    if (days === undefined) {
+      return 0;
+    }
+ 
+    const cutoffTime = Date.now() - days * 24 * 60 * 60 * 1000;
+    const processIds = await this.listLogs();
+    let removedCount = 0;
+ 
+    for (const processId of processIds) {
+      const processDir = this.getProcessDir(processId);
+      try {
+        const stats = await stat(processDir);
+        if (stats.mtime.getTime() < cutoffTime) {
+          await rm(processDir, { recursive: true, force: true });
+          removedCount++;
+        }
+      } catch {
+        // Skip if we can't stat or remove the directory
+      }
+    }
+ 
+    return removedCount;
+  }
+ 
+  /**
+   * Gets the base directory path.
+   */
+  getBaseDir(): string {
+    return this.baseDir;
+  }
+}
+ 
+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/coverage/src/logging/writer.ts.html b/coverage/src/logging/writer.ts.html new file mode 100644 index 0000000..b166c40 --- /dev/null +++ b/coverage/src/logging/writer.ts.html @@ -0,0 +1,757 @@ + + + + + + Code coverage report for src/logging/writer.ts + + + + + + + + + +
+
+

All files / src/logging writer.ts

+
+ +
+ 97.1% + Statements + 67/69 +
+ + +
+ 92% + Branches + 23/25 +
+ + +
+ 95.23% + Functions + 20/21 +
+ + +
+ 96.96% + Lines + 64/66 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+

+
1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 +30 +31 +32 +33 +34 +35 +36 +37 +38 +39 +40 +41 +42 +43 +44 +45 +46 +47 +48 +49 +50 +51 +52 +53 +54 +55 +56 +57 +58 +59 +60 +61 +62 +63 +64 +65 +66 +67 +68 +69 +70 +71 +72 +73 +74 +75 +76 +77 +78 +79 +80 +81 +82 +83 +84 +85 +86 +87 +88 +89 +90 +91 +92 +93 +94 +95 +96 +97 +98 +99 +100 +101 +102 +103 +104 +105 +106 +107 +108 +109 +110 +111 +112 +113 +114 +115 +116 +117 +118 +119 +120 +121 +122 +123 +124 +125 +126 +127 +128 +129 +130 +131 +132 +133 +134 +135 +136 +137 +138 +139 +140 +141 +142 +143 +144 +145 +146 +147 +148 +149 +150 +151 +152 +153 +154 +155 +156 +157 +158 +159 +160 +161 +162 +163 +164 +165 +166 +167 +168 +169 +170 +171 +172 +173 +174 +175 +176 +177 +178 +179 +180 +181 +182 +183 +184 +185 +186 +187 +188 +189 +190 +191 +192 +193 +194 +195 +196 +197 +198 +199 +200 +201 +202 +203 +204 +205 +206 +207 +208 +209 +210 +211 +212 +213 +214 +215 +216 +217 +218 +219 +220 +221 +222 +223 +224 +225  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +114x +19x +19x +19x +19x +19x +19x +19x +19x +  +  +  +  +  +  +  +  +  +  +  +  +27x +27x +  +  +  +  +  +  +  +  +27x +27x +27x +  +  +  +  +  +  +  +  +22x +  +  +22x +22x +  +22x +22x +  +  +22x +  +22x +22x +  +  +22x +22x +  +  +  +  +  +  +  +  +  +  +  +15x +2x +  +13x +  +  +13x +4x +4x +  +  +  +  +  +  +  +  +4x +  +  +  +  +  +  +  +  +  +  +8x +2x +  +6x +  +  +6x +2x +2x +  +  +  +  +  +  +  +  +2x +  +  +  +  +  +  +  +  +  +  +19x +19x +  +  +19x +19x +  +  +40x +19x +  +21x +  +  +  +  +19x +19x +  +  +  +  +  +  +  +  +  +  +  +40x +  +40x +22x +  +22x +22x +22x +  +22x +  +  +  +  +40x +22x +  +22x +22x +22x +  +22x +  +  +  +  +40x +  +  +  +  +  +  +  +3x +  +  +  +  +  +  +  +3x +  +  +  +  +  +  +1x +  +  + 
/**
+ * Process Log Writer
+ *
+ * Handles per-process stdout/stderr capture to individual log files.
+ * Optionally emits log events to an EventBus for real-time streaming.
+ */
+ 
+import { createWriteStream, type WriteStream } from 'node:fs';
+import type { LogManager } from './manager.js';
+import type { EventBus, LogEntryEvent } from '../events/index.js';
+ 
+/**
+ * Formats a timestamp for log output.
+ * Format: [YYYY-MM-DD HH:mm:ss.SSS]
+ */
+function formatTimestamp(date: Date): string {
+  const pad = (n: number, w = 2) => n.toString().padStart(w, '0');
+  const year = date.getFullYear();
+  const month = pad(date.getMonth() + 1);
+  const day = pad(date.getDate());
+  const hours = pad(date.getHours());
+  const minutes = pad(date.getMinutes());
+  const seconds = pad(date.getSeconds());
+  const ms = pad(date.getMilliseconds(), 3);
+  return `[${year}-${month}-${day} ${hours}:${minutes}:${seconds}.${ms}]`;
+}
+ 
+/**
+ * Writes stdout/stderr output to per-process log files.
+ *
+ * Each line of output is prefixed with a timestamp.
+ * Handles backpressure by exposing drain events on the underlying streams.
+ */
+export class ProcessLogWriter {
+  private readonly processId: string;
+  private readonly logManager: LogManager;
+  private readonly eventBus: EventBus | undefined;
+  private stdoutStream: WriteStream | null = null;
+  private stderrStream: WriteStream | null = null;
+ 
+  /**
+   * Creates a new ProcessLogWriter.
+   * @param processId - Unique identifier for the process
+   * @param logManager - LogManager instance for directory management
+   * @param eventBus - Optional EventBus for emitting log entry events
+   */
+  constructor(processId: string, logManager: LogManager, eventBus?: EventBus) {
+    this.processId = processId;
+    this.logManager = logManager;
+    this.eventBus = eventBus;
+  }
+ 
+  /**
+   * Opens file handles for stdout and stderr log files.
+   * Creates the process log directory if it doesn't exist.
+   */
+  async open(): Promise<void> {
+    // Ensure the process directory exists
+    await this.logManager.ensureProcessDir(this.processId);
+ 
+    // Open write streams in append mode
+    const stdoutPath = this.logManager.getLogPath(this.processId, 'stdout');
+    const stderrPath = this.logManager.getLogPath(this.processId, 'stderr');
+ 
+    this.stdoutStream = createWriteStream(stdoutPath, { flags: 'a' });
+    this.stderrStream = createWriteStream(stderrPath, { flags: 'a' });
+ 
+    // Wait for both streams to be ready
+    await Promise.all([
+      new Promise<void>((resolve, reject) => {
+        this.stdoutStream!.once('open', () => resolve());
+        this.stdoutStream!.once('error', reject);
+      }),
+      new Promise<void>((resolve, reject) => {
+        this.stderrStream!.once('open', () => resolve());
+        this.stderrStream!.once('error', reject);
+      }),
+    ]);
+  }
+ 
+  /**
+   * Writes data to the stdout log file with timestamps.
+   * Also emits a LogEntry event if an EventBus was provided.
+   * @param data - String or Buffer to write
+   * @returns Promise that resolves when write is complete (including drain if needed)
+   */
+  async writeStdout(data: string | Buffer): Promise<void> {
+    if (!this.stdoutStream) {
+      throw new Error('Log writer not open. Call open() first.');
+    }
+    await this.writeWithTimestamp(this.stdoutStream, data);
+ 
+    // Emit log entry event for real-time streaming
+    if (this.eventBus) {
+      const content = typeof data === 'string' ? data : data.toString('utf-8');
+      const event: LogEntryEvent = {
+        type: 'log:entry',
+        timestamp: new Date(),
+        payload: {
+          processId: this.processId,
+          stream: 'stdout',
+          data: content,
+        },
+      };
+      this.eventBus.emit(event);
+    }
+  }
+ 
+  /**
+   * Writes data to the stderr log file with timestamps.
+   * Also emits a LogEntry event if an EventBus was provided.
+   * @param data - String or Buffer to write
+   * @returns Promise that resolves when write is complete (including drain if needed)
+   */
+  async writeStderr(data: string | Buffer): Promise<void> {
+    if (!this.stderrStream) {
+      throw new Error('Log writer not open. Call open() first.');
+    }
+    await this.writeWithTimestamp(this.stderrStream, data);
+ 
+    // Emit log entry event for real-time streaming
+    if (this.eventBus) {
+      const content = typeof data === 'string' ? data : data.toString('utf-8');
+      const event: LogEntryEvent = {
+        type: 'log:entry',
+        timestamp: new Date(),
+        payload: {
+          processId: this.processId,
+          stream: 'stderr',
+          data: content,
+        },
+      };
+      this.eventBus.emit(event);
+    }
+  }
+ 
+  /**
+   * Writes data with timestamp prefix, handling backpressure.
+   */
+  private async writeWithTimestamp(
+    stream: WriteStream,
+    data: string | Buffer
+  ): Promise<void> {
+    const content = typeof data === 'string' ? data : data.toString('utf-8');
+    const timestamp = formatTimestamp(new Date());
+ 
+    // Prefix each line with timestamp
+    const lines = content.split('\n');
+    const timestampedLines = lines
+      .map((line, index) => {
+        // Don't add timestamp to empty trailing line from split
+        if (index === lines.length - 1 && line === '') {
+          return '';
+        }
+        return `${timestamp} ${line}`;
+      })
+      .join('\n');
+ 
+    // Write with backpressure handling
+    const canWrite = stream.write(timestampedLines);
+    Iif (!canWrite) {
+      // Wait for drain event before continuing
+      await new Promise<void>((resolve) => {
+        stream.once('drain', resolve);
+      });
+    }
+  }
+ 
+  /**
+   * Flushes and closes both file handles.
+   */
+  async close(): Promise<void> {
+    const closePromises: Promise<void>[] = [];
+ 
+    if (this.stdoutStream) {
+      closePromises.push(
+        new Promise<void>((resolve, reject) => {
+          this.stdoutStream!.end(() => {
+            this.stdoutStream = null;
+            resolve();
+          });
+          this.stdoutStream!.once('error', reject);
+        })
+      );
+    }
+ 
+    if (this.stderrStream) {
+      closePromises.push(
+        new Promise<void>((resolve, reject) => {
+          this.stderrStream!.end(() => {
+            this.stderrStream = null;
+            resolve();
+          });
+          this.stderrStream!.once('error', reject);
+        })
+      );
+    }
+ 
+    await Promise.all(closePromises);
+  }
+ 
+  /**
+   * Gets the stdout write stream for direct piping.
+   * @returns The stdout WriteStream or null if not open
+   */
+  getStdoutStream(): WriteStream | null {
+    return this.stdoutStream;
+  }
+ 
+  /**
+   * Gets the stderr write stream for direct piping.
+   * @returns The stderr WriteStream or null if not open
+   */
+  getStderrStream(): WriteStream | null {
+    return this.stderrStream;
+  }
+ 
+  /**
+   * Gets the process ID for this writer.
+   */
+  getProcessId(): string {
+    return this.processId;
+  }
+}
+ 
+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/coverage/src/preview/compose-generator.ts.html b/coverage/src/preview/compose-generator.ts.html new file mode 100644 index 0000000..0a702e3 --- /dev/null +++ b/coverage/src/preview/compose-generator.ts.html @@ -0,0 +1,658 @@ + + + + + + Code coverage report for src/preview/compose-generator.ts + + + + + + + + + +
+
+

All files / src/preview compose-generator.ts

+
+ +
+ 98.07% + Statements + 51/52 +
+ + +
+ 79.41% + Branches + 27/34 +
+ + +
+ 100% + Functions + 4/4 +
+ + +
+ 97.95% + Lines + 48/49 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+

+
1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 +30 +31 +32 +33 +34 +35 +36 +37 +38 +39 +40 +41 +42 +43 +44 +45 +46 +47 +48 +49 +50 +51 +52 +53 +54 +55 +56 +57 +58 +59 +60 +61 +62 +63 +64 +65 +66 +67 +68 +69 +70 +71 +72 +73 +74 +75 +76 +77 +78 +79 +80 +81 +82 +83 +84 +85 +86 +87 +88 +89 +90 +91 +92 +93 +94 +95 +96 +97 +98 +99 +100 +101 +102 +103 +104 +105 +106 +107 +108 +109 +110 +111 +112 +113 +114 +115 +116 +117 +118 +119 +120 +121 +122 +123 +124 +125 +126 +127 +128 +129 +130 +131 +132 +133 +134 +135 +136 +137 +138 +139 +140 +141 +142 +143 +144 +145 +146 +147 +148 +149 +150 +151 +152 +153 +154 +155 +156 +157 +158 +159 +160 +161 +162 +163 +164 +165 +166 +167 +168 +169 +170 +171 +172 +173 +174 +175 +176 +177 +178 +179 +180 +181 +182 +183 +184 +185 +186 +187 +188 +189 +190 +191 +192  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +9x +  +  +  +  +  +  +9x +  +  +9x +10x +10x +  +  +  +  +  +10x +9x +8x +  +  +  +  +1x +  +  +  +  +  +  +1x +1x +  +  +  +10x +1x +  +  +  +10x +  +  +  +10x +  +  +  +9x +9x +  +  +  +  +  +  +9x +  +  +9x +  +  +9x +  +9x +9x +  +  +9x +  +9x +  +  +  +  +  +  +  +  +  +18x +  +18x +23x +21x +  +  +  +  +  +  +  +18x +4x +3x +1x +  +  +18x +  +18x +21x +18x +18x +18x +  +  +3x +3x +3x +3x +  +  +  +18x +18x +  +  +  +  +  +  +  +  +  +  +  +  +  +7x +  +  +  +  +  +  +  +  +7x +2x +  +  +7x +  + 
/**
+ * Docker Compose Generator
+ *
+ * Generates docker-compose.preview.yml and Caddyfile for preview deployments.
+ * All services share a Docker network; only Caddy publishes a host port.
+ */
+ 
+import yaml from 'js-yaml';
+import type { PreviewConfig, PreviewServiceConfig } from './types.js';
+import { PREVIEW_LABELS } from './types.js';
+ 
+export interface ComposeGeneratorOptions {
+  projectPath: string;
+  port: number;
+  deploymentId: string;
+  labels: Record<string, string>;
+}
+ 
+interface ComposeService {
+  build?: { context: string; dockerfile: string } | string;
+  image?: string;
+  environment?: Record<string, string>;
+  volumes?: string[];
+  labels?: Record<string, string>;
+  networks?: string[];
+  depends_on?: string[];
+}
+ 
+interface ComposeFile {
+  services: Record<string, ComposeService>;
+  networks: Record<string, { driver: string }>;
+}
+ 
+/**
+ * Generate a Docker Compose YAML string for the preview deployment.
+ *
+ * Structure:
+ * - User-defined services with build contexts
+ * - Caddy reverse proxy publishing the single host port
+ * - Shared `preview` network
+ */
+export function generateComposeFile(
+  config: PreviewConfig,
+  opts: ComposeGeneratorOptions,
+): string {
+  const compose: ComposeFile = {
+    services: {},
+    networks: {
+      preview: { driver: 'bridge' },
+    },
+  };
+ 
+  const serviceNames: string[] = [];
+ 
+  // Add user-defined services
+  for (const [name, svc] of Object.entries(config.services)) {
+    serviceNames.push(name);
+    const service: ComposeService = {
+      labels: { ...opts.labels },
+      networks: ['preview'],
+    };
+ 
+    // Build config
+    if (svc.build) {
+      if (typeof svc.build === 'string') {
+        service.build = {
+          context: opts.projectPath,
+          dockerfile: svc.build === '.' ? 'Dockerfile' : svc.build,
+        };
+      } else {
+        service.build = {
+          context: svc.build.context.startsWith('/')
+            ? svc.build.context
+            : `${opts.projectPath}/${svc.build.context}`,
+          dockerfile: svc.build.dockerfile,
+        };
+      }
+    E} else if (svc.image) {
+      service.image = svc.image;
+    }
+ 
+    // Environment
+    if (svc.env && Object.keys(svc.env).length > 0) {
+      service.environment = svc.env;
+    }
+ 
+    // Volumes
+    Iif (svc.volumes && svc.volumes.length > 0) {
+      service.volumes = svc.volumes;
+    }
+ 
+    compose.services[name] = service;
+  }
+ 
+  // Generate and add Caddy proxy service
+  const caddyfile = generateCaddyfile(config);
+  const caddyService: ComposeService = {
+    image: 'caddy:2-alpine',
+    networks: ['preview'],
+    labels: { ...opts.labels },
+  };
+ 
+  // Caddy publishes the single host port
+  (caddyService as Record<string, unknown>).ports = [`${opts.port}:80`];
+ 
+  // Mount Caddyfile via inline config
+  (caddyService as Record<string, unknown>).command = ['caddy', 'run', '--config', '/etc/caddy/Caddyfile'];
+ 
+  // Caddy config will be written to the deployment directory and mounted
+  (caddyService as Record<string, unknown>).volumes = ['./Caddyfile:/etc/caddy/Caddyfile:ro'];
+ 
+  Eif (serviceNames.length > 0) {
+    caddyService.depends_on = serviceNames;
+  }
+ 
+  compose.services['caddy-proxy'] = caddyService;
+ 
+  return yaml.dump(compose, { lineWidth: 120, noRefs: true });
+}
+ 
+/**
+ * Generate a Caddyfile from route mappings in the preview config.
+ *
+ * Routes are sorted by specificity (longest path first) to ensure
+ * more specific routes match before catch-all.
+ */
+export function generateCaddyfile(config: PreviewConfig): string {
+  const routes: Array<{ name: string; route: string; port: number }> = [];
+ 
+  for (const [name, svc] of Object.entries(config.services)) {
+    if (svc.internal) continue;
+    routes.push({
+      name,
+      route: svc.route ?? '/',
+      port: svc.port,
+    });
+  }
+ 
+  // Sort by route specificity (longer paths first, root last)
+  routes.sort((a, b) => {
+    if (a.route === '/') return 1;
+    if (b.route === '/') return -1;
+    return b.route.length - a.route.length;
+  });
+ 
+  const lines: string[] = [':80 {'];
+ 
+  for (const route of routes) {
+    if (route.route === '/') {
+      lines.push(`  handle {`);
+      lines.push(`    reverse_proxy ${route.name}:${route.port}`);
+      lines.push(`  }`);
+    } else {
+      // Strip trailing slash for handle_path
+      const path = route.route.endsWith('/') ? route.route.slice(0, -1) : route.route;
+      lines.push(`  handle_path ${path}/* {`);
+      lines.push(`    reverse_proxy ${route.name}:${route.port}`);
+      lines.push(`  }`);
+    }
+  }
+ 
+  lines.push('}');
+  return lines.join('\n');
+}
+ 
+/**
+ * Generate compose labels for a preview deployment.
+ */
+export function generateLabels(opts: {
+  initiativeId: string;
+  phaseId?: string;
+  projectId: string;
+  branch: string;
+  port: number;
+  previewId: string;
+}): Record<string, string> {
+  const labels: Record<string, string> = {
+    [PREVIEW_LABELS.preview]: 'true',
+    [PREVIEW_LABELS.initiativeId]: opts.initiativeId,
+    [PREVIEW_LABELS.projectId]: opts.projectId,
+    [PREVIEW_LABELS.branch]: opts.branch,
+    [PREVIEW_LABELS.port]: String(opts.port),
+    [PREVIEW_LABELS.previewId]: opts.previewId,
+  };
+ 
+  if (opts.phaseId) {
+    labels[PREVIEW_LABELS.phaseId] = opts.phaseId;
+  }
+ 
+  return labels;
+}
+ 
+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/coverage/src/preview/config-reader.ts.html b/coverage/src/preview/config-reader.ts.html new file mode 100644 index 0000000..e2357b6 --- /dev/null +++ b/coverage/src/preview/config-reader.ts.html @@ -0,0 +1,577 @@ + + + + + + Code coverage report for src/preview/config-reader.ts + + + + + + + + + +
+
+

All files / src/preview config-reader.ts

+
+ +
+ 45.45% + Statements + 20/44 +
+ + +
+ 75% + Branches + 36/48 +
+ + +
+ 33.33% + Functions + 2/6 +
+ + +
+ 45.45% + Lines + 20/44 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+

+
1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 +30 +31 +32 +33 +34 +35 +36 +37 +38 +39 +40 +41 +42 +43 +44 +45 +46 +47 +48 +49 +50 +51 +52 +53 +54 +55 +56 +57 +58 +59 +60 +61 +62 +63 +64 +65 +66 +67 +68 +69 +70 +71 +72 +73 +74 +75 +76 +77 +78 +79 +80 +81 +82 +83 +84 +85 +86 +87 +88 +89 +90 +91 +92 +93 +94 +95 +96 +97 +98 +99 +100 +101 +102 +103 +104 +105 +106 +107 +108 +109 +110 +111 +112 +113 +114 +115 +116 +117 +118 +119 +120 +121 +122 +123 +124 +125 +126 +127 +128 +129 +130 +131 +132 +133 +134 +135 +136 +137 +138 +139 +140 +141 +142 +143 +144 +145 +146 +147 +148 +149 +150 +151 +152 +153 +154 +155 +156 +157 +158 +159 +160 +161 +162 +163 +164 +165  +  +  +  +  +  +  +  +  +  +  +  +  +9x +  +  +9x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +6x +  +6x +  +  +  +6x +1x +  +  +5x +5x +  +5x +7x +  +  +  +7x +7x +1x +  +  +6x +  +  +  +  +  +  +  +  +  +  +  +  +4x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +4x +2x +  +2x +2x +2x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  + 
/**
+ * Preview Config Reader
+ *
+ * Discovers and parses preview configuration from a project directory.
+ * Discovery order: .cw-preview.yml → docker-compose.yml/compose.yml → Dockerfile
+ */
+ 
+import { readFile, access } from 'node:fs/promises';
+import { join } from 'node:path';
+import yaml from 'js-yaml';
+import type { PreviewConfig, PreviewServiceConfig } from './types.js';
+import { createModuleLogger } from '../logger/index.js';
+ 
+const log = createModuleLogger('preview:config');
+ 
+/** Files to check for existing Docker Compose config */
+const COMPOSE_FILES = [
+  'docker-compose.yml',
+  'docker-compose.yaml',
+  'compose.yml',
+  'compose.yaml',
+];
+ 
+/**
+ * Discover and parse preview configuration from a project directory.
+ *
+ * Discovery order:
+ * 1. `.cw-preview.yml` — explicit CW preview config
+ * 2. `docker-compose.yml` / `compose.yml` (+ variants) — wrap existing compose
+ * 3. `Dockerfile` at root — single-service fallback (assumes port 3000)
+ *
+ * @param projectPath - Absolute path to the project directory (at the target branch)
+ * @returns Parsed and normalized PreviewConfig
+ * @throws If no config can be discovered
+ */
+export async function discoverConfig(projectPath: string): Promise<PreviewConfig> {
+  // 1. Check for explicit .cw-preview.yml
+  const cwPreviewPath = join(projectPath, '.cw-preview.yml');
+  if (await fileExists(cwPreviewPath)) {
+    log.info({ path: cwPreviewPath }, 'found .cw-preview.yml');
+    const raw = await readFile(cwPreviewPath, 'utf-8');
+    return parseCwPreviewConfig(raw);
+  }
+ 
+  // 2. Check for existing compose files
+  for (const composeFile of COMPOSE_FILES) {
+    const composePath = join(projectPath, composeFile);
+    if (await fileExists(composePath)) {
+      log.info({ path: composePath }, 'found existing compose file');
+      return parseExistingCompose(composePath, composeFile);
+    }
+  }
+ 
+  // 3. Check for Dockerfile
+  const dockerfilePath = join(projectPath, 'Dockerfile');
+  if (await fileExists(dockerfilePath)) {
+    log.info({ path: dockerfilePath }, 'found Dockerfile, using single-service fallback');
+    return createDockerfileFallback();
+  }
+ 
+  throw new Error(
+    `No preview configuration found in ${projectPath}. ` +
+    `Expected one of: .cw-preview.yml, docker-compose.yml, compose.yml, or Dockerfile`
+  );
+}
+ 
+/**
+ * Parse a `.cw-preview.yml` file into a PreviewConfig.
+ */
+export function parseCwPreviewConfig(raw: string): PreviewConfig {
+  const parsed = yaml.load(raw) as Record<string, unknown>;
+ 
+  Iif (!parsed || typeof parsed !== 'object') {
+    throw new Error('Invalid .cw-preview.yml: expected a YAML object');
+  }
+ 
+  if (!parsed.services || typeof parsed.services !== 'object') {
+    throw new Error('Invalid .cw-preview.yml: missing "services" key');
+  }
+ 
+  const services: Record<string, PreviewServiceConfig> = {};
+  const rawServices = parsed.services as Record<string, Record<string, unknown>>;
+ 
+  for (const [name, svc] of Object.entries(rawServices)) {
+    Iif (!svc || typeof svc !== 'object') {
+      throw new Error(`Invalid service "${name}": expected an object`);
+    }
+ 
+    const port = svc.port as number | undefined;
+    if (port === undefined && !svc.internal) {
+      throw new Error(`Service "${name}" must specify a "port" (or be marked "internal: true")`);
+    }
+ 
+    services[name] = {
+      name,
+      port: port ?? 0,
+      ...(svc.build !== undefined && { build: normalizeBuild(svc.build) }),
+      ...(svc.image !== undefined && { image: svc.image as string }),
+      ...(svc.route !== undefined && { route: svc.route as string }),
+      ...(svc.internal !== undefined && { internal: svc.internal as boolean }),
+      ...(svc.healthcheck !== undefined && { healthcheck: svc.healthcheck as PreviewServiceConfig['healthcheck'] }),
+      ...(svc.env !== undefined && { env: svc.env as Record<string, string> }),
+      ...(svc.volumes !== undefined && { volumes: svc.volumes as string[] }),
+    };
+  }
+ 
+  return {
+    version: 1,
+    services,
+  };
+}
+ 
+/**
+ * Wrap an existing Docker Compose file as a passthrough config.
+ */
+function parseExistingCompose(composePath: string, composeFile: string): PreviewConfig {
+  return {
+    version: 1,
+    compose: composeFile,
+    services: {},
+  };
+}
+ 
+/**
+ * Create a single-service fallback config from a Dockerfile.
+ */
+function createDockerfileFallback(): PreviewConfig {
+  return {
+    version: 1,
+    services: {
+      app: {
+        name: 'app',
+        build: '.',
+        port: 3000,
+      },
+    },
+  };
+}
+ 
+/**
+ * Normalize build config to a consistent format.
+ */
+function normalizeBuild(build: unknown): PreviewServiceConfig['build'] {
+  if (typeof build === 'string') {
+    return build;
+  }
+  Eif (typeof build === 'object' && build !== null) {
+    const b = build as Record<string, unknown>;
+    return {
+      context: (b.context as string) ?? '.',
+      dockerfile: (b.dockerfile as string) ?? 'Dockerfile',
+    };
+  }
+  return '.';
+}
+ 
+async function fileExists(path: string): Promise<boolean> {
+  try {
+    await access(path);
+    return true;
+  } catch {
+    return false;
+  }
+}
+ 
+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/coverage/src/preview/docker-client.ts.html b/coverage/src/preview/docker-client.ts.html new file mode 100644 index 0000000..8804923 --- /dev/null +++ b/coverage/src/preview/docker-client.ts.html @@ -0,0 +1,703 @@ + + + + + + Code coverage report for src/preview/docker-client.ts + + + + + + + + + +
+
+

All files / src/preview docker-client.ts

+
+ +
+ 1.92% + Statements + 1/52 +
+ + +
+ 0% + Branches + 0/19 +
+ + +
+ 0% + Functions + 0/10 +
+ + +
+ 1.92% + Lines + 1/52 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+

+
1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 +30 +31 +32 +33 +34 +35 +36 +37 +38 +39 +40 +41 +42 +43 +44 +45 +46 +47 +48 +49 +50 +51 +52 +53 +54 +55 +56 +57 +58 +59 +60 +61 +62 +63 +64 +65 +66 +67 +68 +69 +70 +71 +72 +73 +74 +75 +76 +77 +78 +79 +80 +81 +82 +83 +84 +85 +86 +87 +88 +89 +90 +91 +92 +93 +94 +95 +96 +97 +98 +99 +100 +101 +102 +103 +104 +105 +106 +107 +108 +109 +110 +111 +112 +113 +114 +115 +116 +117 +118 +119 +120 +121 +122 +123 +124 +125 +126 +127 +128 +129 +130 +131 +132 +133 +134 +135 +136 +137 +138 +139 +140 +141 +142 +143 +144 +145 +146 +147 +148 +149 +150 +151 +152 +153 +154 +155 +156 +157 +158 +159 +160 +161 +162 +163 +164 +165 +166 +167 +168 +169 +170 +171 +172 +173 +174 +175 +176 +177 +178 +179 +180 +181 +182 +183 +184 +185 +186 +187 +188 +189 +190 +191 +192 +193 +194 +195 +196 +197 +198 +199 +200 +201 +202 +203 +204 +205 +206 +207  +  +  +  +  +  +  +  +  +  +  +8x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  + 
/**
+ * Docker Client
+ *
+ * Thin wrapper around Docker CLI via execa for preview lifecycle management.
+ * No SDK dependency — uses `docker compose` subprocess calls.
+ */
+ 
+import { execa } from 'execa';
+import { createModuleLogger } from '../logger/index.js';
+import { COMPOSE_PROJECT_PREFIX, PREVIEW_LABELS } from './types.js';
+ 
+const log = createModuleLogger('preview:docker');
+ 
+/**
+ * Service status from `docker compose ps`.
+ */
+export interface ServiceStatus {
+  name: string;
+  state: string;
+  health: string;
+}
+ 
+/**
+ * Compose project from `docker compose ls`.
+ */
+export interface ComposeProject {
+  Name: string;
+  Status: string;
+  ConfigFiles: string;
+}
+ 
+/**
+ * Check if Docker is available and running.
+ */
+export async function isDockerAvailable(): Promise<boolean> {
+  try {
+    await execa('docker', ['info'], { timeout: 10000 });
+    return true;
+  } catch {
+    return false;
+  }
+}
+ 
+/**
+ * Start a compose project (build and run in background).
+ */
+export async function composeUp(composePath: string, projectName: string): Promise<void> {
+  log.info({ composePath, projectName }, 'starting compose project');
+  const cwd = composePath.substring(0, composePath.lastIndexOf('/'));
+ 
+  await execa('docker', [
+    'compose',
+    '-p', projectName,
+    '-f', composePath,
+    'up',
+    '--build',
+    '-d',
+  ], {
+    cwd,
+    timeout: 600000, // 10 minutes for builds
+  });
+}
+ 
+/**
+ * Stop and remove a compose project.
+ */
+export async function composeDown(projectName: string): Promise<void> {
+  log.info({ projectName }, 'stopping compose project');
+  await execa('docker', [
+    'compose',
+    '-p', projectName,
+    'down',
+    '--volumes',
+    '--remove-orphans',
+  ], {
+    timeout: 60000,
+  });
+}
+ 
+/**
+ * Get service statuses for a compose project.
+ */
+export async function composePs(projectName: string): Promise<ServiceStatus[]> {
+  try {
+    const result = await execa('docker', [
+      'compose',
+      '-p', projectName,
+      'ps',
+      '--format', 'json',
+    ], {
+      timeout: 15000,
+    });
+ 
+    if (!result.stdout.trim()) {
+      return [];
+    }
+ 
+    // docker compose ps --format json outputs one JSON object per line
+    const lines = result.stdout.trim().split('\n');
+    return lines.map((line) => {
+      const container = JSON.parse(line);
+      return {
+        name: container.Service || container.Name || '',
+        state: container.State || 'unknown',
+        health: container.Health || 'none',
+      };
+    });
+  } catch (error) {
+    log.warn({ projectName, err: error }, 'failed to get compose ps');
+    return [];
+  }
+}
+ 
+/**
+ * List all preview compose projects.
+ */
+export async function listPreviewProjects(): Promise<ComposeProject[]> {
+  try {
+    const result = await execa('docker', [
+      'compose',
+      'ls',
+      '--filter', `name=${COMPOSE_PROJECT_PREFIX}`,
+      '--format', 'json',
+    ], {
+      timeout: 15000,
+    });
+ 
+    if (!result.stdout.trim()) {
+      return [];
+    }
+ 
+    return JSON.parse(result.stdout);
+  } catch (error) {
+    log.warn({ err: error }, 'failed to list preview projects');
+    return [];
+  }
+}
+ 
+/**
+ * Get container labels for a compose project.
+ * Returns labels from the first container that has cw.preview=true.
+ */
+export async function getContainerLabels(projectName: string): Promise<Record<string, string>> {
+  try {
+    const result = await execa('docker', [
+      'ps',
+      '--filter', `label=${PREVIEW_LABELS.preview}=true`,
+      '--filter', `label=com.docker.compose.project=${projectName}`,
+      '--format', '{{json .Labels}}',
+    ], {
+      timeout: 15000,
+    });
+ 
+    if (!result.stdout.trim()) {
+      return {};
+    }
+ 
+    // Parse the first line's label string: "key=val,key=val,..."
+    const firstLine = result.stdout.trim().split('\n')[0];
+    const labelStr = firstLine.replace(/^"|"$/g, '');
+    const labels: Record<string, string> = {};
+ 
+    for (const pair of labelStr.split(',')) {
+      const eqIdx = pair.indexOf('=');
+      if (eqIdx > 0) {
+        const key = pair.substring(0, eqIdx);
+        const value = pair.substring(eqIdx + 1);
+        if (key.startsWith('cw.')) {
+          labels[key] = value;
+        }
+      }
+    }
+ 
+    return labels;
+  } catch (error) {
+    log.warn({ projectName, err: error }, 'failed to get container labels');
+    return {};
+  }
+}
+ 
+/**
+ * Get the ports of running preview containers by reading their cw.port labels.
+ */
+export async function getPreviewPorts(): Promise<number[]> {
+  try {
+    const result = await execa('docker', [
+      'ps',
+      '--filter', `label=${PREVIEW_LABELS.preview}=true`,
+      '--format', `{{.Label "${PREVIEW_LABELS.port}"}}`,
+    ], {
+      timeout: 15000,
+    });
+ 
+    if (!result.stdout.trim()) {
+      return [];
+    }
+ 
+    return result.stdout
+      .trim()
+      .split('\n')
+      .map((s) => parseInt(s, 10))
+      .filter((n) => !isNaN(n));
+  } catch {
+    return [];
+  }
+}
+ 
+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/coverage/src/preview/health-checker.ts.html b/coverage/src/preview/health-checker.ts.html new file mode 100644 index 0000000..380e25d --- /dev/null +++ b/coverage/src/preview/health-checker.ts.html @@ -0,0 +1,391 @@ + + + + + + Code coverage report for src/preview/health-checker.ts + + + + + + + + + +
+
+

All files / src/preview health-checker.ts

+
+ +
+ 6.52% + Statements + 3/46 +
+ + +
+ 0% + Branches + 0/19 +
+ + +
+ 0% + Functions + 0/8 +
+ + +
+ 7.69% + Lines + 3/39 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+

+
1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 +30 +31 +32 +33 +34 +35 +36 +37 +38 +39 +40 +41 +42 +43 +44 +45 +46 +47 +48 +49 +50 +51 +52 +53 +54 +55 +56 +57 +58 +59 +60 +61 +62 +63 +64 +65 +66 +67 +68 +69 +70 +71 +72 +73 +74 +75 +76 +77 +78 +79 +80 +81 +82 +83 +84 +85 +86 +87 +88 +89 +90 +91 +92 +93 +94 +95 +96 +97 +98 +99 +100 +101 +102 +103  +  +  +  +  +  +  +  +  +  +8x +  +  +8x +  +  +8x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  + 
/**
+ * Health Checker
+ *
+ * Polls service healthcheck endpoints through the Caddy proxy port
+ * to verify that preview services are ready.
+ */
+ 
+import type { PreviewConfig, HealthResult } from './types.js';
+import { createModuleLogger } from '../logger/index.js';
+ 
+const log = createModuleLogger('preview:health');
+ 
+/** Default timeout for health checks (120 seconds) */
+const DEFAULT_TIMEOUT_MS = 120_000;
+ 
+/** Default polling interval (3 seconds) */
+const DEFAULT_INTERVAL_MS = 3_000;
+ 
+/**
+ * Wait for all non-internal services to become healthy by polling their
+ * healthcheck endpoints through the Caddy proxy.
+ *
+ * @param port - The host port where Caddy is listening
+ * @param config - Preview config with service definitions
+ * @param timeoutMs - Maximum time to wait (default: 120s)
+ * @returns Per-service health results
+ */
+export async function waitForHealthy(
+  port: number,
+  config: PreviewConfig,
+  timeoutMs = DEFAULT_TIMEOUT_MS,
+): Promise<HealthResult[]> {
+  const services = Object.values(config.services).filter((svc) => {
+    if (svc.internal) return false;
+    if (!svc.healthcheck?.path) return false;
+    return true;
+  });
+ 
+  if (services.length === 0) {
+    log.info('no healthcheck endpoints configured, skipping health wait');
+    return [];
+  }
+ 
+  const deadline = Date.now() + timeoutMs;
+  const results = new Map<string, HealthResult>();
+ 
+  // Initialize all as unhealthy
+  for (const svc of services) {
+    results.set(svc.name, { name: svc.name, healthy: false });
+  }
+ 
+  while (Date.now() < deadline) {
+    const pending = services.filter((svc) => !results.get(svc.name)!.healthy);
+    if (pending.length === 0) break;
+ 
+    await Promise.all(
+      pending.map(async (svc) => {
+        const route = svc.route ?? '/';
+        const healthPath = svc.healthcheck!.path;
+        // Build URL through proxy route
+        const basePath = route === '/' ? '' : route;
+        const url = `http://127.0.0.1:${port}${basePath}${healthPath}`;
+ 
+        try {
+          const response = await fetch(url, {
+            signal: AbortSignal.timeout(5000),
+          });
+          if (response.ok) {
+            log.info({ service: svc.name, url }, 'service healthy');
+            results.set(svc.name, { name: svc.name, healthy: true });
+          }
+        } catch {
+          // Not ready yet
+        }
+      }),
+    );
+ 
+    const stillPending = services.filter((svc) => !results.get(svc.name)!.healthy);
+    if (stillPending.length === 0) break;
+ 
+    log.debug(
+      { pending: stillPending.map((s) => s.name) },
+      'waiting for services to become healthy',
+    );
+    await sleep(DEFAULT_INTERVAL_MS);
+  }
+ 
+  // Mark timed-out services
+  for (const svc of services) {
+    const result = results.get(svc.name)!;
+    if (!result.healthy) {
+      result.error = 'health check timed out';
+      log.warn({ service: svc.name }, 'service health check timed out');
+    }
+  }
+ 
+  return Array.from(results.values());
+}
+ 
+function sleep(ms: number): Promise<void> {
+  return new Promise((resolve) => setTimeout(resolve, ms));
+}
+ 
+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/coverage/src/preview/index.html b/coverage/src/preview/index.html new file mode 100644 index 0000000..2249625 --- /dev/null +++ b/coverage/src/preview/index.html @@ -0,0 +1,221 @@ + + + + + + Code coverage report for src/preview + + + + + + + + + +
+
+

All files src/preview

+
+ +
+ 62.18% + Statements + 199/320 +
+ + +
+ 64.41% + Branches + 105/163 +
+ + +
+ 49.05% + Functions + 26/53 +
+ + +
+ 62.45% + Lines + 188/301 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
FileStatementsBranchesFunctionsLines
compose-generator.ts +
+
98.07%51/5279.41%27/34100%4/497.95%48/49
config-reader.ts +
+
45.45%20/4475%36/4833.33%2/645.45%20/44
docker-client.ts +
+
1.92%1/520%0/190%0/101.92%1/52
health-checker.ts +
+
6.52%3/460%0/190%0/87.69%3/39
index.ts +
+
0%0/00%0/00%0/00%0/0
manager.ts +
+
99.02%102/10397.43%38/3973.68%14/19100%96/96
port-allocator.ts +
+
95%19/20100%4/4100%6/694.44%17/18
types.ts +
+
100%3/3100%0/0100%0/0100%3/3
+
+
+
+ + + + + + + + \ No newline at end of file diff --git a/coverage/src/preview/index.ts.html b/coverage/src/preview/index.ts.html new file mode 100644 index 0000000..5a06c10 --- /dev/null +++ b/coverage/src/preview/index.ts.html @@ -0,0 +1,181 @@ + + + + + + Code coverage report for src/preview/index.ts + + + + + + + + + +
+
+

All files / src/preview index.ts

+
+ +
+ 0% + Statements + 0/0 +
+ + +
+ 0% + Branches + 0/0 +
+ + +
+ 0% + Functions + 0/0 +
+ + +
+ 0% + Lines + 0/0 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+

+
1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 +30 +31 +32 +33  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  + 
/**
+ * Preview Module — Barrel Exports
+ */
+ 
+export { PreviewManager } from './manager.js';
+export { discoverConfig, parseCwPreviewConfig } from './config-reader.js';
+export {
+  generateComposeFile,
+  generateCaddyfile,
+  generateLabels,
+} from './compose-generator.js';
+export {
+  isDockerAvailable,
+  composeUp,
+  composeDown,
+  composePs,
+  listPreviewProjects,
+  getContainerLabels,
+} from './docker-client.js';
+export { waitForHealthy } from './health-checker.js';
+export { allocatePort } from './port-allocator.js';
+export type {
+  PreviewConfig,
+  PreviewServiceConfig,
+  PreviewStatus,
+  StartPreviewOptions,
+  HealthResult,
+} from './types.js';
+export {
+  PREVIEW_LABELS,
+  COMPOSE_PROJECT_PREFIX,
+} from './types.js';
+ 
+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/coverage/src/preview/manager.ts.html b/coverage/src/preview/manager.ts.html new file mode 100644 index 0000000..42497c6 --- /dev/null +++ b/coverage/src/preview/manager.ts.html @@ -0,0 +1,1111 @@ + + + + + + Code coverage report for src/preview/manager.ts + + + + + + + + + +
+
+

All files / src/preview manager.ts

+
+ +
+ 99.02% + Statements + 102/103 +
+ + +
+ 97.43% + Branches + 38/39 +
+ + +
+ 73.68% + Functions + 14/19 +
+ + +
+ 100% + Lines + 96/96 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+

+
1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 +30 +31 +32 +33 +34 +35 +36 +37 +38 +39 +40 +41 +42 +43 +44 +45 +46 +47 +48 +49 +50 +51 +52 +53 +54 +55 +56 +57 +58 +59 +60 +61 +62 +63 +64 +65 +66 +67 +68 +69 +70 +71 +72 +73 +74 +75 +76 +77 +78 +79 +80 +81 +82 +83 +84 +85 +86 +87 +88 +89 +90 +91 +92 +93 +94 +95 +96 +97 +98 +99 +100 +101 +102 +103 +104 +105 +106 +107 +108 +109 +110 +111 +112 +113 +114 +115 +116 +117 +118 +119 +120 +121 +122 +123 +124 +125 +126 +127 +128 +129 +130 +131 +132 +133 +134 +135 +136 +137 +138 +139 +140 +141 +142 +143 +144 +145 +146 +147 +148 +149 +150 +151 +152 +153 +154 +155 +156 +157 +158 +159 +160 +161 +162 +163 +164 +165 +166 +167 +168 +169 +170 +171 +172 +173 +174 +175 +176 +177 +178 +179 +180 +181 +182 +183 +184 +185 +186 +187 +188 +189 +190 +191 +192 +193 +194 +195 +196 +197 +198 +199 +200 +201 +202 +203 +204 +205 +206 +207 +208 +209 +210 +211 +212 +213 +214 +215 +216 +217 +218 +219 +220 +221 +222 +223 +224 +225 +226 +227 +228 +229 +230 +231 +232 +233 +234 +235 +236 +237 +238 +239 +240 +241 +242 +243 +244 +245 +246 +247 +248 +249 +250 +251 +252 +253 +254 +255 +256 +257 +258 +259 +260 +261 +262 +263 +264 +265 +266 +267 +268 +269 +270 +271 +272 +273 +274 +275 +276 +277 +278 +279 +280 +281 +282 +283 +284 +285 +286 +287 +288 +289 +290 +291 +292 +293 +294 +295 +296 +297 +298 +299 +300 +301 +302 +303 +304 +305 +306 +307 +308 +309 +310 +311 +312 +313 +314 +315 +316 +317 +318 +319 +320 +321 +322 +323 +324 +325 +326 +327 +328 +329 +330 +331 +332 +333 +334 +335 +336 +337 +338 +339 +340 +341 +342 +343  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +9x +  +  +9x +  +  +  +  +  +  +  +  +  +  +  +22x +22x +22x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +7x +1x +  +  +  +  +  +6x +6x +1x +  +  +5x +  +  +  +  +  +5x +  +  +5x +5x +5x +  +  +5x +  +  +  +  +  +  +  +  +5x +  +  +  +  +  +5x +  +  +5x +5x +  +5x +5x +5x +  +5x +  +  +5x +  +  +  +  +  +  +5x +5x +  +1x +  +1x +  +  +  +  +  +  +  +  +  +  +1x +1x +  +1x +  +  +  +4x +4x +  +4x +1x +1x +1x +1x +  +1x +  +  +  +  +  +  +  +  +  +1x +1x +  +1x +  +  +  +  +  +3x +3x +  +3x +  +  +  +  +  +  +  +  +  +  +  +3x +  +3x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +6x +  +  +6x +6x +  +6x +  +  +5x +5x +  +5x +  +5x +  +  +  +  +  +  +  +  +  +  +4x +4x +  +4x +6x +6x +  +5x +5x +  +4x +  +  +3x +3x +  +  +4x +  +  +  +  +  +  +5x +5x +  +5x +1x +  +  +4x +4x +  +4x +  +  +4x +1x +4x +1x +2x +1x +  +1x +  +  +4x +  +  +  +  +  +  +3x +3x +  +3x +  +4x +4x +1x +  +  +  +  +  +  +  +  +  +  +  +  +  +9x +9x +9x +9x +9x +  +9x +1x +  +  +8x +  +  +  +  +  +  +  +  +  +  +  +  +  + 
/**
+ * Preview Manager
+ *
+ * Orchestrates preview deployment lifecycle: start, stop, list, status.
+ * Uses Docker as the source of truth — no database persistence.
+ */
+ 
+import { join } from 'node:path';
+import { mkdir, writeFile, rm } from 'node:fs/promises';
+import { nanoid } from 'nanoid';
+import type { ProjectRepository } from '../db/repositories/project-repository.js';
+import type { EventBus } from '../events/types.js';
+import type {
+  PreviewStatus,
+  StartPreviewOptions,
+} from './types.js';
+import { COMPOSE_PROJECT_PREFIX, PREVIEW_LABELS } from './types.js';
+import { discoverConfig } from './config-reader.js';
+import { generateComposeFile, generateCaddyfile, generateLabels } from './compose-generator.js';
+import {
+  isDockerAvailable,
+  composeUp,
+  composeDown,
+  composePs,
+  listPreviewProjects,
+  getContainerLabels,
+} from './docker-client.js';
+import { waitForHealthy } from './health-checker.js';
+import { allocatePort } from './port-allocator.js';
+import { getProjectCloneDir } from '../git/project-clones.js';
+import { createModuleLogger } from '../logger/index.js';
+import type {
+  PreviewBuildingEvent,
+  PreviewReadyEvent,
+  PreviewStoppedEvent,
+  PreviewFailedEvent,
+} from '../events/types.js';
+ 
+const log = createModuleLogger('preview');
+ 
+/** Directory for preview deployment artifacts (relative to workspace root) */
+const PREVIEWS_DIR = '.cw-previews';
+ 
+export class PreviewManager {
+  private readonly projectRepository: ProjectRepository;
+  private readonly eventBus: EventBus;
+  private readonly workspaceRoot: string;
+ 
+  constructor(
+    projectRepository: ProjectRepository,
+    eventBus: EventBus,
+    workspaceRoot: string,
+  ) {
+    this.projectRepository = projectRepository;
+    this.eventBus = eventBus;
+    this.workspaceRoot = workspaceRoot;
+  }
+ 
+  /**
+   * Start a preview deployment.
+   *
+   * 1. Check Docker availability
+   * 2. Resolve project clone path
+   * 3. Discover config from project at target branch
+   * 4. Allocate port, generate ID
+   * 5. Generate compose + Caddyfile, write to .cw-previews/<id>/
+   * 6. Run composeUp, wait for healthy
+   * 7. Emit events and return status
+   */
+  async start(options: StartPreviewOptions): Promise<PreviewStatus> {
+    // 1. Check Docker
+    if (!(await isDockerAvailable())) {
+      throw new Error(
+        'Docker is not available. Please ensure Docker is installed and running.',
+      );
+    }
+ 
+    // 2. Resolve project
+    const project = await this.projectRepository.findById(options.projectId);
+    if (!project) {
+      throw new Error(`Project '${options.projectId}' not found`);
+    }
+ 
+    const clonePath = join(
+      this.workspaceRoot,
+      getProjectCloneDir(project.name, project.id),
+    );
+ 
+    // 3. Discover config
+    const config = await discoverConfig(clonePath);
+ 
+    // 4. Allocate port and generate ID
+    const port = await allocatePort();
+    const id = nanoid(10);
+    const projectName = `${COMPOSE_PROJECT_PREFIX}${id}`;
+ 
+    // 5. Generate compose artifacts
+    const labels = generateLabels({
+      initiativeId: options.initiativeId,
+      phaseId: options.phaseId,
+      projectId: options.projectId,
+      branch: options.branch,
+      port,
+      previewId: id,
+    });
+ 
+    const composeYaml = generateComposeFile(config, {
+      projectPath: clonePath,
+      port,
+      deploymentId: id,
+      labels,
+    });
+    const caddyfile = generateCaddyfile(config);
+ 
+    // Write artifacts
+    const deployDir = join(this.workspaceRoot, PREVIEWS_DIR, id);
+    await mkdir(deployDir, { recursive: true });
+ 
+    const composePath = join(deployDir, 'docker-compose.yml');
+    await writeFile(composePath, composeYaml, 'utf-8');
+    await writeFile(join(deployDir, 'Caddyfile'), caddyfile, 'utf-8');
+ 
+    log.info({ id, projectName, port, composePath }, 'preview deployment prepared');
+ 
+    // 6. Emit building event
+    this.eventBus.emit<PreviewBuildingEvent>({
+      type: 'preview:building',
+      timestamp: new Date(),
+      payload: { previewId: id, initiativeId: options.initiativeId, branch: options.branch, port },
+    });
+ 
+    // 7. Build and start
+    try {
+      await composeUp(composePath, projectName);
+    } catch (error) {
+      log.error({ id, err: error }, 'compose up failed');
+ 
+      this.eventBus.emit<PreviewFailedEvent>({
+        type: 'preview:failed',
+        timestamp: new Date(),
+        payload: {
+          previewId: id,
+          initiativeId: options.initiativeId,
+          error: (error as Error).message,
+        },
+      });
+ 
+      // Clean up
+      await composeDown(projectName).catch(() => {});
+      await rm(deployDir, { recursive: true, force: true }).catch(() => {});
+ 
+      throw new Error(`Preview build failed: ${(error as Error).message}`);
+    }
+ 
+    // 8. Health check
+    const healthResults = await waitForHealthy(port, config);
+    const allHealthy = healthResults.every((r) => r.healthy);
+ 
+    if (!allHealthy && healthResults.length > 0) {
+      const failedServices = healthResults
+        .filter((r) => !r.healthy)
+        .map((r) => r.name);
+      log.warn({ id, failedServices }, 'some services failed health checks');
+ 
+      this.eventBus.emit<PreviewFailedEvent>({
+        type: 'preview:failed',
+        timestamp: new Date(),
+        payload: {
+          previewId: id,
+          initiativeId: options.initiativeId,
+          error: `Health checks failed for: ${failedServices.join(', ')}`,
+        },
+      });
+ 
+      await composeDown(projectName).catch(() => {});
+      await rm(deployDir, { recursive: true, force: true }).catch(() => {});
+ 
+      throw new Error(
+        `Preview health checks failed for services: ${failedServices.join(', ')}`,
+      );
+    }
+ 
+    // 9. Success
+    const url = `http://localhost:${port}`;
+    log.info({ id, url }, 'preview deployment ready');
+ 
+    this.eventBus.emit<PreviewReadyEvent>({
+      type: 'preview:ready',
+      timestamp: new Date(),
+      payload: {
+        previewId: id,
+        initiativeId: options.initiativeId,
+        branch: options.branch,
+        port,
+        url,
+      },
+    });
+ 
+    const services = await composePs(projectName);
+ 
+    return {
+      id,
+      projectName,
+      initiativeId: options.initiativeId,
+      phaseId: options.phaseId,
+      projectId: options.projectId,
+      branch: options.branch,
+      port,
+      status: 'running',
+      services,
+      composePath,
+    };
+  }
+ 
+  /**
+   * Stop a preview deployment and clean up artifacts.
+   */
+  async stop(previewId: string): Promise<void> {
+    const projectName = `${COMPOSE_PROJECT_PREFIX}${previewId}`;
+ 
+    // Get labels before stopping to emit event
+    const labels = await getContainerLabels(projectName);
+    const initiativeId = labels[PREVIEW_LABELS.initiativeId] ?? '';
+ 
+    await composeDown(projectName);
+ 
+    // Clean up deployment directory
+    const deployDir = join(this.workspaceRoot, PREVIEWS_DIR, previewId);
+    await rm(deployDir, { recursive: true, force: true }).catch(() => {});
+ 
+    log.info({ previewId, projectName }, 'preview stopped');
+ 
+    this.eventBus.emit<PreviewStoppedEvent>({
+      type: 'preview:stopped',
+      timestamp: new Date(),
+      payload: { previewId, initiativeId },
+    });
+  }
+ 
+  /**
+   * List all active preview deployments, optionally filtered by initiative.
+   */
+  async list(initiativeId?: string): Promise<PreviewStatus[]> {
+    const projects = await listPreviewProjects();
+    const previews: PreviewStatus[] = [];
+ 
+    for (const project of projects) {
+      const labels = await getContainerLabels(project.Name);
+      if (!labels[PREVIEW_LABELS.preview]) continue;
+ 
+      const preview = this.labelsToStatus(project.Name, labels, project.ConfigFiles);
+      if (!preview) continue;
+ 
+      if (initiativeId && preview.initiativeId !== initiativeId) continue;
+ 
+      // Get service statuses
+      preview.services = await composePs(project.Name);
+      previews.push(preview);
+    }
+ 
+    return previews;
+  }
+ 
+  /**
+   * Get the status of a specific preview deployment.
+   */
+  async getStatus(previewId: string): Promise<PreviewStatus | null> {
+    const projectName = `${COMPOSE_PROJECT_PREFIX}${previewId}`;
+    const labels = await getContainerLabels(projectName);
+ 
+    if (!labels[PREVIEW_LABELS.preview]) {
+      return null;
+    }
+ 
+    const preview = this.labelsToStatus(projectName, labels, '');
+    Iif (!preview) return null;
+ 
+    preview.services = await composePs(projectName);
+ 
+    // Determine status from service states
+    if (preview.services.length === 0) {
+      preview.status = 'stopped';
+    } else if (preview.services.every((s) => s.state === 'running')) {
+      preview.status = 'running';
+    } else if (preview.services.some((s) => s.state === 'exited' || s.state === 'dead')) {
+      preview.status = 'failed';
+    } else {
+      preview.status = 'building';
+    }
+ 
+    return preview;
+  }
+ 
+  /**
+   * Stop all preview deployments. Called on server shutdown.
+   */
+  async stopAll(): Promise<void> {
+    const projects = await listPreviewProjects();
+    log.info({ count: projects.length }, 'stopping all preview deployments');
+ 
+    await Promise.all(
+      projects.map(async (project) => {
+        const id = project.Name.replace(COMPOSE_PROJECT_PREFIX, '');
+        await this.stop(id).catch((err) => {
+          log.warn({ projectName: project.Name, err }, 'failed to stop preview');
+        });
+      }),
+    );
+  }
+ 
+  /**
+   * Reconstruct PreviewStatus from Docker container labels.
+   */
+  private labelsToStatus(
+    projectName: string,
+    labels: Record<string, string>,
+    composePath: string,
+  ): PreviewStatus | null {
+    const previewId = labels[PREVIEW_LABELS.previewId] ?? projectName.replace(COMPOSE_PROJECT_PREFIX, '');
+    const initiativeId = labels[PREVIEW_LABELS.initiativeId];
+    const projectId = labels[PREVIEW_LABELS.projectId];
+    const branch = labels[PREVIEW_LABELS.branch];
+    const port = parseInt(labels[PREVIEW_LABELS.port] ?? '0', 10);
+ 
+    if (!initiativeId || !projectId || !branch) {
+      return null;
+    }
+ 
+    return {
+      id: previewId,
+      projectName,
+      initiativeId,
+      phaseId: labels[PREVIEW_LABELS.phaseId],
+      projectId,
+      branch,
+      port,
+      status: 'running',
+      services: [],
+      composePath,
+    };
+  }
+}
+ 
+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/coverage/src/preview/port-allocator.ts.html b/coverage/src/preview/port-allocator.ts.html new file mode 100644 index 0000000..424746b --- /dev/null +++ b/coverage/src/preview/port-allocator.ts.html @@ -0,0 +1,274 @@ + + + + + + Code coverage report for src/preview/port-allocator.ts + + + + + + + + + +
+
+

All files / src/preview port-allocator.ts

+
+ +
+ 95% + Statements + 19/20 +
+ + +
+ 100% + Branches + 4/4 +
+ + +
+ 100% + Functions + 6/6 +
+ + +
+ 94.44% + Lines + 17/18 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+

+
1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 +30 +31 +32 +33 +34 +35 +36 +37 +38 +39 +40 +41 +42 +43 +44 +45 +46 +47 +48 +49 +50 +51 +52 +53 +54 +55 +56 +57 +58 +59 +60 +61 +62 +63 +64  +  +  +  +  +  +  +  +  +  +  +9x +  +  +9x +  +  +9x +  +  +  +  +  +  +  +  +  +  +  +  +4x +4x +  +4x +8x +  +5x +4x +4x +  +  +  +  +  +  +  +  +  +  +5x +5x +  +5x +1x +  +  +5x +4x +4x +  +  +  +  + 
/**
+ * Port Allocator
+ *
+ * Finds the next available port for a preview deployment.
+ * Queries running preview containers and performs a bind test.
+ */
+ 
+import { createServer } from 'node:net';
+import { getPreviewPorts } from './docker-client.js';
+import { createModuleLogger } from '../logger/index.js';
+ 
+const log = createModuleLogger('preview:port');
+ 
+/** Starting port for preview deployments */
+const BASE_PORT = 9100;
+ 
+/** Maximum port to try before giving up */
+const MAX_PORT = 9200;
+ 
+/**
+ * Allocate the next available port for a preview deployment.
+ *
+ * 1. Queries running preview containers for their cw.port labels
+ * 2. Finds the next port >= BASE_PORT that isn't in use
+ * 3. Performs a bind test to verify no external conflict
+ *
+ * @returns An available port number
+ * @throws If no port is available in the range
+ */
+export async function allocatePort(): Promise<number> {
+  const usedPorts = new Set(await getPreviewPorts());
+  log.debug({ usedPorts: Array.from(usedPorts) }, 'ports in use by previews');
+ 
+  for (let port = BASE_PORT; port < MAX_PORT; port++) {
+    if (usedPorts.has(port)) continue;
+ 
+    if (await isPortAvailable(port)) {
+      log.info({ port }, 'allocated port');
+      return port;
+    }
+  }
+ 
+  throw new Error(`No available ports in range ${BASE_PORT}-${MAX_PORT}`);
+}
+ 
+/**
+ * Test if a port is available by attempting to bind to it.
+ */
+async function isPortAvailable(port: number): Promise<boolean> {
+  return new Promise((resolve) => {
+    const server = createServer();
+ 
+    server.once('error', () => {
+      resolve(false);
+    });
+ 
+    server.listen(port, '127.0.0.1', () => {
+      server.close(() => {
+        resolve(true);
+      });
+    });
+  });
+}
+ 
+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/coverage/src/preview/types.ts.html b/coverage/src/preview/types.ts.html new file mode 100644 index 0000000..3950a25 --- /dev/null +++ b/coverage/src/preview/types.ts.html @@ -0,0 +1,343 @@ + + + + + + Code coverage report for src/preview/types.ts + + + + + + + + + +
+
+

All files / src/preview types.ts

+
+ +
+ 100% + Statements + 3/3 +
+ + +
+ 100% + Branches + 0/0 +
+ + +
+ 100% + Functions + 0/0 +
+ + +
+ 100% + Lines + 3/3 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+

+
1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 +30 +31 +32 +33 +34 +35 +36 +37 +38 +39 +40 +41 +42 +43 +44 +45 +46 +47 +48 +49 +50 +51 +52 +53 +54 +55 +56 +57 +58 +59 +60 +61 +62 +63 +64 +65 +66 +67 +68 +69 +70 +71 +72 +73 +74 +75 +76 +77 +78 +79 +80 +81 +82 +83 +84 +85 +86 +87  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +10x +10x +  +  +  +  +  +  +  +  +  +  +  +  +10x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  + 
/**
+ * Preview Deployment Types
+ *
+ * Configuration and status types for Docker-based preview deployments.
+ * Docker IS the source of truth — no database table needed.
+ */
+ 
+/**
+ * Service configuration within a preview deployment.
+ */
+export interface PreviewServiceConfig {
+  name: string;
+  build?: { context: string; dockerfile: string } | string;
+  image?: string;
+  port: number;
+  route?: string;
+  internal?: boolean;
+  healthcheck?: { path: string; interval?: string; retries?: number };
+  env?: Record<string, string>;
+  volumes?: string[];
+}
+ 
+/**
+ * Preview deployment configuration.
+ * Parsed from `.cw-preview.yml`, existing compose file, or inferred from Dockerfile.
+ */
+export interface PreviewConfig {
+  version: 1;
+  compose?: string;
+  services: Record<string, PreviewServiceConfig>;
+}
+ 
+/**
+ * Runtime status of a preview deployment.
+ * Reconstructed from Docker state + container labels.
+ */
+export interface PreviewStatus {
+  id: string;
+  projectName: string;
+  initiativeId: string;
+  phaseId?: string;
+  projectId: string;
+  branch: string;
+  port: number;
+  status: 'building' | 'running' | 'stopped' | 'failed';
+  services: Array<{ name: string; state: string; health: string }>;
+  composePath: string;
+}
+ 
+/**
+ * Docker labels applied to preview containers for metadata retrieval.
+ */
+export const PREVIEW_LABEL_PREFIX = 'cw';
+export const PREVIEW_LABELS = {
+  preview: `${PREVIEW_LABEL_PREFIX}.preview`,
+  initiativeId: `${PREVIEW_LABEL_PREFIX}.initiative-id`,
+  phaseId: `${PREVIEW_LABEL_PREFIX}.phase-id`,
+  branch: `${PREVIEW_LABEL_PREFIX}.branch`,
+  projectId: `${PREVIEW_LABEL_PREFIX}.project-id`,
+  port: `${PREVIEW_LABEL_PREFIX}.port`,
+  previewId: `${PREVIEW_LABEL_PREFIX}.preview-id`,
+} as const;
+ 
+/**
+ * Compose project name prefix for all preview deployments.
+ */
+export const COMPOSE_PROJECT_PREFIX = 'cw-preview-';
+ 
+/**
+ * Options for starting a preview deployment.
+ */
+export interface StartPreviewOptions {
+  initiativeId: string;
+  phaseId?: string;
+  projectId: string;
+  branch: string;
+}
+ 
+/**
+ * Health check result for a single service.
+ */
+export interface HealthResult {
+  name: string;
+  healthy: boolean;
+  error?: string;
+}
+ 
+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/coverage/src/process/index.html b/coverage/src/process/index.html new file mode 100644 index 0000000..6823ba4 --- /dev/null +++ b/coverage/src/process/index.html @@ -0,0 +1,146 @@ + + + + + + Code coverage report for src/process + + + + + + + + + +
+
+

All files src/process

+
+ +
+ 80.73% + Statements + 88/109 +
+ + +
+ 85.36% + Branches + 35/41 +
+ + +
+ 71.42% + Functions + 20/28 +
+ + +
+ 80.37% + Lines + 86/107 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
FileStatementsBranchesFunctionsLines
index.ts +
+
0%0/00%0/00%0/00%0/0
manager.ts +
+
77.41%72/9383.78%31/3760%12/2076.92%70/91
registry.ts +
+
100%16/16100%4/4100%8/8100%16/16
+
+
+
+ + + + + + + + \ No newline at end of file diff --git a/coverage/src/process/index.ts.html b/coverage/src/process/index.ts.html new file mode 100644 index 0000000..806add1 --- /dev/null +++ b/coverage/src/process/index.ts.html @@ -0,0 +1,112 @@ + + + + + + Code coverage report for src/process/index.ts + + + + + + + + + +
+
+

All files / src/process index.ts

+
+ +
+ 0% + Statements + 0/0 +
+ + +
+ 0% + Branches + 0/0 +
+ + +
+ 0% + Functions + 0/0 +
+ + +
+ 0% + Lines + 0/0 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+

+
1 +2 +3 +4 +5 +6 +7 +8 +9 +10  +  +  +  +  +  +  +  +  + 
/**
+ * Process Module
+ *
+ * Exports for process management functionality.
+ */
+ 
+export { ProcessManager } from './manager.js';
+export { ProcessRegistry } from './registry.js';
+export type { ProcessInfo, ProcessStatus, SpawnOptions } from './types.js';
+ 
+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/coverage/src/process/manager.ts.html b/coverage/src/process/manager.ts.html new file mode 100644 index 0000000..d65de92 --- /dev/null +++ b/coverage/src/process/manager.ts.html @@ -0,0 +1,1033 @@ + + + + + + Code coverage report for src/process/manager.ts + + + + + + + + + +
+
+

All files / src/process manager.ts

+
+ +
+ 77.41% + Statements + 72/93 +
+ + +
+ 83.78% + Branches + 31/37 +
+ + +
+ 60% + Functions + 12/20 +
+ + +
+ 76.92% + Lines + 70/91 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+

+
1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 +30 +31 +32 +33 +34 +35 +36 +37 +38 +39 +40 +41 +42 +43 +44 +45 +46 +47 +48 +49 +50 +51 +52 +53 +54 +55 +56 +57 +58 +59 +60 +61 +62 +63 +64 +65 +66 +67 +68 +69 +70 +71 +72 +73 +74 +75 +76 +77 +78 +79 +80 +81 +82 +83 +84 +85 +86 +87 +88 +89 +90 +91 +92 +93 +94 +95 +96 +97 +98 +99 +100 +101 +102 +103 +104 +105 +106 +107 +108 +109 +110 +111 +112 +113 +114 +115 +116 +117 +118 +119 +120 +121 +122 +123 +124 +125 +126 +127 +128 +129 +130 +131 +132 +133 +134 +135 +136 +137 +138 +139 +140 +141 +142 +143 +144 +145 +146 +147 +148 +149 +150 +151 +152 +153 +154 +155 +156 +157 +158 +159 +160 +161 +162 +163 +164 +165 +166 +167 +168 +169 +170 +171 +172 +173 +174 +175 +176 +177 +178 +179 +180 +181 +182 +183 +184 +185 +186 +187 +188 +189 +190 +191 +192 +193 +194 +195 +196 +197 +198 +199 +200 +201 +202 +203 +204 +205 +206 +207 +208 +209 +210 +211 +212 +213 +214 +215 +216 +217 +218 +219 +220 +221 +222 +223 +224 +225 +226 +227 +228 +229 +230 +231 +232 +233 +234 +235 +236 +237 +238 +239 +240 +241 +242 +243 +244 +245 +246 +247 +248 +249 +250 +251 +252 +253 +254 +255 +256 +257 +258 +259 +260 +261 +262 +263 +264 +265 +266 +267 +268 +269 +270 +271 +272 +273 +274 +275 +276 +277 +278 +279 +280 +281 +282 +283 +284 +285 +286 +287 +288 +289 +290 +291 +292 +293 +294 +295 +296 +297 +298 +299 +300 +301 +302 +303 +304 +305 +306 +307 +308 +309 +310 +311 +312 +313 +314 +315 +316 +317  +  +  +  +  +  +  +  +  +  +  +  +  +  +10x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +25x +  +  +  +  +  +  +  +25x +25x +  +  +  +  +  +  +  +  +  +21x +  +  +21x +21x +1x +  +  +  +20x +  +  +  +  +  +  +  +21x +21x +1x +  +  +  +19x +  +  +  +  +  +  +  +  +  +19x +  +  +19x +  +  +19x +3x +  +  +  +  +  +  +  +  +3x +  +  +  +19x +7x +7x +7x +  +  +7x +2x +1x +  +  +  +  +  +  +  +  +1x +  +1x +  +  +  +  +  +  +  +  +  +1x +  +  +  +  +  +  +19x +  +  +  +  +19x +  +19x +  +  +  +  +  +  +  +  +  +7x +7x +  +7x +1x +  +  +6x +  +1x +1x +  +  +5x +  +  +  +  +  +  +  +  +  +  +  +  +  +5x +  +  +5x +  +5x +  +  +  +  +  +  +5x +5x +  +  +  +  +  +  +3x +3x +  +  +  +  +  +  +  +  +  +2x +2x +  +2x +1x +  +  +  +  +1x +1x +  +  +  +  +  +  +  +  +  +  +1x +1x +  +  +  +1x +  +  +1x +  +  +  +  +  +  +  +  +4x +4x +2x +  +  +  +2x +2x +2x +  +  +1x +1x +1x +  +  +  +  +  +  +  +  +5x +5x +  +  +  +  +5x +  +5x +5x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  + 
/**
+ * Process Manager
+ *
+ * Manages spawning, stopping, and lifecycle of child processes.
+ * Uses execa for process spawning with detached mode support.
+ * Emits domain events via optional EventBus for coordination.
+ */
+ 
+import { execa, type ResultPromise } from 'execa';
+import type { ProcessInfo, SpawnOptions } from './types.js';
+import type { ProcessRegistry } from './registry.js';
+import type { EventBus, ProcessSpawnedEvent, ProcessStoppedEvent, ProcessCrashedEvent } from '../events/index.js';
+ 
+/** Stop timeout in milliseconds before sending SIGKILL */
+const STOP_TIMEOUT_MS = 5000;
+ 
+/**
+ * Internal tracking for spawned process handles.
+ * Maps process ID to execa subprocess for control operations.
+ */
+interface ProcessHandle {
+  subprocess: ResultPromise;
+  options: SpawnOptions;
+}
+ 
+/**
+ * Manager for spawning, tracking, and controlling child processes.
+ */
+export class ProcessManager {
+  private handles: Map<string, ProcessHandle> = new Map();
+ 
+  /**
+   * Create a new ProcessManager.
+   * @param registry - Registry for tracking process metadata
+   * @param eventBus - Optional event bus for emitting domain events
+   */
+  constructor(
+    private registry: ProcessRegistry,
+    private eventBus?: EventBus
+  ) {}
+ 
+  /**
+   * Spawn a new child process.
+   * @param options - Spawn configuration
+   * @returns Process info for the spawned process
+   * @throws If process fails to start
+   */
+  async spawn(options: SpawnOptions): Promise<ProcessInfo> {
+    const { id, command, args = [], cwd, env } = options;
+ 
+    // Check if process with this ID already exists
+    const existing = this.registry.get(id);
+    if (existing && existing.status === 'running') {
+      throw new Error(`Process with id '${id}' is already running`);
+    }
+ 
+    // Spawn the process in detached mode
+    const subprocess = execa(command, args, {
+      cwd,
+      env: env ? { ...process.env, ...env } : undefined,
+      detached: true,
+      stdio: 'ignore', // Don't inherit stdio for background processes
+    });
+ 
+    // Ensure we have a PID
+    const pid = subprocess.pid;
+    if (pid === undefined) {
+      throw new Error(`Failed to get PID for process '${id}'`);
+    }
+ 
+    // Create process info
+    const info: ProcessInfo = {
+      id,
+      pid,
+      command,
+      args,
+      startedAt: new Date(),
+      status: 'running',
+    };
+ 
+    // Store handle for later control
+    this.handles.set(id, { subprocess, options });
+ 
+    // Register in registry
+    this.registry.register(info);
+ 
+    // Emit ProcessSpawned event
+    if (this.eventBus) {
+      const event: ProcessSpawnedEvent = {
+        type: 'process:spawned',
+        timestamp: new Date(),
+        payload: {
+          processId: id,
+          pid,
+          command,
+        },
+      };
+      this.eventBus.emit(event);
+    }
+ 
+    // Set up exit handler to update status and emit events
+    subprocess.on('exit', (code, signal) => {
+      const status = code === 0 ? 'stopped' : 'crashed';
+      this.registry.updateStatus(id, status);
+      this.handles.delete(id);
+ 
+      // Emit appropriate event based on exit status
+      if (this.eventBus) {
+        if (status === 'stopped') {
+          const event: ProcessStoppedEvent = {
+            type: 'process:stopped',
+            timestamp: new Date(),
+            payload: {
+              processId: id,
+              pid,
+              exitCode: code,
+            },
+          };
+          this.eventBus.emit(event);
+        } else {
+          const event: ProcessCrashedEvent = {
+            type: 'process:crashed',
+            timestamp: new Date(),
+            payload: {
+              processId: id,
+              pid,
+              exitCode: code,
+              signal,
+            },
+          };
+          this.eventBus.emit(event);
+        }
+      }
+    });
+ 
+    // Suppress unhandled rejection when process is killed
+    // This is expected behavior - we're intentionally killing processes
+    subprocess.catch(() => {
+      // Intentionally ignored - we handle exit via the 'exit' event
+    });
+ 
+    // Unref the subprocess so it doesn't keep the parent alive
+    subprocess.unref();
+ 
+    return info;
+  }
+ 
+  /**
+   * Stop a running process.
+   * Sends SIGTERM first, then SIGKILL after timeout if needed.
+   * @param id - Process ID to stop
+   * @throws If process not found
+   */
+  async stop(id: string): Promise<void> {
+    const handle = this.handles.get(id);
+    const info = this.registry.get(id);
+ 
+    if (!info) {
+      throw new Error(`Process with id '${id}' not found`);
+    }
+ 
+    if (info.status !== 'running') {
+      // Already stopped, just clean up
+      this.handles.delete(id);
+      return;
+    }
+ 
+    Iif (!handle) {
+      // Process exists in registry but we don't have a handle
+      // Try to kill by PID directly
+      try {
+        process.kill(info.pid, 'SIGTERM');
+        await this.waitForExit(info.pid, STOP_TIMEOUT_MS);
+      } catch {
+        // Process might already be dead
+      }
+      this.registry.updateStatus(id, 'stopped');
+      return;
+    }
+ 
+    // Send SIGTERM
+    handle.subprocess.kill('SIGTERM');
+ 
+    // Wait for graceful shutdown
+    const exited = await this.waitForProcessExit(handle.subprocess, STOP_TIMEOUT_MS);
+ 
+    Iif (!exited) {
+      // Force kill with SIGKILL
+      handle.subprocess.kill('SIGKILL');
+      await this.waitForProcessExit(handle.subprocess, 1000).catch(() => {});
+    }
+ 
+    // Update status (exit handler should have done this, but ensure it)
+    this.registry.updateStatus(id, 'stopped');
+    this.handles.delete(id);
+  }
+ 
+  /**
+   * Stop all running processes.
+   */
+  async stopAll(): Promise<void> {
+    const processes = this.registry.getAll().filter(p => p.status === 'running');
+    await Promise.all(processes.map(p => this.stop(p.id).catch(() => {})));
+  }
+ 
+  /**
+   * Restart a process with the same configuration.
+   * @param id - Process ID to restart
+   * @returns New process info
+   * @throws If process not found or original config unavailable
+   */
+  async restart(id: string): Promise<ProcessInfo> {
+    const handle = this.handles.get(id);
+    const info = this.registry.get(id);
+ 
+    if (!info) {
+      throw new Error(`Process with id '${id}' not found`);
+    }
+ 
+    // Get original spawn options
+    let options: SpawnOptions;
+    if (handle) {
+      options = handle.options;
+    } else E{
+      // Reconstruct options from process info
+      options = {
+        id,
+        command: info.command,
+        args: info.args,
+      };
+    }
+ 
+    // Stop if running
+    Eif (info.status === 'running') {
+      await this.stop(id);
+    }
+ 
+    // Unregister old process
+    this.registry.unregister(id);
+ 
+    // Spawn with same options
+    return this.spawn(options);
+  }
+ 
+  /**
+   * Check if a process is currently running.
+   * @param id - Process ID to check
+   * @returns true if process exists and is running
+   */
+  isRunning(id: string): boolean {
+    const info = this.registry.get(id);
+    if (!info || info.status !== 'running') {
+      return false;
+    }
+ 
+    // Double-check by probing the actual process
+    try {
+      process.kill(info.pid, 0);
+      return true;
+    } catch {
+      // Process is dead, update registry
+      this.registry.updateStatus(id, 'crashed');
+      this.handles.delete(id);
+      return false;
+    }
+  }
+ 
+  /**
+   * Wait for a subprocess to exit within a timeout.
+   * @returns true if process exited, false if timeout
+   */
+  private waitForProcessExit(subprocess: ResultPromise, timeoutMs: number): Promise<boolean> {
+    return new Promise(resolve => {
+      const timeout = setTimeout(() => {
+        resolve(false);
+      }, timeoutMs);
+ 
+      // Use both then and catch to handle success and kill scenarios
+      subprocess
+        .then(() => {
+          clearTimeout(timeout);
+          resolve(true);
+        })
+        .catch(() => {
+          // Process was killed (expected) - this is success for our purposes
+          clearTimeout(timeout);
+          resolve(true);
+        });
+    });
+  }
+ 
+  /**
+   * Wait for a PID to exit within a timeout.
+   * @returns true if process exited, false if timeout
+   */
+  private waitForExit(pid: number, timeoutMs: number): Promise<boolean> {
+    return new Promise(resolve => {
+      const start = Date.now();
+      const check = () => {
+        try {
+          process.kill(pid, 0);
+          // Still alive
+          if (Date.now() - start >= timeoutMs) {
+            resolve(false);
+          } else {
+            setTimeout(check, 100);
+          }
+        } catch {
+          // Dead
+          resolve(true);
+        }
+      };
+      check();
+    });
+  }
+}
+ 
+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/coverage/src/process/registry.ts.html b/coverage/src/process/registry.ts.html new file mode 100644 index 0000000..8c573b9 --- /dev/null +++ b/coverage/src/process/registry.ts.html @@ -0,0 +1,370 @@ + + + + + + Code coverage report for src/process/registry.ts + + + + + + + + + +
+
+

All files / src/process registry.ts

+
+ +
+ 100% + Statements + 16/16 +
+ + +
+ 100% + Branches + 4/4 +
+ + +
+ 100% + Functions + 8/8 +
+ + +
+ 100% + Lines + 16/16 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+

+
1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 +30 +31 +32 +33 +34 +35 +36 +37 +38 +39 +40 +41 +42 +43 +44 +45 +46 +47 +48 +49 +50 +51 +52 +53 +54 +55 +56 +57 +58 +59 +60 +61 +62 +63 +64 +65 +66 +67 +68 +69 +70 +71 +72 +73 +74 +75 +76 +77 +78 +79 +80 +81 +82 +83 +84 +85 +86 +87 +88 +89 +90 +91 +92 +93 +94 +95 +96  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +36x +  +  +  +  +  +  +37x +  +  +  +  +  +  +  +4x +  +  +  +  +  +  +  +  +45x +  +  +  +  +  +  +  +4x +  +  +  +  +  +  +  +  +2x +2x +1x +  +  +1x +  +  +  +  +  +  +1x +  +  +  +  +  +  +  +  +  +16x +16x +15x +15x +  +1x +  +  +  +  +  +  +  +11x +  +  + 
/**
+ * Process Registry
+ *
+ * In-memory registry for tracking managed processes.
+ * Provides CRUD operations for process metadata.
+ *
+ * Note: This is in-memory for now. Phase 2 adds SQLite persistence.
+ */
+ 
+import type { ProcessInfo } from './types.js';
+ 
+/**
+ * Registry for tracking managed processes.
+ * Stores process information in memory using a Map.
+ */
+export class ProcessRegistry {
+  private processes: Map<string, ProcessInfo> = new Map();
+ 
+  /**
+   * Register a new process in the registry.
+   * @param info - Process information to register
+   */
+  register(info: ProcessInfo): void {
+    this.processes.set(info.id, info);
+  }
+ 
+  /**
+   * Remove a process from the registry.
+   * @param id - Process ID to unregister
+   */
+  unregister(id: string): void {
+    this.processes.delete(id);
+  }
+ 
+  /**
+   * Get a process by its ID.
+   * @param id - Process ID to look up
+   * @returns Process info if found, undefined otherwise
+   */
+  get(id: string): ProcessInfo | undefined {
+    return this.processes.get(id);
+  }
+ 
+  /**
+   * Get all registered processes.
+   * @returns Array of all process info objects
+   */
+  getAll(): ProcessInfo[] {
+    return Array.from(this.processes.values());
+  }
+ 
+  /**
+   * Find a process by its operating system PID.
+   * @param pid - OS process ID to search for
+   * @returns Process info if found, undefined otherwise
+   */
+  getByPid(pid: number): ProcessInfo | undefined {
+    for (const process of this.processes.values()) {
+      if (process.pid === pid) {
+        return process;
+      }
+    }
+    return undefined;
+  }
+ 
+  /**
+   * Clear all processes from the registry.
+   */
+  clear(): void {
+    this.processes.clear();
+  }
+ 
+  /**
+   * Update a process's status in the registry.
+   * @param id - Process ID to update
+   * @param status - New status value
+   * @returns true if process was found and updated, false otherwise
+   */
+  updateStatus(id: string, status: ProcessInfo['status']): boolean {
+    const process = this.processes.get(id);
+    if (process) {
+      process.status = status;
+      return true;
+    }
+    return false;
+  }
+ 
+  /**
+   * Get the count of registered processes.
+   * @returns Number of processes in the registry
+   */
+  get size(): number {
+    return this.processes.size;
+  }
+}
+ 
+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/coverage/src/server/index.html b/coverage/src/server/index.html new file mode 100644 index 0000000..db9f300 --- /dev/null +++ b/coverage/src/server/index.html @@ -0,0 +1,146 @@ + + + + + + Code coverage report for src/server + + + + + + + + + +
+
+

All files src/server

+
+ +
+ 71.27% + Statements + 129/181 +
+ + +
+ 62.66% + Branches + 47/75 +
+ + +
+ 68.42% + Functions + 26/38 +
+ + +
+ 73.14% + Lines + 128/175 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
FileStatementsBranchesFunctionsLines
index.ts +
+
86.13%87/10174.46%35/4790%18/2086%86/100
shutdown.ts +
+
37.2%16/4310%1/1037.5%3/840%16/40
trpc-adapter.ts +
+
70.27%26/3761.11%11/1850%5/1074.28%26/35
+
+
+
+ + + + + + + + \ No newline at end of file diff --git a/coverage/src/server/index.ts.html b/coverage/src/server/index.ts.html new file mode 100644 index 0000000..8caa74e --- /dev/null +++ b/coverage/src/server/index.ts.html @@ -0,0 +1,1153 @@ + + + + + + Code coverage report for src/server/index.ts + + + + + + + + + +
+
+

All files / src/server index.ts

+
+ +
+ 86.13% + Statements + 87/101 +
+ + +
+ 74.46% + Branches + 35/47 +
+ + +
+ 90% + Functions + 18/20 +
+ + +
+ 86% + Lines + 86/100 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+

+
1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 +30 +31 +32 +33 +34 +35 +36 +37 +38 +39 +40 +41 +42 +43 +44 +45 +46 +47 +48 +49 +50 +51 +52 +53 +54 +55 +56 +57 +58 +59 +60 +61 +62 +63 +64 +65 +66 +67 +68 +69 +70 +71 +72 +73 +74 +75 +76 +77 +78 +79 +80 +81 +82 +83 +84 +85 +86 +87 +88 +89 +90 +91 +92 +93 +94 +95 +96 +97 +98 +99 +100 +101 +102 +103 +104 +105 +106 +107 +108 +109 +110 +111 +112 +113 +114 +115 +116 +117 +118 +119 +120 +121 +122 +123 +124 +125 +126 +127 +128 +129 +130 +131 +132 +133 +134 +135 +136 +137 +138 +139 +140 +141 +142 +143 +144 +145 +146 +147 +148 +149 +150 +151 +152 +153 +154 +155 +156 +157 +158 +159 +160 +161 +162 +163 +164 +165 +166 +167 +168 +169 +170 +171 +172 +173 +174 +175 +176 +177 +178 +179 +180 +181 +182 +183 +184 +185 +186 +187 +188 +189 +190 +191 +192 +193 +194 +195 +196 +197 +198 +199 +200 +201 +202 +203 +204 +205 +206 +207 +208 +209 +210 +211 +212 +213 +214 +215 +216 +217 +218 +219 +220 +221 +222 +223 +224 +225 +226 +227 +228 +229 +230 +231 +232 +233 +234 +235 +236 +237 +238 +239 +240 +241 +242 +243 +244 +245 +246 +247 +248 +249 +250 +251 +252 +253 +254 +255 +256 +257 +258 +259 +260 +261 +262 +263 +264 +265 +266 +267 +268 +269 +270 +271 +272 +273 +274 +275 +276 +277 +278 +279 +280 +281 +282 +283 +284 +285 +286 +287 +288 +289 +290 +291 +292 +293 +294 +295 +296 +297 +298 +299 +300 +301 +302 +303 +304 +305 +306 +307 +308 +309 +310 +311 +312 +313 +314 +315 +316 +317 +318 +319 +320 +321 +322 +323 +324 +325 +326 +327 +328 +329 +330 +331 +332 +333 +334 +335 +336 +337 +338 +339 +340 +341 +342 +343 +344 +345 +346 +347 +348 +349 +350 +351 +352 +353 +354 +355 +356 +357  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +2x +  +  +2x +  +  +2x +  +  +2x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +20x +20x +  +  +  +  +  +  +  +  +20x +  +  +  +  +20x +20x +20x +20x +  +  +  +  +  +  +  +  +17x +1x +  +  +  +16x +16x +1x +  +  +  +  +  +  +15x +  +  +15x +15x +15x +15x +15x +  +  +  +  +15x +  +  +  +  +  +15x +  +  +15x +3x +  +  +  +  +  +  +  +  +3x +  +  +15x +15x +  +  +  +  +  +  +16x +1x +  +  +  +15x +  +  +  +  +16x +3x +  +  +  +  +  +  +3x +  +  +  +15x +15x +15x +  +  +15x +  +  +  +  +15x +15x +  +  +15x +  +  +  +  +  +  +28x +  +  +  +  +  +  +1x +  +  +  +  +  +  +  +  +  +  +  +  +  +11x +  +  +11x +7x +7x +  +  +  +4x +1x +1x +  +  +  +3x +  +1x +1x +  +1x +1x +  +1x +  +  +  +  +  +  +  +7x +  +  +  +  +7x +  +  +  +  +  +  +7x +  +  +  +  +  +  +  +  +  +1x +  +  +  +  +1x +1x +  +  +  +  +  +1x +  +  +  +  +  +  +1x +  +  +  +  +1x +  +  +  +1x +  +  +  +  +  +  +  +  +1x +  +  +  +  +  +  +4x +4x +  +  +  +  +  +  +  +16x +16x +2x +  +2x +  +  +  +  +2x +2x +2x +  +  +1x +1x +1x +  +  +  +14x +14x +  +  +  +  +  +  +  +  +  +  +15x +15x +  +  +  +  +  +  +16x +16x +  +  +  +  +  +  +  +  +  +  +  + 
/**
+ * Coordination Server
+ *
+ * HTTP server with health endpoint for agent coordination.
+ * Uses native node:http for minimal dependencies.
+ * Supports both traditional HTTP endpoints and tRPC for type-safe client communication.
+ */
+ 
+import { createServer, type Server, type IncomingMessage, type ServerResponse } from 'node:http';
+import { writeFile, unlink, readFile, mkdir } from 'node:fs/promises';
+import { dirname } from 'node:path';
+import { homedir } from 'node:os';
+import { join } from 'node:path';
+import type { ServerConfig, ServerState, HealthResponse, StatusResponse } from './types.js';
+import type { ProcessManager } from '../process/index.js';
+import type { LogManager } from '../logging/index.js';
+import type { EventBus, ServerStartedEvent, ServerStoppedEvent } from '../events/index.js';
+import { createTrpcHandler, type TrpcAdapterOptions } from './trpc-adapter.js';
+import { createModuleLogger } from '../logger/index.js';
+ 
+/**
+ * Optional dependencies for tRPC context.
+ * Passed through to the tRPC adapter for procedure access.
+ */
+export type ServerContextDeps = Omit<TrpcAdapterOptions, 'eventBus' | 'serverStartedAt' | 'processCount'>;
+ 
+const log = createModuleLogger('http');
+ 
+/** Default port for the coordination server */
+const DEFAULT_PORT = 3847;
+ 
+/** Default host to bind to */
+const DEFAULT_HOST = '127.0.0.1';
+ 
+/** Default PID file location */
+const DEFAULT_PID_FILE = join(homedir(), '.cw', 'server.pid');
+ 
+/**
+ * HTTP server for agent coordination.
+ *
+ * Routes:
+ * - GET /health - Health check with uptime and process count
+ * - GET /status - Full status with process list
+ */
+export class CoordinationServer {
+  private readonly config: ServerConfig;
+  private readonly processManager: ProcessManager;
+  private readonly logManager: LogManager;
+  private readonly eventBus: EventBus | undefined;
+  private readonly contextDeps: ServerContextDeps;
+  private server: Server | null = null;
+  private state: ServerState | null = null;
+ 
+  constructor(
+    config: Partial<ServerConfig>,
+    processManager: ProcessManager,
+    logManager: LogManager,
+    eventBus?: EventBus,
+    contextDeps?: ServerContextDeps
+  ) {
+    this.config = {
+      port: config.port ?? DEFAULT_PORT,
+      host: config.host ?? DEFAULT_HOST,
+      pidFile: config.pidFile ?? DEFAULT_PID_FILE,
+    };
+    this.processManager = processManager;
+    this.logManager = logManager;
+    this.eventBus = eventBus;
+    this.contextDeps = contextDeps ?? {};
+  }
+ 
+  /**
+   * Starts the HTTP server and writes PID file.
+   * @throws If server is already running or PID file exists (another server running)
+   */
+  async start(): Promise<void> {
+    // Check if already running
+    if (this.server) {
+      throw new Error('Server is already running');
+    }
+ 
+    // Check for existing PID file (another server might be running)
+    const existingPid = await this.checkExistingServer();
+    if (existingPid !== null) {
+      throw new Error(
+        `Another server appears to be running (PID: ${existingPid}). ` +
+        `If this is incorrect, remove ${this.config.pidFile} and try again.`
+      );
+    }
+ 
+    // Create server
+    this.server = createServer((req, res) => this.handleRequest(req, res));
+ 
+    // Start listening
+    await new Promise<void>((resolve, reject) => {
+      this.server!.once('error', reject);
+      this.server!.listen(this.config.port, this.config.host, () => {
+        this.server!.removeListener('error', reject);
+        resolve();
+      });
+    });
+ 
+    // Set server state
+    this.state = {
+      startedAt: new Date(),
+      processCount: 0,
+    };
+ 
+    // Write PID file
+    await this.writePidFile();
+ 
+    // Emit ServerStarted event
+    if (this.eventBus) {
+      const event: ServerStartedEvent = {
+        type: 'server:started',
+        timestamp: new Date(),
+        payload: {
+          port: this.config.port,
+          host: this.config.host,
+          pid: process.pid,
+        },
+      };
+      this.eventBus.emit(event);
+    }
+ 
+    console.log(`Coordination server listening on http://${this.config.host}:${this.config.port}`);
+    log.info({ port: this.config.port, host: this.config.host, pid: process.pid }, 'server listening');
+  }
+ 
+  /**
+   * Stops the HTTP server and removes PID file.
+   */
+  async stop(): Promise<void> {
+    if (!this.server) {
+      return;
+    }
+ 
+    // Calculate uptime before clearing state
+    const uptime = this.state
+      ? Math.floor((Date.now() - this.state.startedAt.getTime()) / 1000)
+      : 0;
+ 
+    // Emit ServerStopped event before stopping
+    if (this.eventBus) {
+      const event: ServerStoppedEvent = {
+        type: 'server:stopped',
+        timestamp: new Date(),
+        payload: {
+          uptime,
+        },
+      };
+      this.eventBus.emit(event);
+    }
+ 
+    // Close server
+    await new Promise<void>((resolve, reject) => {
+      this.server!.close((err) => {
+        Iif (err) {
+          reject(err);
+        } else {
+          resolve();
+        }
+      });
+    });
+ 
+    this.server = null;
+    this.state = null;
+ 
+    // Remove PID file
+    await this.removePidFile();
+  }
+ 
+  /**
+   * Returns whether the server is currently running.
+   */
+  isRunning(): boolean {
+    return this.server !== null && this.server.listening;
+  }
+ 
+  /**
+   * Gets the server port.
+   */
+  getPort(): number {
+    return this.config.port;
+  }
+ 
+  /**
+   * Gets the PID file path.
+   */
+  getPidFile(): string {
+    return this.config.pidFile;
+  }
+ 
+  /**
+   * Handles incoming HTTP requests with simple path matching.
+   */
+  private handleRequest(req: IncomingMessage, res: ServerResponse): void {
+    const url = req.url ?? '/';
+ 
+    // Route tRPC requests to tRPC handler
+    if (url.startsWith('/trpc')) {
+      this.handleTrpc(req, res);
+      return;
+    }
+ 
+    // Only accept GET requests for non-tRPC routes
+    if (req.method !== 'GET') {
+      this.sendJson(res, 405, { error: 'Method not allowed' });
+      return;
+    }
+ 
+    // Simple path routing for backwards-compatible HTTP endpoints
+    switch (url) {
+      case '/health':
+        this.handleHealth(res);
+        break;
+      case '/status':
+        this.handleStatus(res);
+        break;
+      default:
+        this.sendJson(res, 404, { error: 'Not found' });
+    }
+  }
+ 
+  /**
+   * Handles tRPC requests via the fetch adapter.
+   */
+  private handleTrpc(req: IncomingMessage, res: ServerResponse): void {
+    Iif (!this.state || !this.eventBus) {
+      this.sendJson(res, 500, { error: 'Server not initialized or missing eventBus' });
+      return;
+    }
+ 
+    const trpcHandler = createTrpcHandler({
+      eventBus: this.eventBus,
+      serverStartedAt: this.state.startedAt,
+      processCount: this.state.processCount,
+      ...this.contextDeps,
+    });
+ 
+    trpcHandler(req, res).catch((error: Error) => {
+      log.error({ err: error }, 'tRPC handler error');
+      this.sendJson(res, 500, { error: 'Internal server error' });
+    });
+  }
+ 
+  /**
+   * Handles GET /health endpoint.
+   */
+  private handleHealth(res: ServerResponse): void {
+    Iif (!this.state) {
+      this.sendJson(res, 500, { error: 'Server not initialized' });
+      return;
+    }
+ 
+    const uptime = Math.floor((Date.now() - this.state.startedAt.getTime()) / 1000);
+    const response: HealthResponse = {
+      status: 'ok',
+      uptime,
+      processCount: this.state.processCount,
+    };
+ 
+    this.sendJson(res, 200, response);
+  }
+ 
+  /**
+   * Handles GET /status endpoint.
+   */
+  private handleStatus(res: ServerResponse): void {
+    Iif (!this.state) {
+      this.sendJson(res, 500, { error: 'Server not initialized' });
+      return;
+    }
+ 
+    const uptime = Math.floor((Date.now() - this.state.startedAt.getTime()) / 1000);
+ 
+    // Get process list from process manager registry
+    // Note: We access processManager's registry indirectly through its public API
+    const response: StatusResponse = {
+      server: {
+        startedAt: this.state.startedAt.toISOString(),
+        uptime,
+        pid: process.pid,
+      },
+      processes: [],
+    };
+ 
+    this.sendJson(res, 200, response);
+  }
+ 
+  /**
+   * Sends a JSON response.
+   */
+  private sendJson(res: ServerResponse, statusCode: number, data: unknown): void {
+    res.writeHead(statusCode, { 'Content-Type': 'application/json' });
+    res.end(JSON.stringify(data));
+  }
+ 
+  /**
+   * Checks if another server is already running by checking PID file.
+   * @returns The PID if a server is running, null otherwise
+   */
+  private async checkExistingServer(): Promise<number | null> {
+    try {
+      const content = await readFile(this.config.pidFile, 'utf-8');
+      const pid = parseInt(content.trim(), 10);
+ 
+      Iif (isNaN(pid)) {
+        return null;
+      }
+ 
+      // Check if process is actually running
+      try {
+        process.kill(pid, 0);
+        return pid; // Process is alive
+      } catch {
+        // Process is dead, PID file is stale
+        log.warn({ stalePid: pid }, 'stale PID file cleaned up');
+        await this.removePidFile();
+        return null;
+      }
+    } catch (error) {
+      // PID file doesn't exist
+      Eif ((error as NodeJS.ErrnoException).code === 'ENOENT') {
+        return null;
+      }
+      throw error;
+    }
+  }
+ 
+  /**
+   * Writes the PID file.
+   */
+  private async writePidFile(): Promise<void> {
+    // Ensure directory exists
+    await mkdir(dirname(this.config.pidFile), { recursive: true });
+    await writeFile(this.config.pidFile, process.pid.toString(), 'utf-8');
+  }
+ 
+  /**
+   * Removes the PID file.
+   */
+  private async removePidFile(): Promise<void> {
+    try {
+      await unlink(this.config.pidFile);
+    } catch (error) {
+      // Ignore if file doesn't exist
+      if ((error as NodeJS.ErrnoException).code !== 'ENOENT') {
+        throw error;
+      }
+    }
+  }
+}
+ 
+// Re-export types
+export type { ServerConfig, ServerState, HealthResponse, StatusResponse } from './types.js';
+ 
+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/coverage/src/server/shutdown.ts.html b/coverage/src/server/shutdown.ts.html new file mode 100644 index 0000000..bdcf5c4 --- /dev/null +++ b/coverage/src/server/shutdown.ts.html @@ -0,0 +1,490 @@ + + + + + + Code coverage report for src/server/shutdown.ts + + + + + + + + + +
+
+

All files / src/server shutdown.ts

+
+ +
+ 37.2% + Statements + 16/43 +
+ + +
+ 10% + Branches + 1/10 +
+ + +
+ 37.5% + Functions + 3/8 +
+ + +
+ 40% + Lines + 16/40 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+

+
1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 +30 +31 +32 +33 +34 +35 +36 +37 +38 +39 +40 +41 +42 +43 +44 +45 +46 +47 +48 +49 +50 +51 +52 +53 +54 +55 +56 +57 +58 +59 +60 +61 +62 +63 +64 +65 +66 +67 +68 +69 +70 +71 +72 +73 +74 +75 +76 +77 +78 +79 +80 +81 +82 +83 +84 +85 +86 +87 +88 +89 +90 +91 +92 +93 +94 +95 +96 +97 +98 +99 +100 +101 +102 +103 +104 +105 +106 +107 +108 +109 +110 +111 +112 +113 +114 +115 +116 +117 +118 +119 +120 +121 +122 +123 +124 +125 +126 +127 +128 +129 +130 +131 +132 +133 +134 +135 +136  +  +  +  +  +  +  +  +  +  +  +  +  +1x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +6x +6x +  +  +  +  +  +  +  +6x +6x +6x +6x +  +  +  +  +  +  +  +  +3x +  +  +3x +  +  +3x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +3x +3x +  +  +3x +3x +  +  +3x +  +  +  +  +  +  +  +3x +  +  +  +  +  + 
/**
+ * Graceful Shutdown Handler
+ *
+ * Orchestrates clean shutdown of the coordination server.
+ * Handles SIGTERM, SIGINT, SIGHUP with proper cleanup sequence.
+ */
+ 
+import type { CoordinationServer } from './index.js';
+import type { ProcessManager } from '../process/index.js';
+import type { LogManager } from '../logging/index.js';
+import type { PreviewManager } from '../preview/index.js';
+ 
+/** Timeout before force exit in milliseconds */
+const SHUTDOWN_TIMEOUT_MS = 10000;
+ 
+/**
+ * Handles graceful shutdown of the coordination server.
+ *
+ * Shutdown sequence:
+ * 1. Log shutdown initiation
+ * 2. Stop accepting new connections
+ * 3. Stop all managed processes
+ * 4. Close all log file handles (not implemented yet in LogManager)
+ * 5. Remove PID file
+ * 6. Exit with code 0
+ *
+ * If cleanup takes longer than SHUTDOWN_TIMEOUT_MS, force exit with code 1.
+ * Double SIGINT forces immediate exit.
+ */
+export class GracefulShutdown {
+  private readonly server: CoordinationServer;
+  private readonly processManager: ProcessManager;
+  private readonly logManager: LogManager;
+  private readonly previewManager?: PreviewManager;
+  private isShuttingDown = false;
+  private forceExitCount = 0;
+ 
+  constructor(
+    server: CoordinationServer,
+    processManager: ProcessManager,
+    logManager: LogManager,
+    previewManager?: PreviewManager,
+  ) {
+    this.server = server;
+    this.processManager = processManager;
+    this.logManager = logManager;
+    this.previewManager = previewManager;
+  }
+ 
+  /**
+   * Installs signal handlers for graceful shutdown.
+   * Call this after the server has started.
+   */
+  install(): void {
+    // Handle SIGTERM (kill, docker stop)
+    process.on('SIGTERM', () => this.handleSignal('SIGTERM'));
+ 
+    // Handle SIGINT (Ctrl+C)
+    process.on('SIGINT', () => this.handleSignal('SIGINT'));
+ 
+    // Handle SIGHUP (terminal closed)
+    process.on('SIGHUP', () => this.handleSignal('SIGHUP'));
+  }
+ 
+  /**
+   * Handles a shutdown signal.
+   * @param signal - The signal that triggered shutdown
+   */
+  private async handleSignal(signal: string): Promise<void> {
+    // Handle double SIGINT for force exit
+    if (signal === 'SIGINT' && this.isShuttingDown) {
+      this.forceExitCount++;
+      if (this.forceExitCount >= 1) {
+        console.log('\nForce exit requested. Exiting immediately.');
+        process.exit(1);
+      }
+    }
+ 
+    // Only run shutdown sequence once
+    if (this.isShuttingDown) {
+      console.log(`\nAlready shutting down... Press Ctrl+C again to force exit.`);
+      return;
+    }
+ 
+    this.isShuttingDown = true;
+    console.log(`\nReceived ${signal}, shutting down gracefully...`);
+ 
+    // Set timeout for force exit
+    const forceExitTimer = setTimeout(() => {
+      console.error('Shutdown timeout exceeded. Forcing exit.');
+      process.exit(1);
+    }, SHUTDOWN_TIMEOUT_MS);
+ 
+    // Ensure timeout doesn't keep the process alive
+    forceExitTimer.unref();
+ 
+    try {
+      await this.shutdown();
+      clearTimeout(forceExitTimer);
+      console.log('Shutdown complete.');
+      process.exit(0);
+    } catch (error) {
+      clearTimeout(forceExitTimer);
+      console.error('Error during shutdown:', (error as Error).message);
+      process.exit(1);
+    }
+  }
+ 
+  /**
+   * Performs the shutdown sequence.
+   */
+  async shutdown(): Promise<void> {
+    // Step 1: Stop the HTTP server (stops accepting new connections)
+    console.log('  Stopping HTTP server...');
+    await this.server.stop();
+ 
+    // Step 2: Stop all managed processes
+    console.log('  Stopping managed processes...');
+    await this.processManager.stopAll();
+ 
+    // Step 3: Stop all preview deployments
+    Iif (this.previewManager) {
+      console.log('  Stopping preview deployments...');
+      await this.previewManager.stopAll();
+    }
+ 
+    // Step 4: Clean up log manager resources (future: close open file handles)
+    // Currently LogManager doesn't maintain persistent handles that need closing
+    // This is a placeholder for future cleanup needs
+    console.log('  Cleaning up resources...');
+ 
+    // Step 4: PID file is removed by server.stop()
+    // Nothing additional needed here
+  }
+}
+ 
+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/coverage/src/server/trpc-adapter.ts.html b/coverage/src/server/trpc-adapter.ts.html new file mode 100644 index 0000000..c6148c7 --- /dev/null +++ b/coverage/src/server/trpc-adapter.ts.html @@ -0,0 +1,649 @@ + + + + + + Code coverage report for src/server/trpc-adapter.ts + + + + + + + + + +
+
+

All files / src/server trpc-adapter.ts

+
+ +
+ 70.27% + Statements + 26/37 +
+ + +
+ 61.11% + Branches + 11/18 +
+ + +
+ 50% + Functions + 5/10 +
+ + +
+ 74.28% + Lines + 26/35 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+

+
1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 +30 +31 +32 +33 +34 +35 +36 +37 +38 +39 +40 +41 +42 +43 +44 +45 +46 +47 +48 +49 +50 +51 +52 +53 +54 +55 +56 +57 +58 +59 +60 +61 +62 +63 +64 +65 +66 +67 +68 +69 +70 +71 +72 +73 +74 +75 +76 +77 +78 +79 +80 +81 +82 +83 +84 +85 +86 +87 +88 +89 +90 +91 +92 +93 +94 +95 +96 +97 +98 +99 +100 +101 +102 +103 +104 +105 +106 +107 +108 +109 +110 +111 +112 +113 +114 +115 +116 +117 +118 +119 +120 +121 +122 +123 +124 +125 +126 +127 +128 +129 +130 +131 +132 +133 +134 +135 +136 +137 +138 +139 +140 +141 +142 +143 +144 +145 +146 +147 +148 +149 +150 +151 +152 +153 +154 +155 +156 +157 +158 +159 +160 +161 +162 +163 +164 +165 +166 +167 +168 +169 +170 +171 +172 +173 +174 +175 +176 +177 +178 +179 +180 +181 +182 +183 +184 +185 +186 +187 +188 +189  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +7x +  +7x +7x +7x +  +  +  +7x +  +  +  +  +  +  +  +  +  +  +  +  +7x +7x +49x +49x +  +  +49x +  +  +  +  +  +7x +  +  +  +  +  +  +7x +  +  +  +7x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +7x +  +  +7x +14x +  +  +  +7x +7x +7x +7x +14x +14x +7x +7x +  +7x +  +  +7x +  +  +  +  +  +  + 
/**
+ * tRPC HTTP Adapter
+ *
+ * Handles tRPC requests over HTTP using node:http.
+ * Routes /trpc/* requests to the tRPC router.
+ */
+ 
+import type { IncomingMessage, ServerResponse } from 'node:http';
+import { fetchRequestHandler } from '@trpc/server/adapters/fetch';
+import { appRouter, createContext } from '../trpc/index.js';
+import type { EventBus } from '../events/index.js';
+import type { AgentManager } from '../agent/types.js';
+import type { TaskRepository } from '../db/repositories/task-repository.js';
+import type { MessageRepository } from '../db/repositories/message-repository.js';
+import type { InitiativeRepository } from '../db/repositories/initiative-repository.js';
+import type { PhaseRepository } from '../db/repositories/phase-repository.js';
+import type { PageRepository } from '../db/repositories/page-repository.js';
+import type { ProjectRepository } from '../db/repositories/project-repository.js';
+import type { AccountRepository } from '../db/repositories/account-repository.js';
+import type { ChangeSetRepository } from '../db/repositories/change-set-repository.js';
+import type { LogChunkRepository } from '../db/repositories/log-chunk-repository.js';
+import type { ConversationRepository } from '../db/repositories/conversation-repository.js';
+import type { AccountCredentialManager } from '../agent/credentials/types.js';
+import type { DispatchManager, PhaseDispatchManager } from '../dispatch/types.js';
+import type { CoordinationManager } from '../coordination/types.js';
+import type { BranchManager } from '../git/branch-manager.js';
+import type { ExecutionOrchestrator } from '../execution/orchestrator.js';
+import type { PreviewManager } from '../preview/index.js';
+ 
+/**
+ * Options for creating the tRPC request handler.
+ */
+export interface TrpcAdapterOptions {
+  /** Event bus for inter-module communication */
+  eventBus: EventBus;
+  /** When the server started */
+  serverStartedAt: Date;
+  /** Number of managed processes */
+  processCount: number;
+  /** Agent manager for agent lifecycle operations (optional until full wiring) */
+  agentManager?: AgentManager;
+  /** Task repository for task CRUD operations */
+  taskRepository?: TaskRepository;
+  /** Message repository for agent-user communication */
+  messageRepository?: MessageRepository;
+  /** Initiative repository for initiative CRUD operations */
+  initiativeRepository?: InitiativeRepository;
+  /** Phase repository for phase CRUD operations */
+  phaseRepository?: PhaseRepository;
+  /** Dispatch manager for task queue operations */
+  dispatchManager?: DispatchManager;
+  /** Coordination manager for merge queue operations */
+  coordinationManager?: CoordinationManager;
+  /** Phase dispatch manager for phase queue operations */
+  phaseDispatchManager?: PhaseDispatchManager;
+  /** Page repository for page CRUD operations */
+  pageRepository?: PageRepository;
+  /** Project repository for project CRUD and initiative-project junction operations */
+  projectRepository?: ProjectRepository;
+  /** Account repository for account CRUD and load balancing */
+  accountRepository?: AccountRepository;
+  /** Change set repository for agent change set operations */
+  changeSetRepository?: ChangeSetRepository;
+  /** Log chunk repository for agent output persistence */
+  logChunkRepository?: LogChunkRepository;
+  /** Credential manager for account OAuth token management */
+  credentialManager?: AccountCredentialManager;
+  /** Branch manager for git branch operations */
+  branchManager?: BranchManager;
+  /** Execution orchestrator for phase merge/review workflow */
+  executionOrchestrator?: ExecutionOrchestrator;
+  /** Preview manager for Docker-based preview deployments */
+  previewManager?: PreviewManager;
+  /** Conversation repository for inter-agent communication */
+  conversationRepository?: ConversationRepository;
+  /** Absolute path to the workspace root (.cwrc directory) */
+  workspaceRoot?: string;
+}
+ 
+/**
+ * Creates a tRPC request handler for node:http.
+ *
+ * Converts IncomingMessage/ServerResponse to fetch Request/Response
+ * and delegates to the tRPC fetch adapter.
+ *
+ * @param options - Adapter options with context values
+ * @returns Request handler function
+ */
+export function createTrpcHandler(options: TrpcAdapterOptions) {
+  return async (req: IncomingMessage, res: ServerResponse): Promise<void> => {
+    // Build full URL from request
+    const protocol = 'http';
+    const host = req.headers.host ?? 'localhost';
+    const url = new URL(req.url ?? '/', `${protocol}://${host}`);
+ 
+    // Read request body if present
+    let body: string | undefined;
+    Iif (req.method !== 'GET' && req.method !== 'HEAD') {
+      body = await new Promise<string>((resolve) => {
+        let data = '';
+        req.on('data', (chunk: Buffer) => {
+          data += chunk.toString();
+        });
+        req.on('end', () => {
+          resolve(data);
+        });
+      });
+    }
+ 
+    // Convert headers to fetch Headers
+    const headers = new Headers();
+    for (const [key, value] of Object.entries(req.headers)) {
+      Eif (value) {
+        Iif (Array.isArray(value)) {
+          value.forEach((v) => headers.append(key, v));
+        } else {
+          headers.set(key, value);
+        }
+      }
+    }
+ 
+    // Create fetch Request
+    const fetchRequest = new Request(url.toString(), {
+      method: req.method,
+      headers,
+      body: body ?? undefined,
+    });
+ 
+    // Handle with tRPC fetch adapter
+    const fetchResponse = await fetchRequestHandler({
+      endpoint: '/trpc',
+      req: fetchRequest,
+      router: appRouter,
+      createContext: () =>
+        createContext({
+          eventBus: options.eventBus,
+          serverStartedAt: options.serverStartedAt,
+          processCount: options.processCount,
+          agentManager: options.agentManager,
+          taskRepository: options.taskRepository,
+          messageRepository: options.messageRepository,
+          initiativeRepository: options.initiativeRepository,
+          phaseRepository: options.phaseRepository,
+          dispatchManager: options.dispatchManager,
+          coordinationManager: options.coordinationManager,
+          phaseDispatchManager: options.phaseDispatchManager,
+          pageRepository: options.pageRepository,
+          projectRepository: options.projectRepository,
+          accountRepository: options.accountRepository,
+          changeSetRepository: options.changeSetRepository,
+          logChunkRepository: options.logChunkRepository,
+          credentialManager: options.credentialManager,
+          branchManager: options.branchManager,
+          executionOrchestrator: options.executionOrchestrator,
+          previewManager: options.previewManager,
+          conversationRepository: options.conversationRepository,
+          workspaceRoot: options.workspaceRoot,
+        }),
+    });
+ 
+    // Send response
+    res.statusCode = fetchResponse.status;
+ 
+    // Set response headers BEFORE streaming body
+    fetchResponse.headers.forEach((value, key) => {
+      res.setHeader(key, value);
+    });
+ 
+    // Stream body if it's a ReadableStream (SSE subscriptions), otherwise buffer
+    if (fetchResponse.body) {
+      const reader = fetchResponse.body.getReader();
+      const pump = async () => {
+        while (true) {
+          const { done, value } = await reader.read();
+          if (done) {
+            res.end();
+            return;
+          }
+          res.write(value);
+        }
+      };
+      pump().catch(() => res.end());
+    } else E{
+      const responseBody = await fetchResponse.text();
+      res.end(responseBody);
+    }
+  };
+}
+ 
+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/coverage/src/test/fixtures.ts.html b/coverage/src/test/fixtures.ts.html new file mode 100644 index 0000000..8f29c2d --- /dev/null +++ b/coverage/src/test/fixtures.ts.html @@ -0,0 +1,1033 @@ + + + + + + Code coverage report for src/test/fixtures.ts + + + + + + + + + +
+
+

All files / src/test fixtures.ts

+
+ +
+ 96.77% + Statements + 30/31 +
+ + +
+ 80% + Branches + 8/10 +
+ + +
+ 100% + Functions + 1/1 +
+ + +
+ 96.77% + Lines + 30/31 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+

+
1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 +30 +31 +32 +33 +34 +35 +36 +37 +38 +39 +40 +41 +42 +43 +44 +45 +46 +47 +48 +49 +50 +51 +52 +53 +54 +55 +56 +57 +58 +59 +60 +61 +62 +63 +64 +65 +66 +67 +68 +69 +70 +71 +72 +73 +74 +75 +76 +77 +78 +79 +80 +81 +82 +83 +84 +85 +86 +87 +88 +89 +90 +91 +92 +93 +94 +95 +96 +97 +98 +99 +100 +101 +102 +103 +104 +105 +106 +107 +108 +109 +110 +111 +112 +113 +114 +115 +116 +117 +118 +119 +120 +121 +122 +123 +124 +125 +126 +127 +128 +129 +130 +131 +132 +133 +134 +135 +136 +137 +138 +139 +140 +141 +142 +143 +144 +145 +146 +147 +148 +149 +150 +151 +152 +153 +154 +155 +156 +157 +158 +159 +160 +161 +162 +163 +164 +165 +166 +167 +168 +169 +170 +171 +172 +173 +174 +175 +176 +177 +178 +179 +180 +181 +182 +183 +184 +185 +186 +187 +188 +189 +190 +191 +192 +193 +194 +195 +196 +197 +198 +199 +200 +201 +202 +203 +204 +205 +206 +207 +208 +209 +210 +211 +212 +213 +214 +215 +216 +217 +218 +219 +220 +221 +222 +223 +224 +225 +226 +227 +228 +229 +230 +231 +232 +233 +234 +235 +236 +237 +238 +239 +240 +241 +242 +243 +244 +245 +246 +247 +248 +249 +250 +251 +252 +253 +254 +255 +256 +257 +258 +259 +260 +261 +262 +263 +264 +265 +266 +267 +268 +269 +270 +271 +272 +273 +274 +275 +276 +277 +278 +279 +280 +281 +282 +283 +284 +285 +286 +287 +288 +289 +290 +291 +292 +293 +294 +295 +296 +297 +298 +299 +300 +301 +302 +303 +304 +305 +306 +307 +308 +309 +310 +311 +312 +313 +314 +315 +316 +317  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +48x +48x +48x +  +  +48x +48x +48x +  +  +48x +  +  +48x +  +  +  +  +  +48x +53x +  +  +  +  +53x +  +  +53x +53x +  +67x +  +  +  +  +  +  +  +  +  +  +67x +  +  +67x +67x +158x +  +  +  +  +  +  +  +  +  +  +  +158x +  +  +158x +93x +  +  +  +  +  +  +  +  +  +48x +93x +98x +98x +  +  +  +  +  +  +98x +  +  +  +  +  +  +  +  +48x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +8x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +8x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +8x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  + 
/**
+ * Test Fixtures for E2E Testing
+ *
+ * Provides fixture helpers that seed complete task hierarchies
+ * for integration and E2E tests.
+ */
+ 
+import { nanoid } from 'nanoid';
+import type { DrizzleDatabase } from '../db/index.js';
+import {
+  DrizzleInitiativeRepository,
+  DrizzlePhaseRepository,
+  DrizzleTaskRepository,
+} from '../db/repositories/drizzle/index.js';
+import { taskDependencies } from '../db/schema.js';
+ 
+// =============================================================================
+// Fixture Interfaces
+// =============================================================================
+ 
+/**
+ * Task fixture definition.
+ */
+export interface TaskFixture {
+  /** Unique identifier for this task (used for dependency references) */
+  id: string;
+  /** Task name */
+  name: string;
+  /** Task priority */
+  priority?: 'low' | 'medium' | 'high';
+  /** Task category */
+  category?: 'execute' | 'research' | 'discuss' | 'plan' | 'detail' | 'refine' | 'verify' | 'merge' | 'review';
+  /** Names of other tasks in same fixture this task depends on */
+  dependsOn?: string[];
+}
+ 
+/**
+ * Task group fixture definition (replaces Plan).
+ * Tasks are grouped by parent task in the new model.
+ */
+export interface TaskGroupFixture {
+  /** Group name (becomes a detail task) */
+  name: string;
+  /** Tasks in this group */
+  tasks: TaskFixture[];
+}
+ 
+/**
+ * Phase fixture definition.
+ */
+export interface PhaseFixture {
+  /** Phase name */
+  name: string;
+  /** Task groups in this phase (each group becomes a parent detail task) */
+  taskGroups: TaskGroupFixture[];
+}
+ 
+/**
+ * Initiative fixture definition (top-level).
+ */
+export interface InitiativeFixture {
+  /** Initiative name */
+  name: string;
+  /** Phases in this initiative */
+  phases: PhaseFixture[];
+}
+ 
+/**
+ * Result of seeding a fixture.
+ * Maps names to IDs for all created entities.
+ */
+export interface SeededFixture {
+  /** ID of the created initiative */
+  initiativeId: string;
+  /** Map of phase names to IDs */
+  phases: Map<string, string>;
+  /** Map of task group names to parent task IDs */
+  taskGroups: Map<string, string>;
+  /** Map of task names to IDs */
+  tasks: Map<string, string>;
+}
+ 
+// =============================================================================
+// Seed Function
+// =============================================================================
+ 
+/**
+ * Seed a complete task hierarchy from a fixture definition.
+ *
+ * Creates initiative, phases, detail tasks (as parent), and child tasks.
+ * Resolves task dependencies by name to actual task IDs.
+ *
+ * @param db - Drizzle database instance
+ * @param fixture - The fixture definition to seed
+ * @returns SeededFixture with all created entity IDs
+ */
+export async function seedFixture(
+  db: DrizzleDatabase,
+  fixture: InitiativeFixture
+): Promise<SeededFixture> {
+  // Create repositories
+  const initiativeRepo = new DrizzleInitiativeRepository(db);
+  const phaseRepo = new DrizzlePhaseRepository(db);
+  const taskRepo = new DrizzleTaskRepository(db);
+ 
+  // Result maps
+  const phasesMap = new Map<string, string>();
+  const taskGroupsMap = new Map<string, string>();
+  const tasksMap = new Map<string, string>();
+ 
+  // Collect all task dependencies to resolve after creation
+  const pendingDependencies: Array<{ taskId: string; dependsOnNames: string[] }> = [];
+ 
+  // Create initiative
+  const initiative = await initiativeRepo.create({
+    name: fixture.name,
+    status: 'active',
+  });
+ 
+  // Create phases
+  for (const phaseFixture of fixture.phases) {
+    const phase = await phaseRepo.create({
+      initiativeId: initiative.id,
+      name: phaseFixture.name,
+      status: 'pending',
+    });
+    phasesMap.set(phaseFixture.name, phase.id);
+ 
+    // Create task groups as parent detail tasks
+    let taskOrder = 0;
+    for (const groupFixture of phaseFixture.taskGroups) {
+      // Create parent detail task
+      const parentTask = await taskRepo.create({
+        phaseId: phase.id,
+        initiativeId: initiative.id,
+        name: groupFixture.name,
+        description: `Test task group: ${groupFixture.name}`,
+        category: 'detail',
+        type: 'auto',
+        priority: 'medium',
+        status: 'completed', // Detail tasks are completed once child tasks are created
+        order: taskOrder++,
+      });
+      taskGroupsMap.set(groupFixture.name, parentTask.id);
+ 
+      // Create child tasks linked to parent
+      let childOrder = 0;
+      for (const taskFixture of groupFixture.tasks) {
+        const task = await taskRepo.create({
+          parentTaskId: parentTask.id,
+          phaseId: phase.id,
+          initiativeId: initiative.id,
+          name: taskFixture.name,
+          description: `Test task: ${taskFixture.name}`,
+          category: taskFixture.category ?? 'execute',
+          type: 'auto',
+          priority: taskFixture.priority ?? 'medium',
+          status: 'pending',
+          order: childOrder++,
+        });
+        tasksMap.set(taskFixture.id, task.id);
+ 
+        // Collect dependencies to resolve later
+        if (taskFixture.dependsOn && taskFixture.dependsOn.length > 0) {
+          pendingDependencies.push({
+            taskId: task.id,
+            dependsOnNames: taskFixture.dependsOn,
+          });
+        }
+      }
+    }
+  }
+ 
+  // Resolve and insert task dependencies
+  for (const { taskId, dependsOnNames } of pendingDependencies) {
+    for (const depName of dependsOnNames) {
+      const dependsOnTaskId = tasksMap.get(depName);
+      Iif (!dependsOnTaskId) {
+        throw new Error(
+          `Dependency resolution failed: task "${depName}" not found in fixture`
+        );
+      }
+ 
+      // Insert into task_dependencies table
+      await db.insert(taskDependencies).values({
+        id: nanoid(),
+        taskId,
+        dependsOnTaskId,
+        createdAt: new Date(),
+      });
+    }
+  }
+ 
+  return {
+    initiativeId: initiative.id,
+    phases: phasesMap,
+    taskGroups: taskGroupsMap,
+    tasks: tasksMap,
+  };
+}
+ 
+// =============================================================================
+// Convenience Fixtures
+// =============================================================================
+ 
+/**
+ * Simple fixture: 1 initiative -> 1 phase -> 1 task group -> 3 tasks.
+ *
+ * Task dependency structure:
+ * - Task A: no dependencies
+ * - Task B: depends on Task A
+ * - Task C: depends on Task A
+ */
+export const SIMPLE_FIXTURE: InitiativeFixture = {
+  name: 'Simple Test Initiative',
+  phases: [
+    {
+      name: 'Phase 1',
+      taskGroups: [
+        {
+          name: 'Task Group 1',
+          tasks: [
+            { id: 'Task A', name: 'Task A', priority: 'high' },
+            { id: 'Task B', name: 'Task B', priority: 'medium', dependsOn: ['Task A'] },
+            { id: 'Task C', name: 'Task C', priority: 'medium', dependsOn: ['Task A'] },
+          ],
+        },
+      ],
+    },
+  ],
+};
+ 
+/**
+ * Parallel fixture: 1 initiative -> 1 phase -> 2 task groups (each with 2 independent tasks).
+ *
+ * Task structure:
+ * - Group A: Task X, Task Y (independent)
+ * - Group B: Task P, Task Q (independent)
+ */
+export const PARALLEL_FIXTURE: InitiativeFixture = {
+  name: 'Parallel Test Initiative',
+  phases: [
+    {
+      name: 'Parallel Phase',
+      taskGroups: [
+        {
+          name: 'Group A',
+          tasks: [
+            { id: 'Task X', name: 'Task X', priority: 'high' },
+            { id: 'Task Y', name: 'Task Y', priority: 'medium' },
+          ],
+        },
+        {
+          name: 'Group B',
+          tasks: [
+            { id: 'Task P', name: 'Task P', priority: 'high' },
+            { id: 'Task Q', name: 'Task Q', priority: 'low' },
+          ],
+        },
+      ],
+    },
+  ],
+};
+ 
+/**
+ * Complex fixture: 1 initiative -> 2 phases -> 4 task groups with cross-group dependencies.
+ *
+ * Structure:
+ * - Phase 1: Group 1 (Task 1A, 1B), Group 2 (Task 2A depends on 1A)
+ * - Phase 2: Group 3 (Task 3A depends on 1B), Group 4 (Task 4A depends on 2A and 3A)
+ */
+export const COMPLEX_FIXTURE: InitiativeFixture = {
+  name: 'Complex Test Initiative',
+  phases: [
+    {
+      name: 'Phase 1',
+      taskGroups: [
+        {
+          name: 'Group 1',
+          tasks: [
+            { id: 'Task 1A', name: 'Task 1A', priority: 'high' },
+            { id: 'Task 1B', name: 'Task 1B', priority: 'medium' },
+          ],
+        },
+        {
+          name: 'Group 2',
+          tasks: [
+            { id: 'Task 2A', name: 'Task 2A', priority: 'high', dependsOn: ['Task 1A'] },
+          ],
+        },
+      ],
+    },
+    {
+      name: 'Phase 2',
+      taskGroups: [
+        {
+          name: 'Group 3',
+          tasks: [
+            { id: 'Task 3A', name: 'Task 3A', priority: 'high', dependsOn: ['Task 1B'] },
+          ],
+        },
+        {
+          name: 'Group 4',
+          tasks: [
+            {
+              id: 'Task 4A',
+              name: 'Task 4A',
+              priority: 'high',
+              dependsOn: ['Task 2A', 'Task 3A'],
+            },
+          ],
+        },
+      ],
+    },
+  ],
+};
+ 
+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/coverage/src/test/harness.ts.html b/coverage/src/test/harness.ts.html new file mode 100644 index 0000000..488157c --- /dev/null +++ b/coverage/src/test/harness.ts.html @@ -0,0 +1,1945 @@ + + + + + + Code coverage report for src/test/harness.ts + + + + + + + + + +
+
+

All files / src/test harness.ts

+
+ +
+ 81.42% + Statements + 57/70 +
+ + +
+ 30% + Branches + 3/10 +
+ + +
+ 86.11% + Functions + 31/36 +
+ + +
+ 81.15% + Lines + 56/69 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+

+
1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 +30 +31 +32 +33 +34 +35 +36 +37 +38 +39 +40 +41 +42 +43 +44 +45 +46 +47 +48 +49 +50 +51 +52 +53 +54 +55 +56 +57 +58 +59 +60 +61 +62 +63 +64 +65 +66 +67 +68 +69 +70 +71 +72 +73 +74 +75 +76 +77 +78 +79 +80 +81 +82 +83 +84 +85 +86 +87 +88 +89 +90 +91 +92 +93 +94 +95 +96 +97 +98 +99 +100 +101 +102 +103 +104 +105 +106 +107 +108 +109 +110 +111 +112 +113 +114 +115 +116 +117 +118 +119 +120 +121 +122 +123 +124 +125 +126 +127 +128 +129 +130 +131 +132 +133 +134 +135 +136 +137 +138 +139 +140 +141 +142 +143 +144 +145 +146 +147 +148 +149 +150 +151 +152 +153 +154 +155 +156 +157 +158 +159 +160 +161 +162 +163 +164 +165 +166 +167 +168 +169 +170 +171 +172 +173 +174 +175 +176 +177 +178 +179 +180 +181 +182 +183 +184 +185 +186 +187 +188 +189 +190 +191 +192 +193 +194 +195 +196 +197 +198 +199 +200 +201 +202 +203 +204 +205 +206 +207 +208 +209 +210 +211 +212 +213 +214 +215 +216 +217 +218 +219 +220 +221 +222 +223 +224 +225 +226 +227 +228 +229 +230 +231 +232 +233 +234 +235 +236 +237 +238 +239 +240 +241 +242 +243 +244 +245 +246 +247 +248 +249 +250 +251 +252 +253 +254 +255 +256 +257 +258 +259 +260 +261 +262 +263 +264 +265 +266 +267 +268 +269 +270 +271 +272 +273 +274 +275 +276 +277 +278 +279 +280 +281 +282 +283 +284 +285 +286 +287 +288 +289 +290 +291 +292 +293 +294 +295 +296 +297 +298 +299 +300 +301 +302 +303 +304 +305 +306 +307 +308 +309 +310 +311 +312 +313 +314 +315 +316 +317 +318 +319 +320 +321 +322 +323 +324 +325 +326 +327 +328 +329 +330 +331 +332 +333 +334 +335 +336 +337 +338 +339 +340 +341 +342 +343 +344 +345 +346 +347 +348 +349 +350 +351 +352 +353 +354 +355 +356 +357 +358 +359 +360 +361 +362 +363 +364 +365 +366 +367 +368 +369 +370 +371 +372 +373 +374 +375 +376 +377 +378 +379 +380 +381 +382 +383 +384 +385 +386 +387 +388 +389 +390 +391 +392 +393 +394 +395 +396 +397 +398 +399 +400 +401 +402 +403 +404 +405 +406 +407 +408 +409 +410 +411 +412 +413 +414 +415 +416 +417 +418 +419 +420 +421 +422 +423 +424 +425 +426 +427 +428 +429 +430 +431 +432 +433 +434 +435 +436 +437 +438 +439 +440 +441 +442 +443 +444 +445 +446 +447 +448 +449 +450 +451 +452 +453 +454 +455 +456 +457 +458 +459 +460 +461 +462 +463 +464 +465 +466 +467 +468 +469 +470 +471 +472 +473 +474 +475 +476 +477 +478 +479 +480 +481 +482 +483 +484 +485 +486 +487 +488 +489 +490 +491 +492 +493 +494 +495 +496 +497 +498 +499 +500 +501 +502 +503 +504 +505 +506 +507 +508 +509 +510 +511 +512 +513 +514 +515 +516 +517 +518 +519 +520 +521 +522 +523 +524 +525 +526 +527 +528 +529 +530 +531 +532 +533 +534 +535 +536 +537 +538 +539 +540 +541 +542 +543 +544 +545 +546 +547 +548 +549 +550 +551 +552 +553 +554 +555 +556 +557 +558 +559 +560 +561 +562 +563 +564 +565 +566 +567 +568 +569 +570 +571 +572 +573 +574 +575 +576 +577 +578 +579 +580 +581 +582 +583 +584 +585 +586 +587 +588 +589 +590 +591 +592 +593 +594 +595 +596 +597 +598 +599 +600 +601 +602 +603 +604 +605 +606 +607 +608 +609 +610 +611 +612 +613 +614 +615 +616 +617 +618 +619 +620 +621  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +80x +80x +  +  +  +  +  +  +12x +  +  +  +20x +  +  +  +  +  +20x +20x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +22x +  +  +  +  +22x +22x +12x +  +  +10x +  +  +  +  +  +  +  +  +  +  +80x +80x +  +  +  +  +  +  +  +  +  +  +  +  +  +80x +  +  +366x +366x +  +  +  +  +  +  +173x +  +  +  +  +  +  +124x +  +  +  +  +  +  +  +  +  +  +8x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +80x +  +  +80x +  +  +80x +80x +  +  +80x +80x +  +  +80x +  +  +  +  +  +  +80x +  +  +  +  +  +  +80x +  +  +  +  +  +  +  +  +80x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +80x +  +  +80x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +48x +  +  +13x +  +  +  +2x +  +  +  +  +  +  +5x +  +  +  +  +  +  +  +  +1x +  +  +  +  +  +  +2x +  +  +5x +  +46x +  +5x +  +44x +  +  +80x +80x +80x +  +  +  +14x +  +  +  +  +  +  +  +  +  +  +3x +  +  +  +  +  +  +  +  +  +  +1x +  +  +  +  +  +  +  +  +  +  +5x +  +  +  +  +  +  +  +  +  +  +6x +  +  +  +  +  +  +  +  +  +  +2x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +2x +  +  +  +19x +  +  +  +  +  +  +12x +  +  +  +7x +  +  +  +  +  +  +  +  +  +  +4x +  +  +  +80x +  + 
/**
+ * Test Harness for E2E Testing
+ *
+ * Wires up the full system with mocks for E2E testing.
+ * Uses real managers (DispatchManager, CoordinationManager) with
+ * MockAgentManager and MockWorktreeManager for isolation.
+ */
+ 
+import { randomUUID } from 'crypto';
+import { vi } from 'vitest';
+import type { DrizzleDatabase } from '../db/index.js';
+import type { EventBus, DomainEvent } from '../events/types.js';
+import { EventEmitterBus } from '../events/bus.js';
+import type { AgentManager } from '../agent/types.js';
+import { MockAgentManager, type MockAgentScenario } from '../agent/mock-manager.js';
+import type { PendingQuestions, QuestionItem } from '../agent/types.js';
+import type { WorktreeManager, Worktree, WorktreeDiff, MergeResult } from '../git/types.js';
+import type { DispatchManager, PhaseDispatchManager } from '../dispatch/types.js';
+import { DefaultDispatchManager } from '../dispatch/manager.js';
+import { DefaultPhaseDispatchManager } from '../dispatch/phase-manager.js';
+import type { CoordinationManager } from '../coordination/types.js';
+import { DefaultCoordinationManager } from '../coordination/manager.js';
+import type { TaskRepository } from '../db/repositories/task-repository.js';
+import type { MessageRepository } from '../db/repositories/message-repository.js';
+import type { AgentRepository } from '../db/repositories/agent-repository.js';
+import type { InitiativeRepository } from '../db/repositories/initiative-repository.js';
+import type { PhaseRepository } from '../db/repositories/phase-repository.js';
+import type { Initiative, Phase, Task } from '../db/schema.js';
+import { createTestDatabase } from '../db/repositories/drizzle/test-helpers.js';
+import { createRepositories } from '../container.js';
+import {
+  seedFixture,
+  type InitiativeFixture,
+  type SeededFixture,
+} from './fixtures.js';
+import { appRouter, createCallerFactory } from '../trpc/router.js';
+import { createContext, type TRPCContext } from '../trpc/context.js';
+ 
+// =============================================================================
+// MockWorktreeManager
+// =============================================================================
+ 
+/**
+ * Simple in-memory WorktreeManager for testing.
+ * Creates fake worktrees without actual git operations.
+ */
+export class MockWorktreeManager implements WorktreeManager {
+  private worktrees: Map<string, Worktree> = new Map();
+  private mergeResults: Map<string, MergeResult> = new Map();
+ 
+  /**
+   * Set a custom merge result for a specific worktree.
+   * Used to test conflict scenarios.
+   */
+  setMergeResult(worktreeId: string, result: MergeResult): void {
+    this.mergeResults.set(worktreeId, result);
+  }
+ 
+  async create(id: string, branch: string, baseBranch?: string): Promise<Worktree> {
+    const worktree: Worktree = {
+      id,
+      branch,
+      path: `/tmp/test-worktrees/${id}`,
+      isMainWorktree: false,
+    };
+    this.worktrees.set(id, worktree);
+    return worktree;
+  }
+ 
+  async remove(id: string): Promise<void> {
+    if (!this.worktrees.has(id)) {
+      throw new Error(`Worktree not found: ${id}`);
+    }
+    this.worktrees.delete(id);
+    this.mergeResults.delete(id);
+  }
+ 
+  async list(): Promise<Worktree[]> {
+    return Array.from(this.worktrees.values());
+  }
+ 
+  async get(id: string): Promise<Worktree | null> {
+    return this.worktrees.get(id) ?? null;
+  }
+ 
+  async diff(id: string): Promise<WorktreeDiff> {
+    if (!this.worktrees.has(id)) {
+      throw new Error(`Worktree not found: ${id}`);
+    }
+    return {
+      files: [],
+      summary: 'No changes (mock)',
+    };
+  }
+ 
+  async merge(id: string, targetBranch: string): Promise<MergeResult> {
+    Iif (!this.worktrees.has(id)) {
+      throw new Error(`Worktree not found: ${id}`);
+    }
+ 
+    // Return custom result if set, otherwise success
+    const customResult = this.mergeResults.get(id);
+    if (customResult) {
+      return customResult;
+    }
+ 
+    return {
+      success: true,
+      message: `Merged ${id} into ${targetBranch} (mock)`,
+    };
+  }
+ 
+  /**
+   * Clear all worktrees.
+   * Useful for test cleanup.
+   */
+  clear(): void {
+    this.worktrees.clear();
+    this.mergeResults.clear();
+  }
+}
+ 
+// =============================================================================
+// CapturingEventBus
+// =============================================================================
+ 
+/**
+ * EventBus wrapper that captures all emitted events.
+ * Extends EventEmitterBus with event capture functionality.
+ */
+export class CapturingEventBus extends EventEmitterBus {
+  /** All emitted events */
+  emittedEvents: DomainEvent[] = [];
+ 
+  emit<T extends DomainEvent>(event: T): void {
+    this.emittedEvents.push(event);
+    super.emit(event);
+  }
+ 
+  /**
+   * Get events by type.
+   */
+  getEventsByType(type: string): DomainEvent[] {
+    return this.emittedEvents.filter((e) => e.type === type);
+  }
+ 
+  /**
+   * Clear captured events.
+   */
+  clearEvents(): void {
+    this.emittedEvents = [];
+  }
+}
+ 
+// =============================================================================
+// tRPC Caller Type
+// =============================================================================
+ 
+/**
+ * Create caller factory for the app router.
+ */
+const createCaller = createCallerFactory(appRouter);
+ 
+/**
+ * Type for the tRPC caller.
+ */
+export type TRPCCaller = ReturnType<typeof createCaller>;
+ 
+// =============================================================================
+// TestHarness Interface
+// =============================================================================
+ 
+/**
+ * Test harness for E2E testing.
+ * Provides access to all system components and helper methods.
+ */
+export interface TestHarness {
+  // Core components
+  /** In-memory SQLite database */
+  db: DrizzleDatabase;
+  /** Event bus with event capture */
+  eventBus: CapturingEventBus;
+  /** Mock agent manager */
+  agentManager: MockAgentManager;
+  /** Alias for agentManager - used in tests for clarity */
+  mockAgentManager: MockAgentManager;
+  /** Mock worktree manager */
+  worktreeManager: MockWorktreeManager;
+  /** Real dispatch manager wired to mocks */
+  dispatchManager: DispatchManager;
+  /** Real phase dispatch manager wired to phaseRepository */
+  phaseDispatchManager: PhaseDispatchManager;
+  /** Real coordination manager wired to mocks */
+  coordinationManager: CoordinationManager;
+ 
+  // Repositories
+  /** Task repository */
+  taskRepository: TaskRepository;
+  /** Message repository */
+  messageRepository: MessageRepository;
+  /** Agent repository */
+  agentRepository: AgentRepository;
+  /** Initiative repository */
+  initiativeRepository: InitiativeRepository;
+  /** Phase repository */
+  phaseRepository: PhaseRepository;
+ 
+  // tRPC Caller
+  /** tRPC caller for direct procedure calls */
+  caller: TRPCCaller;
+ 
+  // Helpers
+  /**
+   * Seed a fixture into the database.
+   */
+  seedFixture(fixture: InitiativeFixture): Promise<SeededFixture>;
+ 
+  /**
+   * Set scenario for a specific agent name.
+   */
+  setAgentScenario(agentName: string, scenario: MockAgentScenario): void;
+ 
+  /**
+   * Convenience: Set agent to complete with done status.
+   */
+  setAgentDone(agentName: string, result?: string): void;
+ 
+  /**
+   * Convenience: Set agent to ask questions (array form).
+   */
+  setAgentQuestions(
+    agentName: string,
+    questions: QuestionItem[]
+  ): void;
+ 
+  /**
+   * Convenience: Set agent to ask a single question.
+   * Wraps the question in an array internally.
+   */
+  setAgentQuestion(
+    agentName: string,
+    questionId: string,
+    question: string,
+    options?: Array<{ label: string; description?: string }>
+  ): void;
+ 
+  /**
+   * Convenience: Set agent to fail with unrecoverable error.
+   */
+  setAgentError(agentName: string, error: string): void;
+ 
+  /**
+   * Get pending questions for an agent.
+   */
+  getPendingQuestions(agentId: string): Promise<PendingQuestions | null>;
+ 
+  /**
+   * Get events by type.
+   */
+  getEventsByType(type: string): DomainEvent[];
+ 
+  /**
+   * Get emitted events by type (alias for getEventsByType).
+   */
+  getEmittedEvents(type: string): DomainEvent[];
+ 
+  /**
+   * Clear all captured events.
+   */
+  clearEvents(): void;
+ 
+  /**
+   * Clean up all resources.
+   */
+  cleanup(): void;
+ 
+  /**
+   * Advance fake timers (wrapper for vi.runAllTimersAsync).
+   * Only works when vi.useFakeTimers() is active.
+   */
+  advanceTimers(): Promise<void>;
+ 
+  // ==========================================================================
+  // Architect Mode Helpers
+  // ==========================================================================
+ 
+  /**
+   * Set up scenario where architect completes discussion.
+   */
+  setArchitectDiscussComplete(
+    agentName: string,
+    _decisions: unknown[],
+    summary: string
+  ): void;
+ 
+  /**
+   * Set up scenario where architect needs more questions in discuss mode.
+   */
+  setArchitectDiscussQuestions(
+    agentName: string,
+    questions: QuestionItem[]
+  ): void;
+ 
+  /**
+   * Set up scenario where architect completes plan.
+   */
+  setArchitectPlanComplete(
+    agentName: string,
+    _phases: unknown[]
+  ): void;
+ 
+  /**
+   * Set up scenario where architect completes detail.
+   */
+  setArchitectDetailComplete(
+    agentName: string,
+    _tasks: unknown[]
+  ): void;
+ 
+  /**
+   * Set up scenario where architect needs questions in detail mode.
+   */
+  setArchitectDetailQuestions(
+    agentName: string,
+    questions: QuestionItem[]
+  ): void;
+ 
+  // ==========================================================================
+  // Initiative/Phase/Plan Convenience Helpers
+  // ==========================================================================
+ 
+  /**
+   * Get initiative by ID through tRPC.
+   */
+  getInitiative(id: string): Promise<Initiative | null>;
+ 
+  /**
+   * Get phases for initiative through tRPC.
+   */
+  getPhases(initiativeId: string): Promise<Phase[]>;
+ 
+  /**
+   * Create initiative through tRPC.
+   */
+  createInitiative(name: string): Promise<Initiative>;
+ 
+  /**
+   * Create phases from plan output through tRPC.
+   */
+  createPhasesFromPlan(
+    initiativeId: string,
+    phases: Array<{ name: string }>
+  ): Promise<Phase[]>;
+ 
+  /**
+   * Create a detail task through tRPC (replaces createPlan).
+   */
+  createDetailTask(
+    phaseId: string,
+    name: string,
+    description?: string
+  ): Promise<Task>;
+ 
+  /**
+   * Get child tasks of a parent task through tRPC.
+   */
+  getChildTasks(parentTaskId: string): Promise<Task[]>;
+}
+ 
+// =============================================================================
+// createTestHarness Factory
+// =============================================================================
+ 
+/**
+ * Create a fully wired test harness for E2E testing.
+ *
+ * Wires:
+ * - In-memory SQLite database
+ * - CapturingEventBus (captures all events)
+ * - MockAgentManager (simulates agent behavior)
+ * - MockWorktreeManager (fake worktrees)
+ * - Real DefaultDispatchManager (with mock agent manager)
+ * - Real DefaultCoordinationManager (with mock worktree manager)
+ * - All repositories (Drizzle implementations)
+ * - tRPC caller with full context
+ */
+export function createTestHarness(): TestHarness {
+  // Create database
+  const db = createTestDatabase();
+ 
+  // Create event bus with capture
+  const eventBus = new CapturingEventBus();
+ 
+  // Create mock managers
+  const agentManager = new MockAgentManager({ eventBus });
+  const worktreeManager = new MockWorktreeManager();
+ 
+  // Create repositories
+  const repos = createRepositories(db);
+  const { taskRepository, messageRepository, agentRepository, initiativeRepository, phaseRepository } = repos;
+ 
+  // Create real managers wired to mocks
+  const dispatchManager = new DefaultDispatchManager(
+    taskRepository,
+    messageRepository,
+    agentManager,
+    eventBus
+  );
+ 
+  const phaseDispatchManager = new DefaultPhaseDispatchManager(
+    phaseRepository,
+    taskRepository,
+    dispatchManager,
+    eventBus
+  );
+ 
+  const coordinationManager = new DefaultCoordinationManager(
+    worktreeManager,
+    taskRepository,
+    agentRepository,
+    messageRepository,
+    eventBus
+  );
+ 
+  // Create tRPC context with all dependencies
+  const ctx: TRPCContext = createContext({
+    eventBus,
+    serverStartedAt: new Date(),
+    processCount: 0,
+    agentManager,
+    taskRepository,
+    messageRepository,
+    dispatchManager,
+    phaseDispatchManager,
+    coordinationManager,
+    initiativeRepository,
+    phaseRepository,
+  });
+ 
+  // Create tRPC caller
+  const caller = createCaller(ctx);
+ 
+  // Build harness
+  const harness: TestHarness = {
+    // Core components
+    db,
+    eventBus,
+    agentManager,
+    mockAgentManager: agentManager, // Alias for clarity in tests
+    worktreeManager,
+    dispatchManager,
+    phaseDispatchManager,
+    coordinationManager,
+ 
+    // Repositories
+    taskRepository,
+    messageRepository,
+    agentRepository,
+    initiativeRepository,
+    phaseRepository,
+ 
+    // tRPC Caller
+    caller,
+ 
+    // Helpers
+    seedFixture: (fixture: InitiativeFixture) => seedFixture(db, fixture),
+ 
+    setAgentScenario: (agentName: string, scenario: MockAgentScenario) => {
+      agentManager.setScenario(agentName, scenario);
+    },
+ 
+    setAgentDone: (agentName: string, result?: string) => {
+      agentManager.setScenario(agentName, { status: 'done', result });
+    },
+ 
+    setAgentQuestions: (
+      agentName: string,
+      questions: QuestionItem[]
+    ) => {
+      agentManager.setScenario(agentName, { status: 'questions', questions });
+    },
+ 
+    setAgentQuestion: (
+      agentName: string,
+      questionId: string,
+      question: string,
+      options?: Array<{ label: string; description?: string }>
+    ) => {
+      agentManager.setScenario(agentName, {
+        status: 'questions',
+        questions: [{ id: questionId, question, options }],
+      });
+    },
+ 
+    setAgentError: (agentName: string, error: string) => {
+      agentManager.setScenario(agentName, { status: 'error', error });
+    },
+ 
+    getPendingQuestions: (agentId: string) => agentManager.getPendingQuestions(agentId),
+ 
+    getEventsByType: (type: string) => eventBus.getEventsByType(type),
+ 
+    getEmittedEvents: (type: string) => eventBus.getEventsByType(type),
+ 
+    clearEvents: () => eventBus.clearEvents(),
+ 
+    cleanup: () => {
+      agentManager.clear();
+      worktreeManager.clear();
+      eventBus.clearEvents();
+    },
+ 
+    // Timer helper - requires vi.useFakeTimers() to be active
+    advanceTimers: () => vi.runAllTimersAsync(),
+ 
+    // ========================================================================
+    // Architect Mode Helpers
+    // ========================================================================
+ 
+    setArchitectDiscussComplete: (
+      agentName: string,
+      _decisions: unknown[],
+      summary: string
+    ) => {
+      agentManager.setScenario(agentName, {
+        status: 'done',
+        result: summary,
+        delay: 0,
+      });
+    },
+ 
+    setArchitectDiscussQuestions: (
+      agentName: string,
+      questions: QuestionItem[]
+    ) => {
+      agentManager.setScenario(agentName, {
+        status: 'questions',
+        questions,
+        delay: 0,
+      });
+    },
+ 
+    setArchitectPlanComplete: (
+      agentName: string,
+      _phases: unknown[]
+    ) => {
+      agentManager.setScenario(agentName, {
+        status: 'done',
+        result: 'Plan complete',
+        delay: 0,
+      });
+    },
+ 
+    setArchitectDetailComplete: (
+      agentName: string,
+      _tasks: unknown[]
+    ) => {
+      agentManager.setScenario(agentName, {
+        status: 'done',
+        result: 'Detail complete',
+        delay: 0,
+      });
+    },
+ 
+    setArchitectDetailQuestions: (
+      agentName: string,
+      questions: QuestionItem[]
+    ) => {
+      agentManager.setScenario(agentName, {
+        status: 'questions',
+        questions,
+        delay: 0,
+      });
+    },
+ 
+    // ========================================================================
+    // Initiative/Phase/Plan Convenience Helpers
+    // ========================================================================
+ 
+    getInitiative: async (id: string) => {
+      try {
+        return await caller.getInitiative({ id });
+      } catch {
+        return null;
+      }
+    },
+ 
+    getPhases: (initiativeId: string) => {
+      return caller.listPhases({ initiativeId });
+    },
+ 
+    createInitiative: (name: string) => {
+      return caller.createInitiative({ name });
+    },
+ 
+    createPhasesFromPlan: (
+      initiativeId: string,
+      phases: Array<{ name: string }>
+    ) => {
+      return caller.createPhasesFromPlan({ initiativeId, phases });
+    },
+ 
+    createDetailTask: async (phaseId: string, name: string, description?: string) => {
+      return caller.createPhaseTask({
+        phaseId,
+        name,
+        description,
+        category: 'detail',
+        type: 'auto',
+        requiresApproval: true,
+      });
+    },
+ 
+    getChildTasks: (parentTaskId: string) => {
+      return caller.listTasks({ parentTaskId });
+    },
+  };
+ 
+  return harness;
+}
+ 
+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/coverage/src/test/index.html b/coverage/src/test/index.html new file mode 100644 index 0000000..d79a7db --- /dev/null +++ b/coverage/src/test/index.html @@ -0,0 +1,146 @@ + + + + + + Code coverage report for src/test + + + + + + + + + +
+
+

All files src/test

+
+ +
+ 86.13% + Statements + 87/101 +
+ + +
+ 55% + Branches + 11/20 +
+ + +
+ 86.48% + Functions + 32/37 +
+ + +
+ 86% + Lines + 86/100 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
FileStatementsBranchesFunctionsLines
fixtures.ts +
+
96.77%30/3180%8/10100%1/196.77%30/31
harness.ts +
+
81.42%57/7030%3/1086.11%31/3681.15%56/69
index.ts +
+
0%0/00%0/00%0/00%0/0
+
+
+
+ + + + + + + + \ No newline at end of file diff --git a/coverage/src/test/index.ts.html b/coverage/src/test/index.ts.html new file mode 100644 index 0000000..b35da7b --- /dev/null +++ b/coverage/src/test/index.ts.html @@ -0,0 +1,166 @@ + + + + + + Code coverage report for src/test/index.ts + + + + + + + + + +
+
+

All files / src/test index.ts

+
+ +
+ 0% + Statements + 0/0 +
+ + +
+ 0% + Branches + 0/0 +
+ + +
+ 0% + Functions + 0/0 +
+ + +
+ 0% + Lines + 0/0 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+

+
1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  + 
/**
+ * Test Module
+ *
+ * Provides test harness and fixtures for E2E testing.
+ */
+ 
+// Fixture helpers
+export {
+  seedFixture,
+  type TaskFixture,
+  type TaskGroupFixture,
+  type PhaseFixture,
+  type InitiativeFixture,
+  type SeededFixture,
+  SIMPLE_FIXTURE,
+  PARALLEL_FIXTURE,
+  COMPLEX_FIXTURE,
+} from './fixtures.js';
+ 
+// Test harness
+export {
+  createTestHarness,
+  MockWorktreeManager,
+  CapturingEventBus,
+  type TestHarness,
+  type TRPCCaller,
+} from './harness.js';
+ 
+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/coverage/src/test/integration/real-providers/harness.ts.html b/coverage/src/test/integration/real-providers/harness.ts.html new file mode 100644 index 0000000..a278184 --- /dev/null +++ b/coverage/src/test/integration/real-providers/harness.ts.html @@ -0,0 +1,1219 @@ + + + + + + Code coverage report for src/test/integration/real-providers/harness.ts + + + + + + + + + +
+
+

All files / src/test/integration/real-providers harness.ts

+
+ +
+ 8.97% + Statements + 7/78 +
+ + +
+ 4.65% + Branches + 2/43 +
+ + +
+ 0% + Functions + 0/14 +
+ + +
+ 9.45% + Lines + 7/74 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+

+
1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 +30 +31 +32 +33 +34 +35 +36 +37 +38 +39 +40 +41 +42 +43 +44 +45 +46 +47 +48 +49 +50 +51 +52 +53 +54 +55 +56 +57 +58 +59 +60 +61 +62 +63 +64 +65 +66 +67 +68 +69 +70 +71 +72 +73 +74 +75 +76 +77 +78 +79 +80 +81 +82 +83 +84 +85 +86 +87 +88 +89 +90 +91 +92 +93 +94 +95 +96 +97 +98 +99 +100 +101 +102 +103 +104 +105 +106 +107 +108 +109 +110 +111 +112 +113 +114 +115 +116 +117 +118 +119 +120 +121 +122 +123 +124 +125 +126 +127 +128 +129 +130 +131 +132 +133 +134 +135 +136 +137 +138 +139 +140 +141 +142 +143 +144 +145 +146 +147 +148 +149 +150 +151 +152 +153 +154 +155 +156 +157 +158 +159 +160 +161 +162 +163 +164 +165 +166 +167 +168 +169 +170 +171 +172 +173 +174 +175 +176 +177 +178 +179 +180 +181 +182 +183 +184 +185 +186 +187 +188 +189 +190 +191 +192 +193 +194 +195 +196 +197 +198 +199 +200 +201 +202 +203 +204 +205 +206 +207 +208 +209 +210 +211 +212 +213 +214 +215 +216 +217 +218 +219 +220 +221 +222 +223 +224 +225 +226 +227 +228 +229 +230 +231 +232 +233 +234 +235 +236 +237 +238 +239 +240 +241 +242 +243 +244 +245 +246 +247 +248 +249 +250 +251 +252 +253 +254 +255 +256 +257 +258 +259 +260 +261 +262 +263 +264 +265 +266 +267 +268 +269 +270 +271 +272 +273 +274 +275 +276 +277 +278 +279 +280 +281 +282 +283 +284 +285 +286 +287 +288 +289 +290 +291 +292 +293 +294 +295 +296 +297 +298 +299 +300 +301 +302 +303 +304 +305 +306 +307 +308 +309 +310 +311 +312 +313 +314 +315 +316 +317 +318 +319 +320 +321 +322 +323 +324 +325 +326 +327 +328 +329 +330 +331 +332 +333 +334 +335 +336 +337 +338 +339 +340 +341 +342 +343 +344 +345 +346 +347 +348 +349 +350 +351 +352 +353 +354 +355 +356 +357 +358 +359 +360 +361 +362 +363 +364 +365 +366 +367 +368 +369 +370 +371 +372 +373 +374 +375 +376 +377 +378 +379  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +5x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +5x +  +  +  +  +  +5x +  +  +  +  +5x +  +  +  +  +5x +  +  +  +  +  +5x +  +  +  +  +  +5x + 
/**
+ * Real Provider Test Harness
+ *
+ * Extends the existing test infrastructure to use REAL MultiProviderAgentManager
+ * for integration testing with actual CLI providers like Claude and Codex.
+ *
+ * Unlike the standard TestHarness which uses MockAgentManager, this harness:
+ * - Uses real CLI spawning (costs real API credits!)
+ * - Provides poll-based waiting helpers
+ * - Captures events for inspection
+ * - Manages temp directories for worktrees
+ */
+ 
+import { mkdtemp, rm } from 'node:fs/promises';
+import { tmpdir } from 'node:os';
+import { join } from 'node:path';
+import { describe } from 'vitest';
+import type { DrizzleDatabase } from '../../../db/index.js';
+import type { DomainEvent, EventBus } from '../../../events/types.js';
+import { EventEmitterBus } from '../../../events/bus.js';
+import { MultiProviderAgentManager } from '../../../agent/manager.js';
+import type { AgentResult, PendingQuestions, AgentStatus } from '../../../agent/types.js';
+import type { AgentRepository } from '../../../db/repositories/agent-repository.js';
+import type { ProjectRepository } from '../../../db/repositories/project-repository.js';
+import type { AccountRepository } from '../../../db/repositories/account-repository.js';
+import type { InitiativeRepository } from '../../../db/repositories/initiative-repository.js';
+import {
+  DrizzleAgentRepository,
+  DrizzleProjectRepository,
+  DrizzleAccountRepository,
+  DrizzleInitiativeRepository,
+} from '../../../db/repositories/drizzle/index.js';
+import { createTestDatabase } from '../../../db/repositories/drizzle/test-helpers.js';
+ 
+/**
+ * Sleep helper for polling loops.
+ */
+export function sleep(ms: number): Promise<void> {
+  return new Promise((resolve) => setTimeout(resolve, ms));
+}
+ 
+/**
+ * Event bus that captures all emitted events for inspection.
+ */
+export class CapturingEventBus extends EventEmitterBus {
+  emittedEvents: DomainEvent[] = [];
+ 
+  emit<T extends DomainEvent>(event: T): void {
+    this.emittedEvents.push(event);
+    super.emit(event);
+  }
+ 
+  getEventsByType<T extends DomainEvent>(type: T['type']): T[] {
+    return this.emittedEvents.filter((e) => e.type === type) as T[];
+  }
+ 
+  clearEvents(): void {
+    this.emittedEvents = [];
+  }
+}
+ 
+/**
+ * Options for creating a real provider test harness.
+ */
+export interface RealProviderHarnessOptions {
+  /** Which provider to test (default: 'claude') */
+  provider?: 'claude' | 'codex';
+  /** Optional workspace root (temp dir created if omitted) */
+  workspaceRoot?: string;
+}
+ 
+/**
+ * Real Provider Test Harness interface.
+ *
+ * Provides everything needed to test against real CLI providers:
+ * - In-memory database with real repositories
+ * - Real MultiProviderAgentManager (spawns actual CLI processes)
+ * - Event capture for verification
+ * - Polling-based wait helpers
+ */
+export interface RealProviderHarness {
+  /** In-memory SQLite database */
+  db: DrizzleDatabase;
+  /** Event bus with capture capability */
+  eventBus: CapturingEventBus;
+  /** Real agent manager (not mock!) */
+  agentManager: MultiProviderAgentManager;
+  /** Workspace root directory */
+  workspaceRoot: string;
+ 
+  /** Agent repository */
+  agentRepository: AgentRepository;
+  /** Project repository */
+  projectRepository: ProjectRepository;
+  /** Account repository */
+  accountRepository: AccountRepository;
+  /** Initiative repository */
+  initiativeRepository: InitiativeRepository;
+ 
+  /**
+   * Wait for an agent to reach idle or crashed status.
+   * Polls the database at regular intervals.
+   *
+   * @param agentId - The agent ID to wait for
+   * @param timeoutMs - Maximum time to wait (default 120000ms = 2 minutes)
+   * @returns The agent result if completed, or null if crashed/timeout
+   */
+  waitForAgentCompletion(agentId: string, timeoutMs?: number): Promise<AgentResult | null>;
+ 
+  /**
+   * Wait for an agent to enter waiting_for_input status.
+   * Polls the database at regular intervals.
+   *
+   * @param agentId - The agent ID to wait for
+   * @param timeoutMs - Maximum time to wait (default 120000ms)
+   * @returns The pending questions if waiting, or null if timeout/other status
+   */
+  waitForAgentWaiting(agentId: string, timeoutMs?: number): Promise<PendingQuestions | null>;
+ 
+  /**
+   * Wait for an agent to reach a specific status.
+   *
+   * @param agentId - The agent ID to wait for
+   * @param status - The target status
+   * @param timeoutMs - Maximum time to wait (default 120000ms)
+   */
+  waitForAgentStatus(agentId: string, status: AgentStatus, timeoutMs?: number): Promise<void>;
+ 
+  /**
+   * Get captured events filtered by type.
+   */
+  getEventsByType<T extends DomainEvent>(type: T['type']): T[];
+ 
+  /**
+   * Clear all captured events.
+   */
+  clearEvents(): void;
+ 
+  /**
+   * Kill all running agents (for cleanup).
+   */
+  killAllAgents(): Promise<void>;
+ 
+  /**
+   * Clean up all resources (directories, processes).
+   * Call this in afterAll/afterEach.
+   */
+  cleanup(): Promise<void>;
+}
+ 
+/** Default poll interval for status checks */
+const POLL_INTERVAL_MS = 1000;
+ 
+/**
+ * Create a test harness for real provider integration tests.
+ *
+ * This creates:
+ * - In-memory SQLite database
+ * - Temp directory for worktrees (or uses provided workspace)
+ * - Real MultiProviderAgentManager
+ * - Event capture bus
+ *
+ * @example
+ * ```typescript
+ * let harness: RealProviderHarness;
+ *
+ * beforeAll(async () => {
+ *   harness = await createRealProviderHarness({ provider: 'claude' });
+ * });
+ *
+ * afterAll(async () => {
+ *   await harness.cleanup();
+ * });
+ *
+ * it('spawns and completes', async () => {
+ *   const agent = await harness.agentManager.spawn({...});
+ *   const result = await harness.waitForAgentCompletion(agent.id);
+ *   expect(result?.success).toBe(true);
+ * });
+ * ```
+ */
+export async function createRealProviderHarness(
+  options: RealProviderHarnessOptions = {}
+): Promise<RealProviderHarness> {
+  // Create workspace directory (temp if not provided)
+  const workspaceRoot = options.workspaceRoot ?? (await mkdtemp(join(tmpdir(), 'cw-test-')));
+  const ownedWorkspace = !options.workspaceRoot; // Track if we need to clean up
+ 
+  // Initialize git repo in temp workspace (required for worktree operations)
+  if (ownedWorkspace) {
+    const { execSync } = await import('node:child_process');
+    execSync('git init', { cwd: workspaceRoot, stdio: 'ignore' });
+    execSync('git config user.email "test@test.com"', { cwd: workspaceRoot, stdio: 'ignore' });
+    execSync('git config user.name "Test"', { cwd: workspaceRoot, stdio: 'ignore' });
+    // Create initial commit (worktrees require at least one commit)
+    execSync('touch .gitkeep && git add .gitkeep && git commit -m "init"', { cwd: workspaceRoot, stdio: 'ignore' });
+  }
+ 
+  // Create in-memory database
+  const db = createTestDatabase();
+ 
+  // Create repositories
+  const agentRepository = new DrizzleAgentRepository(db);
+  const projectRepository = new DrizzleProjectRepository(db);
+  const accountRepository = new DrizzleAccountRepository(db);
+  const initiativeRepository = new DrizzleInitiativeRepository(db);
+ 
+  // Create event bus with capture (parent class already sets maxListeners to 100)
+  const eventBus = new CapturingEventBus();
+ 
+  // Create REAL agent manager (not mock!)
+  const agentManager = new MultiProviderAgentManager(
+    agentRepository,
+    workspaceRoot,
+    projectRepository,
+    accountRepository,
+    eventBus
+  );
+ 
+  // Build harness
+  const harness: RealProviderHarness = {
+    db,
+    eventBus,
+    agentManager,
+    workspaceRoot,
+    agentRepository,
+    projectRepository,
+    accountRepository,
+    initiativeRepository,
+ 
+    async waitForAgentCompletion(agentId: string, timeoutMs = 120000): Promise<AgentResult | null> {
+      const deadline = Date.now() + timeoutMs;
+ 
+      while (Date.now() < deadline) {
+        const agent = await agentRepository.findById(agentId);
+        if (!agent) return null;
+ 
+        if (agent.status === 'idle' || agent.status === 'stopped') {
+          // Agent completed - get result
+          return agentManager.getResult(agentId);
+        }
+ 
+        if (agent.status === 'crashed') {
+          // Agent crashed - return the error result
+          return agentManager.getResult(agentId);
+        }
+ 
+        if (agent.status === 'waiting_for_input') {
+          // Agent is waiting - return null (not completed)
+          return null;
+        }
+ 
+        // Still running - wait and check again
+        await sleep(POLL_INTERVAL_MS);
+      }
+ 
+      throw new Error(`Timeout waiting for agent ${agentId} to complete after ${timeoutMs}ms`);
+    },
+ 
+    async waitForAgentWaiting(agentId: string, timeoutMs = 120000): Promise<PendingQuestions | null> {
+      const deadline = Date.now() + timeoutMs;
+ 
+      while (Date.now() < deadline) {
+        const agent = await agentRepository.findById(agentId);
+        if (!agent) return null;
+ 
+        if (agent.status === 'waiting_for_input') {
+          return agentManager.getPendingQuestions(agentId);
+        }
+ 
+        if (agent.status === 'idle' || agent.status === 'stopped' || agent.status === 'crashed') {
+          // Agent finished without asking questions
+          return null;
+        }
+ 
+        // Still running - wait and check again
+        await sleep(POLL_INTERVAL_MS);
+      }
+ 
+      throw new Error(`Timeout waiting for agent ${agentId} to request input after ${timeoutMs}ms`);
+    },
+ 
+    async waitForAgentStatus(agentId: string, status: AgentStatus, timeoutMs = 120000): Promise<void> {
+      const deadline = Date.now() + timeoutMs;
+ 
+      while (Date.now() < deadline) {
+        const agent = await agentRepository.findById(agentId);
+        if (!agent) {
+          throw new Error(`Agent ${agentId} not found`);
+        }
+ 
+        if (agent.status === status) {
+          return;
+        }
+ 
+        // Check for terminal states that mean we'll never reach target
+        if (status === 'running' && ['idle', 'stopped', 'crashed', 'waiting_for_input'].includes(agent.status)) {
+          throw new Error(`Agent ${agentId} already in terminal state ${agent.status}, cannot reach ${status}`);
+        }
+ 
+        await sleep(POLL_INTERVAL_MS);
+      }
+ 
+      throw new Error(`Timeout waiting for agent ${agentId} to reach status ${status} after ${timeoutMs}ms`);
+    },
+ 
+    getEventsByType<T extends DomainEvent>(type: T['type']): T[] {
+      return eventBus.getEventsByType<T>(type);
+    },
+ 
+    clearEvents(): void {
+      eventBus.clearEvents();
+    },
+ 
+    async killAllAgents(): Promise<void> {
+      const agents = await agentRepository.findAll();
+      for (const agent of agents) {
+        if (agent.status === 'running') {
+          try {
+            await agentManager.stop(agent.id);
+          } catch {
+            // Ignore errors during cleanup
+          }
+        }
+      }
+    },
+ 
+    async cleanup(): Promise<void> {
+      // Kill any running agents
+      await harness.killAllAgents();
+ 
+      // Clean up workspace directory if we created it
+      if (ownedWorkspace) {
+        try {
+          await rm(workspaceRoot, { recursive: true, force: true });
+        } catch {
+          // Ignore cleanup errors
+        }
+      }
+    },
+  };
+ 
+  return harness;
+}
+ 
+/**
+ * Check if real Claude tests should run.
+ * Set REAL_CLAUDE_TESTS=1 environment variable to enable.
+ */
+export const shouldRunRealClaudeTests = process.env.REAL_CLAUDE_TESTS === '1';
+ 
+/**
+ * Check if real Codex tests should run.
+ * Set REAL_CODEX_TESTS=1 environment variable to enable.
+ */
+export const shouldRunRealCodexTests = process.env.REAL_CODEX_TESTS === '1';
+ 
+/**
+ * Skip wrapper for Claude tests - skips unless REAL_CLAUDE_TESTS=1.
+ */
+export const describeRealClaude: typeof describe = shouldRunRealClaudeTests ? describe : (describe.skip as typeof describe);
+ 
+/**
+ * Skip wrapper for Codex tests - skips unless REAL_CODEX_TESTS=1.
+ */
+export const describeRealCodex: typeof describe = shouldRunRealCodexTests ? describe : (describe.skip as typeof describe);
+ 
+/**
+ * Default test timeout for real CLI tests (2 minutes).
+ * Real API calls take 5-30 seconds typically.
+ */
+export const REAL_TEST_TIMEOUT = 120000;
+ 
+/**
+ * Extended test timeout for slow tests (5 minutes).
+ * Used for schema retry tests and crash recovery tests.
+ */
+export const EXTENDED_TEST_TIMEOUT = 300000;
+ 
+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/coverage/src/test/integration/real-providers/index.html b/coverage/src/test/integration/real-providers/index.html new file mode 100644 index 0000000..8c126ef --- /dev/null +++ b/coverage/src/test/integration/real-providers/index.html @@ -0,0 +1,131 @@ + + + + + + Code coverage report for src/test/integration/real-providers + + + + + + + + + +
+
+

All files src/test/integration/real-providers

+
+ +
+ 10.84% + Statements + 9/83 +
+ + +
+ 4.65% + Branches + 2/43 +
+ + +
+ 0% + Functions + 0/16 +
+ + +
+ 11.39% + Lines + 9/79 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
FileStatementsBranchesFunctionsLines
harness.ts +
+
8.97%7/784.65%2/430%0/149.45%7/74
prompts.ts +
+
40%2/5100%0/00%0/240%2/5
+
+
+
+ + + + + + + + \ No newline at end of file diff --git a/coverage/src/test/integration/real-providers/prompts.ts.html b/coverage/src/test/integration/real-providers/prompts.ts.html new file mode 100644 index 0000000..81ca789 --- /dev/null +++ b/coverage/src/test/integration/real-providers/prompts.ts.html @@ -0,0 +1,424 @@ + + + + + + Code coverage report for src/test/integration/real-providers/prompts.ts + + + + + + + + + +
+
+

All files / src/test/integration/real-providers prompts.ts

+
+ +
+ 40% + Statements + 2/5 +
+ + +
+ 100% + Branches + 0/0 +
+ + +
+ 0% + Functions + 0/2 +
+ + +
+ 40% + Lines + 2/5 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+

+
1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 +30 +31 +32 +33 +34 +35 +36 +37 +38 +39 +40 +41 +42 +43 +44 +45 +46 +47 +48 +49 +50 +51 +52 +53 +54 +55 +56 +57 +58 +59 +60 +61 +62 +63 +64 +65 +66 +67 +68 +69 +70 +71 +72 +73 +74 +75 +76 +77 +78 +79 +80 +81 +82 +83 +84 +85 +86 +87 +88 +89 +90 +91 +92 +93 +94 +95 +96 +97 +98 +99 +100 +101 +102 +103 +104 +105 +106 +107 +108 +109 +110 +111 +112 +113 +114  +  +  +  +  +  +  +  +  +  +4x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +4x +  +  +  +  +  +  +  +  +  +  + 
/**
+ * Minimal Cost Test Prompts
+ *
+ * Carefully crafted prompts designed to minimize token usage while
+ * testing specific CLI behaviors. Each prompt aims for the smallest
+ * possible API cost while still exercising the target functionality.
+ *
+ * Cost estimates assume Claude Sonnet pricing (~$3/M input, $15/M output).
+ */
+ 
+export const MINIMAL_PROMPTS = {
+  /**
+   * ~$0.01 - Cheapest done response
+   * Tests: basic spawn → completion flow, status parsing
+   */
+  done: `Output exactly this JSON with no other text:
+{"status":"done","result":"ok"}`,
+ 
+  /**
+   * ~$0.01 - Cheapest questions response
+   * Tests: waiting_for_input status, questions array parsing
+   */
+  questions: `Output exactly this JSON with no other text:
+{"status":"questions","questions":[{"id":"q1","question":"What is your name?"}]}`,
+ 
+  /**
+   * ~$0.03 - Slow task for timing tests
+   * Tests: streaming during long-running task, crash recovery
+   * Note: Agent may not actually wait 30 seconds, but will produce delayed output
+   */
+  slow: `Think through a simple problem step by step, counting from 1 to 10 slowly, then output:
+{"status":"done","result":"counted to 10"}`,
+ 
+  /**
+   * ~$0.02 - Produces text deltas for streaming tests
+   * Tests: text_delta event parsing, output buffering
+   */
+  streaming: `Count from 1 to 5, outputting each number, then output:
+{"status":"done","result":"counted"}`,
+ 
+  /**
+   * ~$0.03 - Deliberately produces non-JSON first
+   * Tests: schema validation failure, retry logic
+   */
+  badThenGood: `First say "thinking..." on its own line, then output:
+{"status":"done","result":"fixed"}`,
+ 
+  /**
+   * ~$0.02 - Multiple questions
+   * Tests: questions array with multiple items
+   */
+  multipleQuestions: `Output exactly this JSON with no other text:
+{"status":"questions","questions":[{"id":"q1","question":"First question?"},{"id":"q2","question":"Second question?"}]}`,
+ 
+  /**
+   * ~$0.01 - Error signal
+   * Tests: error status handling
+   */
+  error: `Output exactly this JSON with no other text:
+{"status":"error","error":"Test error message"}`,
+ 
+  /**
+   * ~$0.02 - Answer continuation
+   * Tests: session resume with answers
+   */
+  answerContinuation: (answers: Record<string, string>): string => {
+    const answerLines = Object.entries(answers)
+      .map(([id, answer]) => `${id}: ${answer}`)
+      .join('\n');
+    return `I received your answers:
+${answerLines}
+ 
+Now complete the task by outputting:
+{"status":"done","result":"completed with answers"}`;
+  },
+ 
+  /**
+   * ~$0.02 - Context complete for discuss mode
+   * Tests: discuss mode output handling (now uses universal done signal)
+   */
+  discussComplete: `Output exactly this JSON with no other text:
+{"status":"done"}`,
+ 
+  /**
+   * ~$0.02 - Plan complete
+   * Tests: plan mode output handling (now uses universal done signal)
+   */
+  planComplete: `Output exactly this JSON with no other text:
+{"status":"done"}`,
+ 
+  /**
+   * ~$0.02 - Detail complete
+   * Tests: detail mode output handling (now uses universal done signal)
+   */
+  detailComplete: `Output exactly this JSON with no other text:
+{"status":"done"}`,
+} as const;
+ 
+/**
+ * Prompts specifically for Codex provider testing.
+ * Codex may have different output format requirements.
+ */
+export const CODEX_PROMPTS = {
+  /**
+   * Basic completion for Codex
+   */
+  done: `Complete this simple task: output "done" and finish.`,
+ 
+  /**
+   * Produces streaming output
+   */
+  streaming: `Count from 1 to 5, saying each number aloud, then say "finished".`,
+} as const;
+ 
+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/coverage/src/trpc/context.ts.html b/coverage/src/trpc/context.ts.html new file mode 100644 index 0000000..4be194a --- /dev/null +++ b/coverage/src/trpc/context.ts.html @@ -0,0 +1,502 @@ + + + + + + Code coverage report for src/trpc/context.ts + + + + + + + + + +
+
+

All files / src/trpc context.ts

+
+ +
+ 100% + Statements + 1/1 +
+ + +
+ 100% + Branches + 0/0 +
+ + +
+ 100% + Functions + 1/1 +
+ + +
+ 100% + Lines + 1/1 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+

+
1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 +30 +31 +32 +33 +34 +35 +36 +37 +38 +39 +40 +41 +42 +43 +44 +45 +46 +47 +48 +49 +50 +51 +52 +53 +54 +55 +56 +57 +58 +59 +60 +61 +62 +63 +64 +65 +66 +67 +68 +69 +70 +71 +72 +73 +74 +75 +76 +77 +78 +79 +80 +81 +82 +83 +84 +85 +86 +87 +88 +89 +90 +91 +92 +93 +94 +95 +96 +97 +98 +99 +100 +101 +102 +103 +104 +105 +106 +107 +108 +109 +110 +111 +112 +113 +114 +115 +116 +117 +118 +119 +120 +121 +122 +123 +124 +125 +126 +127 +128 +129 +130 +131 +132 +133 +134 +135 +136 +137 +138 +139 +140  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +87x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  + 
/**
+ * tRPC Context
+ *
+ * Defines the context available to all tRPC procedures.
+ * Context is injected into each procedure call.
+ */
+ 
+import type { EventBus, DomainEvent } from '../events/types.js';
+import type { AgentManager } from '../agent/types.js';
+import type { TaskRepository } from '../db/repositories/task-repository.js';
+import type { MessageRepository } from '../db/repositories/message-repository.js';
+import type { InitiativeRepository } from '../db/repositories/initiative-repository.js';
+import type { PhaseRepository } from '../db/repositories/phase-repository.js';
+import type { PageRepository } from '../db/repositories/page-repository.js';
+import type { ProjectRepository } from '../db/repositories/project-repository.js';
+import type { AccountRepository } from '../db/repositories/account-repository.js';
+import type { ChangeSetRepository } from '../db/repositories/change-set-repository.js';
+import type { LogChunkRepository } from '../db/repositories/log-chunk-repository.js';
+import type { ConversationRepository } from '../db/repositories/conversation-repository.js';
+import type { AccountCredentialManager } from '../agent/credentials/types.js';
+import type { DispatchManager, PhaseDispatchManager } from '../dispatch/types.js';
+import type { CoordinationManager } from '../coordination/types.js';
+import type { BranchManager } from '../git/branch-manager.js';
+import type { ExecutionOrchestrator } from '../execution/orchestrator.js';
+import type { PreviewManager } from '../preview/index.js';
+ 
+// Re-export for convenience
+export type { EventBus, DomainEvent };
+ 
+/**
+ * Context available to all tRPC procedures.
+ */
+export interface TRPCContext {
+  /** Event bus for inter-module communication */
+  eventBus: EventBus;
+  /** When the server started (null if not yet started) */
+  serverStartedAt: Date | null;
+  /** Number of managed processes */
+  processCount: number;
+  /** Agent manager for agent lifecycle operations (optional until server wiring complete) */
+  agentManager?: AgentManager;
+  /** Task repository for task CRUD operations (optional until server wiring complete) */
+  taskRepository?: TaskRepository;
+  /** Message repository for agent-user communication (optional until server wiring complete) */
+  messageRepository?: MessageRepository;
+  /** Dispatch manager for task queue operations (optional until server wiring complete) */
+  dispatchManager?: DispatchManager;
+  /** Coordination manager for merge queue operations (optional until server wiring complete) */
+  coordinationManager?: CoordinationManager;
+  /** Initiative repository for initiative CRUD operations (optional until server wiring complete) */
+  initiativeRepository?: InitiativeRepository;
+  /** Phase repository for phase CRUD operations (optional until server wiring complete) */
+  phaseRepository?: PhaseRepository;
+  /** Phase dispatch manager for phase queue operations (optional until server wiring complete) */
+  phaseDispatchManager?: PhaseDispatchManager;
+  /** Page repository for page CRUD operations (optional until server wiring complete) */
+  pageRepository?: PageRepository;
+  /** Project repository for project CRUD and initiative-project junction operations */
+  projectRepository?: ProjectRepository;
+  /** Account repository for account CRUD and load balancing */
+  accountRepository?: AccountRepository;
+  /** Change set repository for agent change set operations */
+  changeSetRepository?: ChangeSetRepository;
+  /** Log chunk repository for agent output persistence */
+  logChunkRepository?: LogChunkRepository;
+  /** Credential manager for account OAuth token management */
+  credentialManager?: AccountCredentialManager;
+  /** Branch manager for git branch operations */
+  branchManager?: BranchManager;
+  /** Execution orchestrator for phase merge/review workflow */
+  executionOrchestrator?: ExecutionOrchestrator;
+  /** Preview manager for Docker-based preview deployments */
+  previewManager?: PreviewManager;
+  /** Conversation repository for inter-agent communication */
+  conversationRepository?: ConversationRepository;
+  /** Absolute path to the workspace root (.cwrc directory) */
+  workspaceRoot?: string;
+}
+ 
+/**
+ * Options for creating the tRPC context.
+ */
+export interface CreateContextOptions {
+  eventBus: EventBus;
+  serverStartedAt: Date | null;
+  processCount: number;
+  agentManager?: AgentManager;
+  taskRepository?: TaskRepository;
+  messageRepository?: MessageRepository;
+  dispatchManager?: DispatchManager;
+  coordinationManager?: CoordinationManager;
+  initiativeRepository?: InitiativeRepository;
+  phaseRepository?: PhaseRepository;
+  phaseDispatchManager?: PhaseDispatchManager;
+  pageRepository?: PageRepository;
+  projectRepository?: ProjectRepository;
+  accountRepository?: AccountRepository;
+  changeSetRepository?: ChangeSetRepository;
+  logChunkRepository?: LogChunkRepository;
+  credentialManager?: AccountCredentialManager;
+  branchManager?: BranchManager;
+  executionOrchestrator?: ExecutionOrchestrator;
+  previewManager?: PreviewManager;
+  conversationRepository?: ConversationRepository;
+  workspaceRoot?: string;
+}
+ 
+/**
+ * Creates the tRPC context for procedure calls.
+ *
+ * @param options - Context creation options
+ * @returns The tRPC context
+ */
+export function createContext(options: CreateContextOptions): TRPCContext {
+  return {
+    eventBus: options.eventBus,
+    serverStartedAt: options.serverStartedAt,
+    processCount: options.processCount,
+    agentManager: options.agentManager,
+    taskRepository: options.taskRepository,
+    messageRepository: options.messageRepository,
+    dispatchManager: options.dispatchManager,
+    coordinationManager: options.coordinationManager,
+    initiativeRepository: options.initiativeRepository,
+    phaseRepository: options.phaseRepository,
+    phaseDispatchManager: options.phaseDispatchManager,
+    pageRepository: options.pageRepository,
+    projectRepository: options.projectRepository,
+    accountRepository: options.accountRepository,
+    changeSetRepository: options.changeSetRepository,
+    logChunkRepository: options.logChunkRepository,
+    credentialManager: options.credentialManager,
+    branchManager: options.branchManager,
+    executionOrchestrator: options.executionOrchestrator,
+    previewManager: options.previewManager,
+    conversationRepository: options.conversationRepository,
+    workspaceRoot: options.workspaceRoot,
+  };
+}
+ 
+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/coverage/src/trpc/index.html b/coverage/src/trpc/index.html new file mode 100644 index 0000000..ebf38b6 --- /dev/null +++ b/coverage/src/trpc/index.html @@ -0,0 +1,176 @@ + + + + + + Code coverage report for src/trpc + + + + + + + + + +
+
+

All files src/trpc

+
+ +
+ 27.45% + Statements + 14/51 +
+ + +
+ 0% + Branches + 0/10 +
+ + +
+ 12.5% + Functions + 1/8 +
+ + +
+ 28.57% + Lines + 14/49 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
FileStatementsBranchesFunctionsLines
context.ts +
+
100%1/1100%0/0100%1/1100%1/1
index.ts +
+
0%0/00%0/00%0/00%0/0
router.ts +
+
100%1/1100%0/0100%0/0100%1/1
subscriptions.ts +
+
15.9%7/440%0/100%0/716.66%7/42
trpc.ts +
+
100%5/5100%0/0100%0/0100%5/5
+
+
+
+ + + + + + + + \ No newline at end of file diff --git a/coverage/src/trpc/index.ts.html b/coverage/src/trpc/index.ts.html new file mode 100644 index 0000000..bf8422a --- /dev/null +++ b/coverage/src/trpc/index.ts.html @@ -0,0 +1,178 @@ + + + + + + Code coverage report for src/trpc/index.ts + + + + + + + + + +
+
+

All files / src/trpc index.ts

+
+ +
+ 0% + Statements + 0/0 +
+ + +
+ 0% + Branches + 0/0 +
+ + +
+ 0% + Functions + 0/0 +
+ + +
+ 0% + Lines + 0/0 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+

+
1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 +30 +31 +32  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  + 
/**
+ * tRPC Module
+ *
+ * Type-safe RPC layer for CLI-server communication.
+ * Same interface for CLI and future WebUI clients.
+ */
+ 
+// Re-export router components
+export {
+  router,
+  publicProcedure,
+  middleware,
+  createCallerFactory,
+  appRouter,
+  healthResponseSchema,
+  statusResponseSchema,
+  processInfoSchema,
+} from './router.js';
+ 
+// Export types
+export type {
+  AppRouter,
+  HealthResponse,
+  StatusResponse,
+  ProcessInfo,
+} from './router.js';
+ 
+// Re-export context
+export { createContext } from './context.js';
+export type { TRPCContext, CreateContextOptions } from './context.js';
+export type { EventBus, DomainEvent } from './context.js';
+ 
+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/coverage/src/trpc/router.ts.html b/coverage/src/trpc/router.ts.html new file mode 100644 index 0000000..74532f6 --- /dev/null +++ b/coverage/src/trpc/router.ts.html @@ -0,0 +1,283 @@ + + + + + + Code coverage report for src/trpc/router.ts + + + + + + + + + +
+
+

All files / src/trpc router.ts

+
+ +
+ 100% + Statements + 1/1 +
+ + +
+ 100% + Branches + 0/0 +
+ + +
+ 100% + Functions + 0/0 +
+ + +
+ 100% + Lines + 1/1 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+

+
1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 +30 +31 +32 +33 +34 +35 +36 +37 +38 +39 +40 +41 +42 +43 +44 +45 +46 +47 +48 +49 +50 +51 +52 +53 +54 +55 +56 +57 +58 +59 +60 +61 +62 +63 +64 +65 +66 +67  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +11x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  + 
/**
+ * tRPC Router — Merge Point
+ *
+ * Combines all domain routers into a single application router.
+ * Each domain file exports a builder function that returns procedure records.
+ */
+ 
+import { router, publicProcedure } from './trpc.js';
+import { systemProcedures } from './routers/system.js';
+import { agentProcedures } from './routers/agent.js';
+import { taskProcedures } from './routers/task.js';
+import { messageProcedures } from './routers/message.js';
+import { dispatchProcedures } from './routers/dispatch.js';
+import { coordinationProcedures } from './routers/coordination.js';
+import { initiativeProcedures } from './routers/initiative.js';
+import { phaseProcedures } from './routers/phase.js';
+import { phaseDispatchProcedures } from './routers/phase-dispatch.js';
+import { architectProcedures } from './routers/architect.js';
+import { projectProcedures } from './routers/project.js';
+import { pageProcedures } from './routers/page.js';
+import { accountProcedures } from './routers/account.js';
+import { changeSetProcedures } from './routers/change-set.js';
+import { subscriptionProcedures } from './routers/subscription.js';
+import { previewProcedures } from './routers/preview.js';
+import { conversationProcedures } from './routers/conversation.js';
+ 
+// Re-export tRPC primitives (preserves existing import paths)
+export { router, publicProcedure, middleware, createCallerFactory } from './trpc.js';
+ 
+// Re-export schemas and types from domain routers
+export {
+  healthResponseSchema,
+  processInfoSchema,
+  statusResponseSchema,
+} from './routers/system.js';
+export type { HealthResponse, StatusResponse, ProcessInfo } from './routers/system.js';
+ 
+export {
+  spawnAgentInputSchema,
+  agentIdentifierSchema,
+  resumeAgentInputSchema,
+} from './routers/agent.js';
+export type { SpawnAgentInput, AgentIdentifier, ResumeAgentInput } from './routers/agent.js';
+ 
+// Application router
+export const appRouter = router({
+  ...systemProcedures(publicProcedure),
+  ...agentProcedures(publicProcedure),
+  ...taskProcedures(publicProcedure),
+  ...messageProcedures(publicProcedure),
+  ...dispatchProcedures(publicProcedure),
+  ...coordinationProcedures(publicProcedure),
+  ...initiativeProcedures(publicProcedure),
+  ...phaseProcedures(publicProcedure),
+  ...phaseDispatchProcedures(publicProcedure),
+  ...architectProcedures(publicProcedure),
+  ...projectProcedures(publicProcedure),
+  ...pageProcedures(publicProcedure),
+  ...accountProcedures(publicProcedure),
+  ...changeSetProcedures(publicProcedure),
+  ...subscriptionProcedures(publicProcedure),
+  ...previewProcedures(publicProcedure),
+  ...conversationProcedures(publicProcedure),
+});
+ 
+export type AppRouter = typeof appRouter;
+ 
+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/coverage/src/trpc/routers/_helpers.ts.html b/coverage/src/trpc/routers/_helpers.ts.html new file mode 100644 index 0000000..b389537 --- /dev/null +++ b/coverage/src/trpc/routers/_helpers.ts.html @@ -0,0 +1,667 @@ + + + + + + Code coverage report for src/trpc/routers/_helpers.ts + + + + + + + + + +
+
+

All files / src/trpc/routers _helpers.ts

+
+ +
+ 15.68% + Statements + 8/51 +
+ + +
+ 11.76% + Branches + 4/34 +
+ + +
+ 23.52% + Functions + 4/17 +
+ + +
+ 15.68% + Lines + 8/51 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+

+
1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 +30 +31 +32 +33 +34 +35 +36 +37 +38 +39 +40 +41 +42 +43 +44 +45 +46 +47 +48 +49 +50 +51 +52 +53 +54 +55 +56 +57 +58 +59 +60 +61 +62 +63 +64 +65 +66 +67 +68 +69 +70 +71 +72 +73 +74 +75 +76 +77 +78 +79 +80 +81 +82 +83 +84 +85 +86 +87 +88 +89 +90 +91 +92 +93 +94 +95 +96 +97 +98 +99 +100 +101 +102 +103 +104 +105 +106 +107 +108 +109 +110 +111 +112 +113 +114 +115 +116 +117 +118 +119 +120 +121 +122 +123 +124 +125 +126 +127 +128 +129 +130 +131 +132 +133 +134 +135 +136 +137 +138 +139 +140 +141 +142 +143 +144 +145 +146 +147 +148 +149 +150 +151 +152 +153 +154 +155 +156 +157 +158 +159 +160 +161 +162 +163 +164 +165 +166 +167 +168 +169 +170 +171 +172 +173 +174 +175 +176 +177 +178 +179 +180 +181 +182 +183 +184 +185 +186 +187 +188 +189 +190 +191 +192 +193 +194 +195  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +27x +  +  +  +  +  +27x +  +  +  +36x +  +  +  +  +  +36x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +40x +  +  +  +  +  +40x +  +  +  +31x +  +  +  +  +  +31x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  + 
/**
+ * Router Helpers
+ *
+ * Shared require*() helpers that validate context dependencies
+ * and throw TRPCError when a required dependency is missing.
+ */
+ 
+import { TRPCError } from '@trpc/server';
+import type { TRPCContext } from '../context.js';
+import type { TaskRepository } from '../../db/repositories/task-repository.js';
+import type { MessageRepository } from '../../db/repositories/message-repository.js';
+import type { InitiativeRepository } from '../../db/repositories/initiative-repository.js';
+import type { PhaseRepository } from '../../db/repositories/phase-repository.js';
+import type { PageRepository } from '../../db/repositories/page-repository.js';
+import type { ProjectRepository } from '../../db/repositories/project-repository.js';
+import type { AccountRepository } from '../../db/repositories/account-repository.js';
+import type { ChangeSetRepository } from '../../db/repositories/change-set-repository.js';
+import type { LogChunkRepository } from '../../db/repositories/log-chunk-repository.js';
+import type { ConversationRepository } from '../../db/repositories/conversation-repository.js';
+import type { DispatchManager, PhaseDispatchManager } from '../../dispatch/types.js';
+import type { CoordinationManager } from '../../coordination/types.js';
+import type { BranchManager } from '../../git/branch-manager.js';
+import type { ExecutionOrchestrator } from '../../execution/orchestrator.js';
+import type { PreviewManager } from '../../preview/index.js';
+ 
+export function requireAgentManager(ctx: TRPCContext) {
+  Iif (!ctx.agentManager) {
+    throw new TRPCError({
+      code: 'INTERNAL_SERVER_ERROR',
+      message: 'Agent manager not available',
+    });
+  }
+  return ctx.agentManager;
+}
+ 
+export function requireTaskRepository(ctx: TRPCContext): TaskRepository {
+  Iif (!ctx.taskRepository) {
+    throw new TRPCError({
+      code: 'INTERNAL_SERVER_ERROR',
+      message: 'Task repository not available',
+    });
+  }
+  return ctx.taskRepository;
+}
+ 
+export function requireMessageRepository(ctx: TRPCContext): MessageRepository {
+  if (!ctx.messageRepository) {
+    throw new TRPCError({
+      code: 'INTERNAL_SERVER_ERROR',
+      message: 'Message repository not available',
+    });
+  }
+  return ctx.messageRepository;
+}
+ 
+export function requireDispatchManager(ctx: TRPCContext): DispatchManager {
+  if (!ctx.dispatchManager) {
+    throw new TRPCError({
+      code: 'INTERNAL_SERVER_ERROR',
+      message: 'Dispatch manager not available',
+    });
+  }
+  return ctx.dispatchManager;
+}
+ 
+export function requireCoordinationManager(ctx: TRPCContext): CoordinationManager {
+  if (!ctx.coordinationManager) {
+    throw new TRPCError({
+      code: 'INTERNAL_SERVER_ERROR',
+      message: 'Coordination manager not available',
+    });
+  }
+  return ctx.coordinationManager;
+}
+ 
+export function requireInitiativeRepository(ctx: TRPCContext): InitiativeRepository {
+  Iif (!ctx.initiativeRepository) {
+    throw new TRPCError({
+      code: 'INTERNAL_SERVER_ERROR',
+      message: 'Initiative repository not available',
+    });
+  }
+  return ctx.initiativeRepository;
+}
+ 
+export function requirePhaseRepository(ctx: TRPCContext): PhaseRepository {
+  Iif (!ctx.phaseRepository) {
+    throw new TRPCError({
+      code: 'INTERNAL_SERVER_ERROR',
+      message: 'Phase repository not available',
+    });
+  }
+  return ctx.phaseRepository;
+}
+ 
+export function requirePhaseDispatchManager(ctx: TRPCContext): PhaseDispatchManager {
+  if (!ctx.phaseDispatchManager) {
+    throw new TRPCError({
+      code: 'INTERNAL_SERVER_ERROR',
+      message: 'Phase dispatch manager not available',
+    });
+  }
+  return ctx.phaseDispatchManager;
+}
+ 
+export function requirePageRepository(ctx: TRPCContext): PageRepository {
+  if (!ctx.pageRepository) {
+    throw new TRPCError({
+      code: 'INTERNAL_SERVER_ERROR',
+      message: 'Page repository not available',
+    });
+  }
+  return ctx.pageRepository;
+}
+ 
+export function requireProjectRepository(ctx: TRPCContext): ProjectRepository {
+  if (!ctx.projectRepository) {
+    throw new TRPCError({
+      code: 'INTERNAL_SERVER_ERROR',
+      message: 'Project repository not available',
+    });
+  }
+  return ctx.projectRepository;
+}
+ 
+export function requireAccountRepository(ctx: TRPCContext): AccountRepository {
+  if (!ctx.accountRepository) {
+    throw new TRPCError({
+      code: 'INTERNAL_SERVER_ERROR',
+      message: 'Account repository not available',
+    });
+  }
+  return ctx.accountRepository;
+}
+ 
+export function requireChangeSetRepository(ctx: TRPCContext): ChangeSetRepository {
+  if (!ctx.changeSetRepository) {
+    throw new TRPCError({
+      code: 'INTERNAL_SERVER_ERROR',
+      message: 'Change set repository not available',
+    });
+  }
+  return ctx.changeSetRepository;
+}
+ 
+export function requireLogChunkRepository(ctx: TRPCContext): LogChunkRepository {
+  if (!ctx.logChunkRepository) {
+    throw new TRPCError({
+      code: 'INTERNAL_SERVER_ERROR',
+      message: 'Log chunk repository not available',
+    });
+  }
+  return ctx.logChunkRepository;
+}
+ 
+export function requireBranchManager(ctx: TRPCContext): BranchManager {
+  if (!ctx.branchManager) {
+    throw new TRPCError({
+      code: 'INTERNAL_SERVER_ERROR',
+      message: 'Branch manager not available',
+    });
+  }
+  return ctx.branchManager;
+}
+ 
+export function requireExecutionOrchestrator(ctx: TRPCContext): ExecutionOrchestrator {
+  if (!ctx.executionOrchestrator) {
+    throw new TRPCError({
+      code: 'INTERNAL_SERVER_ERROR',
+      message: 'Execution orchestrator not available',
+    });
+  }
+  return ctx.executionOrchestrator;
+}
+ 
+export function requirePreviewManager(ctx: TRPCContext): PreviewManager {
+  if (!ctx.previewManager) {
+    throw new TRPCError({
+      code: 'INTERNAL_SERVER_ERROR',
+      message: 'Preview manager not available',
+    });
+  }
+  return ctx.previewManager;
+}
+ 
+export function requireConversationRepository(ctx: TRPCContext): ConversationRepository {
+  if (!ctx.conversationRepository) {
+    throw new TRPCError({
+      code: 'INTERNAL_SERVER_ERROR',
+      message: 'Conversation repository not available',
+    });
+  }
+  return ctx.conversationRepository;
+}
+ 
+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/coverage/src/trpc/routers/account.ts.html b/coverage/src/trpc/routers/account.ts.html new file mode 100644 index 0000000..b3719ba --- /dev/null +++ b/coverage/src/trpc/routers/account.ts.html @@ -0,0 +1,313 @@ + + + + + + Code coverage report for src/trpc/routers/account.ts + + + + + + + + + +
+
+

All files / src/trpc/routers account.ts

+
+ +
+ 6.25% + Statements + 1/16 +
+ + +
+ 100% + Branches + 0/0 +
+ + +
+ 12.5% + Functions + 1/8 +
+ + +
+ 6.25% + Lines + 1/16 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+

+
1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 +30 +31 +32 +33 +34 +35 +36 +37 +38 +39 +40 +41 +42 +43 +44 +45 +46 +47 +48 +49 +50 +51 +52 +53 +54 +55 +56 +57 +58 +59 +60 +61 +62 +63 +64 +65 +66 +67 +68 +69 +70 +71 +72 +73 +74 +75 +76 +77  +  +  +  +  +  +  +  +  +  +11x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  + 
/**
+ * Account Router — list, add, remove, refresh, update auth, mark exhausted, providers
+ */
+ 
+import { z } from 'zod';
+import type { ProcedureBuilder } from '../trpc.js';
+import { requireAccountRepository } from './_helpers.js';
+import { listProviders as listProviderNames } from '../../agent/providers/registry.js';
+ 
+export function accountProcedures(publicProcedure: ProcedureBuilder) {
+  return {
+    listAccounts: publicProcedure
+      .query(async ({ ctx }) => {
+        const repo = requireAccountRepository(ctx);
+        return repo.findAll();
+      }),
+ 
+    addAccount: publicProcedure
+      .input(z.object({
+        email: z.string().min(1),
+        provider: z.string().default('claude'),
+        configJson: z.string().optional(),
+        credentials: z.string().optional(),
+      }))
+      .mutation(async ({ ctx, input }) => {
+        const repo = requireAccountRepository(ctx);
+        return repo.create({
+          email: input.email,
+          provider: input.provider,
+          configJson: input.configJson,
+          credentials: input.credentials,
+        });
+      }),
+ 
+    removeAccount: publicProcedure
+      .input(z.object({ id: z.string().min(1) }))
+      .mutation(async ({ ctx, input }) => {
+        const repo = requireAccountRepository(ctx);
+        await repo.delete(input.id);
+        return { success: true };
+      }),
+ 
+    refreshAccounts: publicProcedure
+      .mutation(async ({ ctx }) => {
+        const repo = requireAccountRepository(ctx);
+        const cleared = await repo.clearExpiredExhaustion();
+        return { cleared };
+      }),
+ 
+    updateAccountAuth: publicProcedure
+      .input(z.object({
+        id: z.string().min(1),
+        configJson: z.string(),
+        credentials: z.string(),
+      }))
+      .mutation(async ({ ctx, input }) => {
+        const repo = requireAccountRepository(ctx);
+        return repo.updateAccountAuth(input.id, input.configJson, input.credentials);
+      }),
+ 
+    markAccountExhausted: publicProcedure
+      .input(z.object({
+        id: z.string().min(1),
+        until: z.string().datetime(),
+      }))
+      .mutation(async ({ ctx, input }) => {
+        const repo = requireAccountRepository(ctx);
+        return repo.markExhausted(input.id, new Date(input.until));
+      }),
+ 
+    listProviderNames: publicProcedure
+      .query(() => {
+        return listProviderNames();
+      }),
+  };
+}
+ 
+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/coverage/src/trpc/routers/agent.ts.html b/coverage/src/trpc/routers/agent.ts.html new file mode 100644 index 0000000..66d1fd3 --- /dev/null +++ b/coverage/src/trpc/routers/agent.ts.html @@ -0,0 +1,829 @@ + + + + + + Code coverage report for src/trpc/routers/agent.ts + + + + + + + + + +
+
+

All files / src/trpc/routers agent.ts

+
+ +
+ 18.18% + Statements + 16/88 +
+ + +
+ 14.28% + Branches + 4/28 +
+ + +
+ 28% + Functions + 7/25 +
+ + +
+ 18.82% + Lines + 16/85 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+

+
1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 +30 +31 +32 +33 +34 +35 +36 +37 +38 +39 +40 +41 +42 +43 +44 +45 +46 +47 +48 +49 +50 +51 +52 +53 +54 +55 +56 +57 +58 +59 +60 +61 +62 +63 +64 +65 +66 +67 +68 +69 +70 +71 +72 +73 +74 +75 +76 +77 +78 +79 +80 +81 +82 +83 +84 +85 +86 +87 +88 +89 +90 +91 +92 +93 +94 +95 +96 +97 +98 +99 +100 +101 +102 +103 +104 +105 +106 +107 +108 +109 +110 +111 +112 +113 +114 +115 +116 +117 +118 +119 +120 +121 +122 +123 +124 +125 +126 +127 +128 +129 +130 +131 +132 +133 +134 +135 +136 +137 +138 +139 +140 +141 +142 +143 +144 +145 +146 +147 +148 +149 +150 +151 +152 +153 +154 +155 +156 +157 +158 +159 +160 +161 +162 +163 +164 +165 +166 +167 +168 +169 +170 +171 +172 +173 +174 +175 +176 +177 +178 +179 +180 +181 +182 +183 +184 +185 +186 +187 +188 +189 +190 +191 +192 +193 +194 +195 +196 +197 +198 +199 +200 +201 +202 +203 +204 +205 +206 +207 +208 +209 +210 +211 +212 +213 +214 +215 +216 +217 +218 +219 +220 +221 +222 +223 +224 +225 +226 +227 +228 +229 +230 +231 +232 +233 +234 +235 +236 +237 +238 +239 +240 +241 +242 +243 +244 +245 +246 +247 +248 +249  +  +  +  +  +  +  +  +  +  +  +  +  +11x +  +  +  +  +  +  +  +  +  +  +  +11x +  +  +6x +  +  +  +  +  +11x +  +  +  +3x +  +  +  +  +  +  +  +  +  +9x +  +  +  +  +  +  +9x +  +  +  +  +  +  +  +  +  +  +9x +  +  +  +11x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +3x +3x +  +  +  +  +  +6x +  +  +  +  +  +  +  +  +  +  +  +  +3x +3x +3x +3x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  + 
/**
+ * Agent Router — spawn, stop, delete, list, get, resume, result, questions, output
+ */
+ 
+import { TRPCError } from '@trpc/server';
+import { z } from 'zod';
+import { tracked, type TrackedEnvelope } from '@trpc/server';
+import type { ProcedureBuilder } from '../trpc.js';
+import type { TRPCContext } from '../context.js';
+import type { AgentInfo, AgentResult, PendingQuestions } from '../../agent/types.js';
+import type { AgentOutputEvent } from '../../events/types.js';
+import { requireAgentManager, requireLogChunkRepository } from './_helpers.js';
+ 
+export const spawnAgentInputSchema = z.object({
+  name: z.string().min(1).optional(),
+  taskId: z.string().min(1),
+  prompt: z.string().min(1),
+  cwd: z.string().optional(),
+  mode: z.enum(['execute', 'discuss', 'plan', 'detail', 'refine']).optional(),
+  provider: z.string().optional(),
+  initiativeId: z.string().min(1).optional(),
+});
+ 
+export type SpawnAgentInput = z.infer<typeof spawnAgentInputSchema>;
+ 
+export const agentIdentifierSchema = z.object({
+  name: z.string().optional(),
+  id: z.string().optional(),
+}).refine(data => data.name || data.id, {
+  message: 'Either name or id must be provided',
+});
+ 
+export type AgentIdentifier = z.infer<typeof agentIdentifierSchema>;
+ 
+export const resumeAgentInputSchema = z.object({
+  name: z.string().optional(),
+  id: z.string().optional(),
+  answers: z.record(z.string(), z.string()),
+}).refine(data => data.name || data.id, {
+  message: 'Either name or id must be provided',
+});
+ 
+export type ResumeAgentInput = z.infer<typeof resumeAgentInputSchema>;
+ 
+async function resolveAgent(
+  ctx: TRPCContext,
+  input: { name?: string; id?: string }
+): Promise<AgentInfo> {
+  Iif (!ctx.agentManager) {
+    throw new TRPCError({
+      code: 'INTERNAL_SERVER_ERROR',
+      message: 'Agent manager not available',
+    });
+  }
+ 
+  const agent = input.name
+    ? await ctx.agentManager.getByName(input.name)
+    : await ctx.agentManager.get(input.id!);
+ 
+  if (!agent) {
+    throw new TRPCError({
+      code: 'NOT_FOUND',
+      message: `Agent '${input.name ?? input.id}' not found`,
+    });
+  }
+ 
+  return agent;
+}
+ 
+export function agentProcedures(publicProcedure: ProcedureBuilder) {
+  return {
+    spawnAgent: publicProcedure
+      .input(spawnAgentInputSchema)
+      .mutation(async ({ ctx, input }) => {
+        const agentManager = requireAgentManager(ctx);
+        return agentManager.spawn({
+          name: input.name,
+          taskId: input.taskId,
+          prompt: input.prompt,
+          cwd: input.cwd,
+          mode: input.mode,
+          provider: input.provider,
+          initiativeId: input.initiativeId,
+        });
+      }),
+ 
+    stopAgent: publicProcedure
+      .input(agentIdentifierSchema)
+      .mutation(async ({ ctx, input }) => {
+        const agentManager = requireAgentManager(ctx);
+        const agent = await resolveAgent(ctx, input);
+        await agentManager.stop(agent.id);
+        return { success: true, name: agent.name };
+      }),
+ 
+    deleteAgent: publicProcedure
+      .input(agentIdentifierSchema)
+      .mutation(async ({ ctx, input }) => {
+        const agentManager = requireAgentManager(ctx);
+        const agent = await resolveAgent(ctx, input);
+        await agentManager.delete(agent.id);
+        return { success: true, name: agent.name };
+      }),
+ 
+    dismissAgent: publicProcedure
+      .input(agentIdentifierSchema)
+      .mutation(async ({ ctx, input }) => {
+        const agentManager = requireAgentManager(ctx);
+        const agent = await resolveAgent(ctx, input);
+        await agentManager.dismiss(agent.id);
+        return { success: true, name: agent.name };
+      }),
+ 
+    listAgents: publicProcedure
+      .query(async ({ ctx }) => {
+        const agentManager = requireAgentManager(ctx);
+        return agentManager.list();
+      }),
+ 
+    getAgent: publicProcedure
+      .input(agentIdentifierSchema)
+      .query(async ({ ctx, input }) => {
+        return resolveAgent(ctx, input);
+      }),
+ 
+    getAgentByName: publicProcedure
+      .input(z.object({ name: z.string().min(1) }))
+      .query(async ({ ctx, input }) => {
+        const agentManager = requireAgentManager(ctx);
+        return agentManager.getByName(input.name);
+      }),
+ 
+    resumeAgent: publicProcedure
+      .input(resumeAgentInputSchema)
+      .mutation(async ({ ctx, input }) => {
+        const agentManager = requireAgentManager(ctx);
+        const agent = await resolveAgent(ctx, input);
+        await agentManager.resume(agent.id, input.answers);
+        return { success: true, name: agent.name };
+      }),
+ 
+    getAgentResult: publicProcedure
+      .input(agentIdentifierSchema)
+      .query(async ({ ctx, input }): Promise<AgentResult | null> => {
+        const agentManager = requireAgentManager(ctx);
+        const agent = await resolveAgent(ctx, input);
+        return agentManager.getResult(agent.id);
+      }),
+ 
+    getAgentQuestions: publicProcedure
+      .input(agentIdentifierSchema)
+      .query(async ({ ctx, input }): Promise<PendingQuestions | null> => {
+        const agentManager = requireAgentManager(ctx);
+        const agent = await resolveAgent(ctx, input);
+        return agentManager.getPendingQuestions(agent.id);
+      }),
+ 
+    listWaitingAgents: publicProcedure
+      .query(async ({ ctx }) => {
+        const agentManager = requireAgentManager(ctx);
+        const allAgents = await agentManager.list();
+        return allAgents.filter(agent => agent.status === 'waiting_for_input');
+      }),
+ 
+    getActiveRefineAgent: publicProcedure
+      .input(z.object({ initiativeId: z.string().min(1) }))
+      .query(async ({ ctx, input }): Promise<AgentInfo | null> => {
+        const agentManager = requireAgentManager(ctx);
+        const allAgents = await agentManager.list();
+        const candidates = allAgents
+          .filter(
+            (a) =>
+              a.mode === 'refine' &&
+              a.initiativeId === input.initiativeId &&
+              ['running', 'waiting_for_input', 'idle', 'crashed'].includes(a.status) &&
+              !a.userDismissedAt,
+          )
+          .sort(
+            (a, b) =>
+              new Date(b.createdAt).getTime() - new Date(a.createdAt).getTime(),
+          );
+        return candidates[0] ?? null;
+      }),
+ 
+    getAgentOutput: publicProcedure
+      .input(agentIdentifierSchema)
+      .query(async ({ ctx, input }): Promise<string> => {
+        const agent = await resolveAgent(ctx, input);
+        const logChunkRepo = requireLogChunkRepository(ctx);
+ 
+        const chunks = await logChunkRepo.findByAgentId(agent.id);
+        return chunks.map(c => c.content).join('');
+      }),
+ 
+    onAgentOutput: publicProcedure
+      .input(z.object({ agentId: z.string().min(1) }))
+      .subscription(async function* (opts): AsyncGenerator<TrackedEnvelope<{ agentId: string; data: string }>> {
+        const { agentId } = opts.input;
+        const signal = opts.signal ?? new AbortController().signal;
+        const eventBus = opts.ctx.eventBus;
+ 
+        let eventCounter = 0;
+        const queue: string[] = [];
+        let resolve: (() => void) | null = null;
+ 
+        const handler = (event: AgentOutputEvent) => {
+          if (event.payload.agentId !== agentId) return;
+          queue.push(event.payload.data);
+          if (resolve) {
+            const r = resolve;
+            resolve = null;
+            r();
+          }
+        };
+ 
+        eventBus.on('agent:output', handler);
+ 
+        const cleanup = () => {
+          eventBus.off('agent:output', handler);
+          if (resolve) {
+            const r = resolve;
+            resolve = null;
+            r();
+          }
+        };
+ 
+        signal.addEventListener('abort', cleanup, { once: true });
+ 
+        try {
+          while (!signal.aborted) {
+            while (queue.length > 0) {
+              const data = queue.shift()!;
+              const id = `${agentId}-live-${eventCounter++}`;
+              yield tracked(id, { agentId, data });
+            }
+ 
+            if (!signal.aborted) {
+              await new Promise<void>((r) => {
+                resolve = r;
+              });
+            }
+          }
+        } finally {
+          cleanup();
+        }
+      }),
+  };
+}
+ 
+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/coverage/src/trpc/routers/architect.ts.html b/coverage/src/trpc/routers/architect.ts.html new file mode 100644 index 0000000..b90c41d --- /dev/null +++ b/coverage/src/trpc/routers/architect.ts.html @@ -0,0 +1,1180 @@ + + + + + + Code coverage report for src/trpc/routers/architect.ts + + + + + + + + + +
+
+

All files / src/trpc/routers architect.ts

+
+ +
+ 71.69% + Statements + 76/106 +
+ + +
+ 57.69% + Branches + 45/78 +
+ + +
+ 78.57% + Functions + 11/14 +
+ + +
+ 71.28% + Lines + 72/101 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+

+
1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 +30 +31 +32 +33 +34 +35 +36 +37 +38 +39 +40 +41 +42 +43 +44 +45 +46 +47 +48 +49 +50 +51 +52 +53 +54 +55 +56 +57 +58 +59 +60 +61 +62 +63 +64 +65 +66 +67 +68 +69 +70 +71 +72 +73 +74 +75 +76 +77 +78 +79 +80 +81 +82 +83 +84 +85 +86 +87 +88 +89 +90 +91 +92 +93 +94 +95 +96 +97 +98 +99 +100 +101 +102 +103 +104 +105 +106 +107 +108 +109 +110 +111 +112 +113 +114 +115 +116 +117 +118 +119 +120 +121 +122 +123 +124 +125 +126 +127 +128 +129 +130 +131 +132 +133 +134 +135 +136 +137 +138 +139 +140 +141 +142 +143 +144 +145 +146 +147 +148 +149 +150 +151 +152 +153 +154 +155 +156 +157 +158 +159 +160 +161 +162 +163 +164 +165 +166 +167 +168 +169 +170 +171 +172 +173 +174 +175 +176 +177 +178 +179 +180 +181 +182 +183 +184 +185 +186 +187 +188 +189 +190 +191 +192 +193 +194 +195 +196 +197 +198 +199 +200 +201 +202 +203 +204 +205 +206 +207 +208 +209 +210 +211 +212 +213 +214 +215 +216 +217 +218 +219 +220 +221 +222 +223 +224 +225 +226 +227 +228 +229 +230 +231 +232 +233 +234 +235 +236 +237 +238 +239 +240 +241 +242 +243 +244 +245 +246 +247 +248 +249 +250 +251 +252 +253 +254 +255 +256 +257 +258 +259 +260 +261 +262 +263 +264 +265 +266 +267 +268 +269 +270 +271 +272 +273 +274 +275 +276 +277 +278 +279 +280 +281 +282 +283 +284 +285 +286 +287 +288 +289 +290 +291 +292 +293 +294 +295 +296 +297 +298 +299 +300 +301 +302 +303 +304 +305 +306 +307 +308 +309 +310 +311 +312 +313 +314 +315 +316 +317 +318 +319 +320 +321 +322 +323 +324 +325 +326 +327 +328 +329 +330 +331 +332 +333 +334 +335 +336 +337 +338 +339 +340 +341 +342 +343 +344 +345 +346 +347 +348 +349 +350 +351 +352 +353 +354 +355 +356 +357 +358 +359 +360 +361 +362 +363 +364 +365 +366  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +16x +  +  +  +  +  +  +  +16x +16x +  +  +  +  +16x +  +  +  +  +  +20x +16x +16x +16x +11x +11x +15x +4x +4x +  +  +  +  +  +  +24x +  +16x +  +  +  +11x +  +  +  +  +  +  +  +  +3x +3x +3x +  +3x +3x +  +  +  +  +  +  +3x +  +  +  +  +  +  +  +3x +  +3x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +8x +8x +8x +  +8x +8x +  +  +  +  +  +  +  +8x +8x +  +4x +  +  +  +  +8x +1x +  +  +  +8x +  +4x +  +  +  +8x +1x +  +  +  +  +  +7x +  +  +  +  +  +  +  +7x +  +7x +  +7x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +10x +10x +10x +10x +  +10x +10x +  +  +  +  +  +10x +10x +  +  +  +  +  +  +  +10x +10x +3x +  +  +  +10x +10x +10x +3x +3x +3x +  +2x +1x +1x +1x +  +  +10x +1x +  +10x +1x +  +  +  +  +  +9x +10x +  +  +  +  +  +  +  +  +9x +  +9x +  +9x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  + 
/**
+ * Architect Router — discuss, plan, refine, detail spawn procedures
+ */
+ 
+import { TRPCError } from '@trpc/server';
+import { z } from 'zod';
+import type { ProcedureBuilder } from '../trpc.js';
+import {
+  requireAgentManager,
+  requireInitiativeRepository,
+  requirePhaseRepository,
+  requirePageRepository,
+  requireTaskRepository,
+} from './_helpers.js';
+import {
+  buildDiscussPrompt,
+  buildPlanPrompt,
+  buildRefinePrompt,
+  buildDetailPrompt,
+} from '../../agent/prompts/index.js';
+import { isPlanningCategory } from '../../git/branch-naming.js';
+import type { PhaseRepository } from '../../db/repositories/phase-repository.js';
+import type { TaskRepository } from '../../db/repositories/task-repository.js';
+import type { PageRepository } from '../../db/repositories/page-repository.js';
+import type { Phase, Task } from '../../db/schema.js';
+import type { PageForSerialization } from '../../agent/content-serializer.js';
+ 
+async function gatherInitiativeContext(
+  phaseRepo: PhaseRepository | undefined,
+  taskRepo: TaskRepository | undefined,
+  pageRepo: PageRepository | undefined,
+  initiativeId: string,
+): Promise<{
+  phases: Array<Phase & { dependsOn?: string[] }>;
+  tasks: Task[];
+  pages: PageForSerialization[];
+}> {
+  const [rawPhases, deps, initiativeTasks, pages] = await Promise.all([
+    phaseRepo?.findByInitiativeId(initiativeId) ?? [],
+    phaseRepo?.findDependenciesByInitiativeId(initiativeId) ?? [],
+    taskRepo?.findByInitiativeId(initiativeId) ?? [],
+    pageRepo?.findByInitiativeId(initiativeId) ?? [],
+  ]);
+ 
+  // Merge dependencies into each phase as a dependsOn array
+  const depsByPhase = new Map<string, string[]>();
+  for (const dep of deps) {
+    const arr = depsByPhase.get(dep.phaseId) ?? [];
+    arr.push(dep.dependsOnPhaseId);
+    depsByPhase.set(dep.phaseId, arr);
+  }
+  const phases = rawPhases.map((ph) => ({
+    ...ph,
+    dependsOn: depsByPhase.get(ph.id) ?? [],
+  }));
+ 
+  // Collect tasks from all phases (some tasks only have phaseId, not initiativeId)
+  const taskIds = new Set(initiativeTasks.map((t) => t.id));
+  const allTasks = [...initiativeTasks];
+  Eif (taskRepo) {
+    for (const ph of rawPhases) {
+      const phaseTasks = await taskRepo.findByPhaseId(ph.id);
+      for (const t of phaseTasks) {
+        if (!taskIds.has(t.id)) {
+          taskIds.add(t.id);
+          allTasks.push(t);
+        }
+      }
+    }
+  }
+ 
+  // Only include implementation tasks in agent context — planning tasks are irrelevant noise
+  const implementationTasks = allTasks.filter(t => !isPlanningCategory(t.category));
+ 
+  return { phases, tasks: implementationTasks, pages };
+}
+ 
+export function architectProcedures(publicProcedure: ProcedureBuilder) {
+  return {
+    spawnArchitectDiscuss: publicProcedure
+      .input(z.object({
+        name: z.string().min(1).optional(),
+        initiativeId: z.string().min(1),
+        context: z.string().optional(),
+        provider: z.string().optional(),
+      }))
+      .mutation(async ({ ctx, input }) => {
+        const agentManager = requireAgentManager(ctx);
+        const initiativeRepo = requireInitiativeRepository(ctx);
+        const taskRepo = requireTaskRepository(ctx);
+ 
+        const initiative = await initiativeRepo.findById(input.initiativeId);
+        Iif (!initiative) {
+          throw new TRPCError({
+            code: 'NOT_FOUND',
+            message: `Initiative '${input.initiativeId}' not found`,
+          });
+        }
+ 
+        const task = await taskRepo.create({
+          initiativeId: input.initiativeId,
+          name: `Discuss: ${initiative.name}`,
+          description: input.context ?? 'Gather context and requirements for initiative',
+          category: 'discuss',
+          status: 'in_progress',
+        });
+ 
+        const prompt = buildDiscussPrompt();
+ 
+        return agentManager.spawn({
+          name: input.name,
+          taskId: task.id,
+          prompt,
+          mode: 'discuss',
+          provider: input.provider,
+          initiativeId: input.initiativeId,
+          inputContext: { initiative },
+        });
+      }),
+ 
+    spawnArchitectPlan: publicProcedure
+      .input(z.object({
+        name: z.string().min(1).optional(),
+        initiativeId: z.string().min(1),
+        contextSummary: z.string().optional(),
+        provider: z.string().optional(),
+      }))
+      .mutation(async ({ ctx, input }) => {
+        const agentManager = requireAgentManager(ctx);
+        const initiativeRepo = requireInitiativeRepository(ctx);
+        const taskRepo = requireTaskRepository(ctx);
+ 
+        const initiative = await initiativeRepo.findById(input.initiativeId);
+        Iif (!initiative) {
+          throw new TRPCError({
+            code: 'NOT_FOUND',
+            message: `Initiative '${input.initiativeId}' not found`,
+          });
+        }
+ 
+        // Auto-dismiss stale plan agents
+        const allAgents = await agentManager.list();
+        const staleAgents = allAgents.filter(
+          (a) =>
+            a.mode === 'plan' &&
+            a.initiativeId === input.initiativeId &&
+            ['crashed', 'idle'].includes(a.status) &&
+            !a.userDismissedAt,
+        );
+        for (const stale of staleAgents) {
+          await agentManager.dismiss(stale.id);
+        }
+ 
+        // Reject if a plan agent is already active for this initiative
+        const activePlanAgents = allAgents.filter(
+          (a) =>
+            a.mode === 'plan' &&
+            a.initiativeId === input.initiativeId &&
+            ['running', 'waiting_for_input'].includes(a.status),
+        );
+        if (activePlanAgents.length > 0) {
+          throw new TRPCError({
+            code: 'CONFLICT',
+            message: 'A plan agent is already running for this initiative',
+          });
+        }
+ 
+        const task = await taskRepo.create({
+          initiativeId: input.initiativeId,
+          name: `Plan: ${initiative.name}`,
+          description: 'Plan initiative into phases',
+          category: 'plan',
+          status: 'in_progress',
+        });
+ 
+        const context = await gatherInitiativeContext(ctx.phaseRepository, ctx.taskRepository, ctx.pageRepository, input.initiativeId);
+ 
+        const prompt = buildPlanPrompt();
+ 
+        return agentManager.spawn({
+          name: input.name,
+          taskId: task.id,
+          prompt,
+          mode: 'plan',
+          provider: input.provider,
+          initiativeId: input.initiativeId,
+          inputContext: {
+            initiative,
+            pages: context.pages.length > 0 ? context.pages : undefined,
+            phases: context.phases.length > 0 ? context.phases : undefined,
+            tasks: context.tasks.length > 0 ? context.tasks : undefined,
+          },
+        });
+      }),
+ 
+    spawnArchitectRefine: publicProcedure
+      .input(z.object({
+        name: z.string().min(1).optional(),
+        initiativeId: z.string().min(1),
+        instruction: z.string().optional(),
+        provider: z.string().optional(),
+      }))
+      .mutation(async ({ ctx, input }) => {
+        const agentManager = requireAgentManager(ctx);
+        const initiativeRepo = requireInitiativeRepository(ctx);
+        const pageRepo = requirePageRepository(ctx);
+        const taskRepo = requireTaskRepository(ctx);
+ 
+        const initiative = await initiativeRepo.findById(input.initiativeId);
+        if (!initiative) {
+          throw new TRPCError({
+            code: 'NOT_FOUND',
+            message: `Initiative '${input.initiativeId}' not found`,
+          });
+        }
+ 
+        // Bug #10: Auto-dismiss stale (crashed/idle) refine agents before checking for active ones
+        const allAgents = await agentManager.list();
+        const staleAgents = allAgents.filter(
+          (a) =>
+            a.mode === 'refine' &&
+            a.initiativeId === input.initiativeId &&
+            ['crashed', 'idle'].includes(a.status) &&
+            !a.userDismissedAt,
+        );
+        for (const stale of staleAgents) {
+          await agentManager.dismiss(stale.id);
+        }
+ 
+        // Bug #9: Prevent concurrent refine agents on the same initiative
+        const activeRefineAgents = allAgents.filter(
+          (a) =>
+            a.mode === 'refine' &&
+            a.initiativeId === input.initiativeId &&
+            ['running', 'waiting_for_input'].includes(a.status),
+        );
+        if (activeRefineAgents.length > 0) {
+          throw new TRPCError({
+            code: 'CONFLICT',
+            message: `A refine agent is already running for this initiative`,
+          });
+        }
+ 
+        const pages = await pageRepo.findByInitiativeId(input.initiativeId);
+ 
+        if (pages.length === 0) {
+          throw new TRPCError({
+            code: 'BAD_REQUEST',
+            message: 'Initiative has no page content to refine',
+          });
+        }
+ 
+        const task = await taskRepo.create({
+          initiativeId: input.initiativeId,
+          name: `Refine: ${initiative.name}`,
+          description: input.instruction ?? 'Review and propose edits to initiative content',
+          category: 'refine',
+          status: 'in_progress',
+        });
+ 
+        const prompt = buildRefinePrompt();
+ 
+        return agentManager.spawn({
+          name: input.name,
+          taskId: task.id,
+          prompt,
+          mode: 'refine',
+          provider: input.provider,
+          initiativeId: input.initiativeId,
+          inputContext: { initiative, pages },
+        });
+      }),
+ 
+    spawnArchitectDetail: publicProcedure
+      .input(z.object({
+        name: z.string().min(1).optional(),
+        phaseId: z.string().min(1),
+        taskName: z.string().min(1).optional(),
+        context: z.string().optional(),
+        provider: z.string().optional(),
+      }))
+      .mutation(async ({ ctx, input }) => {
+        const agentManager = requireAgentManager(ctx);
+        const phaseRepo = requirePhaseRepository(ctx);
+        const taskRepo = requireTaskRepository(ctx);
+        const initiativeRepo = requireInitiativeRepository(ctx);
+ 
+        const phase = await phaseRepo.findById(input.phaseId);
+        Iif (!phase) {
+          throw new TRPCError({
+            code: 'NOT_FOUND',
+            message: `Phase '${input.phaseId}' not found`,
+          });
+        }
+        const initiative = await initiativeRepo.findById(phase.initiativeId);
+        Iif (!initiative) {
+          throw new TRPCError({
+            code: 'NOT_FOUND',
+            message: `Initiative '${phase.initiativeId}' not found`,
+          });
+        }
+ 
+        // Auto-dismiss stale detail agents for this phase
+        const allAgents = await agentManager.list();
+        const detailAgents = allAgents.filter(
+          (a) => a.mode === 'detail' && !a.userDismissedAt,
+        );
+ 
+        // Look up tasks to find which phase each detail agent targets
+        const activeForPhase: typeof detailAgents = [];
+        const staleForPhase: typeof detailAgents = [];
+        for (const agent of detailAgents) {
+          Iif (!agent.taskId) continue;
+          const agentTask = await taskRepo.findById(agent.taskId);
+          if (agentTask?.phaseId !== input.phaseId) continue;
+ 
+          if (['crashed', 'idle'].includes(agent.status)) {
+            staleForPhase.push(agent);
+          E} else if (['running', 'waiting_for_input'].includes(agent.status)) {
+            activeForPhase.push(agent);
+          }
+        }
+        for (const stale of staleForPhase) {
+          await agentManager.dismiss(stale.id);
+        }
+        if (activeForPhase.length > 0) {
+          throw new TRPCError({
+            code: 'CONFLICT',
+            message: `A detail agent is already running for phase "${phase.name}"`,
+          });
+        }
+ 
+        const detailTaskName = input.taskName ?? `Detail: ${phase.name}`;
+        const task = await taskRepo.create({
+          phaseId: phase.id,
+          initiativeId: phase.initiativeId,
+          name: detailTaskName,
+          description: input.context ?? `Detail phase "${phase.name}" into executable tasks`,
+          category: 'detail',
+          status: 'in_progress',
+        });
+ 
+        const context = await gatherInitiativeContext(ctx.phaseRepository, ctx.taskRepository, ctx.pageRepository, phase.initiativeId);
+ 
+        const prompt = buildDetailPrompt();
+ 
+        return agentManager.spawn({
+          name: input.name,
+          taskId: task.id,
+          prompt,
+          mode: 'detail',
+          provider: input.provider,
+          initiativeId: phase.initiativeId,
+          inputContext: {
+            initiative,
+            phase,
+            task,
+            pages: context.pages.length > 0 ? context.pages : undefined,
+            phases: context.phases.length > 0 ? context.phases : undefined,
+            tasks: context.tasks.length > 0 ? context.tasks : undefined,
+          },
+        });
+      }),
+  };
+}
+ 
+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/coverage/src/trpc/routers/change-set.ts.html b/coverage/src/trpc/routers/change-set.ts.html new file mode 100644 index 0000000..303b57e --- /dev/null +++ b/coverage/src/trpc/routers/change-set.ts.html @@ -0,0 +1,523 @@ + + + + + + Code coverage report for src/trpc/routers/change-set.ts + + + + + + + + + +
+
+

All files / src/trpc/routers change-set.ts

+
+ +
+ 1.51% + Statements + 1/66 +
+ + +
+ 0% + Branches + 0/53 +
+ + +
+ 25% + Functions + 1/4 +
+ + +
+ 1.58% + Lines + 1/63 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+

+
1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 +30 +31 +32 +33 +34 +35 +36 +37 +38 +39 +40 +41 +42 +43 +44 +45 +46 +47 +48 +49 +50 +51 +52 +53 +54 +55 +56 +57 +58 +59 +60 +61 +62 +63 +64 +65 +66 +67 +68 +69 +70 +71 +72 +73 +74 +75 +76 +77 +78 +79 +80 +81 +82 +83 +84 +85 +86 +87 +88 +89 +90 +91 +92 +93 +94 +95 +96 +97 +98 +99 +100 +101 +102 +103 +104 +105 +106 +107 +108 +109 +110 +111 +112 +113 +114 +115 +116 +117 +118 +119 +120 +121 +122 +123 +124 +125 +126 +127 +128 +129 +130 +131 +132 +133 +134 +135 +136 +137 +138 +139 +140 +141 +142 +143 +144 +145 +146 +147  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +11x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  + 
/**
+ * Change Set Router — list, get, revert workflows
+ */
+ 
+import { TRPCError } from '@trpc/server';
+import { z } from 'zod';
+import type { ProcedureBuilder } from '../trpc.js';
+import {
+  requireChangeSetRepository,
+  requirePhaseRepository,
+  requireTaskRepository,
+  requirePageRepository,
+} from './_helpers.js';
+ 
+export function changeSetProcedures(publicProcedure: ProcedureBuilder) {
+  return {
+    listChangeSets: publicProcedure
+      .input(z.object({
+        initiativeId: z.string().min(1).optional(),
+        agentId: z.string().min(1).optional(),
+      }))
+      .query(async ({ ctx, input }) => {
+        const repo = requireChangeSetRepository(ctx);
+        if (input.agentId) {
+          return repo.findByAgentId(input.agentId);
+        }
+        if (input.initiativeId) {
+          return repo.findByInitiativeId(input.initiativeId);
+        }
+        throw new TRPCError({
+          code: 'BAD_REQUEST',
+          message: 'Either agentId or initiativeId is required',
+        });
+      }),
+ 
+    getChangeSet: publicProcedure
+      .input(z.object({ id: z.string().min(1) }))
+      .query(async ({ ctx, input }) => {
+        const repo = requireChangeSetRepository(ctx);
+        const cs = await repo.findByIdWithEntries(input.id);
+        if (!cs) {
+          throw new TRPCError({ code: 'NOT_FOUND', message: `ChangeSet '${input.id}' not found` });
+        }
+        return cs;
+      }),
+ 
+    revertChangeSet: publicProcedure
+      .input(z.object({ id: z.string().min(1), force: z.boolean().optional() }))
+      .mutation(async ({ ctx, input }) => {
+        const repo = requireChangeSetRepository(ctx);
+        const cs = await repo.findByIdWithEntries(input.id);
+        if (!cs) {
+          throw new TRPCError({ code: 'NOT_FOUND', message: `ChangeSet '${input.id}' not found` });
+        }
+        if (cs.status === 'reverted') {
+          throw new TRPCError({ code: 'BAD_REQUEST', message: 'ChangeSet is already reverted' });
+        }
+ 
+        const phaseRepo = requirePhaseRepository(ctx);
+        const taskRepo = requireTaskRepository(ctx);
+        const pageRepo = requirePageRepository(ctx);
+ 
+        // Conflict detection (unless force)
+        if (!input.force) {
+          const conflicts: string[] = [];
+          for (const entry of cs.entries) {
+            if (entry.action === 'create') {
+              if (entry.entityType === 'phase') {
+                const phase = await phaseRepo.findById(entry.entityId);
+                if (phase && phase.status === 'in_progress') {
+                  conflicts.push(`Phase "${phase.name}" is in progress`);
+                }
+              } else if (entry.entityType === 'task') {
+                const task = await taskRepo.findById(entry.entityId);
+                if (task && task.status === 'in_progress') {
+                  conflicts.push(`Task "${task.name}" is in progress`);
+                }
+              }
+            } else if (entry.action === 'update' && entry.entityType === 'page' && entry.newState) {
+              const page = await pageRepo.findById(entry.entityId);
+              if (page) {
+                const expectedContent = JSON.parse(entry.newState).content;
+                if (page.content !== expectedContent) {
+                  conflicts.push(`Page "${page.title}" was modified since change set was applied`);
+                }
+              }
+            }
+          }
+          if (conflicts.length > 0) {
+            return { success: false as const, conflicts };
+          }
+        }
+ 
+        // Apply reverts in reverse entry order
+        const reversedEntries = [...cs.entries].reverse();
+        for (const entry of reversedEntries) {
+          try {
+            if (entry.action === 'create') {
+              switch (entry.entityType) {
+                case 'phase':
+                  try { await phaseRepo.delete(entry.entityId); } catch { /* already deleted */ }
+                  break;
+                case 'task':
+                  try { await taskRepo.delete(entry.entityId); } catch { /* already deleted */ }
+                  break;
+                case 'phase_dependency': {
+                  const depData = JSON.parse(entry.newState || '{}');
+                  if (depData.phaseId && depData.dependsOnPhaseId) {
+                    try { await phaseRepo.removeDependency(depData.phaseId, depData.dependsOnPhaseId); } catch { /* already removed */ }
+                  }
+                  break;
+                }
+              }
+            } else if (entry.action === 'update' && entry.previousState) {
+              const prev = JSON.parse(entry.previousState);
+              switch (entry.entityType) {
+                case 'page':
+                  await pageRepo.update(entry.entityId, {
+                    content: prev.content,
+                    title: prev.title,
+                  });
+                  ctx.eventBus.emit({
+                    type: 'page:updated',
+                    timestamp: new Date(),
+                    payload: { pageId: entry.entityId, initiativeId: cs.initiativeId, title: prev.title },
+                  });
+                  break;
+              }
+            }
+          } catch (err) {
+            // Log but continue reverting other entries
+          }
+        }
+ 
+        await repo.markReverted(input.id);
+ 
+        ctx.eventBus.emit({
+          type: 'changeset:reverted' as const,
+          timestamp: new Date(),
+          payload: { changeSetId: cs.id, initiativeId: cs.initiativeId },
+        });
+ 
+        return { success: true as const };
+      }),
+  };
+}
+ 
+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/coverage/src/trpc/routers/conversation.ts.html b/coverage/src/trpc/routers/conversation.ts.html new file mode 100644 index 0000000..8ec1738 --- /dev/null +++ b/coverage/src/trpc/routers/conversation.ts.html @@ -0,0 +1,928 @@ + + + + + + Code coverage report for src/trpc/routers/conversation.ts + + + + + + + + + +
+
+

All files / src/trpc/routers conversation.ts

+
+ +
+ 0.89% + Statements + 1/112 +
+ + +
+ 0% + Branches + 0/62 +
+ + +
+ 6.25% + Functions + 1/16 +
+ + +
+ 0.93% + Lines + 1/107 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+

+
1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 +30 +31 +32 +33 +34 +35 +36 +37 +38 +39 +40 +41 +42 +43 +44 +45 +46 +47 +48 +49 +50 +51 +52 +53 +54 +55 +56 +57 +58 +59 +60 +61 +62 +63 +64 +65 +66 +67 +68 +69 +70 +71 +72 +73 +74 +75 +76 +77 +78 +79 +80 +81 +82 +83 +84 +85 +86 +87 +88 +89 +90 +91 +92 +93 +94 +95 +96 +97 +98 +99 +100 +101 +102 +103 +104 +105 +106 +107 +108 +109 +110 +111 +112 +113 +114 +115 +116 +117 +118 +119 +120 +121 +122 +123 +124 +125 +126 +127 +128 +129 +130 +131 +132 +133 +134 +135 +136 +137 +138 +139 +140 +141 +142 +143 +144 +145 +146 +147 +148 +149 +150 +151 +152 +153 +154 +155 +156 +157 +158 +159 +160 +161 +162 +163 +164 +165 +166 +167 +168 +169 +170 +171 +172 +173 +174 +175 +176 +177 +178 +179 +180 +181 +182 +183 +184 +185 +186 +187 +188 +189 +190 +191 +192 +193 +194 +195 +196 +197 +198 +199 +200 +201 +202 +203 +204 +205 +206 +207 +208 +209 +210 +211 +212 +213 +214 +215 +216 +217 +218 +219 +220 +221 +222 +223 +224 +225 +226 +227 +228 +229 +230 +231 +232 +233 +234 +235 +236 +237 +238 +239 +240 +241 +242 +243 +244 +245 +246 +247 +248 +249 +250 +251 +252 +253 +254 +255 +256 +257 +258 +259 +260 +261 +262 +263 +264 +265 +266 +267 +268 +269 +270 +271 +272 +273 +274 +275 +276 +277 +278 +279 +280 +281 +282  +  +  +  +  +  +  +  +  +  +  +  +11x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  + 
/**
+ * Conversation Router — inter-agent communication procedures
+ */
+ 
+import { TRPCError } from '@trpc/server';
+import { tracked, type TrackedEnvelope } from '@trpc/server';
+import { z } from 'zod';
+import type { ProcedureBuilder } from '../trpc.js';
+import { requireConversationRepository, requireAgentManager, requireTaskRepository } from './_helpers.js';
+import type { ConversationCreatedEvent, ConversationAnsweredEvent } from '../../events/types.js';
+ 
+export function conversationProcedures(publicProcedure: ProcedureBuilder) {
+  return {
+    createConversation: publicProcedure
+      .input(z.object({
+        fromAgentId: z.string().min(1),
+        toAgentId: z.string().min(1).optional(),
+        phaseId: z.string().min(1).optional(),
+        taskId: z.string().min(1).optional(),
+        question: z.string().min(1),
+      }))
+      .mutation(async ({ ctx, input }) => {
+        const repo = requireConversationRepository(ctx);
+        const agentManager = requireAgentManager(ctx);
+ 
+        let toAgentId = input.toAgentId;
+ 
+        // Resolve target agent from taskId
+        if (!toAgentId && input.taskId) {
+          const agents = await agentManager.list();
+          const match = agents.find(a => a.taskId === input.taskId && a.status === 'running');
+          if (!match) {
+            throw new TRPCError({
+              code: 'NOT_FOUND',
+              message: `No running agent found for task '${input.taskId}'`,
+            });
+          }
+          toAgentId = match.id;
+        }
+ 
+        // Resolve target agent from phaseId
+        if (!toAgentId && input.phaseId) {
+          const taskRepo = requireTaskRepository(ctx);
+          const tasks = await taskRepo.findByPhaseId(input.phaseId);
+          const taskIds = new Set(tasks.map(t => t.id));
+          const agents = await agentManager.list();
+          const match = agents.find(a => a.taskId && taskIds.has(a.taskId) && a.status === 'running');
+          if (!match) {
+            throw new TRPCError({
+              code: 'NOT_FOUND',
+              message: `No running agent found for phase '${input.phaseId}'`,
+            });
+          }
+          toAgentId = match.id;
+        }
+ 
+        if (!toAgentId) {
+          throw new TRPCError({
+            code: 'BAD_REQUEST',
+            message: 'Must provide toAgentId, taskId, or phaseId to identify target agent',
+          });
+        }
+ 
+        const conversation = await repo.create({
+          fromAgentId: input.fromAgentId,
+          toAgentId,
+          initiativeId: null,
+          phaseId: input.phaseId ?? null,
+          taskId: input.taskId ?? null,
+          question: input.question,
+        });
+ 
+        ctx.eventBus.emit({
+          type: 'conversation:created' as const,
+          timestamp: new Date(),
+          payload: {
+            conversationId: conversation.id,
+            fromAgentId: input.fromAgentId,
+            toAgentId,
+          },
+        });
+ 
+        return conversation;
+      }),
+ 
+    getPendingConversations: publicProcedure
+      .input(z.object({
+        agentId: z.string().min(1),
+      }))
+      .query(async ({ ctx, input }) => {
+        const repo = requireConversationRepository(ctx);
+        return repo.findPendingForAgent(input.agentId);
+      }),
+ 
+    getConversation: publicProcedure
+      .input(z.object({
+        id: z.string().min(1),
+      }))
+      .query(async ({ ctx, input }) => {
+        const repo = requireConversationRepository(ctx);
+        return repo.findById(input.id);
+      }),
+ 
+    answerConversation: publicProcedure
+      .input(z.object({
+        id: z.string().min(1),
+        answer: z.string().min(1),
+      }))
+      .mutation(async ({ ctx, input }) => {
+        const repo = requireConversationRepository(ctx);
+        const existing = await repo.findById(input.id);
+        if (!existing) {
+          throw new TRPCError({
+            code: 'NOT_FOUND',
+            message: `Conversation '${input.id}' not found`,
+          });
+        }
+        if (existing.status === 'answered') {
+          throw new TRPCError({
+            code: 'BAD_REQUEST',
+            message: `Conversation '${input.id}' is already answered`,
+          });
+        }
+ 
+        const updated = await repo.answer(input.id, input.answer);
+ 
+        ctx.eventBus.emit({
+          type: 'conversation:answered' as const,
+          timestamp: new Date(),
+          payload: {
+            conversationId: input.id,
+            fromAgentId: existing.fromAgentId,
+            toAgentId: existing.toAgentId,
+          },
+        });
+ 
+        return updated;
+      }),
+ 
+    onPendingConversation: publicProcedure
+      .input(z.object({ agentId: z.string().min(1) }))
+      .subscription(async function* (opts): AsyncGenerator<TrackedEnvelope<{
+        conversationId: string;
+        fromAgentId: string;
+        question: string;
+        phaseId: string | null;
+        taskId: string | null;
+      }>> {
+        const { agentId } = opts.input;
+        const signal = opts.signal ?? new AbortController().signal;
+        const eventBus = opts.ctx.eventBus;
+        const repo = requireConversationRepository(opts.ctx);
+ 
+        // First yield any already-pending conversations
+        const existing = await repo.findPendingForAgent(agentId);
+        let eventCounter = 0;
+        for (const conv of existing) {
+          yield tracked(`conv-${eventCounter++}`, {
+            conversationId: conv.id,
+            fromAgentId: conv.fromAgentId,
+            question: conv.question,
+            phaseId: conv.phaseId,
+            taskId: conv.taskId,
+          });
+        }
+ 
+        // Then listen for new conversation:created events
+        const queue: string[] = []; // conversation IDs
+        let resolve: (() => void) | null = null;
+ 
+        const handler = (event: ConversationCreatedEvent) => {
+          if (event.payload.toAgentId !== agentId) return;
+          queue.push(event.payload.conversationId);
+          if (resolve) {
+            const r = resolve;
+            resolve = null;
+            r();
+          }
+        };
+ 
+        eventBus.on('conversation:created', handler);
+ 
+        const cleanup = () => {
+          eventBus.off('conversation:created', handler);
+          if (resolve) {
+            const r = resolve;
+            resolve = null;
+            r();
+          }
+        };
+ 
+        signal.addEventListener('abort', cleanup, { once: true });
+ 
+        try {
+          while (!signal.aborted) {
+            while (queue.length > 0) {
+              const convId = queue.shift()!;
+              const conv = await repo.findById(convId);
+              if (conv && conv.status === 'pending') {
+                yield tracked(`conv-${eventCounter++}`, {
+                  conversationId: conv.id,
+                  fromAgentId: conv.fromAgentId,
+                  question: conv.question,
+                  phaseId: conv.phaseId,
+                  taskId: conv.taskId,
+                });
+              }
+            }
+ 
+            if (!signal.aborted) {
+              await new Promise<void>((r) => {
+                resolve = r;
+              });
+            }
+          }
+        } finally {
+          cleanup();
+        }
+      }),
+ 
+    onConversationAnswer: publicProcedure
+      .input(z.object({ conversationId: z.string().min(1) }))
+      .subscription(async function* (opts): AsyncGenerator<TrackedEnvelope<{ answer: string }>> {
+        const { conversationId } = opts.input;
+        const signal = opts.signal ?? new AbortController().signal;
+        const eventBus = opts.ctx.eventBus;
+        const repo = requireConversationRepository(opts.ctx);
+ 
+        // Check if already answered
+        const existing = await repo.findById(conversationId);
+        if (existing && existing.status === 'answered' && existing.answer) {
+          yield tracked('answer-0', { answer: existing.answer });
+          return;
+        }
+ 
+        // Listen for conversation:answered events matching this ID
+        let answered = false;
+        let resolve: (() => void) | null = null;
+ 
+        const handler = (event: ConversationAnsweredEvent) => {
+          if (event.payload.conversationId !== conversationId) return;
+          answered = true;
+          if (resolve) {
+            const r = resolve;
+            resolve = null;
+            r();
+          }
+        };
+ 
+        eventBus.on('conversation:answered', handler);
+ 
+        const cleanup = () => {
+          eventBus.off('conversation:answered', handler);
+          if (resolve) {
+            const r = resolve;
+            resolve = null;
+            r();
+          }
+        };
+ 
+        signal.addEventListener('abort', cleanup, { once: true });
+ 
+        try {
+          while (!signal.aborted && !answered) {
+            await new Promise<void>((r) => {
+              resolve = r;
+            });
+          }
+ 
+          if (answered) {
+            const conv = await repo.findById(conversationId);
+            if (conv && conv.answer) {
+              yield tracked('answer-0', { answer: conv.answer });
+            }
+          }
+        } finally {
+          cleanup();
+        }
+      }),
+  };
+}
+ 
+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/coverage/src/trpc/routers/coordination.ts.html b/coverage/src/trpc/routers/coordination.ts.html new file mode 100644 index 0000000..eb16e5a --- /dev/null +++ b/coverage/src/trpc/routers/coordination.ts.html @@ -0,0 +1,208 @@ + + + + + + Code coverage report for src/trpc/routers/coordination.ts + + + + + + + + + +
+
+

All files / src/trpc/routers coordination.ts

+
+ +
+ 9.09% + Statements + 1/11 +
+ + +
+ 100% + Branches + 0/0 +
+ + +
+ 20% + Functions + 1/5 +
+ + +
+ 9.09% + Lines + 1/11 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+

+
1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 +30 +31 +32 +33 +34 +35 +36 +37 +38 +39 +40 +41 +42  +  +  +  +  +  +  +  +  +11x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  + 
/**
+ * Coordination Router — merge queue operations
+ */
+ 
+import { z } from 'zod';
+import type { ProcedureBuilder } from '../trpc.js';
+import { requireCoordinationManager } from './_helpers.js';
+ 
+export function coordinationProcedures(publicProcedure: ProcedureBuilder) {
+  return {
+    queueMerge: publicProcedure
+      .input(z.object({ taskId: z.string().min(1) }))
+      .mutation(async ({ ctx, input }) => {
+        const coordinationManager = requireCoordinationManager(ctx);
+        await coordinationManager.queueMerge(input.taskId);
+        return { success: true };
+      }),
+ 
+    processMerges: publicProcedure
+      .input(z.object({
+        targetBranch: z.string().default('main'),
+      }))
+      .mutation(async ({ ctx, input }) => {
+        const coordinationManager = requireCoordinationManager(ctx);
+        const results = await coordinationManager.processMerges(input.targetBranch);
+        return { results };
+      }),
+ 
+    getMergeQueueStatus: publicProcedure
+      .query(async ({ ctx }) => {
+        const coordinationManager = requireCoordinationManager(ctx);
+        return coordinationManager.getQueueState();
+      }),
+ 
+    getNextMergeable: publicProcedure
+      .query(async ({ ctx }) => {
+        const coordinationManager = requireCoordinationManager(ctx);
+        return coordinationManager.getNextMergeable();
+      }),
+  };
+}
+ 
+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/coverage/src/trpc/routers/dispatch.ts.html b/coverage/src/trpc/routers/dispatch.ts.html new file mode 100644 index 0000000..bab5040 --- /dev/null +++ b/coverage/src/trpc/routers/dispatch.ts.html @@ -0,0 +1,202 @@ + + + + + + Code coverage report for src/trpc/routers/dispatch.ts + + + + + + + + + +
+
+

All files / src/trpc/routers dispatch.ts

+
+ +
+ 9.09% + Statements + 1/11 +
+ + +
+ 100% + Branches + 0/0 +
+ + +
+ 20% + Functions + 1/5 +
+ + +
+ 9.09% + Lines + 1/11 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+

+
1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 +30 +31 +32 +33 +34 +35 +36 +37 +38 +39 +40  +  +  +  +  +  +  +  +  +11x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  + 
/**
+ * Dispatch Router — queue, dispatchNext, getQueueState, completeTask
+ */
+ 
+import { z } from 'zod';
+import type { ProcedureBuilder } from '../trpc.js';
+import { requireDispatchManager } from './_helpers.js';
+ 
+export function dispatchProcedures(publicProcedure: ProcedureBuilder) {
+  return {
+    queueTask: publicProcedure
+      .input(z.object({ taskId: z.string().min(1) }))
+      .mutation(async ({ ctx, input }) => {
+        const dispatchManager = requireDispatchManager(ctx);
+        await dispatchManager.queue(input.taskId);
+        return { success: true };
+      }),
+ 
+    dispatchNext: publicProcedure
+      .mutation(async ({ ctx }) => {
+        const dispatchManager = requireDispatchManager(ctx);
+        return dispatchManager.dispatchNext();
+      }),
+ 
+    getQueueState: publicProcedure
+      .query(async ({ ctx }) => {
+        const dispatchManager = requireDispatchManager(ctx);
+        return dispatchManager.getQueueState();
+      }),
+ 
+    completeTask: publicProcedure
+      .input(z.object({ taskId: z.string().min(1) }))
+      .mutation(async ({ ctx, input }) => {
+        const dispatchManager = requireDispatchManager(ctx);
+        await dispatchManager.completeTask(input.taskId);
+        return { success: true };
+      }),
+  };
+}
+ 
+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/coverage/src/trpc/routers/index.html b/coverage/src/trpc/routers/index.html new file mode 100644 index 0000000..f4d0a0f --- /dev/null +++ b/coverage/src/trpc/routers/index.html @@ -0,0 +1,371 @@ + + + + + + Code coverage report for src/trpc/routers + + + + + + + + + +
+
+

All files src/trpc/routers

+
+ +
+ 19.77% + Statements + 161/814 +
+ + +
+ 19.36% + Branches + 79/408 +
+ + +
+ 25.13% + Functions + 45/179 +
+ + +
+ 19.94% + Lines + 157/787 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
FileStatementsBranchesFunctionsLines
_helpers.ts +
+
15.68%8/5111.76%4/3423.52%4/1715.68%8/51
account.ts +
+
6.25%1/16100%0/012.5%1/86.25%1/16
agent.ts +
+
18.18%16/8814.28%4/2828%7/2518.82%16/85
architect.ts +
+
71.69%76/10657.69%45/7878.57%11/1471.28%72/101
change-set.ts +
+
1.51%1/660%0/5325%1/41.58%1/63
conversation.ts +
+
0.89%1/1120%0/626.25%1/160.93%1/107
coordination.ts +
+
9.09%1/11100%0/020%1/59.09%1/11
dispatch.ts +
+
9.09%1/11100%0/020%1/59.09%1/11
initiative.ts +
+
13.46%7/5221.87%7/3220%2/1014.28%7/49
message.ts +
+
4.54%1/220%0/816.66%1/65%1/20
page.ts +
+
3.03%1/330%0/611.11%1/93.03%1/33
phase-dispatch.ts +
+
67.85%19/2870%7/1040%2/567.85%19/28
phase.ts +
+
11.25%9/800%0/2018.75%3/1611.39%9/79
preview.ts +
+
10%1/10100%0/020%1/510%1/10
project.ts +
+
1.92%1/520%0/2910%1/101.92%1/52
subscription.ts +
+
11.11%1/90%0/820%1/511.11%1/9
system.ts +
+
30.76%8/2637.5%6/1650%3/634.78%8/23
task.ts +
+
19.51%8/4125%6/2423.07%3/1320.51%8/39
+
+
+
+ + + + + + + + \ No newline at end of file diff --git a/coverage/src/trpc/routers/initiative.ts.html b/coverage/src/trpc/routers/initiative.ts.html new file mode 100644 index 0000000..d7a5ba9 --- /dev/null +++ b/coverage/src/trpc/routers/initiative.ts.html @@ -0,0 +1,544 @@ + + + + + + Code coverage report for src/trpc/routers/initiative.ts + + + + + + + + + +
+
+

All files / src/trpc/routers initiative.ts

+
+ +
+ 13.46% + Statements + 7/52 +
+ + +
+ 21.87% + Branches + 7/32 +
+ + +
+ 20% + Functions + 2/10 +
+ + +
+ 14.28% + Lines + 7/49 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+

+
1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 +30 +31 +32 +33 +34 +35 +36 +37 +38 +39 +40 +41 +42 +43 +44 +45 +46 +47 +48 +49 +50 +51 +52 +53 +54 +55 +56 +57 +58 +59 +60 +61 +62 +63 +64 +65 +66 +67 +68 +69 +70 +71 +72 +73 +74 +75 +76 +77 +78 +79 +80 +81 +82 +83 +84 +85 +86 +87 +88 +89 +90 +91 +92 +93 +94 +95 +96 +97 +98 +99 +100 +101 +102 +103 +104 +105 +106 +107 +108 +109 +110 +111 +112 +113 +114 +115 +116 +117 +118 +119 +120 +121 +122 +123 +124 +125 +126 +127 +128 +129 +130 +131 +132 +133 +134 +135 +136 +137 +138 +139 +140 +141 +142 +143 +144 +145 +146 +147 +148 +149 +150 +151 +152 +153 +154  +  +  +  +  +  +  +  +  +  +11x +  +  +  +  +  +  +  +  +19x +  +19x +  +  +  +  +  +  +  +  +  +  +  +  +19x +  +  +  +  +  +  +19x +  +  +  +  +19x +  +  +  +  +  +  +  +  +  +19x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  + 
/**
+ * Initiative Router — create, list, get, update, merge config
+ */
+ 
+import { TRPCError } from '@trpc/server';
+import { z } from 'zod';
+import type { ProcedureBuilder } from '../trpc.js';
+import { requireInitiativeRepository, requireProjectRepository, requireTaskRepository } from './_helpers.js';
+ 
+export function initiativeProcedures(publicProcedure: ProcedureBuilder) {
+  return {
+    createInitiative: publicProcedure
+      .input(z.object({
+        name: z.string().min(1),
+        branch: z.string().nullable().optional(),
+        projectIds: z.array(z.string().min(1)).min(1).optional(),
+        executionMode: z.enum(['yolo', 'review_per_phase']).optional(),
+      }))
+      .mutation(async ({ ctx, input }) => {
+        const repo = requireInitiativeRepository(ctx);
+ 
+        Iif (input.projectIds && input.projectIds.length > 0) {
+          const projectRepo = requireProjectRepository(ctx);
+          for (const pid of input.projectIds) {
+            const project = await projectRepo.findById(pid);
+            if (!project) {
+              throw new TRPCError({
+                code: 'NOT_FOUND',
+                message: `Project '${pid}' not found`,
+              });
+            }
+          }
+        }
+ 
+        const initiative = await repo.create({
+          name: input.name,
+          status: 'active',
+          ...(input.executionMode && { executionMode: input.executionMode }),
+          ...(input.branch && { branch: input.branch }),
+        });
+ 
+        Iif (input.projectIds && input.projectIds.length > 0) {
+          const projectRepo = requireProjectRepository(ctx);
+          await projectRepo.setInitiativeProjects(initiative.id, input.projectIds);
+        }
+ 
+        Iif (ctx.pageRepository) {
+          await ctx.pageRepository.create({
+            initiativeId: initiative.id,
+            parentPageId: null,
+            title: input.name,
+            content: null,
+            sortOrder: 0,
+          });
+        }
+ 
+        return initiative;
+      }),
+ 
+    listInitiatives: publicProcedure
+      .input(z.object({
+        status: z.enum(['active', 'completed', 'archived']).optional(),
+      }).optional())
+      .query(async ({ ctx, input }) => {
+        const repo = requireInitiativeRepository(ctx);
+        if (input?.status) {
+          return repo.findByStatus(input.status);
+        }
+        return repo.findAll();
+      }),
+ 
+    getInitiative: publicProcedure
+      .input(z.object({ id: z.string().min(1) }))
+      .query(async ({ ctx, input }) => {
+        const repo = requireInitiativeRepository(ctx);
+        const initiative = await repo.findById(input.id);
+        if (!initiative) {
+          throw new TRPCError({
+            code: 'NOT_FOUND',
+            message: `Initiative '${input.id}' not found`,
+          });
+        }
+ 
+        let projects: Array<{ id: string; name: string; url: string }> = [];
+        if (ctx.projectRepository) {
+          const fullProjects = await ctx.projectRepository.findProjectsByInitiativeId(input.id);
+          projects = fullProjects.map((p) => ({ id: p.id, name: p.name, url: p.url }));
+        }
+ 
+        let branchLocked = false;
+        if (ctx.taskRepository) {
+          const tasks = await ctx.taskRepository.findByInitiativeId(input.id);
+          branchLocked = tasks.some((t) => t.status !== 'pending');
+        }
+ 
+        return { ...initiative, projects, branchLocked };
+      }),
+ 
+    updateInitiative: publicProcedure
+      .input(z.object({
+        id: z.string().min(1),
+        name: z.string().min(1).optional(),
+        status: z.enum(['active', 'completed', 'archived']).optional(),
+      }))
+      .mutation(async ({ ctx, input }) => {
+        const repo = requireInitiativeRepository(ctx);
+        const { id, ...data } = input;
+        return repo.update(id, data);
+      }),
+ 
+    deleteInitiative: publicProcedure
+      .input(z.object({ id: z.string().min(1) }))
+      .mutation(async ({ ctx, input }) => {
+        const repo = requireInitiativeRepository(ctx);
+        await repo.delete(input.id);
+        return { success: true };
+      }),
+ 
+    updateInitiativeConfig: publicProcedure
+      .input(z.object({
+        initiativeId: z.string().min(1),
+        mergeRequiresApproval: z.boolean().optional(),
+        executionMode: z.enum(['yolo', 'review_per_phase']).optional(),
+        branch: z.string().nullable().optional(),
+      }))
+      .mutation(async ({ ctx, input }) => {
+        const repo = requireInitiativeRepository(ctx);
+        const { initiativeId, ...data } = input;
+ 
+        const existing = await repo.findById(initiativeId);
+        if (!existing) {
+          throw new TRPCError({
+            code: 'NOT_FOUND',
+            message: `Initiative '${initiativeId}' not found`,
+          });
+        }
+ 
+        // Prevent branch changes once work has started
+        if (data.branch !== undefined && ctx.taskRepository) {
+          const tasks = await ctx.taskRepository.findByInitiativeId(initiativeId);
+          const hasStarted = tasks.some((t) => t.status !== 'pending');
+          if (hasStarted) {
+            throw new TRPCError({
+              code: 'PRECONDITION_FAILED',
+              message: 'Cannot change branch after work has started',
+            });
+          }
+        }
+ 
+        return repo.update(initiativeId, data);
+      }),
+  };
+}
+ 
+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/coverage/src/trpc/routers/message.ts.html b/coverage/src/trpc/routers/message.ts.html new file mode 100644 index 0000000..ce1a662 --- /dev/null +++ b/coverage/src/trpc/routers/message.ts.html @@ -0,0 +1,316 @@ + + + + + + Code coverage report for src/trpc/routers/message.ts + + + + + + + + + +
+
+

All files / src/trpc/routers message.ts

+
+ +
+ 4.54% + Statements + 1/22 +
+ + +
+ 0% + Branches + 0/8 +
+ + +
+ 16.66% + Functions + 1/6 +
+ + +
+ 5% + Lines + 1/20 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+

+
1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 +30 +31 +32 +33 +34 +35 +36 +37 +38 +39 +40 +41 +42 +43 +44 +45 +46 +47 +48 +49 +50 +51 +52 +53 +54 +55 +56 +57 +58 +59 +60 +61 +62 +63 +64 +65 +66 +67 +68 +69 +70 +71 +72 +73 +74 +75 +76 +77 +78  +  +  +  +  +  +  +  +  +  +11x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  + 
/**
+ * Message Router — list, get, respond
+ */
+ 
+import { TRPCError } from '@trpc/server';
+import { z } from 'zod';
+import type { ProcedureBuilder } from '../trpc.js';
+import { requireMessageRepository } from './_helpers.js';
+ 
+export function messageProcedures(publicProcedure: ProcedureBuilder) {
+  return {
+    listMessages: publicProcedure
+      .input(z.object({
+        agentId: z.string().optional(),
+        status: z.enum(['pending', 'read', 'responded']).optional(),
+      }))
+      .query(async ({ ctx, input }) => {
+        const messageRepository = requireMessageRepository(ctx);
+ 
+        let messages = await messageRepository.findByRecipient('user');
+ 
+        if (input.agentId) {
+          messages = messages.filter(m => m.senderId === input.agentId);
+        }
+ 
+        if (input.status) {
+          messages = messages.filter(m => m.status === input.status);
+        }
+ 
+        return messages;
+      }),
+ 
+    getMessage: publicProcedure
+      .input(z.object({ id: z.string().min(1) }))
+      .query(async ({ ctx, input }) => {
+        const messageRepository = requireMessageRepository(ctx);
+        const message = await messageRepository.findById(input.id);
+        if (!message) {
+          throw new TRPCError({
+            code: 'NOT_FOUND',
+            message: `Message '${input.id}' not found`,
+          });
+        }
+        return message;
+      }),
+ 
+    respondToMessage: publicProcedure
+      .input(z.object({
+        id: z.string().min(1),
+        response: z.string().min(1),
+      }))
+      .mutation(async ({ ctx, input }) => {
+        const messageRepository = requireMessageRepository(ctx);
+ 
+        const existing = await messageRepository.findById(input.id);
+        if (!existing) {
+          throw new TRPCError({
+            code: 'NOT_FOUND',
+            message: `Message '${input.id}' not found`,
+          });
+        }
+ 
+        const responseMessage = await messageRepository.create({
+          senderType: 'user',
+          recipientType: 'agent',
+          recipientId: existing.senderId,
+          type: 'response',
+          content: input.response,
+          parentMessageId: input.id,
+        });
+ 
+        await messageRepository.update(input.id, { status: 'responded' });
+ 
+        return responseMessage;
+      }),
+  };
+}
+ 
+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/coverage/src/trpc/routers/page.ts.html b/coverage/src/trpc/routers/page.ts.html new file mode 100644 index 0000000..b01aa56 --- /dev/null +++ b/coverage/src/trpc/routers/page.ts.html @@ -0,0 +1,436 @@ + + + + + + Code coverage report for src/trpc/routers/page.ts + + + + + + + + + +
+
+

All files / src/trpc/routers page.ts

+
+ +
+ 3.03% + Statements + 1/33 +
+ + +
+ 0% + Branches + 0/6 +
+ + +
+ 11.11% + Functions + 1/9 +
+ + +
+ 3.03% + Lines + 1/33 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+

+
1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 +30 +31 +32 +33 +34 +35 +36 +37 +38 +39 +40 +41 +42 +43 +44 +45 +46 +47 +48 +49 +50 +51 +52 +53 +54 +55 +56 +57 +58 +59 +60 +61 +62 +63 +64 +65 +66 +67 +68 +69 +70 +71 +72 +73 +74 +75 +76 +77 +78 +79 +80 +81 +82 +83 +84 +85 +86 +87 +88 +89 +90 +91 +92 +93 +94 +95 +96 +97 +98 +99 +100 +101 +102 +103 +104 +105 +106 +107 +108 +109 +110 +111 +112 +113 +114 +115 +116 +117 +118  +  +  +  +  +  +  +  +  +  +11x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  + 
/**
+ * Page Router — CRUD, tree operations
+ */
+ 
+import { TRPCError } from '@trpc/server';
+import { z } from 'zod';
+import type { ProcedureBuilder } from '../trpc.js';
+import { requirePageRepository } from './_helpers.js';
+ 
+export function pageProcedures(publicProcedure: ProcedureBuilder) {
+  return {
+    getRootPage: publicProcedure
+      .input(z.object({ initiativeId: z.string().min(1) }))
+      .query(async ({ ctx, input }) => {
+        const repo = requirePageRepository(ctx);
+        return repo.getOrCreateRootPage(input.initiativeId);
+      }),
+ 
+    getPage: publicProcedure
+      .input(z.object({ id: z.string().min(1) }))
+      .query(async ({ ctx, input }) => {
+        const repo = requirePageRepository(ctx);
+        const page = await repo.findById(input.id);
+        if (!page) {
+          throw new TRPCError({
+            code: 'NOT_FOUND',
+            message: `Page '${input.id}' not found`,
+          });
+        }
+        return page;
+      }),
+ 
+    getPageUpdatedAtMap: publicProcedure
+      .input(z.object({ ids: z.array(z.string().min(1)) }))
+      .query(async ({ ctx, input }) => {
+        const repo = requirePageRepository(ctx);
+        const foundPages = await repo.findByIds(input.ids);
+        const map: Record<string, string> = {};
+        for (const p of foundPages) {
+          map[p.id] = p.updatedAt instanceof Date ? p.updatedAt.toISOString() : String(p.updatedAt);
+        }
+        return map;
+      }),
+ 
+    listPages: publicProcedure
+      .input(z.object({ initiativeId: z.string().min(1) }))
+      .query(async ({ ctx, input }) => {
+        const repo = requirePageRepository(ctx);
+        return repo.findByInitiativeId(input.initiativeId);
+      }),
+ 
+    listChildPages: publicProcedure
+      .input(z.object({ parentPageId: z.string().min(1) }))
+      .query(async ({ ctx, input }) => {
+        const repo = requirePageRepository(ctx);
+        return repo.findByParentPageId(input.parentPageId);
+      }),
+ 
+    createPage: publicProcedure
+      .input(z.object({
+        initiativeId: z.string().min(1),
+        parentPageId: z.string().min(1).nullable(),
+        title: z.string().min(1),
+      }))
+      .mutation(async ({ ctx, input }) => {
+        const repo = requirePageRepository(ctx);
+        const page = await repo.create({
+          initiativeId: input.initiativeId,
+          parentPageId: input.parentPageId,
+          title: input.title,
+          content: null,
+          sortOrder: 0,
+        });
+        ctx.eventBus.emit({
+          type: 'page:created',
+          timestamp: new Date(),
+          payload: { pageId: page.id, initiativeId: input.initiativeId, title: input.title },
+        });
+        return page;
+      }),
+ 
+    updatePage: publicProcedure
+      .input(z.object({
+        id: z.string().min(1),
+        title: z.string().min(1).optional(),
+        content: z.string().nullable().optional(),
+        sortOrder: z.number().int().optional(),
+      }))
+      .mutation(async ({ ctx, input }) => {
+        const repo = requirePageRepository(ctx);
+        const { id, ...data } = input;
+        const page = await repo.update(id, data);
+        ctx.eventBus.emit({
+          type: 'page:updated',
+          timestamp: new Date(),
+          payload: { pageId: id, initiativeId: page.initiativeId, title: input.title },
+        });
+        return page;
+      }),
+ 
+    deletePage: publicProcedure
+      .input(z.object({ id: z.string().min(1) }))
+      .mutation(async ({ ctx, input }) => {
+        const repo = requirePageRepository(ctx);
+        const page = await repo.findById(input.id);
+        await repo.delete(input.id);
+        if (page) {
+          ctx.eventBus.emit({
+            type: 'page:deleted',
+            timestamp: new Date(),
+            payload: { pageId: input.id, initiativeId: page.initiativeId },
+          });
+        }
+        return { success: true };
+      }),
+  };
+}
+ 
+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/coverage/src/trpc/routers/phase-dispatch.ts.html b/coverage/src/trpc/routers/phase-dispatch.ts.html new file mode 100644 index 0000000..2129097 --- /dev/null +++ b/coverage/src/trpc/routers/phase-dispatch.ts.html @@ -0,0 +1,367 @@ + + + + + + Code coverage report for src/trpc/routers/phase-dispatch.ts + + + + + + + + + +
+
+

All files / src/trpc/routers phase-dispatch.ts

+
+ +
+ 67.85% + Statements + 19/28 +
+ + +
+ 70% + Branches + 7/10 +
+ + +
+ 40% + Functions + 2/5 +
+ + +
+ 67.85% + Lines + 19/28 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+

+
1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 +30 +31 +32 +33 +34 +35 +36 +37 +38 +39 +40 +41 +42 +43 +44 +45 +46 +47 +48 +49 +50 +51 +52 +53 +54 +55 +56 +57 +58 +59 +60 +61 +62 +63 +64 +65 +66 +67 +68 +69 +70 +71 +72 +73 +74 +75 +76 +77 +78 +79 +80 +81 +82 +83 +84 +85 +86 +87 +88 +89 +90 +91 +92 +93 +94 +95  +  +  +  +  +  +  +  +  +  +  +11x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +4x +  +4x +4x +  +  +  +  +  +4x +  +  +  +  +  +  +4x +4x +  +4x +15x +  +  +  +  +  +  +  +  +  +15x +15x +  +  +4x +15x +11x +11x +12x +12x +12x +  +  +  +  +  +4x +  +  +  + 
/**
+ * Phase Dispatch Router — queue, dispatch, state, child tasks
+ */
+ 
+import { TRPCError } from '@trpc/server';
+import { z } from 'zod';
+import type { Task } from '../../db/schema.js';
+import type { ProcedureBuilder } from '../trpc.js';
+import { requirePhaseDispatchManager, requireTaskRepository } from './_helpers.js';
+ 
+export function phaseDispatchProcedures(publicProcedure: ProcedureBuilder) {
+  return {
+    queuePhase: publicProcedure
+      .input(z.object({ phaseId: z.string().min(1) }))
+      .mutation(async ({ ctx, input }) => {
+        const phaseDispatchManager = requirePhaseDispatchManager(ctx);
+        await phaseDispatchManager.queuePhase(input.phaseId);
+        return { success: true };
+      }),
+ 
+    dispatchNextPhase: publicProcedure
+      .mutation(async ({ ctx }) => {
+        const phaseDispatchManager = requirePhaseDispatchManager(ctx);
+        return phaseDispatchManager.dispatchNextPhase();
+      }),
+ 
+    getPhaseQueueState: publicProcedure
+      .query(async ({ ctx }) => {
+        const phaseDispatchManager = requirePhaseDispatchManager(ctx);
+        return phaseDispatchManager.getPhaseQueueState();
+      }),
+ 
+    createChildTasks: publicProcedure
+      .input(z.object({
+        parentTaskId: z.string().min(1),
+        tasks: z.array(z.object({
+          number: z.number().int().positive(),
+          name: z.string().min(1),
+          description: z.string(),
+          type: z.enum(['auto', 'checkpoint:human-verify', 'checkpoint:decision', 'checkpoint:human-action']).default('auto'),
+          dependencies: z.array(z.number().int().positive()).optional(),
+        })),
+      }))
+      .mutation(async ({ ctx, input }) => {
+        const taskRepo = requireTaskRepository(ctx);
+ 
+        const parentTask = await taskRepo.findById(input.parentTaskId);
+        Iif (!parentTask) {
+          throw new TRPCError({
+            code: 'NOT_FOUND',
+            message: `Parent task '${input.parentTaskId}' not found`,
+          });
+        }
+        Iif (parentTask.category !== 'detail') {
+          throw new TRPCError({
+            code: 'BAD_REQUEST',
+            message: `Parent task must have category 'detail', got '${parentTask.category}'`,
+          });
+        }
+ 
+        const numberToId = new Map<number, string>();
+        const created: Task[] = [];
+ 
+        for (const taskInput of input.tasks) {
+          const task = await taskRepo.create({
+            parentTaskId: input.parentTaskId,
+            phaseId: parentTask.phaseId,
+            initiativeId: parentTask.initiativeId,
+            name: taskInput.name,
+            description: taskInput.description,
+            type: taskInput.type,
+            order: taskInput.number,
+            status: 'pending',
+          });
+          numberToId.set(taskInput.number, task.id);
+          created.push(task);
+        }
+ 
+        for (const taskInput of input.tasks) {
+          if (taskInput.dependencies && taskInput.dependencies.length > 0) {
+            const taskId = numberToId.get(taskInput.number)!;
+            for (const depNumber of taskInput.dependencies) {
+              const dependsOnTaskId = numberToId.get(depNumber);
+              Eif (dependsOnTaskId) {
+                await taskRepo.createDependency(taskId, dependsOnTaskId);
+              }
+            }
+          }
+        }
+ 
+        return created;
+      }),
+  };
+}
+ 
+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/coverage/src/trpc/routers/phase.ts.html b/coverage/src/trpc/routers/phase.ts.html new file mode 100644 index 0000000..65e5491 --- /dev/null +++ b/coverage/src/trpc/routers/phase.ts.html @@ -0,0 +1,799 @@ + + + + + + Code coverage report for src/trpc/routers/phase.ts + + + + + + + + + +
+
+

All files / src/trpc/routers phase.ts

+
+ +
+ 11.25% + Statements + 9/80 +
+ + +
+ 0% + Branches + 0/20 +
+ + +
+ 18.75% + Functions + 3/16 +
+ + +
+ 11.39% + Lines + 9/79 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+

+
1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 +30 +31 +32 +33 +34 +35 +36 +37 +38 +39 +40 +41 +42 +43 +44 +45 +46 +47 +48 +49 +50 +51 +52 +53 +54 +55 +56 +57 +58 +59 +60 +61 +62 +63 +64 +65 +66 +67 +68 +69 +70 +71 +72 +73 +74 +75 +76 +77 +78 +79 +80 +81 +82 +83 +84 +85 +86 +87 +88 +89 +90 +91 +92 +93 +94 +95 +96 +97 +98 +99 +100 +101 +102 +103 +104 +105 +106 +107 +108 +109 +110 +111 +112 +113 +114 +115 +116 +117 +118 +119 +120 +121 +122 +123 +124 +125 +126 +127 +128 +129 +130 +131 +132 +133 +134 +135 +136 +137 +138 +139 +140 +141 +142 +143 +144 +145 +146 +147 +148 +149 +150 +151 +152 +153 +154 +155 +156 +157 +158 +159 +160 +161 +162 +163 +164 +165 +166 +167 +168 +169 +170 +171 +172 +173 +174 +175 +176 +177 +178 +179 +180 +181 +182 +183 +184 +185 +186 +187 +188 +189 +190 +191 +192 +193 +194 +195 +196 +197 +198 +199 +200 +201 +202 +203 +204 +205 +206 +207 +208 +209 +210 +211 +212 +213 +214 +215 +216 +217 +218 +219 +220 +221 +222 +223 +224 +225 +226 +227 +228 +229 +230 +231 +232 +233 +234 +235 +236 +237 +238 +239  +  +  +  +  +  +  +  +  +  +  +  +  +11x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +2x +2x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +12x +12x +12x +15x +  +  +  +  +15x +  +12x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  + 
/**
+ * Phase Router — create, list, get, update, dependencies, bulk create
+ */
+ 
+import { TRPCError } from '@trpc/server';
+import { z } from 'zod';
+import type { Phase } from '../../db/schema.js';
+import type { ProcedureBuilder } from '../trpc.js';
+import { requirePhaseRepository, requireTaskRepository, requireBranchManager, requireInitiativeRepository, requireProjectRepository, requireExecutionOrchestrator } from './_helpers.js';
+import { phaseBranchName } from '../../git/branch-naming.js';
+import { ensureProjectClone } from '../../git/project-clones.js';
+ 
+export function phaseProcedures(publicProcedure: ProcedureBuilder) {
+  return {
+    createPhase: publicProcedure
+      .input(z.object({
+        initiativeId: z.string().min(1),
+        name: z.string().min(1),
+      }))
+      .mutation(async ({ ctx, input }) => {
+        const repo = requirePhaseRepository(ctx);
+        return repo.create({
+          initiativeId: input.initiativeId,
+          name: input.name,
+          status: 'pending',
+        });
+      }),
+ 
+    listPhases: publicProcedure
+      .input(z.object({ initiativeId: z.string().min(1) }))
+      .query(async ({ ctx, input }) => {
+        const repo = requirePhaseRepository(ctx);
+        return repo.findByInitiativeId(input.initiativeId);
+      }),
+ 
+    getPhase: publicProcedure
+      .input(z.object({ id: z.string().min(1) }))
+      .query(async ({ ctx, input }) => {
+        const repo = requirePhaseRepository(ctx);
+        const phase = await repo.findById(input.id);
+        if (!phase) {
+          throw new TRPCError({
+            code: 'NOT_FOUND',
+            message: `Phase '${input.id}' not found`,
+          });
+        }
+        return phase;
+      }),
+ 
+    updatePhase: publicProcedure
+      .input(z.object({
+        id: z.string().min(1),
+        name: z.string().min(1).optional(),
+        content: z.string().nullable().optional(),
+        status: z.enum(['pending', 'approved', 'in_progress', 'completed', 'blocked', 'pending_review']).optional(),
+      }))
+      .mutation(async ({ ctx, input }) => {
+        const repo = requirePhaseRepository(ctx);
+        const { id, ...data } = input;
+        return repo.update(id, data);
+      }),
+ 
+    approvePhase: publicProcedure
+      .input(z.object({ phaseId: z.string().min(1) }))
+      .mutation(async ({ ctx, input }) => {
+        const repo = requirePhaseRepository(ctx);
+        const taskRepo = requireTaskRepository(ctx);
+ 
+        const phase = await repo.findById(input.phaseId);
+        if (!phase) {
+          throw new TRPCError({
+            code: 'NOT_FOUND',
+            message: `Phase '${input.phaseId}' not found`,
+          });
+        }
+        if (phase.status !== 'pending') {
+          throw new TRPCError({
+            code: 'BAD_REQUEST',
+            message: `Phase must be pending to approve (current status: ${phase.status})`,
+          });
+        }
+ 
+        // Validate phase has work tasks (filter out detail tasks)
+        const phaseTasks = await taskRepo.findByPhaseId(input.phaseId);
+        const workTasks = phaseTasks.filter((t) => t.category !== 'detail');
+        if (workTasks.length === 0) {
+          throw new TRPCError({
+            code: 'BAD_REQUEST',
+            message: 'Phase must have tasks before it can be approved',
+          });
+        }
+ 
+        return repo.update(input.phaseId, { status: 'approved' });
+      }),
+ 
+    deletePhase: publicProcedure
+      .input(z.object({ id: z.string().min(1) }))
+      .mutation(async ({ ctx, input }) => {
+        const repo = requirePhaseRepository(ctx);
+        await repo.delete(input.id);
+        return { success: true };
+      }),
+ 
+    createPhasesFromPlan: publicProcedure
+      .input(z.object({
+        initiativeId: z.string().min(1),
+        phases: z.array(z.object({
+          name: z.string().min(1),
+        })),
+      }))
+      .mutation(async ({ ctx, input }) => {
+        const repo = requirePhaseRepository(ctx);
+        const created: Phase[] = [];
+        for (const p of input.phases) {
+          const phase = await repo.create({
+            initiativeId: input.initiativeId,
+            name: p.name,
+            status: 'pending',
+          });
+          created.push(phase);
+        }
+        return created;
+      }),
+ 
+    listInitiativePhaseDependencies: publicProcedure
+      .input(z.object({ initiativeId: z.string().min(1) }))
+      .query(async ({ ctx, input }) => {
+        const repo = requirePhaseRepository(ctx);
+        return repo.findDependenciesByInitiativeId(input.initiativeId);
+      }),
+ 
+    createPhaseDependency: publicProcedure
+      .input(z.object({
+        phaseId: z.string().min(1),
+        dependsOnPhaseId: z.string().min(1),
+      }))
+      .mutation(async ({ ctx, input }) => {
+        const repo = requirePhaseRepository(ctx);
+ 
+        const phase = await repo.findById(input.phaseId);
+        if (!phase) {
+          throw new TRPCError({
+            code: 'NOT_FOUND',
+            message: `Phase '${input.phaseId}' not found`,
+          });
+        }
+ 
+        const dependsOnPhase = await repo.findById(input.dependsOnPhaseId);
+        if (!dependsOnPhase) {
+          throw new TRPCError({
+            code: 'NOT_FOUND',
+            message: `Phase '${input.dependsOnPhaseId}' not found`,
+          });
+        }
+ 
+        await repo.createDependency(input.phaseId, input.dependsOnPhaseId);
+        return { success: true };
+      }),
+ 
+    getPhaseDependencies: publicProcedure
+      .input(z.object({ phaseId: z.string().min(1) }))
+      .query(async ({ ctx, input }) => {
+        const repo = requirePhaseRepository(ctx);
+        const dependencies = await repo.getDependencies(input.phaseId);
+        return { dependencies };
+      }),
+ 
+    getPhaseDependents: publicProcedure
+      .input(z.object({ phaseId: z.string().min(1) }))
+      .query(async ({ ctx, input }) => {
+        const repo = requirePhaseRepository(ctx);
+        const dependents = await repo.getDependents(input.phaseId);
+        return { dependents };
+      }),
+ 
+    removePhaseDependency: publicProcedure
+      .input(z.object({
+        phaseId: z.string().min(1),
+        dependsOnPhaseId: z.string().min(1),
+      }))
+      .mutation(async ({ ctx, input }) => {
+        const repo = requirePhaseRepository(ctx);
+        await repo.removeDependency(input.phaseId, input.dependsOnPhaseId);
+        return { success: true };
+      }),
+ 
+    getPhaseReviewDiff: publicProcedure
+      .input(z.object({ phaseId: z.string().min(1) }))
+      .query(async ({ ctx, input }) => {
+        const phaseRepo = requirePhaseRepository(ctx);
+        const initiativeRepo = requireInitiativeRepository(ctx);
+        const projectRepo = requireProjectRepository(ctx);
+        const branchManager = requireBranchManager(ctx);
+ 
+        const phase = await phaseRepo.findById(input.phaseId);
+        if (!phase) {
+          throw new TRPCError({ code: 'NOT_FOUND', message: `Phase '${input.phaseId}' not found` });
+        }
+        if (phase.status !== 'pending_review') {
+          throw new TRPCError({ code: 'BAD_REQUEST', message: `Phase is not pending review (status: ${phase.status})` });
+        }
+ 
+        const initiative = await initiativeRepo.findById(phase.initiativeId);
+        if (!initiative?.branch) {
+          throw new TRPCError({ code: 'BAD_REQUEST', message: 'Initiative has no branch configured' });
+        }
+ 
+        const initBranch = initiative.branch;
+        const phBranch = phaseBranchName(initBranch, phase.name);
+ 
+        const projects = await projectRepo.findProjectsByInitiativeId(phase.initiativeId);
+        let rawDiff = '';
+ 
+        for (const project of projects) {
+          const clonePath = await ensureProjectClone(project, ctx.workspaceRoot!);
+          const diff = await branchManager.diffBranches(clonePath, initBranch, phBranch);
+          if (diff) {
+            rawDiff += diff + '\n';
+          }
+        }
+ 
+        return {
+          phaseName: phase.name,
+          sourceBranch: phBranch,
+          targetBranch: initBranch,
+          rawDiff,
+        };
+      }),
+ 
+    approvePhaseReview: publicProcedure
+      .input(z.object({ phaseId: z.string().min(1) }))
+      .mutation(async ({ ctx, input }) => {
+        const orchestrator = requireExecutionOrchestrator(ctx);
+        await orchestrator.approveAndMergePhase(input.phaseId);
+        return { success: true };
+      }),
+  };
+}
+ 
+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/coverage/src/trpc/routers/preview.ts.html b/coverage/src/trpc/routers/preview.ts.html new file mode 100644 index 0000000..9c1e873 --- /dev/null +++ b/coverage/src/trpc/routers/preview.ts.html @@ -0,0 +1,238 @@ + + + + + + Code coverage report for src/trpc/routers/preview.ts + + + + + + + + + +
+
+

All files / src/trpc/routers preview.ts

+
+ +
+ 10% + Statements + 1/10 +
+ + +
+ 100% + Branches + 0/0 +
+ + +
+ 20% + Functions + 1/5 +
+ + +
+ 10% + Lines + 1/10 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+

+
1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 +30 +31 +32 +33 +34 +35 +36 +37 +38 +39 +40 +41 +42 +43 +44 +45 +46 +47 +48 +49 +50 +51 +52  +  +  +  +  +  +  +  +  +11x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  + 
/**
+ * Preview Router — start, stop, list, status for Docker-based preview deployments
+ */
+ 
+import { z } from 'zod';
+import type { ProcedureBuilder } from '../trpc.js';
+import { requirePreviewManager } from './_helpers.js';
+ 
+export function previewProcedures(publicProcedure: ProcedureBuilder) {
+  return {
+    startPreview: publicProcedure
+      .input(z.object({
+        initiativeId: z.string().min(1),
+        phaseId: z.string().min(1).optional(),
+        projectId: z.string().min(1),
+        branch: z.string().min(1),
+      }))
+      .mutation(async ({ ctx, input }) => {
+        const previewManager = requirePreviewManager(ctx);
+        return previewManager.start(input);
+      }),
+ 
+    stopPreview: publicProcedure
+      .input(z.object({
+        previewId: z.string().min(1),
+      }))
+      .mutation(async ({ ctx, input }) => {
+        const previewManager = requirePreviewManager(ctx);
+        await previewManager.stop(input.previewId);
+        return { success: true };
+      }),
+ 
+    listPreviews: publicProcedure
+      .input(z.object({
+        initiativeId: z.string().min(1).optional(),
+      }).optional())
+      .query(async ({ ctx, input }) => {
+        const previewManager = requirePreviewManager(ctx);
+        return previewManager.list(input?.initiativeId);
+      }),
+ 
+    getPreviewStatus: publicProcedure
+      .input(z.object({
+        previewId: z.string().min(1),
+      }))
+      .query(async ({ ctx, input }) => {
+        const previewManager = requirePreviewManager(ctx);
+        return previewManager.getStatus(input.previewId);
+      }),
+  };
+}
+ 
+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/coverage/src/trpc/routers/project.ts.html b/coverage/src/trpc/routers/project.ts.html new file mode 100644 index 0000000..c5ea90c --- /dev/null +++ b/coverage/src/trpc/routers/project.ts.html @@ -0,0 +1,556 @@ + + + + + + Code coverage report for src/trpc/routers/project.ts + + + + + + + + + +
+
+

All files / src/trpc/routers project.ts

+
+ +
+ 1.92% + Statements + 1/52 +
+ + +
+ 0% + Branches + 0/29 +
+ + +
+ 10% + Functions + 1/10 +
+ + +
+ 1.92% + Lines + 1/52 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+

+
1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 +30 +31 +32 +33 +34 +35 +36 +37 +38 +39 +40 +41 +42 +43 +44 +45 +46 +47 +48 +49 +50 +51 +52 +53 +54 +55 +56 +57 +58 +59 +60 +61 +62 +63 +64 +65 +66 +67 +68 +69 +70 +71 +72 +73 +74 +75 +76 +77 +78 +79 +80 +81 +82 +83 +84 +85 +86 +87 +88 +89 +90 +91 +92 +93 +94 +95 +96 +97 +98 +99 +100 +101 +102 +103 +104 +105 +106 +107 +108 +109 +110 +111 +112 +113 +114 +115 +116 +117 +118 +119 +120 +121 +122 +123 +124 +125 +126 +127 +128 +129 +130 +131 +132 +133 +134 +135 +136 +137 +138 +139 +140 +141 +142 +143 +144 +145 +146 +147 +148 +149 +150 +151 +152 +153 +154 +155 +156 +157 +158  +  +  +  +  +  +  +  +  +  +  +  +  +  +11x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  + 
/**
+ * Project Router — register, list, get, delete, initiative associations
+ */
+ 
+import { TRPCError } from '@trpc/server';
+import { z } from 'zod';
+import { join } from 'node:path';
+import { rm } from 'node:fs/promises';
+import type { ProcedureBuilder } from '../trpc.js';
+import { requireProjectRepository } from './_helpers.js';
+import { cloneProject } from '../../git/clone.js';
+import { getProjectCloneDir } from '../../git/project-clones.js';
+ 
+export function projectProcedures(publicProcedure: ProcedureBuilder) {
+  return {
+    registerProject: publicProcedure
+      .input(z.object({
+        name: z.string().min(1),
+        url: z.string().min(1),
+        defaultBranch: z.string().min(1).optional(),
+      }))
+      .mutation(async ({ ctx, input }) => {
+        const repo = requireProjectRepository(ctx);
+ 
+        let project;
+        try {
+          project = await repo.create({
+            name: input.name,
+            url: input.url,
+            ...(input.defaultBranch && { defaultBranch: input.defaultBranch }),
+          });
+        } catch (error) {
+          const msg = (error as Error).message;
+          if (msg.includes('UNIQUE') || msg.includes('unique')) {
+            throw new TRPCError({
+              code: 'CONFLICT',
+              message: `A project with that name or URL already exists`,
+            });
+          }
+          throw error;
+        }
+ 
+        if (ctx.workspaceRoot) {
+          const clonePath = join(ctx.workspaceRoot, getProjectCloneDir(input.name, project.id));
+ 
+          try {
+            await cloneProject(input.url, clonePath);
+          } catch (cloneError) {
+            await repo.delete(project.id);
+            throw new TRPCError({
+              code: 'INTERNAL_SERVER_ERROR',
+              message: `Failed to clone repository: ${(cloneError as Error).message}`,
+            });
+          }
+ 
+          // Validate that the specified default branch exists in the cloned repo
+          const branchToValidate = input.defaultBranch ?? 'main';
+          if (ctx.branchManager) {
+            const exists = await ctx.branchManager.remoteBranchExists(clonePath, branchToValidate);
+            if (!exists) {
+              // Clean up: remove project and clone
+              await rm(clonePath, { recursive: true, force: true }).catch(() => {});
+              await repo.delete(project.id);
+              throw new TRPCError({
+                code: 'BAD_REQUEST',
+                message: `Branch '${branchToValidate}' does not exist in the repository`,
+              });
+            }
+          }
+        }
+ 
+        return project;
+      }),
+ 
+    listProjects: publicProcedure
+      .query(async ({ ctx }) => {
+        const repo = requireProjectRepository(ctx);
+        return repo.findAll();
+      }),
+ 
+    getProject: publicProcedure
+      .input(z.object({ id: z.string().min(1) }))
+      .query(async ({ ctx, input }) => {
+        const repo = requireProjectRepository(ctx);
+        const project = await repo.findById(input.id);
+        if (!project) {
+          throw new TRPCError({
+            code: 'NOT_FOUND',
+            message: `Project '${input.id}' not found`,
+          });
+        }
+        return project;
+      }),
+ 
+    deleteProject: publicProcedure
+      .input(z.object({ id: z.string().min(1) }))
+      .mutation(async ({ ctx, input }) => {
+        const repo = requireProjectRepository(ctx);
+        const project = await repo.findById(input.id);
+        if (project && ctx.workspaceRoot) {
+          const clonePath = join(ctx.workspaceRoot, getProjectCloneDir(project.name, project.id));
+          await rm(clonePath, { recursive: true, force: true }).catch(() => {});
+        }
+        await repo.delete(input.id);
+        return { success: true };
+      }),
+ 
+    updateProject: publicProcedure
+      .input(z.object({
+        id: z.string().min(1),
+        defaultBranch: z.string().min(1).optional(),
+      }))
+      .mutation(async ({ ctx, input }) => {
+        const repo = requireProjectRepository(ctx);
+        const { id, ...data } = input;
+        const existing = await repo.findById(id);
+        if (!existing) {
+          throw new TRPCError({
+            code: 'NOT_FOUND',
+            message: `Project '${id}' not found`,
+          });
+        }
+ 
+        // Validate that the new default branch exists in the repo
+        if (data.defaultBranch && ctx.workspaceRoot && ctx.branchManager) {
+          const clonePath = join(ctx.workspaceRoot, getProjectCloneDir(existing.name, existing.id));
+          const exists = await ctx.branchManager.remoteBranchExists(clonePath, data.defaultBranch);
+          if (!exists) {
+            throw new TRPCError({
+              code: 'BAD_REQUEST',
+              message: `Branch '${data.defaultBranch}' does not exist in the repository`,
+            });
+          }
+        }
+ 
+        return repo.update(id, data);
+      }),
+ 
+    getInitiativeProjects: publicProcedure
+      .input(z.object({ initiativeId: z.string().min(1) }))
+      .query(async ({ ctx, input }) => {
+        const repo = requireProjectRepository(ctx);
+        return repo.findProjectsByInitiativeId(input.initiativeId);
+      }),
+ 
+    updateInitiativeProjects: publicProcedure
+      .input(z.object({
+        initiativeId: z.string().min(1),
+        projectIds: z.array(z.string().min(1)).min(1),
+      }))
+      .mutation(async ({ ctx, input }) => {
+        const repo = requireProjectRepository(ctx);
+        await repo.setInitiativeProjects(input.initiativeId, input.projectIds);
+        return { success: true };
+      }),
+  };
+}
+ 
+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/coverage/src/trpc/routers/subscription.ts.html b/coverage/src/trpc/routers/subscription.ts.html new file mode 100644 index 0000000..623dda7 --- /dev/null +++ b/coverage/src/trpc/routers/subscription.ts.html @@ -0,0 +1,220 @@ + + + + + + Code coverage report for src/trpc/routers/subscription.ts + + + + + + + + + +
+
+

All files / src/trpc/routers subscription.ts

+
+ +
+ 11.11% + Statements + 1/9 +
+ + +
+ 0% + Branches + 0/8 +
+ + +
+ 20% + Functions + 1/5 +
+ + +
+ 11.11% + Lines + 1/9 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+

+
1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 +30 +31 +32 +33 +34 +35 +36 +37 +38 +39 +40 +41 +42 +43 +44 +45 +46  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +11x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  + 
/**
+ * Subscription Router — SSE event streams
+ */
+ 
+import { z } from 'zod';
+import type { ProcedureBuilder } from '../trpc.js';
+import {
+  eventBusIterable,
+  ALL_EVENT_TYPES,
+  AGENT_EVENT_TYPES,
+  TASK_EVENT_TYPES,
+  PAGE_EVENT_TYPES,
+} from '../subscriptions.js';
+ 
+export function subscriptionProcedures(publicProcedure: ProcedureBuilder) {
+  return {
+    onEvent: publicProcedure
+      .input(z.object({ lastEventId: z.string().nullish() }).optional())
+      .subscription(async function* (opts) {
+        const signal = opts.signal ?? new AbortController().signal;
+        yield* eventBusIterable(opts.ctx.eventBus, ALL_EVENT_TYPES, signal);
+      }),
+ 
+    onAgentUpdate: publicProcedure
+      .input(z.object({ lastEventId: z.string().nullish() }).optional())
+      .subscription(async function* (opts) {
+        const signal = opts.signal ?? new AbortController().signal;
+        yield* eventBusIterable(opts.ctx.eventBus, AGENT_EVENT_TYPES, signal);
+      }),
+ 
+    onTaskUpdate: publicProcedure
+      .input(z.object({ lastEventId: z.string().nullish() }).optional())
+      .subscription(async function* (opts) {
+        const signal = opts.signal ?? new AbortController().signal;
+        yield* eventBusIterable(opts.ctx.eventBus, TASK_EVENT_TYPES, signal);
+      }),
+ 
+    onPageUpdate: publicProcedure
+      .input(z.object({ lastEventId: z.string().nullish() }).optional())
+      .subscription(async function* (opts) {
+        const signal = opts.signal ?? new AbortController().signal;
+        yield* eventBusIterable(opts.ctx.eventBus, PAGE_EVENT_TYPES, signal);
+      }),
+  };
+}
+ 
+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/coverage/src/trpc/routers/system.ts.html b/coverage/src/trpc/routers/system.ts.html new file mode 100644 index 0000000..57e2d56 --- /dev/null +++ b/coverage/src/trpc/routers/system.ts.html @@ -0,0 +1,415 @@ + + + + + + Code coverage report for src/trpc/routers/system.ts + + + + + + + + + +
+
+

All files / src/trpc/routers system.ts

+
+ +
+ 30.76% + Statements + 8/26 +
+ + +
+ 37.5% + Branches + 6/16 +
+ + +
+ 50% + Functions + 3/6 +
+ + +
+ 34.78% + Lines + 8/23 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+

+
1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 +30 +31 +32 +33 +34 +35 +36 +37 +38 +39 +40 +41 +42 +43 +44 +45 +46 +47 +48 +49 +50 +51 +52 +53 +54 +55 +56 +57 +58 +59 +60 +61 +62 +63 +64 +65 +66 +67 +68 +69 +70 +71 +72 +73 +74 +75 +76 +77 +78 +79 +80 +81 +82 +83 +84 +85 +86 +87 +88 +89 +90 +91 +92 +93 +94 +95 +96 +97 +98 +99 +100 +101 +102 +103 +104 +105 +106 +107 +108 +109 +110 +111  +  +  +  +  +  +  +  +  +  +  +  +11x +  +  +  +  +  +  +  +11x +  +  +  +  +  +  +  +  +  +11x +  +  +  +  +  +  +  +  +  +  +  +11x +  +  +  +9x +  +  +  +9x +  +  +  +  +  +  +  +  +  +10x +  +  +  +10x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  + 
/**
+ * System Router — health, status, systemHealthCheck
+ */
+ 
+import { z } from 'zod';
+import { join } from 'node:path';
+import { access } from 'node:fs/promises';
+import type { ProcedureBuilder } from '../trpc.js';
+import { requireAccountRepository, requireProjectRepository } from './_helpers.js';
+import { checkAccountHealth } from '../../agent/accounts/usage.js';
+import { getProjectCloneDir } from '../../git/project-clones.js';
+ 
+export const healthResponseSchema = z.object({
+  status: z.literal('ok'),
+  uptime: z.number().int().nonnegative(),
+  processCount: z.number().int().nonnegative(),
+});
+ 
+export type HealthResponse = z.infer<typeof healthResponseSchema>;
+ 
+export const processInfoSchema = z.object({
+  id: z.string(),
+  pid: z.number().int().positive(),
+  command: z.string(),
+  status: z.string(),
+  startedAt: z.string(),
+});
+ 
+export type ProcessInfo = z.infer<typeof processInfoSchema>;
+ 
+export const statusResponseSchema = z.object({
+  server: z.object({
+    startedAt: z.string(),
+    uptime: z.number().int().nonnegative(),
+    pid: z.number().int().positive(),
+  }),
+  processes: z.array(processInfoSchema),
+});
+ 
+export type StatusResponse = z.infer<typeof statusResponseSchema>;
+ 
+export function systemProcedures(publicProcedure: ProcedureBuilder) {
+  return {
+    health: publicProcedure
+      .output(healthResponseSchema)
+      .query(({ ctx }): HealthResponse => {
+        const uptime = ctx.serverStartedAt
+          ? Math.floor((Date.now() - ctx.serverStartedAt.getTime()) / 1000)
+          : 0;
+ 
+        return {
+          status: 'ok',
+          uptime,
+          processCount: ctx.processCount,
+        };
+      }),
+ 
+    status: publicProcedure
+      .output(statusResponseSchema)
+      .query(({ ctx }): StatusResponse => {
+        const uptime = ctx.serverStartedAt
+          ? Math.floor((Date.now() - ctx.serverStartedAt.getTime()) / 1000)
+          : 0;
+ 
+        return {
+          server: {
+            startedAt: ctx.serverStartedAt?.toISOString() ?? '',
+            uptime,
+            pid: process.pid,
+          },
+          processes: [],
+        };
+      }),
+ 
+    systemHealthCheck: publicProcedure
+      .query(async ({ ctx }) => {
+        const uptime = ctx.serverStartedAt
+          ? Math.floor((Date.now() - ctx.serverStartedAt.getTime()) / 1000)
+          : 0;
+ 
+        const accountRepo = requireAccountRepository(ctx);
+        const allAccounts = await accountRepo.findAll();
+        const allAgents = ctx.agentManager ? await ctx.agentManager.list() : [];
+ 
+        const accounts = await Promise.all(
+          allAccounts.map(account => checkAccountHealth(account, allAgents, ctx.credentialManager, ctx.workspaceRoot ?? undefined))
+        );
+ 
+        const projectRepo = requireProjectRepository(ctx);
+        const allProjects = await projectRepo.findAll();
+ 
+        const projects = await Promise.all(
+          allProjects.map(async project => {
+            let repoExists = false;
+            if (ctx.workspaceRoot) {
+              const clonePath = join(ctx.workspaceRoot, getProjectCloneDir(project.name, project.id));
+              try { await access(clonePath); repoExists = true; } catch { repoExists = false; }
+            }
+            return { id: project.id, name: project.name, url: project.url, repoExists };
+          })
+        );
+ 
+        return {
+          server: { status: 'ok' as const, uptime, startedAt: ctx.serverStartedAt?.toISOString() ?? null },
+          accounts,
+          projects,
+        };
+      }),
+  };
+}
+ 
+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/coverage/src/trpc/routers/task.ts.html b/coverage/src/trpc/routers/task.ts.html new file mode 100644 index 0000000..ac6b9c9 --- /dev/null +++ b/coverage/src/trpc/routers/task.ts.html @@ -0,0 +1,571 @@ + + + + + + Code coverage report for src/trpc/routers/task.ts + + + + + + + + + +
+
+

All files / src/trpc/routers task.ts

+
+ +
+ 19.51% + Statements + 8/41 +
+ + +
+ 25% + Branches + 6/24 +
+ + +
+ 23.07% + Functions + 3/13 +
+ + +
+ 20.51% + Lines + 8/39 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+

+
1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 +30 +31 +32 +33 +34 +35 +36 +37 +38 +39 +40 +41 +42 +43 +44 +45 +46 +47 +48 +49 +50 +51 +52 +53 +54 +55 +56 +57 +58 +59 +60 +61 +62 +63 +64 +65 +66 +67 +68 +69 +70 +71 +72 +73 +74 +75 +76 +77 +78 +79 +80 +81 +82 +83 +84 +85 +86 +87 +88 +89 +90 +91 +92 +93 +94 +95 +96 +97 +98 +99 +100 +101 +102 +103 +104 +105 +106 +107 +108 +109 +110 +111 +112 +113 +114 +115 +116 +117 +118 +119 +120 +121 +122 +123 +124 +125 +126 +127 +128 +129 +130 +131 +132 +133 +134 +135 +136 +137 +138 +139 +140 +141 +142 +143 +144 +145 +146 +147 +148 +149 +150 +151 +152 +153 +154 +155 +156 +157 +158 +159 +160 +161 +162 +163  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +11x +  +  +  +4x +4x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +7x +7x +  +7x +7x +  +  +  +  +  +  +7x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  + 
/**
+ * Task Router — CRUD, approval, listing by parent/initiative/phase
+ */
+ 
+import { TRPCError } from '@trpc/server';
+import { z } from 'zod';
+import type { ProcedureBuilder } from '../trpc.js';
+import {
+  requireTaskRepository,
+  requireInitiativeRepository,
+  requirePhaseRepository,
+  requireDispatchManager,
+} from './_helpers.js';
+ 
+export function taskProcedures(publicProcedure: ProcedureBuilder) {
+  return {
+    listTasks: publicProcedure
+      .input(z.object({ parentTaskId: z.string().min(1) }))
+      .query(async ({ ctx, input }) => {
+        const taskRepository = requireTaskRepository(ctx);
+        return taskRepository.findByParentTaskId(input.parentTaskId);
+      }),
+ 
+    getTask: publicProcedure
+      .input(z.object({ id: z.string().min(1) }))
+      .query(async ({ ctx, input }) => {
+        const taskRepository = requireTaskRepository(ctx);
+        const task = await taskRepository.findById(input.id);
+        if (!task) {
+          throw new TRPCError({
+            code: 'NOT_FOUND',
+            message: `Task '${input.id}' not found`,
+          });
+        }
+        return task;
+      }),
+ 
+    updateTaskStatus: publicProcedure
+      .input(z.object({
+        id: z.string().min(1),
+        status: z.enum(['pending_approval', 'pending', 'in_progress', 'completed', 'blocked']),
+      }))
+      .mutation(async ({ ctx, input }) => {
+        const taskRepository = requireTaskRepository(ctx);
+        const existing = await taskRepository.findById(input.id);
+        if (!existing) {
+          throw new TRPCError({
+            code: 'NOT_FOUND',
+            message: `Task '${input.id}' not found`,
+          });
+        }
+        return taskRepository.update(input.id, { status: input.status });
+      }),
+ 
+    createInitiativeTask: publicProcedure
+      .input(z.object({
+        initiativeId: z.string().min(1),
+        name: z.string().min(1),
+        description: z.string().optional(),
+        category: z.enum(['execute', 'research', 'discuss', 'plan', 'detail', 'refine', 'verify', 'merge', 'review']).optional(),
+        type: z.enum(['auto', 'checkpoint:human-verify', 'checkpoint:decision', 'checkpoint:human-action']).optional(),
+        requiresApproval: z.boolean().nullable().optional(),
+      }))
+      .mutation(async ({ ctx, input }) => {
+        const taskRepository = requireTaskRepository(ctx);
+        const initiativeRepo = requireInitiativeRepository(ctx);
+ 
+        const initiative = await initiativeRepo.findById(input.initiativeId);
+        if (!initiative) {
+          throw new TRPCError({
+            code: 'NOT_FOUND',
+            message: `Initiative '${input.initiativeId}' not found`,
+          });
+        }
+ 
+        return taskRepository.create({
+          initiativeId: input.initiativeId,
+          name: input.name,
+          description: input.description ?? null,
+          category: input.category ?? 'execute',
+          type: input.type ?? 'auto',
+          requiresApproval: input.requiresApproval ?? null,
+          status: 'pending',
+        });
+      }),
+ 
+    createPhaseTask: publicProcedure
+      .input(z.object({
+        phaseId: z.string().min(1),
+        name: z.string().min(1),
+        description: z.string().optional(),
+        category: z.enum(['execute', 'research', 'discuss', 'plan', 'detail', 'refine', 'verify', 'merge', 'review']).optional(),
+        type: z.enum(['auto', 'checkpoint:human-verify', 'checkpoint:decision', 'checkpoint:human-action']).optional(),
+        requiresApproval: z.boolean().nullable().optional(),
+      }))
+      .mutation(async ({ ctx, input }) => {
+        const taskRepository = requireTaskRepository(ctx);
+        const phaseRepo = requirePhaseRepository(ctx);
+ 
+        const phase = await phaseRepo.findById(input.phaseId);
+        Iif (!phase) {
+          throw new TRPCError({
+            code: 'NOT_FOUND',
+            message: `Phase '${input.phaseId}' not found`,
+          });
+        }
+ 
+        return taskRepository.create({
+          phaseId: input.phaseId,
+          name: input.name,
+          description: input.description ?? null,
+          category: input.category ?? 'execute',
+          type: input.type ?? 'auto',
+          requiresApproval: input.requiresApproval ?? null,
+          status: 'pending',
+        });
+      }),
+ 
+    listPendingApprovals: publicProcedure
+      .input(z.object({
+        initiativeId: z.string().optional(),
+        phaseId: z.string().optional(),
+        category: z.enum(['execute', 'research', 'discuss', 'plan', 'detail', 'refine', 'verify', 'merge', 'review']).optional(),
+      }).optional())
+      .query(async ({ ctx, input }) => {
+        const taskRepository = requireTaskRepository(ctx);
+        return taskRepository.findPendingApproval(input);
+      }),
+ 
+    listInitiativeTasks: publicProcedure
+      .input(z.object({ initiativeId: z.string().min(1) }))
+      .query(async ({ ctx, input }) => {
+        const taskRepository = requireTaskRepository(ctx);
+        const tasks = await taskRepository.findByInitiativeId(input.initiativeId);
+        return tasks.filter((t) => t.category !== 'detail');
+      }),
+ 
+    listPhaseTasks: publicProcedure
+      .input(z.object({ phaseId: z.string().min(1) }))
+      .query(async ({ ctx, input }) => {
+        const taskRepository = requireTaskRepository(ctx);
+        const tasks = await taskRepository.findByPhaseId(input.phaseId);
+        return tasks.filter((t) => t.category !== 'detail');
+      }),
+ 
+    deleteTask: publicProcedure
+      .input(z.object({ id: z.string().min(1) }))
+      .mutation(async ({ ctx, input }) => {
+        const taskRepository = requireTaskRepository(ctx);
+        await taskRepository.delete(input.id);
+        return { success: true };
+      }),
+ 
+    approveTask: publicProcedure
+      .input(z.object({ taskId: z.string().min(1) }))
+      .mutation(async ({ ctx, input }) => {
+        const dispatchManager = requireDispatchManager(ctx);
+        await dispatchManager.approveTask(input.taskId);
+        return { success: true };
+      }),
+  };
+}
+ 
+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/coverage/src/trpc/subscriptions.ts.html b/coverage/src/trpc/subscriptions.ts.html new file mode 100644 index 0000000..31e6bbc --- /dev/null +++ b/coverage/src/trpc/subscriptions.ts.html @@ -0,0 +1,739 @@ + + + + + + Code coverage report for src/trpc/subscriptions.ts + + + + + + + + + +
+
+

All files / src/trpc subscriptions.ts

+
+ +
+ 15.9% + Statements + 7/44 +
+ + +
+ 0% + Branches + 0/10 +
+ + +
+ 0% + Functions + 0/7 +
+ + +
+ 16.66% + Lines + 7/42 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+

+
1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 +30 +31 +32 +33 +34 +35 +36 +37 +38 +39 +40 +41 +42 +43 +44 +45 +46 +47 +48 +49 +50 +51 +52 +53 +54 +55 +56 +57 +58 +59 +60 +61 +62 +63 +64 +65 +66 +67 +68 +69 +70 +71 +72 +73 +74 +75 +76 +77 +78 +79 +80 +81 +82 +83 +84 +85 +86 +87 +88 +89 +90 +91 +92 +93 +94 +95 +96 +97 +98 +99 +100 +101 +102 +103 +104 +105 +106 +107 +108 +109 +110 +111 +112 +113 +114 +115 +116 +117 +118 +119 +120 +121 +122 +123 +124 +125 +126 +127 +128 +129 +130 +131 +132 +133 +134 +135 +136 +137 +138 +139 +140 +141 +142 +143 +144 +145 +146 +147 +148 +149 +150 +151 +152 +153 +154 +155 +156 +157 +158 +159 +160 +161 +162 +163 +164 +165 +166 +167 +168 +169 +170 +171 +172 +173 +174 +175 +176 +177 +178 +179 +180 +181 +182 +183 +184 +185 +186 +187 +188 +189 +190 +191 +192 +193 +194 +195 +196 +197 +198 +199 +200 +201 +202 +203 +204 +205 +206 +207 +208 +209 +210 +211 +212 +213 +214 +215 +216 +217 +218 +219  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +11x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +11x +  +  +  +  +  +  +  +  +  +  +  +  +  +11x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +11x +  +  +  +  +  +  +11x +  +  +11x +  +  +11x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  + 
/**
+ * tRPC Subscription Helpers
+ *
+ * Bridges EventBus domain events into tRPC async generator subscriptions.
+ * Uses a queue-based approach: EventBus handlers push events into a queue,
+ * the async generator yields from the queue, and waits on a promise when empty.
+ */
+ 
+import { tracked, type TrackedEnvelope } from '@trpc/server';
+import type { EventBus, DomainEvent, DomainEventType } from '../events/types.js';
+ 
+/**
+ * Shape of events yielded by subscription procedures.
+ */
+export interface SubscriptionEventData {
+  id: string;
+  type: string;
+  payload: unknown;
+  timestamp: string;
+}
+ 
+/**
+ * All domain event types in the system.
+ */
+export const ALL_EVENT_TYPES: DomainEventType[] = [
+  'process:spawned',
+  'process:stopped',
+  'process:crashed',
+  'server:started',
+  'server:stopped',
+  'log:entry',
+  'worktree:created',
+  'worktree:removed',
+  'worktree:merged',
+  'worktree:conflict',
+  'agent:spawned',
+  'agent:stopped',
+  'agent:crashed',
+  'agent:resumed',
+  'agent:account_switched',
+  'agent:deleted',
+  'agent:waiting',
+  'agent:output',
+  'task:queued',
+  'task:dispatched',
+  'task:completed',
+  'task:blocked',
+  'phase:queued',
+  'phase:started',
+  'phase:completed',
+  'phase:blocked',
+  'phase:pending_review',
+  'phase:merged',
+  'task:merged',
+  'merge:queued',
+  'merge:started',
+  'merge:completed',
+  'merge:conflicted',
+  'page:created',
+  'page:updated',
+  'page:deleted',
+  'changeset:created',
+  'changeset:reverted',
+  'conversation:created',
+  'conversation:answered',
+];
+ 
+/**
+ * Agent-specific event types.
+ */
+export const AGENT_EVENT_TYPES: DomainEventType[] = [
+  'agent:spawned',
+  'agent:stopped',
+  'agent:crashed',
+  'agent:resumed',
+  'agent:account_switched',
+  'agent:deleted',
+  'agent:waiting',
+  'agent:output',
+];
+ 
+/**
+ * Task and phase event types.
+ */
+export const TASK_EVENT_TYPES: DomainEventType[] = [
+  'task:queued',
+  'task:dispatched',
+  'task:completed',
+  'task:blocked',
+  'task:merged',
+  'phase:queued',
+  'phase:started',
+  'phase:completed',
+  'phase:blocked',
+  'phase:pending_review',
+  'phase:merged',
+];
+ 
+/**
+ * Page event types.
+ */
+export const PAGE_EVENT_TYPES: DomainEventType[] = [
+  'page:created',
+  'page:updated',
+  'page:deleted',
+];
+ 
+/** Counter for generating unique event IDs */
+let eventCounter = 0;
+ 
+/** Drop oldest events when the queue exceeds this size */
+const MAX_QUEUE_SIZE = 1000;
+ 
+/** Yield a synthetic heartbeat after this many ms of silence */
+const HEARTBEAT_INTERVAL_MS = 30_000;
+ 
+/**
+ * Creates an async generator that bridges EventBus events into a pull-based stream.
+ *
+ * Uses a queue + deferred promise pattern:
+ * - EventBus handlers push events into a queue array
+ * - The async generator yields from the queue
+ * - When the queue is empty, it waits on a promise that resolves when the next event arrives
+ * - Cleans up handlers on AbortSignal abort
+ *
+ * Bounded queue: events beyond MAX_QUEUE_SIZE are dropped (oldest first).
+ * Heartbeat: a synthetic `__heartbeat__` event is yielded when no real events
+ * arrive within HEARTBEAT_INTERVAL_MS, allowing clients to detect silent disconnects.
+ *
+ * Each yielded event is wrapped with `tracked(id, data)` to enable client-side reconnection.
+ *
+ * @param eventBus - The EventBus to subscribe to
+ * @param eventTypes - Array of event type strings to listen for
+ * @param signal - AbortSignal to cancel the subscription
+ */
+export async function* eventBusIterable(
+  eventBus: EventBus,
+  eventTypes: DomainEventType[],
+  signal: AbortSignal,
+): AsyncGenerator<TrackedEnvelope<SubscriptionEventData>> {
+  const queue: DomainEvent[] = [];
+  let resolve: (() => void) | null = null;
+ 
+  // Handler that pushes events into the queue and resolves the waiter
+  const handler = (event: DomainEvent) => {
+    queue.push(event);
+    // Drop oldest when queue overflows
+    while (queue.length > MAX_QUEUE_SIZE) {
+      queue.shift();
+    }
+    if (resolve) {
+      const r = resolve;
+      resolve = null;
+      r();
+    }
+  };
+ 
+  // Subscribe to all requested event types
+  for (const eventType of eventTypes) {
+    eventBus.on(eventType as DomainEvent['type'], handler);
+  }
+ 
+  // Cleanup function
+  const cleanup = () => {
+    for (const eventType of eventTypes) {
+      eventBus.off(eventType as DomainEvent['type'], handler);
+    }
+    // Resolve any pending waiter so the generator can exit
+    if (resolve) {
+      const r = resolve;
+      resolve = null;
+      r();
+    }
+  };
+ 
+  // Clean up when the client disconnects
+  signal.addEventListener('abort', cleanup, { once: true });
+ 
+  try {
+    while (!signal.aborted) {
+      // Drain the queue
+      while (queue.length > 0) {
+        const event = queue.shift()!;
+        const id = `${Date.now()}-${eventCounter++}`;
+        const data: SubscriptionEventData = {
+          id,
+          type: event.type,
+          payload: event.payload,
+          timestamp: event.timestamp.toISOString(),
+        };
+        yield tracked(id, data);
+      }
+ 
+      // Wait for the next event, abort, or heartbeat timeout
+      if (!signal.aborted) {
+        const gotEvent = await Promise.race([
+          new Promise<true>((r) => {
+            resolve = () => r(true);
+          }),
+          new Promise<false>((r) => setTimeout(() => r(false), HEARTBEAT_INTERVAL_MS)),
+        ]);
+ 
+        if (!gotEvent && !signal.aborted) {
+          // No real event arrived — yield heartbeat
+          const id = `${Date.now()}-${eventCounter++}`;
+          yield tracked(id, {
+            id,
+            type: '__heartbeat__',
+            payload: null,
+            timestamp: new Date().toISOString(),
+          });
+        }
+      }
+    }
+  } finally {
+    cleanup();
+  }
+}
+ 
+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/coverage/src/trpc/trpc.ts.html b/coverage/src/trpc/trpc.ts.html new file mode 100644 index 0000000..f851bc9 --- /dev/null +++ b/coverage/src/trpc/trpc.ts.html @@ -0,0 +1,139 @@ + + + + + + Code coverage report for src/trpc/trpc.ts + + + + + + + + + +
+
+

All files / src/trpc trpc.ts

+
+ +
+ 100% + Statements + 5/5 +
+ + +
+ 100% + Branches + 0/0 +
+ + +
+ 100% + Functions + 0/0 +
+ + +
+ 100% + Lines + 5/5 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+

+
1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19  +  +  +  +  +  +  +  +  +  +12x +  +12x +12x +12x +12x +  +  + 
/**
+ * tRPC Initialization
+ *
+ * Extracted from router.ts to break circular dependencies.
+ * All domain routers import from here instead of router.ts.
+ */
+ 
+import { initTRPC } from '@trpc/server';
+import type { TRPCContext } from './context.js';
+ 
+const t = initTRPC.context<TRPCContext>().create();
+ 
+export const router = t.router;
+export const publicProcedure = t.procedure;
+export const middleware = t.middleware;
+export const createCallerFactory = t.createCallerFactory;
+ 
+export type ProcedureBuilder = typeof t.procedure;
+ 
+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/docs/agent.md b/docs/agent.md index 6113992..5d120da 100644 --- a/docs/agent.md +++ b/docs/agent.md @@ -1,6 +1,6 @@ # Agent Module -`src/agent/` — Agent lifecycle management, output parsing, multi-provider support, and account failover. +`apps/server/agent/` — Agent lifecycle management, output parsing, multi-provider support, and account failover. ## File Inventory @@ -169,7 +169,7 @@ Agents can communicate with each other via the `conversations` table, coordinate ## Prompt Architecture -Mode-specific prompts in `prompts/` use XML tags as top-level structural delimiters, with markdown formatting inside tags. This separates first-order instructions from second-order content (task descriptions, examples, templates) per Anthropic best practices. The old `src/agent/prompts.ts` (flat markdown) has been deleted. +Mode-specific prompts in `prompts/` use XML tags as top-level structural delimiters, with markdown formatting inside tags. This separates first-order instructions from second-order content (task descriptions, examples, templates) per Anthropic best practices. The old `apps/server/agent/prompts.ts` (flat markdown) has been deleted. ### XML Tag Structure @@ -217,4 +217,4 @@ Examples within mode-specific tags use `` > `` / ### Execute Prompt Dispatch -`buildExecutePrompt(taskDescription?)` accepts an optional task description wrapped in a `` tag. The dispatch manager (`src/dispatch/manager.ts`) wraps `task.description || task.name` in `buildExecutePrompt()` so execute agents receive full system context alongside their task. The `` and `` blocks are appended by the agent manager at spawn time. +`buildExecutePrompt(taskDescription?)` accepts an optional task description wrapped in a `` tag. The dispatch manager (`apps/server/dispatch/manager.ts`) wraps `task.description || task.name` in `buildExecutePrompt()` so execute agents receive full system context alongside their task. The `` and `` blocks are appended by the agent manager at spawn time. diff --git a/docs/architecture.md b/docs/architecture.md index cd0ed0f..c77ed22 100644 --- a/docs/architecture.md +++ b/docs/architecture.md @@ -23,7 +23,7 @@ CLI (cw) ├── CoordinationManager (merge queue, conflict resolution) └── PreviewManager (Docker-based preview deployments) -Web UI (packages/web/) +Web UI (apps/web/) └── React 19 + TanStack Router + tRPC React Query ├── Initiative management (CRUD, projects) ├── Page editor (Tiptap rich text) @@ -36,9 +36,9 @@ Web UI (packages/web/) ### Hexagonal Architecture (Ports & Adapters) Every data-access layer follows this pattern: -- **Port** (interface): `src/db/repositories/-repository.ts` -- **Adapter** (implementation): `src/db/repositories/drizzle/-repository.ts` -- Re-exported from barrel files so consumers import from `src/db/` +- **Port** (interface): `apps/server/db/repositories/-repository.ts` +- **Adapter** (implementation): `apps/server/db/repositories/drizzle/-repository.ts` +- Re-exported from barrel files so consumers import from `apps/server/db/` ### Event-Driven Communication All inter-module communication flows through a typed `EventBus`: @@ -55,20 +55,20 @@ Agent providers (Claude, Codex, etc.) are defined as configuration objects, not | Module | Path | Purpose | Docs | |--------|------|---------|------| -| Agent | `src/agent/` | Agent lifecycle, output parsing, accounts | [agent.md](agent.md) | -| Database | `src/db/` | Schema, repositories, migrations | [database.md](database.md) | -| Server & API | `src/server/`, `src/trpc/` | HTTP server, tRPC procedures | [server-api.md](server-api.md) | -| Frontend | `packages/web/` | React UI, components, hooks | [frontend.md](frontend.md) | -| CLI & Config | `src/cli/`, `src/config/` | CLI commands, workspace config | [cli-config.md](cli-config.md) | -| Dispatch | `src/dispatch/` | Task/phase queue and dispatch | [dispatch-events.md](dispatch-events.md) | -| Coordination | `src/coordination/` | Merge queue, conflict resolution | [server-api.md](server-api.md#coordination) | -| Git | `src/git/` | Worktree management, project clones | [git-process-logging.md](git-process-logging.md) | -| Process | `src/process/` | Child process spawn/track/stop | [git-process-logging.md](git-process-logging.md) | -| Logging | `src/logger/`, `src/logging/` | Structured logging, file capture | [git-process-logging.md](git-process-logging.md) | -| Events | `src/events/` | EventBus, typed event system | [dispatch-events.md](dispatch-events.md) | +| Agent | `apps/server/agent/` | Agent lifecycle, output parsing, accounts | [agent.md](agent.md) | +| Database | `apps/server/db/` | Schema, repositories, migrations | [database.md](database.md) | +| Server & API | `apps/server/server/`, `apps/server/trpc/` | HTTP server, tRPC procedures | [server-api.md](server-api.md) | +| Frontend | `apps/web/` | React UI, components, hooks | [frontend.md](frontend.md) | +| CLI & Config | `apps/server/cli/`, `apps/server/config/` | CLI commands, workspace config | [cli-config.md](cli-config.md) | +| Dispatch | `apps/server/dispatch/` | Task/phase queue and dispatch | [dispatch-events.md](dispatch-events.md) | +| Coordination | `apps/server/coordination/` | Merge queue, conflict resolution | [server-api.md](server-api.md#coordination) | +| Git | `apps/server/git/` | Worktree management, project clones | [git-process-logging.md](git-process-logging.md) | +| Process | `apps/server/process/` | Child process spawn/track/stop | [git-process-logging.md](git-process-logging.md) | +| Logging | `apps/server/logger/`, `apps/server/logging/` | Structured logging, file capture | [git-process-logging.md](git-process-logging.md) | +| Events | `apps/server/events/` | EventBus, typed event system | [dispatch-events.md](dispatch-events.md) | | Shared | `packages/shared/` | Types shared between frontend/backend | [frontend.md](frontend.md) | -| Preview | `src/preview/` | Docker-based preview deployments | [preview.md](preview.md) | -| Tests | `src/test/` | E2E, integration, fixtures | [testing.md](testing.md) | +| Preview | `apps/server/preview/` | Docker-based preview deployments | [preview.md](preview.md) | +| Tests | `apps/server/test/` | E2E, integration, fixtures | [testing.md](testing.md) | ## Entity Relationships diff --git a/docs/cli-config.md b/docs/cli-config.md index 22fc68b..1de3be7 100644 --- a/docs/cli-config.md +++ b/docs/cli-config.md @@ -1,10 +1,10 @@ # CLI & Configuration -`src/cli/` — CLI commands, `src/config/` — workspace configuration, `src/bin/` — entry point. +`apps/server/cli/` — CLI commands, `apps/server/config/` — workspace configuration, `apps/server/bin/` — entry point. ## Entry Point -`src/bin/cw.ts` — hashbang entry that imports and runs the CLI. +`apps/server/bin/cw.ts` — hashbang entry that imports and runs the CLI. ## CLI Framework @@ -136,7 +136,7 @@ This includes all repositories, managers, and the credential manager. The server ## Workspace Configuration -`src/config/` module: +`apps/server/config/` module: ### .cwrc File JSON file at workspace root that marks a `cw` workspace: diff --git a/docs/database-migrations.md b/docs/database-migrations.md index 30d00a3..9b47735 100644 --- a/docs/database-migrations.md +++ b/docs/database-migrations.md @@ -4,10 +4,10 @@ This project uses [drizzle-kit](https://orm.drizzle.team/kit-docs/overview) for ## Overview -- **Schema definition:** `src/db/schema.ts` (drizzle-orm table definitions) +- **Schema definition:** `apps/server/db/schema.ts` (drizzle-orm table definitions) - **Migration output:** `drizzle/` directory (SQL files + meta journal) - **Config:** `drizzle.config.ts` -- **Runtime migrator:** `src/db/ensure-schema.ts` (calls `drizzle-orm/better-sqlite3/migrator`) +- **Runtime migrator:** `apps/server/db/ensure-schema.ts` (calls `drizzle-orm/better-sqlite3/migrator`) ## How It Works @@ -17,7 +17,7 @@ On every server startup, `ensureSchema(db)` runs all pending migrations from the ### Making schema changes -1. Edit `src/db/schema.ts` with your table/column changes +1. Edit `apps/server/db/schema.ts` with your table/column changes 2. Generate a migration: ```bash npx drizzle-kit generate @@ -29,7 +29,7 @@ On every server startup, `ensureSchema(db)` runs all pending migrations from the Migrations are applied automatically on server startup. No manual step needed. -For tests, the same `ensureSchema()` function is called on in-memory SQLite databases in `src/db/repositories/drizzle/test-helpers.ts`. +For tests, the same `ensureSchema()` function is called on in-memory SQLite databases in `apps/server/db/repositories/drizzle/test-helpers.ts`. ### Checking migration status diff --git a/docs/database.md b/docs/database.md index e3d7307..ad29c3b 100644 --- a/docs/database.md +++ b/docs/database.md @@ -1,13 +1,13 @@ # Database Module -`src/db/` — SQLite database via better-sqlite3 + Drizzle ORM with hexagonal architecture. +`apps/server/db/` — SQLite database via better-sqlite3 + Drizzle ORM with hexagonal architecture. ## Architecture -- **Schema**: `src/db/schema.ts` — all tables, columns, relations -- **Ports** (interfaces): `src/db/repositories/*.ts` — 10 repository interfaces -- **Adapters** (implementations): `src/db/repositories/drizzle/*.ts` — 10 Drizzle adapters -- **Barrel exports**: `src/db/index.ts` re-exports everything +- **Schema**: `apps/server/db/schema.ts` — all tables, columns, relations +- **Ports** (interfaces): `apps/server/db/repositories/*.ts` — 10 repository interfaces +- **Adapters** (implementations): `apps/server/db/repositories/drizzle/*.ts` — 10 Drizzle adapters +- **Barrel exports**: `apps/server/db/index.ts` re-exports everything All adapters use nanoid() for IDs, auto-manage timestamps, and use Drizzle's `.returning()` for atomic reads after writes. diff --git a/docs/dispatch-events.md b/docs/dispatch-events.md index 19f8f4e..f314e3d 100644 --- a/docs/dispatch-events.md +++ b/docs/dispatch-events.md @@ -1,10 +1,10 @@ # Dispatch & Events -`src/dispatch/` — Task and phase dispatch queues. `src/events/` — Typed event bus. +`apps/server/dispatch/` — Task and phase dispatch queues. `apps/server/events/` — Typed event bus. ## Event Bus -`src/events/` — Typed pub/sub system for inter-module communication. +`apps/server/events/` — Typed pub/sub system for inter-module communication. ### Architecture - **Port**: `EventBus` interface with `emit(event)` and `on(type, handler)` @@ -46,7 +46,7 @@ AccountCredentialsRefreshedEvent { accountId, expiresAt, previousExpiresAt? } ## Task Dispatch -`src/dispatch/` — In-memory queue with dependency-ordered dispatch. +`apps/server/dispatch/` — In-memory queue with dependency-ordered dispatch. ### Architecture - **Port**: `DispatchManager` interface diff --git a/docs/frontend.md b/docs/frontend.md index b59a4c2..5e64267 100644 --- a/docs/frontend.md +++ b/docs/frontend.md @@ -1,6 +1,6 @@ # Frontend -`packages/web/` — React web UI for managing initiatives, agents, and content. +`apps/web/` — React web UI for managing initiatives, agents, and content. ## Tech Stack @@ -134,4 +134,4 @@ Configured in `src/lib/trpc.ts`. Uses `@trpc/react-query` with TanStack Query fo `packages/shared/` exports: - `sortByPriorityAndQueueTime()` — priority-based task sorting - `topologicalSort()` / `groupByPipelineColumn()` — phase DAG layout -- Shared type re-exports from `packages/shared/src/types.ts` +- Shared type re-exports from `packages/shared/src/types.ts` (which re-exports from `apps/server/`) diff --git a/docs/git-process-logging.md b/docs/git-process-logging.md index 3579a0a..b1a7b20 100644 --- a/docs/git-process-logging.md +++ b/docs/git-process-logging.md @@ -2,7 +2,7 @@ Three infrastructure modules supporting agent execution. -## Git Module (`src/git/`) +## Git Module (`apps/server/git/`) Manages git worktrees for isolated agent workspaces. @@ -31,7 +31,7 @@ Worktrees stored in `.cw-worktrees/` subdirectory of the repo. Each agent gets a 4. On conflict: `git merge --abort`, emit `worktree:conflict` with conflicting file list 5. Restore original branch -### BranchManager (`src/git/branch-manager.ts`) +### BranchManager (`apps/server/git/branch-manager.ts`) - **Port**: `BranchManager` interface - **Adapter**: `SimpleGitBranchManager` using simple-git @@ -56,7 +56,7 @@ Worktrees stored in `.cw-worktrees/` subdirectory of the repo. Each agent gets a --- -## Process Module (`src/process/`) +## Process Module (`apps/server/process/`) Spawns, tracks, and controls child processes. @@ -85,13 +85,13 @@ Spawns, tracks, and controls child processes. --- -## Logger Module (`src/logger/`) +## Logger Module (`apps/server/logger/`) Structured logging via **pino**. ### Usage ```typescript -import { createModuleLogger } from './logger/index.js'; +import { createModuleLogger } from '../logger/index.js'; const log = createModuleLogger('my-module'); log.info({ key: 'value' }, 'message'); ``` @@ -109,7 +109,7 @@ log.info({ key: 'value' }, 'message'); --- -## Logging Module (`src/logging/`) +## Logging Module (`apps/server/logging/`) File-based per-process output capture (separate from pino). diff --git a/docs/logging.md b/docs/logging.md index 2a536ff..5c89f25 100644 --- a/docs/logging.md +++ b/docs/logging.md @@ -6,7 +6,7 @@ Codewalk District uses [pino](https://getpino.io/) for structured JSON logging o - **pino** writes structured JSON to **stderr** so CLI user output on stdout stays clean - **console.log** remains for CLI command handlers (user-facing output on stdout) -- The `src/logging/` module (ProcessLogWriter/LogManager) is a separate concern — it captures per-agent process stdout/stderr to files +- The `apps/server/logging/` module (ProcessLogWriter/LogManager) is a separate concern — it captures per-agent process stdout/stderr to files ## Environment Variables @@ -42,12 +42,12 @@ log.debug({ path, count }, 'processing items'); | Module | Used in | |--------|---------| -| `agent-manager` | `src/agent/manager.ts` | -| `dispatch` | `src/dispatch/manager.ts` | -| `http` | `src/server/index.ts` | -| `server` | `src/cli/index.ts` (startup) | -| `git` | `src/git/manager.ts`, `src/git/clone.ts`, `src/git/project-clones.ts` | -| `db` | `src/db/ensure-schema.ts` | +| `agent-manager` | `apps/server/agent/manager.ts` | +| `dispatch` | `apps/server/dispatch/manager.ts` | +| `http` | `apps/server/server/index.ts` | +| `server` | `apps/server/cli/index.ts` (startup) | +| `git` | `apps/server/git/manager.ts`, `apps/server/git/clone.ts`, `apps/server/git/project-clones.ts` | +| `db` | `apps/server/db/ensure-schema.ts` | ## Testing diff --git a/docs/preview.md b/docs/preview.md index 2ce50be..ea8bd78 100644 --- a/docs/preview.md +++ b/docs/preview.md @@ -1,6 +1,6 @@ # Preview Deployments -`src/preview/` — Docker-based preview deployments for reviewing changes in a running application. +`apps/server/preview/` — Docker-based preview deployments for reviewing changes in a running application. ## Overview @@ -56,7 +56,7 @@ services: frontend: build: context: . - dockerfile: packages/web/Dockerfile + dockerfile: apps/web/Dockerfile port: 3000 route: / healthcheck: @@ -160,10 +160,10 @@ Polls `getPreviewStatus` with `refetchInterval: 3000` while active. ## Container Wiring -- `PreviewManager` instantiated in `src/container.ts` with `(projectRepository, eventBus, workspaceRoot)` +- `PreviewManager` instantiated in `apps/server/container.ts` with `(projectRepository, eventBus, workspaceRoot)` - Added to `Container` interface and `toContextDeps()` - `GracefulShutdown` calls `previewManager.stopAll()` during shutdown -- `requirePreviewManager(ctx)` helper in `src/trpc/routers/_helpers.ts` +- `requirePreviewManager(ctx)` helper in `apps/server/trpc/routers/_helpers.ts` ## Dependencies diff --git a/docs/server-api.md b/docs/server-api.md index b574303..78ad60d 100644 --- a/docs/server-api.md +++ b/docs/server-api.md @@ -1,6 +1,6 @@ # Server & API Module -`src/server/` — HTTP server, `src/trpc/` — tRPC procedures, `src/coordination/` — merge queue. +`apps/server/server/` — HTTP server, `apps/server/trpc/` — tRPC procedures, `apps/server/coordination/` — merge queue. ## HTTP Server @@ -194,7 +194,7 @@ Subscriptions use `eventBusIterable()` — queue-based async generator, max 1000 ## Coordination Module -`src/coordination/` manages merge queue: +`apps/server/coordination/` manages merge queue: - **CoordinationManager** port: `queueMerge`, `getNextMergeable`, `processMerges`, `handleConflict`, `getQueueState` - **DefaultCoordinationManager** adapter: in-memory queue, dependency-ordered processing diff --git a/docs/testing.md b/docs/testing.md index c3702be..5aff365 100644 --- a/docs/testing.md +++ b/docs/testing.md @@ -1,6 +1,6 @@ # Testing -`src/test/` — Test infrastructure, fixtures, and test suites. +`apps/server/test/` — Test infrastructure, fixtures, and test suites. ## Framework @@ -10,15 +10,15 @@ ### Unit Tests Located alongside source files (`*.test.ts`): -- `src/agent/*.test.ts` — Manager, output handler, completion detection, file I/O, process manager -- `src/db/repositories/drizzle/*.test.ts` — Repository adapters -- `src/dispatch/*.test.ts` — Dispatch manager -- `src/git/manager.test.ts` — Worktree operations -- `src/process/*.test.ts` — Process registry and manager -- `src/logging/*.test.ts` — Log manager and writer +- `apps/server/agent/*.test.ts` — Manager, output handler, completion detection, file I/O, process manager +- `apps/server/db/repositories/drizzle/*.test.ts` — Repository adapters +- `apps/server/dispatch/*.test.ts` — Dispatch manager +- `apps/server/git/manager.test.ts` — Worktree operations +- `apps/server/process/*.test.ts` — Process registry and manager +- `apps/server/logging/*.test.ts` — Log manager and writer ### E2E Tests (Mocked Agents) -`src/test/e2e/`: +`apps/server/test/e2e/`: | File | Scenarios | |------|-----------| | `happy-path.test.ts` | Single task, parallel, complex flows | @@ -32,14 +32,14 @@ Located alongside source files (`*.test.ts`): These use `MockAgentManager` which bypasses the real subprocess pipeline. They test dispatch/coordination logic only. ### Cassette Tests (Pipeline Integration, Zero API Cost) -`src/test/cassette/` — Tests the full agent execution pipeline using pre-recorded cassettes. +`apps/server/test/cassette/` — Tests the full agent execution pipeline using pre-recorded cassettes. Unlike E2E tests, cassette tests exercise the real `ProcessManager → FileTailer → OutputHandler → SignalManager` path. Unlike real provider tests, they cost nothing to run in CI. See **[Cassette System](#cassette-system)** below for full documentation. ### Integration Tests (Real Providers) -`src/test/integration/real-providers/` — **skipped by default** (cost real money): +`apps/server/test/integration/real-providers/` — **skipped by default** (cost real money): | File | Provider | Cost | |------|----------|------| | `claude-manager.test.ts` | Claude CLI | ~$0.10 | @@ -51,7 +51,7 @@ Enable with env vars: `REAL_CLAUDE_TESTS=1`, `REAL_CODEX_TESTS=1` ## Test Infrastructure -### TestHarness (`src/test/harness.ts`) +### TestHarness (`apps/server/test/harness.ts`) Central test utility providing: - In-memory SQLite database with schema applied - All 10 repository instances @@ -61,7 +61,7 @@ Central test utility providing: - `DefaultDispatchManager` and `DefaultPhaseDispatchManager` - 25+ helper methods for test scenarios -### Fixtures (`src/test/fixtures.ts`) +### Fixtures (`apps/server/test/fixtures.ts`) Pre-built task hierarchies for testing: | Fixture | Structure | |---------|-----------| @@ -69,7 +69,7 @@ Pre-built task hierarchies for testing: | `PARALLEL_FIXTURE` | 1 initiative → 1 phase → 2 groups → 4 independent tasks | | `COMPLEX_FIXTURE` | 1 initiative → 2 phases → 4 groups → cross-phase dependencies | -### Real Provider Harness (`src/test/integration/real-providers/harness.ts`) +### Real Provider Harness (`apps/server/test/integration/real-providers/harness.ts`) - Creates real database, real agent manager with real CLI tools - Provides `describeRealClaude()` / `describeRealCodex()` that skip when env var not set - `MINIMAL_PROMPTS` — cheap prompts for testing output parsing @@ -85,23 +85,23 @@ See **[test-inventory.md](test-inventory.md)** for a complete catalog of every t npm test # Specific test file -npm test -- src/agent/manager.test.ts +npm test -- apps/server/agent/manager.test.ts # Cassette tests — replay pre-recorded cassettes (no API cost) -npm test -- src/test/cassette/ +npm test -- apps/server/test/cassette/ # Record new cassettes locally (requires real Claude CLI) -CW_CASSETTE_RECORD=1 npm test -- src/test/integration/real-providers/claude-manager.test.ts +CW_CASSETTE_RECORD=1 npm test -- apps/server/test/integration/real-providers/claude-manager.test.ts # Real provider tests (costs money!) -REAL_CLAUDE_TESTS=1 npm test -- src/test/integration/real-providers/ --test-timeout=300000 +REAL_CLAUDE_TESTS=1 npm test -- apps/server/test/integration/real-providers/ --test-timeout=300000 ``` --- ## Cassette System -`src/test/cassette/` — VCR-style recording and replay for the agent subprocess pipeline. +`apps/server/test/cassette/` — VCR-style recording and replay for the agent subprocess pipeline. ### Why it exists @@ -223,7 +223,7 @@ describe('agent pipeline (cassette)', () => { ### Cassette directory ``` -src/test/cassettes/ +apps/server/test/cassettes/ .json ← committed to git; one file per recorded scenario .gitkeep ``` diff --git a/drizzle.config.ts b/drizzle.config.ts index a78b15c..161a3c4 100644 --- a/drizzle.config.ts +++ b/drizzle.config.ts @@ -3,7 +3,7 @@ import { join } from 'node:path'; import { homedir } from 'node:os'; export default defineConfig({ - schema: './src/db/schema.ts', + schema: './apps/server/db/schema.ts', out: './drizzle', dialect: 'sqlite', dbCredentials: { diff --git a/package-lock.json b/package-lock.json index abae7ee..9f1571f 100644 --- a/package-lock.json +++ b/package-lock.json @@ -9,6 +9,7 @@ "version": "0.0.1", "license": "ISC", "workspaces": [ + "apps/*", "packages/*" ], "dependencies": { @@ -46,6 +47,628 @@ "vitest": "^4.0.18" } }, + "apps/web": { + "name": "@codewalk-district/web", + "version": "0.0.1", + "dependencies": { + "@codewalk-district/shared": "*", + "@radix-ui/react-dialog": "^1.1.15", + "@radix-ui/react-label": "^2.1.8", + "@radix-ui/react-select": "^2.2.6", + "@tanstack/react-query": "^5.75.0", + "@tanstack/react-router": "^1.158.0", + "@tiptap/extension-link": "^3.19.0", + "@tiptap/extension-placeholder": "^3.19.0", + "@tiptap/extension-table": "^3.19.0", + "@tiptap/html": "^3.19.0", + "@tiptap/pm": "^3.19.0", + "@tiptap/react": "^3.19.0", + "@tiptap/starter-kit": "^3.19.0", + "@tiptap/suggestion": "^3.19.0", + "@trpc/client": "^11.9.0", + "@trpc/react-query": "^11.9.0", + "class-variance-authority": "^0.7.1", + "clsx": "^2.1.1", + "lucide-react": "^0.563.0", + "react": "^19.0.0", + "react-dom": "^19.0.0", + "sonner": "^2.0.7", + "tailwind-merge": "^3.4.0", + "tippy.js": "^6.3.7" + }, + "devDependencies": { + "@radix-ui/react-dropdown-menu": "^2.1.16", + "@radix-ui/react-slot": "^1.2.4", + "@tailwindcss/typography": "^0.5.19", + "@tanstack/router-plugin": "^1.158.0", + "@types/node": "^25.2.0", + "@types/react": "^19.0.0", + "@types/react-dom": "^19.0.0", + "@vitejs/plugin-react": "^4.3.4", + "autoprefixer": "^10.4.24", + "postcss": "^8.5.6", + "tailwindcss": "^3.4.19", + "tailwindcss-animate": "^1.0.7", + "typescript": "^5.7.3", + "vite": "^6.1.0" + } + }, + "apps/web/node_modules/@esbuild/aix-ppc64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.25.12.tgz", + "integrity": "sha512-Hhmwd6CInZ3dwpuGTF8fJG6yoWmsToE+vYgD4nytZVxcu1ulHpUQRAB1UJ8+N1Am3Mz4+xOByoQoSZf4D+CpkA==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "aix" + ], + "engines": { + "node": ">=18" + } + }, + "apps/web/node_modules/@esbuild/android-arm": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.25.12.tgz", + "integrity": "sha512-VJ+sKvNA/GE7Ccacc9Cha7bpS8nyzVv0jdVgwNDaR4gDMC/2TTRc33Ip8qrNYUcpkOHUT5OZ0bUcNNVZQ9RLlg==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "apps/web/node_modules/@esbuild/android-arm64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.25.12.tgz", + "integrity": "sha512-6AAmLG7zwD1Z159jCKPvAxZd4y/VTO0VkprYy+3N2FtJ8+BQWFXU+OxARIwA46c5tdD9SsKGZ/1ocqBS/gAKHg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "apps/web/node_modules/@esbuild/android-x64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.25.12.tgz", + "integrity": "sha512-5jbb+2hhDHx5phYR2By8GTWEzn6I9UqR11Kwf22iKbNpYrsmRB18aX/9ivc5cabcUiAT/wM+YIZ6SG9QO6a8kg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "apps/web/node_modules/@esbuild/darwin-arm64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.25.12.tgz", + "integrity": "sha512-N3zl+lxHCifgIlcMUP5016ESkeQjLj/959RxxNYIthIg+CQHInujFuXeWbWMgnTo4cp5XVHqFPmpyu9J65C1Yg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=18" + } + }, + "apps/web/node_modules/@esbuild/darwin-x64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.25.12.tgz", + "integrity": "sha512-HQ9ka4Kx21qHXwtlTUVbKJOAnmG1ipXhdWTmNXiPzPfWKpXqASVcWdnf2bnL73wgjNrFXAa3yYvBSd9pzfEIpA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=18" + } + }, + "apps/web/node_modules/@esbuild/freebsd-arm64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.25.12.tgz", + "integrity": "sha512-gA0Bx759+7Jve03K1S0vkOu5Lg/85dou3EseOGUes8flVOGxbhDDh/iZaoek11Y8mtyKPGF3vP8XhnkDEAmzeg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=18" + } + }, + "apps/web/node_modules/@esbuild/freebsd-x64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.25.12.tgz", + "integrity": "sha512-TGbO26Yw2xsHzxtbVFGEXBFH0FRAP7gtcPE7P5yP7wGy7cXK2oO7RyOhL5NLiqTlBh47XhmIUXuGciXEqYFfBQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=18" + } + }, + "apps/web/node_modules/@esbuild/linux-arm": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.25.12.tgz", + "integrity": "sha512-lPDGyC1JPDou8kGcywY0YILzWlhhnRjdof3UlcoqYmS9El818LLfJJc3PXXgZHrHCAKs/Z2SeZtDJr5MrkxtOw==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "apps/web/node_modules/@esbuild/linux-arm64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.25.12.tgz", + "integrity": "sha512-8bwX7a8FghIgrupcxb4aUmYDLp8pX06rGh5HqDT7bB+8Rdells6mHvrFHHW2JAOPZUbnjUpKTLg6ECyzvas2AQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "apps/web/node_modules/@esbuild/linux-ia32": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.25.12.tgz", + "integrity": "sha512-0y9KrdVnbMM2/vG8KfU0byhUN+EFCny9+8g202gYqSSVMonbsCfLjUO+rCci7pM0WBEtz+oK/PIwHkzxkyharA==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "apps/web/node_modules/@esbuild/linux-loong64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.25.12.tgz", + "integrity": "sha512-h///Lr5a9rib/v1GGqXVGzjL4TMvVTv+s1DPoxQdz7l/AYv6LDSxdIwzxkrPW438oUXiDtwM10o9PmwS/6Z0Ng==", + "cpu": [ + "loong64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "apps/web/node_modules/@esbuild/linux-mips64el": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.25.12.tgz", + "integrity": "sha512-iyRrM1Pzy9GFMDLsXn1iHUm18nhKnNMWscjmp4+hpafcZjrr2WbT//d20xaGljXDBYHqRcl8HnxbX6uaA/eGVw==", + "cpu": [ + "mips64el" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "apps/web/node_modules/@esbuild/linux-ppc64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.25.12.tgz", + "integrity": "sha512-9meM/lRXxMi5PSUqEXRCtVjEZBGwB7P/D4yT8UG/mwIdze2aV4Vo6U5gD3+RsoHXKkHCfSxZKzmDssVlRj1QQA==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "apps/web/node_modules/@esbuild/linux-riscv64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.25.12.tgz", + "integrity": "sha512-Zr7KR4hgKUpWAwb1f3o5ygT04MzqVrGEGXGLnj15YQDJErYu/BGg+wmFlIDOdJp0PmB0lLvxFIOXZgFRrdjR0w==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "apps/web/node_modules/@esbuild/linux-s390x": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.25.12.tgz", + "integrity": "sha512-MsKncOcgTNvdtiISc/jZs/Zf8d0cl/t3gYWX8J9ubBnVOwlk65UIEEvgBORTiljloIWnBzLs4qhzPkJcitIzIg==", + "cpu": [ + "s390x" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "apps/web/node_modules/@esbuild/linux-x64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.25.12.tgz", + "integrity": "sha512-uqZMTLr/zR/ed4jIGnwSLkaHmPjOjJvnm6TVVitAa08SLS9Z0VM8wIRx7gWbJB5/J54YuIMInDquWyYvQLZkgw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "apps/web/node_modules/@esbuild/netbsd-arm64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.25.12.tgz", + "integrity": "sha512-xXwcTq4GhRM7J9A8Gv5boanHhRa/Q9KLVmcyXHCTaM4wKfIpWkdXiMog/KsnxzJ0A1+nD+zoecuzqPmCRyBGjg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=18" + } + }, + "apps/web/node_modules/@esbuild/netbsd-x64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.25.12.tgz", + "integrity": "sha512-Ld5pTlzPy3YwGec4OuHh1aCVCRvOXdH8DgRjfDy/oumVovmuSzWfnSJg+VtakB9Cm0gxNO9BzWkj6mtO1FMXkQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=18" + } + }, + "apps/web/node_modules/@esbuild/openbsd-arm64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.25.12.tgz", + "integrity": "sha512-fF96T6KsBo/pkQI950FARU9apGNTSlZGsv1jZBAlcLL1MLjLNIWPBkj5NlSz8aAzYKg+eNqknrUJ24QBybeR5A==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=18" + } + }, + "apps/web/node_modules/@esbuild/openbsd-x64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.25.12.tgz", + "integrity": "sha512-MZyXUkZHjQxUvzK7rN8DJ3SRmrVrke8ZyRusHlP+kuwqTcfWLyqMOE3sScPPyeIXN/mDJIfGXvcMqCgYKekoQw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=18" + } + }, + "apps/web/node_modules/@esbuild/openharmony-arm64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/openharmony-arm64/-/openharmony-arm64-0.25.12.tgz", + "integrity": "sha512-rm0YWsqUSRrjncSXGA7Zv78Nbnw4XL6/dzr20cyrQf7ZmRcsovpcRBdhD43Nuk3y7XIoW2OxMVvwuRvk9XdASg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openharmony" + ], + "engines": { + "node": ">=18" + } + }, + "apps/web/node_modules/@esbuild/sunos-x64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.25.12.tgz", + "integrity": "sha512-3wGSCDyuTHQUzt0nV7bocDy72r2lI33QL3gkDNGkod22EsYl04sMf0qLb8luNKTOmgF/eDEDP5BFNwoBKH441w==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "sunos" + ], + "engines": { + "node": ">=18" + } + }, + "apps/web/node_modules/@esbuild/win32-arm64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.25.12.tgz", + "integrity": "sha512-rMmLrur64A7+DKlnSuwqUdRKyd3UE7oPJZmnljqEptesKM8wx9J8gx5u0+9Pq0fQQW8vqeKebwNXdfOyP+8Bsg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "apps/web/node_modules/@esbuild/win32-ia32": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.25.12.tgz", + "integrity": "sha512-HkqnmmBoCbCwxUKKNPBixiWDGCpQGVsrQfJoVGYLPT41XWF8lHuE5N6WhVia2n4o5QK5M4tYr21827fNhi4byQ==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "apps/web/node_modules/@esbuild/win32-x64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.25.12.tgz", + "integrity": "sha512-alJC0uCZpTFrSL0CCDjcgleBXPnCrEAhTBILpeAp7M/OFgoqtAetfBzX0xM00MUsVVPpVjlPuMbREqnZCXaTnA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "apps/web/node_modules/@types/node": { + "version": "25.3.3", + "resolved": "https://registry.npmjs.org/@types/node/-/node-25.3.3.tgz", + "integrity": "sha512-DpzbrH7wIcBaJibpKo9nnSQL0MTRdnWttGyE5haGwK86xgMOkFLp7vEyfQPGLOJh5wNYiJ3V9PmUMDhV9u8kkQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "undici-types": "~7.18.0" + } + }, + "apps/web/node_modules/esbuild": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.25.12.tgz", + "integrity": "sha512-bbPBYYrtZbkt6Os6FiTLCTFxvq4tt3JKall1vRwshA3fdVztsLAatFaZobhkBC8/BrPetoa0oksYoKXoG4ryJg==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "bin": { + "esbuild": "bin/esbuild" + }, + "engines": { + "node": ">=18" + }, + "optionalDependencies": { + "@esbuild/aix-ppc64": "0.25.12", + "@esbuild/android-arm": "0.25.12", + "@esbuild/android-arm64": "0.25.12", + "@esbuild/android-x64": "0.25.12", + "@esbuild/darwin-arm64": "0.25.12", + "@esbuild/darwin-x64": "0.25.12", + "@esbuild/freebsd-arm64": "0.25.12", + "@esbuild/freebsd-x64": "0.25.12", + "@esbuild/linux-arm": "0.25.12", + "@esbuild/linux-arm64": "0.25.12", + "@esbuild/linux-ia32": "0.25.12", + "@esbuild/linux-loong64": "0.25.12", + "@esbuild/linux-mips64el": "0.25.12", + "@esbuild/linux-ppc64": "0.25.12", + "@esbuild/linux-riscv64": "0.25.12", + "@esbuild/linux-s390x": "0.25.12", + "@esbuild/linux-x64": "0.25.12", + "@esbuild/netbsd-arm64": "0.25.12", + "@esbuild/netbsd-x64": "0.25.12", + "@esbuild/openbsd-arm64": "0.25.12", + "@esbuild/openbsd-x64": "0.25.12", + "@esbuild/openharmony-arm64": "0.25.12", + "@esbuild/sunos-x64": "0.25.12", + "@esbuild/win32-arm64": "0.25.12", + "@esbuild/win32-ia32": "0.25.12", + "@esbuild/win32-x64": "0.25.12" + } + }, + "apps/web/node_modules/undici-types": { + "version": "7.18.2", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-7.18.2.tgz", + "integrity": "sha512-AsuCzffGHJybSaRrmr5eHr81mwJU3kjw6M+uprWvCXiNeN9SOGwQ3Jn8jb8m3Z6izVgknn1R0FTCEAP2QrLY/w==", + "dev": true, + "license": "MIT" + }, + "apps/web/node_modules/vite": { + "version": "6.4.1", + "resolved": "https://registry.npmjs.org/vite/-/vite-6.4.1.tgz", + "integrity": "sha512-+Oxm7q9hDoLMyJOYfUYBuHQo+dkAloi33apOPP56pzj+vsdJDzr+j1NISE5pyaAuKL4A3UD34qd0lx5+kfKp2g==", + "dev": true, + "license": "MIT", + "dependencies": { + "esbuild": "^0.25.0", + "fdir": "^6.4.4", + "picomatch": "^4.0.2", + "postcss": "^8.5.3", + "rollup": "^4.34.9", + "tinyglobby": "^0.2.13" + }, + "bin": { + "vite": "bin/vite.js" + }, + "engines": { + "node": "^18.0.0 || ^20.0.0 || >=22.0.0" + }, + "funding": { + "url": "https://github.com/vitejs/vite?sponsor=1" + }, + "optionalDependencies": { + "fsevents": "~2.3.3" + }, + "peerDependencies": { + "@types/node": "^18.0.0 || ^20.0.0 || >=22.0.0", + "jiti": ">=1.21.0", + "less": "*", + "lightningcss": "^1.21.0", + "sass": "*", + "sass-embedded": "*", + "stylus": "*", + "sugarss": "*", + "terser": "^5.16.0", + "tsx": "^4.8.1", + "yaml": "^2.4.2" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + }, + "jiti": { + "optional": true + }, + "less": { + "optional": true + }, + "lightningcss": { + "optional": true + }, + "sass": { + "optional": true + }, + "sass-embedded": { + "optional": true + }, + "stylus": { + "optional": true + }, + "sugarss": { + "optional": true + }, + "terser": { + "optional": true + }, + "tsx": { + "optional": true + }, + "yaml": { + "optional": true + } + } + }, "node_modules/@alloc/quick-lru": { "version": "5.2.0", "resolved": "https://registry.npmjs.org/@alloc/quick-lru/-/quick-lru-5.2.0.tgz", @@ -418,7 +1041,7 @@ "link": true }, "node_modules/@codewalk-district/web": { - "resolved": "packages/web", + "resolved": "apps/web", "link": true }, "node_modules/@drizzle-team/brocli": { @@ -8284,6 +8907,7 @@ "packages/web": { "name": "@codewalk-district/web", "version": "0.0.1", + "extraneous": true, "dependencies": { "@codewalk-district/shared": "*", "@radix-ui/react-dialog": "^1.1.15", @@ -8326,582 +8950,6 @@ "typescript": "^5.7.3", "vite": "^6.1.0" } - }, - "packages/web/node_modules/@esbuild/aix-ppc64": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.25.12.tgz", - "integrity": "sha512-Hhmwd6CInZ3dwpuGTF8fJG6yoWmsToE+vYgD4nytZVxcu1ulHpUQRAB1UJ8+N1Am3Mz4+xOByoQoSZf4D+CpkA==", - "cpu": [ - "ppc64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "aix" - ], - "engines": { - "node": ">=18" - } - }, - "packages/web/node_modules/@esbuild/android-arm": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.25.12.tgz", - "integrity": "sha512-VJ+sKvNA/GE7Ccacc9Cha7bpS8nyzVv0jdVgwNDaR4gDMC/2TTRc33Ip8qrNYUcpkOHUT5OZ0bUcNNVZQ9RLlg==", - "cpu": [ - "arm" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">=18" - } - }, - "packages/web/node_modules/@esbuild/android-arm64": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.25.12.tgz", - "integrity": "sha512-6AAmLG7zwD1Z159jCKPvAxZd4y/VTO0VkprYy+3N2FtJ8+BQWFXU+OxARIwA46c5tdD9SsKGZ/1ocqBS/gAKHg==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">=18" - } - }, - "packages/web/node_modules/@esbuild/android-x64": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.25.12.tgz", - "integrity": "sha512-5jbb+2hhDHx5phYR2By8GTWEzn6I9UqR11Kwf22iKbNpYrsmRB18aX/9ivc5cabcUiAT/wM+YIZ6SG9QO6a8kg==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">=18" - } - }, - "packages/web/node_modules/@esbuild/darwin-arm64": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.25.12.tgz", - "integrity": "sha512-N3zl+lxHCifgIlcMUP5016ESkeQjLj/959RxxNYIthIg+CQHInujFuXeWbWMgnTo4cp5XVHqFPmpyu9J65C1Yg==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">=18" - } - }, - "packages/web/node_modules/@esbuild/darwin-x64": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.25.12.tgz", - "integrity": "sha512-HQ9ka4Kx21qHXwtlTUVbKJOAnmG1ipXhdWTmNXiPzPfWKpXqASVcWdnf2bnL73wgjNrFXAa3yYvBSd9pzfEIpA==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">=18" - } - }, - "packages/web/node_modules/@esbuild/freebsd-arm64": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.25.12.tgz", - "integrity": "sha512-gA0Bx759+7Jve03K1S0vkOu5Lg/85dou3EseOGUes8flVOGxbhDDh/iZaoek11Y8mtyKPGF3vP8XhnkDEAmzeg==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "freebsd" - ], - "engines": { - "node": ">=18" - } - }, - "packages/web/node_modules/@esbuild/freebsd-x64": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.25.12.tgz", - "integrity": "sha512-TGbO26Yw2xsHzxtbVFGEXBFH0FRAP7gtcPE7P5yP7wGy7cXK2oO7RyOhL5NLiqTlBh47XhmIUXuGciXEqYFfBQ==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "freebsd" - ], - "engines": { - "node": ">=18" - } - }, - "packages/web/node_modules/@esbuild/linux-arm": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.25.12.tgz", - "integrity": "sha512-lPDGyC1JPDou8kGcywY0YILzWlhhnRjdof3UlcoqYmS9El818LLfJJc3PXXgZHrHCAKs/Z2SeZtDJr5MrkxtOw==", - "cpu": [ - "arm" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "packages/web/node_modules/@esbuild/linux-arm64": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.25.12.tgz", - "integrity": "sha512-8bwX7a8FghIgrupcxb4aUmYDLp8pX06rGh5HqDT7bB+8Rdells6mHvrFHHW2JAOPZUbnjUpKTLg6ECyzvas2AQ==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "packages/web/node_modules/@esbuild/linux-ia32": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.25.12.tgz", - "integrity": "sha512-0y9KrdVnbMM2/vG8KfU0byhUN+EFCny9+8g202gYqSSVMonbsCfLjUO+rCci7pM0WBEtz+oK/PIwHkzxkyharA==", - "cpu": [ - "ia32" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "packages/web/node_modules/@esbuild/linux-loong64": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.25.12.tgz", - "integrity": "sha512-h///Lr5a9rib/v1GGqXVGzjL4TMvVTv+s1DPoxQdz7l/AYv6LDSxdIwzxkrPW438oUXiDtwM10o9PmwS/6Z0Ng==", - "cpu": [ - "loong64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "packages/web/node_modules/@esbuild/linux-mips64el": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.25.12.tgz", - "integrity": "sha512-iyRrM1Pzy9GFMDLsXn1iHUm18nhKnNMWscjmp4+hpafcZjrr2WbT//d20xaGljXDBYHqRcl8HnxbX6uaA/eGVw==", - "cpu": [ - "mips64el" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "packages/web/node_modules/@esbuild/linux-ppc64": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.25.12.tgz", - "integrity": "sha512-9meM/lRXxMi5PSUqEXRCtVjEZBGwB7P/D4yT8UG/mwIdze2aV4Vo6U5gD3+RsoHXKkHCfSxZKzmDssVlRj1QQA==", - "cpu": [ - "ppc64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "packages/web/node_modules/@esbuild/linux-riscv64": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.25.12.tgz", - "integrity": "sha512-Zr7KR4hgKUpWAwb1f3o5ygT04MzqVrGEGXGLnj15YQDJErYu/BGg+wmFlIDOdJp0PmB0lLvxFIOXZgFRrdjR0w==", - "cpu": [ - "riscv64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "packages/web/node_modules/@esbuild/linux-s390x": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.25.12.tgz", - "integrity": "sha512-MsKncOcgTNvdtiISc/jZs/Zf8d0cl/t3gYWX8J9ubBnVOwlk65UIEEvgBORTiljloIWnBzLs4qhzPkJcitIzIg==", - "cpu": [ - "s390x" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "packages/web/node_modules/@esbuild/linux-x64": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.25.12.tgz", - "integrity": "sha512-uqZMTLr/zR/ed4jIGnwSLkaHmPjOjJvnm6TVVitAa08SLS9Z0VM8wIRx7gWbJB5/J54YuIMInDquWyYvQLZkgw==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "packages/web/node_modules/@esbuild/netbsd-arm64": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.25.12.tgz", - "integrity": "sha512-xXwcTq4GhRM7J9A8Gv5boanHhRa/Q9KLVmcyXHCTaM4wKfIpWkdXiMog/KsnxzJ0A1+nD+zoecuzqPmCRyBGjg==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "netbsd" - ], - "engines": { - "node": ">=18" - } - }, - "packages/web/node_modules/@esbuild/netbsd-x64": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.25.12.tgz", - "integrity": "sha512-Ld5pTlzPy3YwGec4OuHh1aCVCRvOXdH8DgRjfDy/oumVovmuSzWfnSJg+VtakB9Cm0gxNO9BzWkj6mtO1FMXkQ==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "netbsd" - ], - "engines": { - "node": ">=18" - } - }, - "packages/web/node_modules/@esbuild/openbsd-arm64": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.25.12.tgz", - "integrity": "sha512-fF96T6KsBo/pkQI950FARU9apGNTSlZGsv1jZBAlcLL1MLjLNIWPBkj5NlSz8aAzYKg+eNqknrUJ24QBybeR5A==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "openbsd" - ], - "engines": { - "node": ">=18" - } - }, - "packages/web/node_modules/@esbuild/openbsd-x64": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.25.12.tgz", - "integrity": "sha512-MZyXUkZHjQxUvzK7rN8DJ3SRmrVrke8ZyRusHlP+kuwqTcfWLyqMOE3sScPPyeIXN/mDJIfGXvcMqCgYKekoQw==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "openbsd" - ], - "engines": { - "node": ">=18" - } - }, - "packages/web/node_modules/@esbuild/openharmony-arm64": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/openharmony-arm64/-/openharmony-arm64-0.25.12.tgz", - "integrity": "sha512-rm0YWsqUSRrjncSXGA7Zv78Nbnw4XL6/dzr20cyrQf7ZmRcsovpcRBdhD43Nuk3y7XIoW2OxMVvwuRvk9XdASg==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "openharmony" - ], - "engines": { - "node": ">=18" - } - }, - "packages/web/node_modules/@esbuild/sunos-x64": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.25.12.tgz", - "integrity": "sha512-3wGSCDyuTHQUzt0nV7bocDy72r2lI33QL3gkDNGkod22EsYl04sMf0qLb8luNKTOmgF/eDEDP5BFNwoBKH441w==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "sunos" - ], - "engines": { - "node": ">=18" - } - }, - "packages/web/node_modules/@esbuild/win32-arm64": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.25.12.tgz", - "integrity": "sha512-rMmLrur64A7+DKlnSuwqUdRKyd3UE7oPJZmnljqEptesKM8wx9J8gx5u0+9Pq0fQQW8vqeKebwNXdfOyP+8Bsg==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=18" - } - }, - "packages/web/node_modules/@esbuild/win32-ia32": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.25.12.tgz", - "integrity": "sha512-HkqnmmBoCbCwxUKKNPBixiWDGCpQGVsrQfJoVGYLPT41XWF8lHuE5N6WhVia2n4o5QK5M4tYr21827fNhi4byQ==", - "cpu": [ - "ia32" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=18" - } - }, - "packages/web/node_modules/@esbuild/win32-x64": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.25.12.tgz", - "integrity": "sha512-alJC0uCZpTFrSL0CCDjcgleBXPnCrEAhTBILpeAp7M/OFgoqtAetfBzX0xM00MUsVVPpVjlPuMbREqnZCXaTnA==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=18" - } - }, - "packages/web/node_modules/@types/node": { - "version": "25.2.0", - "resolved": "https://registry.npmjs.org/@types/node/-/node-25.2.0.tgz", - "integrity": "sha512-DZ8VwRFUNzuqJ5khrvwMXHmvPe+zGayJhr2CDNiKB1WBE1ST8Djl00D0IC4vvNmHMdj6DlbYRIaFE7WHjlDl5w==", - "dev": true, - "license": "MIT", - "dependencies": { - "undici-types": "~7.16.0" - } - }, - "packages/web/node_modules/esbuild": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.25.12.tgz", - "integrity": "sha512-bbPBYYrtZbkt6Os6FiTLCTFxvq4tt3JKall1vRwshA3fdVztsLAatFaZobhkBC8/BrPetoa0oksYoKXoG4ryJg==", - "dev": true, - "hasInstallScript": true, - "license": "MIT", - "bin": { - "esbuild": "bin/esbuild" - }, - "engines": { - "node": ">=18" - }, - "optionalDependencies": { - "@esbuild/aix-ppc64": "0.25.12", - "@esbuild/android-arm": "0.25.12", - "@esbuild/android-arm64": "0.25.12", - "@esbuild/android-x64": "0.25.12", - "@esbuild/darwin-arm64": "0.25.12", - "@esbuild/darwin-x64": "0.25.12", - "@esbuild/freebsd-arm64": "0.25.12", - "@esbuild/freebsd-x64": "0.25.12", - "@esbuild/linux-arm": "0.25.12", - "@esbuild/linux-arm64": "0.25.12", - "@esbuild/linux-ia32": "0.25.12", - "@esbuild/linux-loong64": "0.25.12", - "@esbuild/linux-mips64el": "0.25.12", - "@esbuild/linux-ppc64": "0.25.12", - "@esbuild/linux-riscv64": "0.25.12", - "@esbuild/linux-s390x": "0.25.12", - "@esbuild/linux-x64": "0.25.12", - "@esbuild/netbsd-arm64": "0.25.12", - "@esbuild/netbsd-x64": "0.25.12", - "@esbuild/openbsd-arm64": "0.25.12", - "@esbuild/openbsd-x64": "0.25.12", - "@esbuild/openharmony-arm64": "0.25.12", - "@esbuild/sunos-x64": "0.25.12", - "@esbuild/win32-arm64": "0.25.12", - "@esbuild/win32-ia32": "0.25.12", - "@esbuild/win32-x64": "0.25.12" - } - }, - "packages/web/node_modules/undici-types": { - "version": "7.16.0", - "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-7.16.0.tgz", - "integrity": "sha512-Zz+aZWSj8LE6zoxD+xrjh4VfkIG8Ya6LvYkZqtUQGJPZjYl53ypCaUwWqo7eI0x66KBGeRo+mlBEkMSeSZ38Nw==", - "dev": true, - "license": "MIT" - }, - "packages/web/node_modules/vite": { - "version": "6.4.1", - "resolved": "https://registry.npmjs.org/vite/-/vite-6.4.1.tgz", - "integrity": "sha512-+Oxm7q9hDoLMyJOYfUYBuHQo+dkAloi33apOPP56pzj+vsdJDzr+j1NISE5pyaAuKL4A3UD34qd0lx5+kfKp2g==", - "dev": true, - "license": "MIT", - "dependencies": { - "esbuild": "^0.25.0", - "fdir": "^6.4.4", - "picomatch": "^4.0.2", - "postcss": "^8.5.3", - "rollup": "^4.34.9", - "tinyglobby": "^0.2.13" - }, - "bin": { - "vite": "bin/vite.js" - }, - "engines": { - "node": "^18.0.0 || ^20.0.0 || >=22.0.0" - }, - "funding": { - "url": "https://github.com/vitejs/vite?sponsor=1" - }, - "optionalDependencies": { - "fsevents": "~2.3.3" - }, - "peerDependencies": { - "@types/node": "^18.0.0 || ^20.0.0 || >=22.0.0", - "jiti": ">=1.21.0", - "less": "*", - "lightningcss": "^1.21.0", - "sass": "*", - "sass-embedded": "*", - "stylus": "*", - "sugarss": "*", - "terser": "^5.16.0", - "tsx": "^4.8.1", - "yaml": "^2.4.2" - }, - "peerDependenciesMeta": { - "@types/node": { - "optional": true - }, - "jiti": { - "optional": true - }, - "less": { - "optional": true - }, - "lightningcss": { - "optional": true - }, - "sass": { - "optional": true - }, - "sass-embedded": { - "optional": true - }, - "stylus": { - "optional": true - }, - "sugarss": { - "optional": true - }, - "terser": { - "optional": true - }, - "tsx": { - "optional": true - }, - "yaml": { - "optional": true - } - } } } } diff --git a/package.json b/package.json index 550b759..fd1e935 100644 --- a/package.json +++ b/package.json @@ -4,6 +4,7 @@ "description": "Multi-agent workspace for orchestrating multiple Claude Code agents", "type": "module", "workspaces": [ + "apps/*", "packages/*" ], "main": "./dist/index.js", @@ -12,12 +13,12 @@ }, "scripts": { "build": "tsc", - "dev": "tsx watch src/bin/cw.ts", + "dev": "tsx watch apps/server/bin/cw.ts", "clean": "rimraf dist", "test": "vitest run", "test:watch": "vitest", "test:coverage": "vitest run --coverage", - "dev:web": "npm run dev --workspace=packages/web" + "dev:web": "npm run dev --workspace=apps/web" }, "keywords": [ "claude", diff --git a/packages/shared/src/trpc.ts b/packages/shared/src/trpc.ts index 9a99f02..31bcffa 100644 --- a/packages/shared/src/trpc.ts +++ b/packages/shared/src/trpc.ts @@ -1 +1 @@ -export type { AppRouter } from '../../../src/trpc/router.js'; +export type { AppRouter } from '../../../apps/server/trpc/router.js'; diff --git a/packages/shared/src/types.ts b/packages/shared/src/types.ts index 89642a1..8e58a3f 100644 --- a/packages/shared/src/types.ts +++ b/packages/shared/src/types.ts @@ -1,5 +1,5 @@ -export type { Initiative, Phase, Task, Agent, Message, Page, Project, Account, ChangeSet, ChangeSetEntry } from '../../../src/db/schema.js'; -export type { PendingQuestions, QuestionItem } from '../../../src/agent/types.js'; +export type { Initiative, Phase, Task, Agent, Message, Page, Project, Account, ChangeSet, ChangeSetEntry } from '../../../apps/server/db/schema.js'; +export type { PendingQuestions, QuestionItem } from '../../../apps/server/agent/types.js'; export type ExecutionMode = 'yolo' | 'review_per_phase'; export type PhaseStatus = 'pending' | 'approved' | 'in_progress' | 'completed' | 'blocked' | 'pending_review'; diff --git a/tests/integration/cli-server.test.ts b/tests/integration/cli-server.test.ts index b96abb6..2d46686 100644 --- a/tests/integration/cli-server.test.ts +++ b/tests/integration/cli-server.test.ts @@ -6,12 +6,12 @@ */ import { describe, it, expect, beforeAll, afterAll } from 'vitest'; -import { CoordinationServer } from '../../src/server/index.js'; -import { ProcessManager, ProcessRegistry } from '../../src/process/index.js'; -import { LogManager } from '../../src/logging/index.js'; -import { createEventBus } from '../../src/events/index.js'; -import { createTrpcClient } from '../../src/cli/trpc-client.js'; -import type { TrpcClient } from '../../src/cli/trpc-client.js'; +import { CoordinationServer } from '../../apps/server/server/index.js'; +import { ProcessManager, ProcessRegistry } from '../../apps/server/process/index.js'; +import { LogManager } from '../../apps/server/logging/index.js'; +import { createEventBus } from '../../apps/server/events/index.js'; +import { createTrpcClient } from '../../apps/server/cli/trpc-client.js'; +import type { TrpcClient } from '../../apps/server/cli/trpc-client.js'; describe('CLI-Server Integration', () => { let server: CoordinationServer; diff --git a/tsconfig.json b/tsconfig.json index 1158e87..f48805c 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -4,7 +4,7 @@ "module": "NodeNext", "moduleResolution": "NodeNext", "outDir": "./dist", - "rootDir": "./src", + "rootDir": "./apps/server", "strict": true, "esModuleInterop": true, "declaration": true, @@ -12,6 +12,6 @@ "forceConsistentCasingInFileNames": true, "resolveJsonModule": true }, - "include": ["src/**/*"], + "include": ["apps/server/**/*"], "exclude": ["node_modules", "dist"] } diff --git a/vitest.config.ts b/vitest.config.ts index 28c0b8f..3c324f3 100644 --- a/vitest.config.ts +++ b/vitest.config.ts @@ -9,7 +9,7 @@ export default defineConfig({ }, // Test file pattern include: ['**/*.test.ts'], - exclude: ['**/node_modules/**', '**/dist/**', 'packages/**'], + exclude: ['**/node_modules/**', '**/dist/**', 'apps/web/**', 'packages/**'], // TypeScript support uses tsconfig.json automatically // Coverage reporter (optional, for future use) coverage: {