{"uuid": "d19a0b3a-33a4-4f3b-943b-f9d04cdf62f7", "vulnerability_lookup_origin": "1a89b78e-f703-45f3-bb86-59eb712668bd", "author": "9f56dd64-161d-43a6-b9c3-555944290a09", "vulnerability": "CVE-2022-24765", "type": "seen", "source": "https://gist.github.com/xwa5/3fad7514a482ddd87182dcedcc51c0cc", "content": "\n\n\n\n\ndoarchon \u2014 Wiki\n\n\n\n\n*{margin:0;padding:0;box-sizing:border-box}\n:root{\n  --bg:#ffffff;--sidebar-bg:#f8f9fb;--border:#e5e7eb;\n  --text:#1e293b;--text-muted:#64748b;--primary:#2563eb;\n  --primary-soft:#eff6ff;--hover:#f1f5f9;--code-bg:#f1f5f9;\n  --radius:8px;--shadow:0 1px 3px rgba(0,0,0,.08);\n}\nbody{font-family:-apple-system,BlinkMacSystemFont,'Segoe UI',Roboto,sans-serif;\n  line-height:1.65;color:var(--text);background:var(--bg)}\n\n.layout{display:flex;min-height:100vh}\n.sidebar{width:280px;background:var(--sidebar-bg);border-right:1px solid var(--border);\n  position:fixed;top:0;left:0;bottom:0;overflow-y:auto;padding:24px 16px;\n  display:flex;flex-direction:column;z-index:10}\n.content{margin-left:280px;flex:1;padding:48px 64px;max-width:960px}\n\n.sidebar-header{margin-bottom:20px;padding-bottom:16px;border-bottom:1px solid var(--border)}\n.sidebar-title{font-size:16px;font-weight:700;color:var(--text);display:flex;align-items:center;gap:8px}\n.sidebar-title svg{flex-shrink:0}\n.sidebar-meta{font-size:11px;color:var(--text-muted);margin-top:6px}\n.nav-section{margin-bottom:2px}\n.nav-item{display:block;padding:7px 12px;border-radius:var(--radius);cursor:pointer;\n  font-size:13px;color:var(--text);text-decoration:none;transition:all .15s;\n  white-space:nowrap;overflow:hidden;text-overflow:ellipsis}\n.nav-item:hover{background:var(--hover)}\n.nav-item.active{background:var(--primary-soft);color:var(--primary);font-weight:600}\n.nav-item.overview{font-weight:600;margin-bottom:4px}\n.nav-children{padding-left:14px;border-left:1px solid var(--border);margin-left:12px}\n.nav-group-label{font-size:11px;font-weight:600;color:var(--text-muted);\n  text-transform:uppercase;letter-spacing:.5px;padding:12px 12px 4px;user-select:none}\n.sidebar-footer{margin-top:auto;padding-top:16px;border-top:1px solid var(--border);\n  font-size:11px;color:var(--text-muted);text-align:center}\n\n.content h1{font-size:28px;font-weight:700;margin-bottom:8px;line-height:1.3}\n.content h2{font-size:22px;font-weight:600;margin:32px 0 12px;padding-bottom:6px;border-bottom:1px solid var(--border)}\n.content h3{font-size:17px;font-weight:600;margin:24px 0 8px}\n.content h4{font-size:15px;font-weight:600;margin:20px 0 6px}\n.content p{margin:12px 0}\n.content ul,.content ol{margin:12px 0 12px 24px}\n.content li{margin:4px 0}\n.content a{color:var(--primary);text-decoration:none}\n.content a:hover{text-decoration:underline}\n.content blockquote{border-left:3px solid var(--primary);padding:8px 16px;margin:16px 0;\n  background:var(--primary-soft);border-radius:0 var(--radius) var(--radius) 0;\n  color:var(--text-muted);font-size:14px}\n.content code{font-family:'SF Mono',Consolas,'Courier New',monospace;font-size:13px;\n  background:var(--code-bg);padding:2px 6px;border-radius:4px}\n.content pre{background:#1e293b;color:#e2e8f0;border-radius:var(--radius);padding:16px;\n  overflow-x:auto;margin:16px 0}\n.content pre code{background:none;padding:0;font-size:13px;line-height:1.6;color:inherit}\n.content table{border-collapse:collapse;width:100%;margin:16px 0}\n.content th,.content td{border:1px solid var(--border);padding:8px 12px;text-align:left;font-size:14px}\n.content th{background:var(--sidebar-bg);font-weight:600}\n.content img{max-width:100%;border-radius:var(--radius)}\n.content hr{border:none;border-top:1px solid var(--border);margin:32px 0}\n.content .mermaid{margin:20px 0;text-align:center}\n\n.menu-toggle{display:none;position:fixed;top:12px;left:12px;z-index:20;\n  background:var(--bg);border:1px solid var(--border);border-radius:var(--radius);\n  padding:8px 12px;cursor:pointer;font-size:18px;box-shadow:var(--shadow)}\n@media(max-width:768px){\n  .sidebar{transform:translateX(-100%);transition:transform .2s}\n  .sidebar.open{transform:translateX(0);box-shadow:2px 0 12px rgba(0,0,0,.1)}\n  .content{margin-left:0;padding:24px 20px;padding-top:56px}\n  .menu-toggle{display:block}\n}\n.empty-state{text-align:center;padding:80px 20px;color:var(--text-muted)}\n.empty-state h2{font-size:20px;margin-bottom:8px;border:none}\n\n\n\n\n&#9776;\n\n\n\n\n\n\n\n\n\ndoarchon\n\n\n\n\n\n\n\nGenerated by GitNexus\n\n\n\n\n\nLoading\u2026\n\n\n\nvar PAGES = {\"api-server-and-integrations\":\"# API Server and Integrations\\n\\n# API Server and Integrations\\n\\nThe `packages/server` module provides Archon\u2019s HTTP server, web UI transport, platform adapters, external service clients, startup migrations, background schedulers, and operational notifications.\\n\\nThe main entry point is `packages/server/src/index.ts`. The server can run as:\\n\\n- A full multi-platform server with Web, Telegram, Discord, Slack, GitHub, Gitea, and GitLab integrations.\\n- A standalone Web/API server using `ServerOptions.skipPlatformAdapters`.\\n- A production server that serves the compiled web UI.\\n- A development server that exposes API and streaming endpoints while the front end runs separately.\\n\\n## Architecture\\n\\n```mermaid\\nflowchart TD\\n    Entry[startServer] --&gt; Bootstrap[Environment and providers]\\n    Bootstrap --&gt; DB[Database connection and migrations]\\n    DB --&gt; Web[WebAdapter and SSE transport]\\n    Web --&gt; Routes[Hono API and webhook routes]\\n    Bootstrap --&gt; Platforms[Platform adapters]\\n    Platforms --&gt; Workflow[handleMessage and orchestrator]\\n    Routes --&gt; Workflow\\n    Bootstrap --&gt; Jobs[Background schedulers]\\n    Jobs --&gt; Notifications[Runtime trace and InfoFlow notifications]\\n    Routes --&gt; External[GitCase and BOS clients]\\n```\\n\\n## Server startup\\n\\n`startServer(opts?: ServerOptions)` owns the complete server lifecycle.\\n\\n### `ServerOptions`\\n\\n```ts\\nexport interface ServerOptions {\\n  webDistPath?: string;\\n  port?: number;\\n  skipPlatformAdapters?: boolean;\\n}\\n```\\n\\n- `webDistPath` overrides the production web distribution directory. This is useful for the CLI binary, which may download the web assets separately.\\n- `port` overrides the automatically selected port. Valid ports are `1` through `65535`.\\n- `skipPlatformAdapters` starts only the Web/API server and disables Telegram, Discord, Slack, GitHub, Gitea, and GitLab initialization.\\n\\n### Bootstrap order\\n\\nThe module deliberately performs environment setup before importing application components that read configuration:\\n\\n1. `@archon/paths/strip-cwd-env-boot` removes environment variables automatically loaded from the current working directory by Bun.\\n2. Development/source builds load the repository `.env` using `dotenv`.\\n3. `loadArchonEnv(process.cwd())` loads user-scoped and repository-scoped Archon configuration:\\n   - `~/.archon/.env`\\n   - `/.archon/.env`\\n4. The repository-scoped Archon file overrides the user-scoped file.\\n5. If no Claude credentials are explicitly configured, `CLAUDE_USE_GLOBAL_AUTH` defaults to `true`.\\n6. `registerBuiltinProviders()` and `registerCommunityProviders()` initialize the provider registry before any provider lookup occurs.\\n\\nThis ordering is important when the server is started from inside a target repository. Repository credentials must not leak into the server process before Archon\u2019s environment loader takes effect.\\n\\n### Credential validation\\n\\nThe server accepts either Claude or Codex credentials:\\n\\n- Claude:\\n  - `CLAUDE_API_KEY`\\n  - `CLAUDE_CODE_OAUTH_TOKEN`\\n  - `CLAUDE_USE_GLOBAL_AUTH`\\n- Codex:\\n  - `CODEX_ID_TOKEN`\\n  - `CODEX_ACCESS_TOKEN`\\n\\nIf neither provider has credentials, startup logs `no_ai_credentials` and exits. Missing credentials for one provider produce warnings, but do not prevent startup when the other provider is configured.\\n\\nThe database is checked with `SELECT 1`, and `runMigrations()` is then executed. Migration failures are fatal.\\n\\n### Startup initialization\\n\\nAfter the database is available, `startServer()` initializes:\\n\\n- `startEvaluationWorker()`\\n- SLA rollup refresh scheduling\\n- `syncBundledWorkflowsToDB()`\\n- `syncBundledCommandsToDB()`\\n- `migrateUserWorkflowsToDB()`\\n- `syncUgateTokensToFiles()`\\n- `startCodebaseRestoreService()`\\n- Core configuration through `loadConfig()` and `logConfig()`\\n- Cleanup scheduling through `startCleanupScheduler()`\\n- Runtime trace retention\\n- Conversation concurrency control through `ConversationLockManager`\\n- Web transport and persistence\\n- Workflow trace recording and export\\n- Knowledge sync dispatch\\n- Workflow notifications\\n- SLA InfoFlow notifications\\n- Scheduled task execution\\n\\nSome startup tasks are intentionally non-blocking. For example, codebase restoration and orphaned workflow recovery run in the background so network or repository failures do not prevent the HTTP server from becoming available.\\n\\n## Web server and API routes\\n\\nThe server uses `OpenAPIHono` from `@hono/zod-openapi`.\\n\\n### Request handling\\n\\nA global validation hook is configured with `validationErrorHook`. The application also installs:\\n\\n- A global `app.onError()` handler that logs request failures and returns:\\n  ```json\\n  { \\\"error\\\": \\\"Internal server error\\\" }\\n  ```\\n- Request-header debug logging for every request.\\n\\n### Route registration\\n\\nThe following route groups are registered during startup:\\n\\n- `registerApiRoutes()`\\n  - Web UI API\\n  - Conversation and workflow operations\\n  - Orchestrator dispatch support\\n- `registerAuthRoutes()`\\n  - UUAP authentication\\n- `registerProductSpaceRoutes()`\\n  - Product Space management\\n- `registerKnowledgeRoutes()`\\n- `registerKnowledgeChatRoutes()`\\n- `registerKnowledgeProxyRoutes()`\\n  - Proxying requests to the AI-Ku knowledge service\\n- `registerWebhookRoutes()`\\n  - GitHub, Gitea, and GitLab webhook processing\\n- `registerHealthRoutes()`\\n  - Health and active-platform reporting\\n\\n`registerApiRoutes()` returns route helpers, including `dispatchToOrchestrator`. That dispatcher is also passed to `recoverOrphanedWorkflows()` after the server starts listening.\\n\\n### Static web UI\\n\\nIn production, or whenever `WEB_UI_DEV` is not set, the server serves the web bundle:\\n\\n- `/assets/*`\\n- `/logo.png`\\n- An SPA fallback for unmatched routes\\n\\nThe web directory defaults to a path derived from `import.meta.dir`, but can be overridden with `ServerOptions.webDistPath`.\\n\\nBefore serving `index.html`, the server calls:\\n\\n- `buildRuntimeConfig()`\\n- `injectRuntimeConfig()`\\n\\nThis injects `window.__RUNTIME_CONFIG__` into the HTML, allowing one static image to use environment-specific runtime settings such as `INFOFLOW_CHAT_URL`.\\n\\n### Listening configuration\\n\\nThe server binds to:\\n\\n- `HOST`, defaulting to `0.0.0.0`\\n- An explicit `opts.port`, or the result of `getPort()`\\n\\n`Bun.serve()` uses an idle timeout of 255 seconds, the maximum supported value, to avoid terminating long-lived SSE connections.\\n\\n## Web conversations and streaming\\n\\nThe Web integration is always enabled.\\n\\nThe components are connected as follows:\\n\\n1. `SSETransport` manages server-sent event connections.\\n2. `MessagePersistence` buffers and persists conversation events.\\n3. `WorkflowEventBridge` converts workflow events into transport events.\\n4. `WebAdapter` combines these components and starts the web integration.\\n\\nThe transport and persistence objects use callbacks that reference each other. These references are safe because the callbacks are invoked asynchronously after construction.\\n\\nWhen an SSE client disconnects, the transport cleanup callback calls `persistence.flush(conversationId)`. It flushes rather than clears the conversation mapping because workflow execution may continue after the client disconnects.\\n\\n`persistence.startPeriodicFlush()` periodically writes buffered messages. During shutdown, `flushAll()` runs before adapters and the database pool are stopped.\\n\\n## Platform adapters\\n\\nPlatform integrations are initialized conditionally from environment variables. Each adapter feeds messages into the common `handleMessage()` workflow path.\\n\\n`activePlatforms` is a mutable array shared with the health route. It starts with `Web`, and each successfully started adapter appends its platform name. It must remain a live reference because some adapters, notably Telegram, start after the HTTP listener begins accepting requests.\\n\\n### GitHub\\n\\nEnabled when both are configured:\\n\\n- `GITHUB_TOKEN`\\n- `WEBHOOK_SECRET`\\n\\nThe server creates a `GitHubAdapter` with:\\n\\n- GitHub token\\n- Webhook secret\\n- `ConversationLockManager`\\n- Bot mention, resolved from:\\n  - `GITHUB_BOT_MENTION`\\n  - `BOT_DISPLAY_NAME`\\n  - `config.botName`\\n\\nThe adapter is started before webhook routes are registered.\\n\\n### Gitea\\n\\nEnabled when all are configured:\\n\\n- `GITEA_URL`\\n- `GITEA_TOKEN`\\n- `GITEA_WEBHOOK_SECRET`\\n\\n`GiteaAdapter` receives the same lock manager and bot-mention fallback pattern as GitHub.\\n\\n### GitLab\\n\\nEnabled when both are configured:\\n\\n- `GITLAB_TOKEN`\\n- `GITLAB_WEBHOOK_SECRET`\\n\\n`GITLAB_URL` is optional and is passed to `GitLabAdapter` when present.\\n\\n### Discord\\n\\nEnabled with `DISCORD_BOT_TOKEN`.\\n\\n`DiscordAdapter` supports:\\n\\n- `DISCORD_STREAMING_MODE=stream|batch`, defaulting to `batch`\\n- Mention-gated activation in guild channels\\n- Direct-message activation without a mention\\n- Automatic thread creation through `ensureThread()`\\n- Thread history context\\n- Parent channel context inheritance\\n\\nFor each accepted message, the handler:\\n\\n1. Resolves the conversation ID.\\n2. Ignores empty content.\\n3. Ignores unmentioned guild messages.\\n4. Removes the bot mention.\\n5. Ensures the message is in a thread.\\n6. Loads prior thread history, excluding the current message.\\n7. Resolves the parent channel.\\n8. Acquires the conversation lock.\\n9. Calls `handleMessage()` asynchronously.\\n\\nDiscord startup failures are isolated. Invalid tokens and missing privileged intents are logged, but the Web server remains available and the Discord adapter is discarded.\\n\\n### Slack\\n\\nEnabled when both are configured:\\n\\n- `SLACK_BOT_TOKEN`\\n- `SLACK_APP_TOKEN`\\n\\n`SlackAdapter` supports `SLACK_STREAMING_MODE=stream|batch`, defaulting to `batch`.\\n\\nSlack messages follow the same common workflow path as Discord:\\n\\n- Empty messages are ignored.\\n- Bot mentions are stripped.\\n- Thread history is loaded when applicable.\\n- Parent conversation context is passed to `handleMessage()`.\\n- `ConversationLockManager` provides concurrency control.\\n\\nUnlike Discord, Slack startup errors are not wrapped in a local `try/catch` in `startServer()`. A configuration or login error can therefore reject server startup.\\n\\n### Telegram\\n\\nEnabled with `TELEGRAM_BOT_TOKEN`.\\n\\nThe default mode is `stream`; override it with `TELEGRAM_STREAMING_MODE=stream|batch`.\\n\\nTelegram authentication is handled internally by `TelegramAdapter`. Incoming messages are dispatched through `ConversationLockManager` and `handleMessage()`.\\n\\nTelegram starts after the HTTP listener is active. If it fails to start, the server logs `telegram.start_failed`, removes the adapter, and continues without Telegram.\\n\\n### Message error handling\\n\\n`createMessageErrorHandler(platform, adapter, conversationId)` creates a platform-specific asynchronous error callback.\\n\\nWhen processing fails:\\n\\n1. The error is logged as `message_processing_failed`.\\n2. `classifyAndFormatError()` creates a user-facing error message.\\n3. The adapter sends that message to the conversation.\\n4. A second failure while sending the error is logged as `error_message_send_failed`.\\n\\n### Unhandled promise rejections\\n\\n`handleUnhandledRejection()` implements fail-fast behavior:\\n\\n- Rejections containing `Operation aborted` are treated as Claude SDK cleanup races and logged without exiting.\\n- All other unhandled rejections are logged at fatal level and terminate the process.\\n\\nThis exception is needed because an SDK `PostToolUse` hook can attempt to write to a subprocess pipe after a DAG node has already been aborted.\\n\\n## Concurrency control\\n\\n`ConversationLockManager` is initialized with `MAX_CONCURRENT_CONVERSATIONS`, defaulting to `12`.\\n\\nThe limit is a real backpressure gate. It controls how many conversations or workflows can run concurrently; excess work waits in a queue. The default leaves capacity for health checks, conversation creation, and other database operations.\\n\\nThe configured value should generally remain near the database pool capacity. Setting it too high can cause concurrent workflows to exhaust the database pool and event loop.\\n\\n## Background services\\n\\n### Runtime trace retention\\n\\n`startRuntimeTraceRetentionScheduler()` obtains the policy from `runtime.getRuntimeTracePolicy()` and immediately calls `runtimeTraceDb.enforceRuntimeTraceRetention()`.\\n\\nIt then repeats every six hours. The scheduler logs deletion, archival, and archival failures when work was performed.\\n\\n`stopRuntimeTraceRetentionScheduler()` clears the timer during shutdown.\\n\\n### Runtime trace alerts\\n\\n`startRuntimeTraceAlertScheduler()` is enabled by default unless:\\n\\n```text\\nARCHON_TRACE_ALERT_ENABLED=false\\n```\\n\\nConfiguration:\\n\\n- `ARCHON_TRACE_ALERT_TARGETS`\\n  - Comma-separated targets\\n  - Defaults to `web`\\n- `ARCHON_TRACE_ALERT_WINDOW_MINUTES`\\n  - Defaults to `15`\\n- `ARCHON_TRACE_ALERT_INTERVAL_SECONDS`\\n  - Defaults to `60`\\n- `ARCHON_TRACE_ALERT_COOLDOWN_MINUTES`\\n  - Defaults to `15`\\n\\nThe scheduler:\\n\\n1. Calls `runtimeTraceDb.buildRuntimeTraceAlertsForWindow()`.\\n2. Persists candidates with `recordRuntimeTraceAlerts()`.\\n3. Ignores informational or inactive alerts.\\n4. Applies an in-memory cooldown keyed by `alert.dedupe_key`.\\n5. Emits a `runtime_trace_alert` event on `getRuntimeTraceEventBus()`.\\n6. Sends the alert to configured Slack, Telegram, or webhook targets.\\n\\nSlack and Telegram require both an enabled target and a destination:\\n\\n- Slack: `ARCHON_TRACE_ALERT_SLACK_CHANNEL`\\n- Telegram: `ARCHON_TRACE_ALERT_TELEGRAM_CHAT`\\n\\nWebhook targets are read from `ARCHON_TRACE_ALERT_WEBHOOK_URLS`. Only HTTP and HTTPS URLs are accepted. Requests are sent concurrently with `Promise.allSettled()` so one webhook failure does not prevent delivery to others.\\n\\n### SLA rollup refresh\\n\\n`startSlaRollupRefreshScheduler()` immediately invokes `observabilityDb.refreshDirtySlaRollupBuckets()` and repeats every five seconds.\\n\\nThe refresh is intentionally prompt even when no dashboard request is active. Source-row triggers perform invalidation; this scheduler drains dirty five-minute buckets.\\n\\nThe scheduler is stopped by `stopSlaRollupRefreshScheduler()`.\\n\\n### Knowledge sync recovery\\n\\n`startWorkflowRunKnowledgeSyncDispatcher()` runs once immediately and then every 60 seconds.\\n\\nIt:\\n\\n- Reads at most 20 pending knowledge-sync run IDs.\\n- Dispatches each with `dispatchWorkflowRunToAiKu()`.\\n- Does not retry jobs in an `unknown` state because the remote service may already have accepted them.\\n- Prevents overlapping scans with a local `running` flag.\\n- Logs individual dispatch failures and scan failures without terminating the server.\\n\\nThe returned stop function clears the interval.\\n\\n### Scheduled tasks\\n\\n`startScheduledTaskScheduler(buildScheduledTaskDeps())` starts the core scheduled-task runner. Due tasks create orchestration sessions; the orchestration service calls back through HTTP to trigger workflow runs.\\n\\n`stopScheduledTaskScheduler()` is called during graceful shutdown.\\n\\n### Workflow recovery\\n\\nAfter `server_listening` is logged, `recoverOrphanedWorkflows()` scans rows left in `running` state by a previous process generation.\\n\\nRecovery is best-effort and does not block startup. Configuration options include:\\n\\n- `WORKFLOW_MAX_RESTART_RECOVERY`\\n- `WORKFLOW_RESTART_RECOVERY_STAGGER_MS`\\n- `WORKFLOW_RESTART_RECOVERY_MAX_AGE_DAYS`\\n\\nRuns that cannot be safely re-dispatched remain available for cancellation or abandonment through the Web UI or CLI.\\n\\n## InfoFlow integration\\n\\nInfoFlow is used for workflow approval commands and SLA notifications.\\n\\n### Sending messages\\n\\n`sendInfoflowMessage()` accepts:\\n\\n```ts\\nexport interface SendInfoflowMessageInput {\\n  chatType: 'single' | 'group';\\n  target: string;\\n  content: string;\\n  atUserIds?: readonly string[];\\n  clientMessageId?: string | number;\\n}\\n```\\n\\nRequired credentials:\\n\\n- `INFOFLOW_AK`\\n- `INFOFLOW_SK`\\n\\nOptional configuration:\\n\\n- `INFOFLOW_BASE_URL`\\n- `INFOFLOW_TOKEN_BASE_URL`\\n- `INFOFLOW_GROUP_BASE_URL`\\n- `INFOFLOW_TIMEOUT_SECONDS`\\n\\nDefaults:\\n\\n- Single-chat base URL: `https://apiin.im.baidu.com`\\n- Group-chat base URL: `https://open-ruliu.baidu-int.com/open-plat`\\n\\nSingle messages are sent as Markdown (`msgtype: 'md'`). Group messages can include mentions and a client message ID.\\n\\n### InfoFlow webhook verification\\n\\n`services/infoflow-webhook.ts` handles encrypted InfoFlow callbacks.\\n\\nConfiguration is loaded by `readInfoflowWebhookConfig()`:\\n\\n- `INFOFLOW_CHECK_TOKEN`\\n- `INFOFLOW_ENCODING_AES_KEY`\\n\\nThe callback flow is:\\n\\n1. `verifyInfoflowCallbackUrl()` verifies the signed URL and decrypts `echoStr` during endpoint registration.\\n2. `decryptInfoflowCallback()` extracts `` from the XML body.\\n3. `verifyInfoflowSignature()` checks the SHA-1 signature using a timing-safe comparison.\\n4. `decryptInfoflowPayload()` decrypts the AES-256-CBC payload.\\n5. `parseInfoflowPlainMessage()` extracts message fields from XML.\\n6. `parseInfoflowCommand()` recognizes approval commands.\\n7. `handleInfoflowIncomingMessage()` loads the workflow run and calls:\\n   - `approveWorkflowRunAndResume()`\\n   - `rejectWorkflowRunAndResume()`\\n   - `breakpointRetryWorkflowRunAndResume()`\\n\\nSupported command forms include:\\n\\n```text\\napprove  [comment]\\nreject  [comment]\\nretry \\n/workflow approve  [comment]\\n\u6279\u51c6  [comment]\\n\u62d2\u7edd  [comment]\\n\u91cd\u8bd5 \\n```\\n\\nUnrecognized content returns `{ handled: false }`.\\n\\n### SLA notifications\\n\\n`startSlaInfoflowNotifier()` is disabled unless:\\n\\n```text\\nINFOFLOW_SLA_NOTIFY_ENABLED=true\\n```\\n\\nIt also requires:\\n\\n- `NODE_ENV=production`\\n- PostgreSQL\\n- A target from `INFOFLOW_SLA_NOTIFY_TARGET` or `BAIDU_CC_USERNAME`\\n\\nThe notifier can provide three notification types:\\n\\n1. Workflow self-node failures\\n2. Daily SLA summaries\\n3. SLA threshold breach alerts\\n\\nConfiguration includes:\\n\\n- `INFOFLOW_SLA_NOTIFY_CHAT_TYPE=single|group`\\n- `INFOFLOW_SLA_NOTIFY_AT_USER_IDS`\\n- `INFOFLOW_SLA_WORKFLOW_ERROR_NOTIFY_ENABLED`\\n- `INFOFLOW_SLA_DAILY_SUMMARY_ENABLED`\\n- `INFOFLOW_SLA_DAILY_SUMMARY_HOUR`\\n- `INFOFLOW_SLA_DAILY_SUMMARY_MINUTE`\\n- `INFOFLOW_SLA_BREACH_ALERT_ENABLED`\\n- `INFOFLOW_SLA_BREACH_THRESHOLD_PERCENT`\\n- `ARCHON_FRONTEND_URL`\\n\\nDelivery is deduplicated through database delivery records:\\n\\n- `claimSlaNotificationDelivery()`\\n- `markSlaNotificationDeliverySent()`\\n- `markSlaNotificationDeliveryFailed()`\\n\\nGroup messages use the claimed delivery ID as `clientMessageId`.\\n\\n#### Workflow failure notifications\\n\\nA real-time poll runs every 30 seconds and reads persisted workflow failures in batches of 100. It uses a one-minute overlap and a `(occurred_at, id)` cursor to avoid missing events across polling boundaries.\\n\\nMessages are formatted by `buildSlaInfoflowContent()`. `inferSlaWorkflowRootCauseInsight()` classifies common failures, including:\\n\\n- Control-plane or service connection timeouts\\n- Missing workflow commands\\n- Missing local CLI dependencies\\n- Sandbox lifecycle failures\\n- Node execution timeouts\\n- Provider streaming failures\\n- Bash/script failures\\n- Generic workflow-node failures\\n\\nCredentials are sanitized before error text is included in notifications.\\n\\n#### Daily summaries\\n\\n`startDailySlaSummaryScheduler()` schedules the next summary in Beijing time. The default schedule is 10:00 Asia/Shanghai and can be changed with:\\n\\n- `INFOFLOW_SLA_DAILY_SUMMARY_HOUR`\\n- `INFOFLOW_SLA_DAILY_SUMMARY_MINUTE`\\n\\n`buildSlaDailySummaryContent()` aggregates SLA, traffic, and probe metrics and includes the most significant workflow issues.\\n\\n#### Threshold alerts\\n\\n`startSlaBreachMonitor()` evaluates a 24-hour window every five minutes. The default threshold is 99%, configurable through `INFOFLOW_SLA_BREACH_THRESHOLD_PERCENT`.\\n\\n`evaluateSlaThresholdBreaches()` evaluates:\\n\\n- User-perceived SLA\\n- Environment stability\\n- System stability\\n- Workflow stability\\n\\nAn alert is sent only when the observability data has complete bucket coverage. `claimSlaBreachEpisode()` ensures one alert is generated per breach episode; `resolveSlaBreachEpisode()` marks the episode recovered after all metrics return above the threshold.\\n\\n## GitCase client\\n\\n`packages/server/src/gitcase-client.ts` provides a shared client for the internal GitCase test-case management platform.\\n\\nThe base URL is configured through `GITCASE_BASE_URL` and defaults to:\\n\\n```text\\nhttp://10.11.87.162:80\\n```\\n\\nRequests include the service headers:\\n\\n- `baidu-service-name`\\n- `baidu-service-token`\\n- `baidu-service-username`\\n\\nThese values come from:\\n\\n- `GITCASE_SERVICE_NAME`\\n- `GITCASE_SERVICE_TOKEN`\\n- `GITCASE_SERVICE_USERNAME`\\n\\nA per-call `username` argument overrides the service username, allowing routes to operate on behalf of the logged-in user.\\n\\n### Generic request helpers\\n\\n- `gitcaseGet()`\\n  - Performs a JSON GET.\\n  - Includes query parameters.\\n  - Throws with status, URL, and response body on non-2xx responses.\\n  - Throws with response metadata when the body is not JSON.\\n- `gitcaseGetList()`\\n  - Applies default pagination:\\n    - `page=0`\\n    - `size=500`\\n    - `sort=id,desc`\\n  - Unwraps arrays, `{ data: [] }`, and Spring-style `{ data: { content: [] } }` responses.\\n- `gitcasePost()`\\n  - Sends a JSON body with query parameters.\\n- `gitcasePostRaw()`\\n  - Sends a body without query parameters.\\n  - Supports already-stringified payloads and raw array bodies.\\n\\n### Case and tag operations\\n\\nThe client exposes helpers used by `routes/api/gitcase.ts`:\\n\\n- `gitcaseBulkCreateCases()`\\n- `gitcaseBulkAppendLabels()`\\n- `gitcaseBulkReplaceLabels()`\\n- `gitcaseGetSpaceTags()`\\n- `gitcaseAddSpaceTag()`\\n- `gitcaseListCases()`\\n- `gitcaseGetCasesDetail()`\\n\\n`gitcaseGetSpaceTags()` returns an empty array on failure. `gitcaseAddSpaceTag()` returns `-1` on failure; other request helpers throw so callers can decide how to handle upstream errors.\\n\\n`gitcaseListCases()` uses `gitcasePost()` because the endpoint requires both filters in the request body and pagination/filter parameters in the query string.\\n\\n## Baidu Object Storage client\\n\\n`packages/server/src/bos-client.ts` wraps the Baidu Cloud BOS SDK.\\n\\nThe BOS client is lazily created by `getBosClient()` and cached for the process lifetime. Required configuration:\\n\\n- `BCE_BOS_ENDPOINT`\\n- `BCE_ACCESS_KEY_ID`\\n- `BCE_SECRET_ACCESS_KEY`\\n- `BCE_BOS_BUCKET`\\n\\nThe endpoint may be supplied with or without a protocol. Missing configuration produces an explicit error.\\n\\n### Object operations\\n\\n- `getBosObjectContent(bosPath)`\\n  - Downloads an object.\\n  - Returns its `Buffer`, content type, and response metadata.\\n- `uploadToBos(key, content, contentType?)`\\n  - Uploads a string with `putObjectFromString()`.\\n  - Uploads a `Buffer` with `putObject()`.\\n  - Returns `{ key, bucket }`.\\n- `uploadFileToBos(key, filePath, contentType?)`\\n  - Uploads a local file with `putObjectFromFile()`.\\n- `generateBosPresignedUrl(key, expiresInSeconds?)`\\n  - Generates a signed URL.\\n  - Defaults to 1,800 seconds.\\n\\nThe workflow exporter uses `uploadToBos()` and `uploadFileToBos()` when dispatching workflow runs to AI-Ku. The case-info API uses `uploadToBos()` for file synchronization.\\n\\n## Workflow and command synchronization\\n\\n### Bundled workflows\\n\\n`syncBundledWorkflowsToDB()` imports `BUNDLED_WORKFLOWS` as system-scoped workflows.\\n\\nFor each workflow it:\\n\\n1. Parses the YAML with `parseWorkflow()` to obtain a description.\\n2. Uses `getDefaultWorkflowsPath()` to provide a source path for parsing.\\n3. Calls `upsertSystemWorkflow()`.\\n4. Logs per-item failures and a summary.\\n\\nParsing failures are warnings; the workflow is still synchronized with a null description when possible.\\n\\nThe operation is idempotent and does not modify product-scoped forks.\\n\\n### Bundled commands\\n\\n`syncBundledCommandsToDB()` imports `BUNDLED_COMMANDS` as system commands.\\n\\nIt:\\n\\n1. Extracts descriptions using `extractCommandDescription()`.\\n2. Looks up existing commands with `getSystemCommandByName()`.\\n3. Creates missing commands with `createSystemCommand()`.\\n4. Updates changed content or descriptions with `updateSystemCommand()`.\\n5. Reports inserted, updated, unchanged, and failed counts.\\n\\n### Project workflows\\n\\n`syncProjectWorkflowsToDB(codebaseId, productId, cwd)` discovers project workflow files with:\\n\\n```ts\\ndiscoverWorkflows(cwd, { loadDefaults: false })\\n```\\n\\nOnly entries with `source === 'project'` are imported. Existing database records always win; the function inserts only names absent from `listProjectWorkflowNames(productId, codebaseId)`.\\n\\nDiscovery and individual insert failures are logged and do not abort the entire synchronization.\\n\\n### Legacy user workflows\\n\\n`migrateUserWorkflowsToDB()` migrates rows from `remote_agent_user_workflows` into product-scoped workflows.\\n\\nBehavior:\\n\\n- Detects PostgreSQL and SQLite separately.\\n- Skips silently when the legacy table does not exist.\\n- Resolves the owner username through `remote_agent_users`.\\n- Creates a deterministic legacy product space ID using `legacyProductId(ownerUserId)`.\\n- Ensures the owner is a `product_admin`.\\n- Inserts workflows idempotently.\\n- Preserves original timestamps and definitions.\\n\\nPostgreSQL uses `ON CONFLICT DO NOTHING`. SQLite checks for an existing product/name pair before inserting.\\n\\n## Runtime configuration injection\\n\\n`runtime-config.ts` bridges build-time front-end configuration and deployment-time environment variables.\\n\\n`buildRuntimeConfig(env = process.env)` currently exposes:\\n\\n```ts\\ninterface RuntimeConfig {\\n  infoflowChatUrl?: string;\\n}\\n```\\n\\nThe value comes from `INFOFLOW_CHAT_URL`.\\n\\n`injectRuntimeConfig(html, config)` serializes the configuration and escapes `&lt;` as `\\\\u003c` before inserting:\\n\\n```html\\nwindow.__RUNTIME_CONFIG__={...};&lt;\\/script&gt;\\n```\\n\\nThe script is inserted immediately before `&lt;\\/head&gt;`, or prepended when no head tag exists.\\n\\n## Graceful shutdown\\n\\nThe shutdown handler registered for `SIGINT` and `SIGTERM` stops services in dependency order:\\n\\n1. Cleanup scheduler\\n2. Runtime trace retention\\n3. SLA rollup refresh\\n4. Scheduled tasks\\n5. Evaluation worker\\n6. Runtime trace alert scheduler\\n7. Workflow trace recorder\\n8. Workflow run exporter\\n9. Knowledge sync dispatcher\\n10. Workflow notification listener\\n11. SLA InfoFlow notifier\\n12. Message persistence periodic flush\\n13. Full message flush\\n14. Telegram, Discord, Slack, Gitea, and GitLab adapters\\n15. `WebAdapter`\\n16. Telemetry through `shutdownTelemetry()`\\n17. Database pool through `pool.end()`\\n\\nThe process exits with status `0` after a successful pool close and status `1` if closing the pool fails.\\n\\nWhen adding a long-running service to this module, return a stop function and invoke it from `shutdown()` to avoid orphaned timers, open connections, or incomplete message persistence.\",\"authentication-and-identity\":\"# Authentication and Identity\\n\\n# Authentication and Identity\\n\\nThe Authentication and Identity module provides two related authentication layers:\\n\\n- **Application identity** in `packages/server/src/routes/auth.ts`, using UUAP SSO or test credentials to issue system JWTs.\\n- **Optional perimeter authentication** in `auth-service/server.js`, a standalone username/password service intended for reverse-proxy `forward_auth` integration.\\n\\nThe web application persists the system JWT in a Zustand store and uses it to access protected application APIs. Server-side identity is represented by a local user record linked to a UUAP username.\\n\\n## Architecture\\n\\n```mermaid\\nflowchart LR\\n  Browser[Web application]\\n  Guard[ProtectedRoute]\\n  Store[useAuthStore]\\n  AuthRoutes[Auth API routes]\\n  UUAP[UUAP SSO]\\n  UserDB[Auth database]\\n  Spaces[Personal spaces]\\n  UgateFiles[Local ugate token files]\\n\\n  Browser --&gt; Guard\\n  Guard --&gt; Store\\n  Store --&gt;|Bearer JWT| AuthRoutes\\n  AuthRoutes --&gt; UUAP\\n  AuthRoutes --&gt; UserDB\\n  AuthRoutes --&gt; Spaces\\n  AuthRoutes --&gt; UgateFiles\\n```\\n\\nThe optional `auth-service` is separate from this flow. It authenticates browser requests at a proxy boundary using a signed cookie; it does not create Archon JWTs or local user records.\\n\\n---\\n\\n## Server Auth Routes\\n\\n`registerAuthRoutes(app)` registers the OpenAPI-described routes on an `OpenAPIHono` application. It is called by server startup, along with `syncUgateTokensToFiles()`.\\n\\nThe module uses:\\n\\n- `UuapClient` from `@archon/auth/uuap/client` for UUAP ticket and session validation.\\n- `signToken()` from `@archon/auth/jwt` to issue application JWTs.\\n- `requireAuth` from `@archon/auth/middleware` to validate Bearer JWTs and populate `c.get('userId')`.\\n- User and token persistence functions from `@archon/auth/db`.\\n- `ensurePersonalSpace()` from `@archon/core/db/product-spaces` to provision a user\u2019s personal space on first authenticated login.\\n\\n### Route Protection\\n\\nRoutes requiring the system JWT are registered after `app.use(path, requireAuth)`. Authenticated handlers retrieve the authenticated local user ID through:\\n\\n```ts\\nconst userId = c.get('userId');\\n```\\n\\nThey then look up the user with `getUserById(userId)` where needed.\\n\\nProtected endpoints require an `Authorization` header containing a Bearer JWT:\\n\\n```http\\nAuthorization: Bearer \\n```\\n\\nThe following endpoints are protected:\\n\\n- `GET /api/auth/me`\\n- `GET`, `POST`, and `DELETE /api/auth/ugate-token`\\n- `GET /api/auth/ugate-token/users`\\n- `GET` and `PUT /api/auth/icafe-space`\\n\\n`POST /api/auth/logout` is intentionally stateless and does not invalidate a JWT.\\n\\n---\\n\\n## Authentication Flows\\n\\n### UUAP Browser SSO\\n\\nThe browser SSO flow begins at `GET /api/auth/uuap`.\\n\\n1. The handler calls `getUuapConfig()` to read UUAP configuration.\\n2. It builds a callback URL using:\\n   - `ARCHON_EXTERNAL_URL`, when set; otherwise,\\n   - the request origin.\\n3. It redirects the browser to `${UUAP_BASE_URL}/login` with the callback URL as the UUAP `service` parameter.\\n4. UUAP redirects to `GET /api/auth/uuap/callback` with a ticket.\\n5. The callback:\\n   - reads the configured UUAP pToken cookie;\\n   - exchanges the ticket with `UuapClient.exchangeTicket()`;\\n   - validates the resulting session through `UuapClient.verifySession(pToken, sToken)`;\\n   - creates or updates the local user with `findOrCreateUser()`;\\n   - provisions the user\u2019s personal product space with `ensurePersonalSpace()`;\\n   - issues an application JWT through `signToken(dbUser.id)`;\\n   - redirects to the frontend with `?token=`.\\n\\nThe callback selects the frontend origin from `ARCHON_FRONTEND_URL` when present, otherwise from the incoming request origin.\\n\\n#### Redirect Safety\\n\\nThe original desired frontend path is carried as `redirect` through the SSO flow. `toSafePath()` normalizes it to a path and optional query string before it is appended to the frontend origin. This prevents the callback from redirecting to an externally supplied host.\\n\\nAuthentication errors redirect to the login page:\\n\\n| Condition | Redirect |\\n| --- | --- |\\n| Missing ticket or missing UUAP pToken | `/login?error=auth_failed` |\\n| Invalid UUAP ticket/session | `/login?error=auth_failed` |\\n| Missing or unavailable UUAP configuration/service | `/login?error=uuap_unavailable` |\\n\\n### Programmatic UUAP Token Exchange\\n\\n`POST /api/auth/token-exchange` supports non-browser clients that already hold UUAP session credentials.\\n\\n```json\\n{\\n  \\\"pToken\\\": \\\"\u2026\\\",\\n  \\\"sToken\\\": \\\"\u2026\\\"\\n}\\n```\\n\\nThe handler:\\n\\n1. Loads UUAP configuration through `getUuapConfig()`.\\n2. Calls `UuapClient.verifySession(pToken, sToken, { apiToken: true })`.\\n3. Finds or creates the corresponding local user.\\n4. Ensures that user has a personal space.\\n5. Returns a system JWT.\\n\\nA missing UUAP configuration or failed UUAP validation returns `401`:\\n\\n```json\\n{\\n  \\\"error\\\": \\\"Invalid UUAP credentials\\\"\\n}\\n```\\n\\nFor configuration failures, the externally returned error is:\\n\\n```json\\n{\\n  \\\"error\\\": \\\"UUAP not configured\\\"\\n}\\n```\\n\\n### Test Authentication\\n\\nTest login is disabled unless:\\n\\n```bash\\nTEST_AUTH_ENABLED=true\\n```\\n\\nWhen enabled, `POST /api/auth/test-login` accepts one of two roles:\\n\\n```json\\n{\\n  \\\"role\\\": \\\"admin\\\"\\n}\\n```\\n\\nor:\\n\\n```json\\n{\\n  \\\"role\\\": \\\"user\\\"\\n}\\n```\\n\\nThe handler calls `ensureTestUser(role)`, then returns a JWT for that local test user.\\n\\n```json\\n{\\n  \\\"token\\\": \\\"\\\"\\n}\\n```\\n\\nWhen test auth is disabled, this route returns `404`. Invalid or missing roles return `400`.\\n\\n`GET /api/auth/config` is public and lets clients discover whether test login is available:\\n\\n```json\\n{\\n  \\\"testAuthEnabled\\\": false\\n}\\n```\\n\\nDo not enable `TEST_AUTH_ENABLED` in production environments.\\n\\n---\\n\\n## API Reference\\n\\nOpenAPI route definitions are declared with `createRoute()` and registered through the local `registerOpenApiRoute()` wrapper. The wrapper casts handlers because response schemas are used for OpenAPI generation rather than runtime response validation.\\n\\n### Login and Session Endpoints\\n\\n| Method | Path | Authentication | Description |\\n| --- | --- | --- | --- |\\n| `GET` | `/api/auth/config` | No | Returns whether test auth is enabled. |\\n| `GET` | `/api/auth/uuap` | No | Redirects the browser to UUAP login. |\\n| `GET` | `/api/auth/uuap/callback` | No | Completes UUAP ticket exchange and redirects to the frontend with a JWT. |\\n| `POST` | `/api/auth/token-exchange` | No | Exchanges UUAP pToken and sToken for a system JWT. |\\n| `POST` | `/api/auth/test-login` | No, feature-gated | Issues a JWT for a test user when enabled. |\\n| `GET` | `/api/auth/me` | Bearer JWT | Returns the current local user. |\\n| `POST` | `/api/auth/logout` | No | Returns `{ ok: true }`; the client must discard its token. |\\n\\n### Current User\\n\\n`GET /api/auth/me` returns the user associated with the JWT subject:\\n\\n```json\\n{\\n  \\\"id\\\": \\\"user-id\\\",\\n  \\\"uuapId\\\": \\\"uuap-username\\\",\\n  \\\"username\\\": \\\"username\\\",\\n  \\\"realName\\\": \\\"Display Name\\\",\\n  \\\"email\\\": \\\"user@example.com\\\",\\n  \\\"lastLogin\\\": \\\"2025-01-01T00:00:00.000Z\\\",\\n  \\\"createdAt\\\": \\\"2025-01-01T00:00:00.000Z\\\",\\n  \\\"role\\\": \\\"user\\\"\\n}\\n```\\n\\nThe response shape is defined by `userInfoSchema` and mirrored by the frontend `UserInfo` interface.\\n\\nA valid JWT whose user no longer exists returns `404` rather than `401`.\\n\\n### Logout\\n\\n`POST /api/auth/logout` always returns:\\n\\n```json\\n{\\n  \\\"ok\\\": true\\n}\\n```\\n\\nJWTs are stateless, so this endpoint does not revoke server-side state. The actual logout operation is client-side token removal through `useAuthStore.getState().logout()` or the `logout` action exposed by the hook.\\n\\n---\\n\\n## ugate Token Management\\n\\nugate tokens are stored in two places:\\n\\n1. In the auth database, associated with a username.\\n2. In a local file used by tools that need token access without querying the database.\\n\\nThe local token file is:\\n\\n```text\\n~/.config/uuap/.eac_ugate_token_{username}\\n```\\n\\nIts JSON contents are:\\n\\n```json\\n{\\n  \\\"token\\\": \\\"\\\",\\n  \\\"permanent\\\": true\\n}\\n```\\n\\n`writeUgateTokenFile()` creates the directory if necessary and writes files with mode `0o600`.\\n\\n### Save a ugate Token\\n\\n`POST /api/auth/ugate-token` accepts a pasted string, not a bare JWT:\\n\\n```json\\n{\\n  \\\"tokenInput\\\": \\\"ugate token: eyJhbGciOi...\\\"\\n}\\n```\\n\\n`extractJwtFromInput()` accepts either an ASCII or Chinese colon:\\n\\n```text\\nugate token: \\nugate token\uff1a\\n```\\n\\nIt extracts exactly three base64url JWT segments and ignores trailing prose. Invalid input returns `400` with an error explaining the expected format.\\n\\n`parseJwtUsername()` decodes the JWT payload and reads its `username` claim. It does **not** verify the ugate JWT signature; the claim is used only to choose a token filename and association. Usernames containing `/`, `\\\\`, or `.` are rejected to prevent path traversal.\\n\\n#### Test-User Dual Storage\\n\\nFor regular UUAP users, the authenticated application username and the username in the ugate JWT are expected to match.\\n\\nTest users are different: a test user might be named `admin` or `user`, while their submitted ugate JWT contains a real UUAP username. To make both UI lookup and tool lookup work, the save handler performs a dual write when the names differ:\\n\\n- Writes the token file for both usernames.\\n- Stores the token under both usernames in the database.\\n\\nThe authenticated username is the primary association used by `GET /api/auth/ugate-token`.\\n\\nDatabase failures after the filesystem write are logged but are non-fatal to the save request. This preserves the usable local token file even if token persistence is unavailable.\\n\\nSuccessful responses use `saveUgateTokenResultSchema`:\\n\\n```json\\n{\\n  \\\"ok\\\": true,\\n  \\\"username\\\": \\\"authenticated-username\\\"\\n}\\n```\\n\\n### Get Token Status\\n\\n`GET /api/auth/ugate-token` reports presence without returning the secret:\\n\\n```json\\n{\\n  \\\"configured\\\": true,\\n  \\\"masked\\\": \\\"****abcd\\\"\\n}\\n```\\n\\n`toUgateTokenStatus()` derives `configured` from whether a database token exists and exposes only its final four characters in `masked`.\\n\\n### Delete a Token\\n\\n`DELETE /api/auth/ugate-token` removes the current user\u2019s database record and local token file:\\n\\n```json\\n{\\n  \\\"configured\\\": false,\\n  \\\"masked\\\": null\\n}\\n```\\n\\nFor test users, the handler first parses the stored token to discover the embedded ugate username. If it differs from the authenticated username, the alternate database record and file are also removed on a best-effort basis.\\n\\n`deleteUgateTokenFile()` treats `ENOENT` as success, allowing deletion to succeed when the file was already absent.\\n\\n### List Configured Users\\n\\n`GET /api/auth/ugate-token/users` returns whether the **current user** has a configured token:\\n\\n```json\\n{\\n  \\\"users\\\": [\\\"current-username\\\"]\\n}\\n```\\n\\nDespite its route summary, it does not enumerate all users with tokens. It checks the caller\u2019s username via `hasUgateToken()` and either returns that one username or an empty array.\\n\\n### Startup Synchronization\\n\\n`syncUgateTokensToFiles()` restores database-backed token files at server startup.\\n\\n1. It calls `listAllUgateTokens()`.\\n2. For each `{ username, token }`, it calls `writeUgateTokenFile()`.\\n3. Individual write failures are logged and do not stop remaining tokens from syncing.\\n\\nIf the database token table is not yet available, the initial query failure is logged as a warning and synchronization is skipped. This supports startup before migrations have created the relevant table.\\n\\nCall this once during server initialization, not per request.\\n\\n---\\n\\n## iCafe Space Configuration\\n\\nThe iCafe space preference is stored per username and is dependent on a configured ugate token.\\n\\n| Method | Path | Description |\\n| --- | --- | --- |\\n| `GET` | `/api/auth/icafe-space` | Returns the current user\u2019s configured `prefixCode`, or `null`. |\\n| `PUT` | `/api/auth/icafe-space` | Sets or clears the current user\u2019s iCafe space. |\\n\\n### Read Configuration\\n\\n`GET /api/auth/icafe-space` returns:\\n\\n```json\\n{\\n  \\\"icafeSpace\\\": \\\"prefix-code\\\"\\n}\\n```\\n\\nIf the JWT references a missing local user, it returns:\\n\\n```json\\n{\\n  \\\"icafeSpace\\\": null\\n}\\n```\\n\\n### Set or Clear Configuration\\n\\n`PUT /api/auth/icafe-space` accepts:\\n\\n```json\\n{\\n  \\\"icafeSpace\\\": \\\"prefix-code\\\"\\n}\\n```\\n\\nTo clear the value:\\n\\n```json\\n{\\n  \\\"icafeSpace\\\": null\\n}\\n```\\n\\nThe handler trims non-null input and converts an empty string to `null` before calling `setIcafeSpace()`.\\n\\nA user must save a ugate token before configuring iCafe space. Otherwise, the endpoint returns `400`:\\n\\n```json\\n{\\n  \\\"error\\\": \\\"\u8bf7\u5148\u4fdd\u5b58 ugate token \u518d\u914d\u7f6e iCafe \u7a7a\u95f4\\\"\\n}\\n```\\n\\n---\\n\\n## Configuration\\n\\n### UUAP Configuration\\n\\n`getUuapConfig()` reads the following environment variables:\\n\\n| Variable | Required | Default | Purpose |\\n| --- | --- | --- | --- |\\n| `UUAP_APP_KEY` | Yes | \u2014 | UUAP application key. |\\n| `UUAP_SECRET_KEY` | Yes | \u2014 | UUAP application secret. |\\n| `UUAP_BASE_URL` | No | `https://uuap.baidu.com` | UUAP server base URL. |\\n| `UUAP_P_TOKEN_NAME` | No | `UUAP_P_TOKEN` | Cookie name containing the UUAP pToken. |\\n| `ARCHON_EXTERNAL_URL` | No | Request origin | Public server URL used to build the UUAP callback URL. |\\n| `ARCHON_FRONTEND_URL` | No | Request origin | Frontend origin used after successful callback. |\\n| `TEST_AUTH_ENABLED` | No | disabled | Enables `POST /api/auth/test-login` only when exactly `true`. |\\n\\n`UUAP_APP_KEY` and `UUAP_SECRET_KEY` are required for UUAP browser login and token exchange. Missing configuration is handled per-request so the application can still run in environments that use test auth or do not need UUAP.\\n\\n---\\n\\n## Web Client Integration\\n\\n### `useAuthStore`\\n\\n`packages/web/src/stores/auth-store.ts` defines the persisted authentication state.\\n\\n```ts\\ninterface AuthState {\\n  token: string | null;\\n  userInfo: UserInfo | null;\\n  setToken: (token: string) =&gt; void;\\n  setUserInfo: (user: UserInfo) =&gt; void;\\n  logout: () =&gt; void;\\n}\\n```\\n\\nThe Zustand store is persisted under the local-storage key:\\n\\n```text\\narchon-auth\\n```\\n\\nOnly `token` and `userInfo` are persisted through `partialize`.\\n\\n`logout()`:\\n\\n1. Clears the token and cached user information.\\n2. Redirects the browser to `/login`.\\n\\nIt does not need to call `POST /api/auth/logout`, because JWT invalidation is client-side in the current stateless design.\\n\\nThe storage factory handles non-browser or SSR-like runtimes by returning an in-memory no-op storage implementation if `window.localStorage` is unavailable.\\n\\n### `ProtectedRoute`\\n\\n`ProtectedRoute` in `packages/web/src/lib/auth-guard.tsx` wraps protected React Router routes.\\n\\nIts behavior is:\\n\\n1. If a stored token exists but `userInfo` is absent, call `getMe()` and cache the result with `setUserInfo()`.\\n2. If `?token=` is present but the token is not yet stored, render `null`.\\n   - This gives the application-level token receiver time to persist the callback token.\\n   - It prevents child components from issuing protected API requests before the Authorization header is available.\\n3. If no token exists, navigate to `/login`.\\n   - The requested path and query are retained in `redirect`.\\n4. If a token exists, render ``.\\n\\nThe redirect target is built from:\\n\\n```ts\\nconst target = `${location.pathname}${location.search}`;\\n```\\n\\nThis preserves nested protected routes and their query parameters through login.\\n\\n---\\n\\n## Optional Proxy Authentication Service\\n\\n`auth-service/server.js` is a standalone Node.js HTTP service. It is designed to be used by a reverse proxy, such as Caddy, as a `forward_auth` target.\\n\\nThis service is independent from the system JWT mechanism:\\n\\n- It does not call UUAP.\\n- It does not call `signToken()`.\\n- It does not use the Archon user database.\\n- It gates HTTP access using a signed browser cookie.\\n\\n### Configuration\\n\\n| Variable | Required | Default | Purpose |\\n| --- | --- | --- | --- |\\n| `AUTH_PORT` | No | `9000` | Service listen port. |\\n| `AUTH_USERNAME` | Yes | \u2014 | Accepted username. |\\n| `AUTH_PASSWORD_HASH` | Yes | \u2014 | bcrypt password hash. |\\n| `COOKIE_SECRET` | Yes | \u2014 | HMAC key for session-cookie signatures. |\\n| `COOKIE_MAX_AGE` | No | `86400` | Cookie lifetime in seconds. |\\n\\nThe service exits at startup if required values are missing or if `AUTH_PASSWORD_HASH` is not a valid bcrypt hash.\\n\\nThe source includes the hash-generation command:\\n\\n```bash\\ndocker compose --profile auth run --rm auth-service \\\\\\n  node -e \\\"require('bcryptjs').hash('YOUR_PASSWORD', 12).then(h =&gt; console.log(h))\\\"\\n```\\n\\n### Routes\\n\\n| Method | Path | Purpose |\\n| --- | --- | --- |\\n| `GET` | `/verify` | Reverse-proxy authorization check. |\\n| `GET` | `/login` | Displays the login form. |\\n| `POST` | `/login` | Verifies credentials and sets a session cookie. |\\n| Any | `/logout` | Clears the session cookie and redirects to `/login`. |\\n\\n### Cookie Handling\\n\\nThe cookie name is fixed as:\\n\\n```text\\narchon_auth\\n```\\n\\n`signCookie(value)` produces:\\n\\n```text\\nvalue.base64url-hmac-sha256-signature\\n```\\n\\n`verifyCookie(signed)` recomputes the HMAC and compares signatures with `timingSafeEqual()`. A valid login stores the signed value for the literal session value:\\n\\n```text\\nauthenticated\\n```\\n\\nCookies are issued with:\\n\\n```text\\nHttpOnly; Secure; SameSite=Lax; Path=/; Max-Age=\\n```\\n\\n### Proxy Verification Flow\\n\\nA proxy calls `GET /verify` for each protected request.\\n\\n- If `archon_auth` contains a valid signed `authenticated` value, the service returns:\\n  - `200`\\n  - `X-Auth-User: `\\n- Otherwise, it returns a `302` redirect to `/login?rd=`.\\n\\nThe original request target is taken from `X-Forwarded-Uri`. `isSafeRedirect()` permits only safe relative paths:\\n\\n- `/`\\n- Paths beginning with one slash followed by a non-slash, non-backslash character\\n- No `://` substring\\n\\nThis blocks absolute URLs, protocol-relative URLs, and common backslash redirect bypasses.\\n\\n### Login Handling\\n\\n`POST /login`:\\n\\n1. Reads a form-urlencoded request body with `readBody()`.\\n2. Enforces a 4 KB maximum body size.\\n3. Checks the username with strict equality against `AUTH_USERNAME`.\\n4. verifies the password through `bcrypt.compare()`.\\n5. Validates the requested return path with `isSafeRedirect()`.\\n6. Issues the signed session cookie and redirects to the safe return path.\\n\\nThe login page escapes error text through `escapeHtml()` before inserting it into HTML.\\n\\n---\\n\\n## Extension and Maintenance Notes\\n\\n### Adding a New Authenticated Endpoint\\n\\nWhen adding an endpoint to `auth.ts`:\\n\\n1. Define its OpenAPI route with `createRoute()`.\\n2. Add `app.use('/api/auth/new-path', requireAuth)` before registering the handler if it needs a system JWT.\\n3. Obtain the JWT subject with `c.get('userId')`.\\n4. Resolve the local user with `getUserById()` if the handler requires username or role data.\\n5. Register the route using `registerOpenApiRoute()`.\\n\\nKeep the OpenAPI schema aligned with the actual response. The local wrapper bypasses typed response constraints, so OpenAPI schemas do not provide runtime response validation.\\n\\n### Handling Secrets\\n\\n- Never return raw ugate tokens from an API response.\\n- Use `toUgateTokenStatus()` for UI-facing token status.\\n- Preserve the file mode used by `writeUgateTokenFile()` (`0o600`).\\n- Keep filename construction behind `parseJwtUsername()` validation or equivalent identifier validation.\\n- Do not log token values, UUAP pTokens, sTokens, or JWTs.\\n\\n### Preserving User Provisioning\\n\\nBoth successful UUAP flows call:\\n\\n```ts\\nawait ensurePersonalSpace(dbUser.id, dbUser.username);\\n```\\n\\nAny new login or token-issuance path for real users should preserve this step. It ensures a newly recognized identity has the expected personal product-space resources before using the application.\",\"chat-and-platform-adapters\":\"# Chat and Platform Adapters\\n\\n# Chat and Platform Adapters\\n\\nThis module provides output adapters that let orchestration code communicate through different delivery surfaces without coupling the orchestrator to a specific UI or transport.\\n\\nThe included components cover:\\n\\n- `splitIntoParagraphChunks()` for safely fitting long messages into platform limits.\\n- `CLIAdapter` for command-line output and optional assistant-message persistence.\\n- `WebAdapter` for the browser application, Server-Sent Events (SSE), structured streaming events, workflow event bridging, and buffered persistence.\\n\\nBoth adapters implement the platform adapter contracts from `@archon/core`, allowing orchestration code to send messages, identify the active platform, and choose stream or batch behavior consistently.\\n\\n```mermaid\\nflowchart LR\\n  O[Orchestrator] --&gt;|IPlatformAdapter| C[CLIAdapter]\\n  O --&gt;|IWebPlatformAdapter| W[WebAdapter]\\n\\n  C --&gt; STDOUT[stdout]\\n  C --&gt; MDB[Message DB]\\n\\n  W --&gt; P[MessagePersistence]\\n  W --&gt; T[SSETransport]\\n  W --&gt; B[WorkflowEventBridge]\\n  T --&gt; UI[React frontend]\\n```\\n\\n## Adapter Contracts and Platform Identity\\n\\nThe adapters use types from `@archon/core`:\\n\\n- `IPlatformAdapter` is implemented by `CLIAdapter`.\\n- `IWebPlatformAdapter` is implemented by `WebAdapter`.\\n- `MessageMetadata` accompanies normal assistant messages and can include categories, workflow state, dispatch details, and results.\\n\\nThe common operations are:\\n\\n| Method | Purpose |\\n|---|---|\\n| `sendMessage(conversationId, message, metadata?)` | Deliver a complete assistant message to the platform. |\\n| `ensureThread(originalConversationId, ...)` | Resolve a conversation or thread ID appropriate for the platform. |\\n| `getStreamingMode()` | Tell the caller whether the adapter expects incremental streaming or complete batched output. |\\n| `getPlatformType()` | Identify the platform for platform-specific orchestration behavior. |\\n| `start()` / `stop()` | Initialize or tear down adapter resources. |\\n\\nNeither the CLI nor web adapter creates platform threads. Their `ensureThread()` implementations return the original conversation ID unchanged. Chat providers that need native threads should implement thread creation or lookup in their own adapters.\\n\\n---\\n\\n## Message Splitting\\n\\n### `splitIntoParagraphChunks(message, maxLength)`\\n\\n`splitIntoParagraphChunks()` lives in `packages/adapters/src/utils/message-splitting.ts`. It prepares messages for delivery platforms with message-length limits while attempting to retain readable formatting.\\n\\nIt is used by several provider adapters, including Slack, Discord, Telegram, GitHub, GitLab, and Gitea adapters.\\n\\n```ts\\nimport { splitIntoParagraphChunks } from '@archon/adapters/utils/message-splitting';\\n\\nconst chunks = splitIntoParagraphChunks(message, 2000);\\nfor (const chunk of chunks) {\\n  await platformSend(chunk);\\n}\\n```\\n\\n### Splitting behavior\\n\\nThe function performs a two-pass split:\\n\\n1. **Paragraph pass**: splits the input at one or more blank lines (`\\\\n\\\\n+`), then recombines paragraphs into chunks up to `maxLength`.\\n2. **Line fallback**: any chunk that still exceeds `maxLength` is split at individual line boundaries (`\\\\n`).\\n\\nThe function returns an empty array for an empty string:\\n\\n```ts\\nsplitIntoParagraphChunks('', 2000); // []\\n```\\n\\nIt logs the number of generated chunks at debug level using the `message-splitting` logger:\\n\\n```ts\\ngetLog().debug({ chunkCount: finalChunks.length }, 'message.split_completed');\\n```\\n\\n### Important limitation\\n\\nThe line-level fallback does not split a single line that exceeds `maxLength`. If the source contains an extremely long unbroken token\u2014such as encoded content, a large URL, or a minified payload\u2014the returned chunk can remain longer than `maxLength`.\\n\\nCallers that require a strict hard limit must add token- or character-level splitting after calling `splitIntoParagraphChunks()`.\\n\\n---\\n\\n## CLI Adapter\\n\\n`CLIAdapter` in `packages/cli/src/adapters/cli-adapter.ts` implements `IPlatformAdapter` for local command-line execution.\\n\\nIts primary purpose is to make workflows runnable through CLI commands while preserving assistant responses in the message database when a conversation database ID has been registered.\\n\\n### Construction\\n\\n```ts\\nimport { CLIAdapter } from './adapters/cli-adapter';\\n\\nconst adapter = new CLIAdapter({\\n  streamingMode: 'batch',\\n});\\n```\\n\\n`CLIAdapterOptions` supports one setting:\\n\\n```ts\\ninterface CLIAdapterOptions {\\n  streamingMode?: 'stream' | 'batch';\\n}\\n```\\n\\nThe default is `'batch'`.\\n\\nAlthough the adapter reports a configurable streaming mode, `sendMessage()` always emits the supplied message as one `console.log()` operation. The mode is used by orchestration code to decide how it should produce output.\\n\\n### Conversation-to-database mapping\\n\\nBefore messages can be persisted, callers must associate the platform conversation ID with a database UUID:\\n\\n```ts\\nadapter.setConversationDbId(conversationId, dbId);\\n```\\n\\nInternally, `CLIAdapter` stores the association in:\\n\\n```ts\\nprivate readonly dbIdMap = new Map();\\n```\\n\\nThe map key is the platform conversation ID, and its value is the database conversation UUID. CLI workflow setup calls `setConversationDbId()` after conversation creation and before workflow execution.\\n\\nWithout this mapping, messages are still printed to stdout but are not persisted.\\n\\n### Sending messages\\n\\n```ts\\nawait adapter.sendMessage(conversationId, message, metadata);\\n```\\n\\n`sendMessage()` performs these steps:\\n\\n1. Prints `message` with `console.log(message)`.\\n2. Looks up the conversation database ID from `dbIdMap`.\\n3. If a database ID exists, builds persistence metadata from:\\n   - `metadata.category`\\n   - `metadata.workflowDispatch`\\n   - `metadata.workflowResult`\\n4. Persists the assistant message with:\\n\\n   ```ts\\n   messageDb.addMessage(dbId, 'assistant', message, persistMeta);\\n   ```\\n\\n5. Logs, but does not rethrow, persistence failures.\\n\\nThis failure isolation is intentional: an unavailable database must not prevent CLI output from reaching the user.\\n\\nThe warning is logged through the lazy `cli.adapter` logger under the event name:\\n\\n```text\\ncli_message_persist_failed\\n```\\n\\n### Platform behavior\\n\\n| Method | Return / behavior |\\n|---|---|\\n| `ensureThread(originalConversationId)` | Returns `originalConversationId`; CLI has no native threading. |\\n| `getStreamingMode()` | Returns the configured `'stream'` or `'batch'` mode. |\\n| `getPlatformType()` | Returns `'cli'`. |\\n| `start()` | No-op. |\\n| `stop()` | No-op. |\\n\\nThe orchestrator uses `getPlatformType()` to distinguish CLI execution from platform-specific flows, including thread-context and isolation behavior.\\n\\n---\\n\\n## Web Adapter\\n\\n`WebAdapter` in `packages/server/src/adapters/web.ts` implements `IWebPlatformAdapter` for the React frontend.\\n\\nIt is the boundary between server-side orchestration and browser-side rendering. Its responsibilities are broader than the CLI adapter because it manages live SSE streams, persists buffered chat output, tracks tool lifecycle events, emits workflow status, and bridges worker workflow events to parent conversations.\\n\\n### Dependencies\\n\\n`WebAdapter` is constructed with three collaborators:\\n\\n```ts\\nconst adapter = new WebAdapter(transport, persistence, workflowBridge);\\n```\\n\\n| Dependency | Responsibility |\\n|---|---|\\n| `SSETransport` | Owns active SSE writers and emits serialized events to the matching conversation stream. |\\n| `MessagePersistence` | Buffers and persists text, tool calls, and tool results against database conversations. |\\n| `WorkflowEventBridge` | Bridges progress and output from worker workflow conversations to parent conversations. |\\n\\nThe adapter does not own these components; it coordinates them.\\n\\n### Lifecycle\\n\\n`start()` initializes the supporting services:\\n\\n```ts\\nawait adapter.start();\\n```\\n\\nIt:\\n\\n1. Registers a step-transition callback on `WorkflowEventBridge`.\\n2. Flushes persistence for a worker conversation whenever the bridge reports a step transition.\\n3. Starts the workflow bridge.\\n4. Starts the SSE transport.\\n5. Starts periodic persistence flushing.\\n\\nThe step-transition flush ensures workflow output is persisted incrementally rather than only at workflow completion. Failures are logged with `step_transition_flush_failed`.\\n\\n`stop()` shuts down in the reverse operational direction:\\n\\n```ts\\nawait adapter.stop();\\n```\\n\\nIt:\\n\\n1. Stops periodic persistence flushing.\\n2. Flushes all pending persistence buffers.\\n3. Stops SSE transport.\\n4. Stops workflow event bridging.\\n5. Clears persistence state.\\n6. Clears generated tool ID counters and running-tool state.\\n\\nServer startup creates `WebAdapter`; API routes use it to dispatch messages, control conversation lock state, and emit direct SSE events.\\n\\n---\\n\\n## SSE Stream Management\\n\\n### Registering and removing streams\\n\\nA browser connection must be registered against a conversation:\\n\\n```ts\\nadapter.registerStream(conversationId, stream);\\n```\\n\\n`registerStream()` delegates to `SSETransport.registerStream()`. Transport behavior replaces any existing stream for the same conversation, supporting browser refreshes and new tabs.\\n\\nTo detach the stream:\\n\\n```ts\\nadapter.removeStream(conversationId, expectedStream);\\n```\\n\\nIn addition to delegating to `SSETransport.removeStream()`, this clears per-conversation tool state:\\n\\n```ts\\nthis.runningTools.delete(conversationId);\\nthis.toolCallCounter.delete(conversationId);\\n```\\n\\nThis cleanup is important. Without it, a reconnect could receive stale tool completion events for tool calls created under a previous SSE connection.\\n\\n`expectedStream` allows the transport layer to avoid removing a newer connection when an older connection closes.\\n\\n### Checking stream availability\\n\\n```ts\\nconst connected = adapter.hasActiveStream(conversationId);\\n```\\n\\nThis delegates to `SSETransport.hasActiveStream()` and is useful when callers need to determine whether live browser delivery is currently possible.\\n\\n### Direct event emission\\n\\n`emitSSE()` forwards a fully serialized event directly to the transport:\\n\\n```ts\\nawait adapter.emitSSE(conversationId, event);\\n```\\n\\nAPI conversation dispatch uses this path when it already has an SSE event payload. Unlike higher-level methods, `emitSSE()` does not persist data, apply metadata handling, or alter the event.\\n\\n---\\n\\n## Sending Complete Text Messages\\n\\n### `sendMessage()`\\n\\n```ts\\nawait adapter.sendMessage(conversationId, message, metadata);\\n```\\n\\nFor normal assistant output, `WebAdapter.sendMessage()`:\\n\\n1. Buffers the text in `MessagePersistence`:\\n\\n   ```ts\\n   this.persistence.appendText(conversationId, message, metadata);\\n   ```\\n\\n2. Emits text to workflow output listeners:\\n\\n   ```ts\\n   this.workflowBridge.emitOutput(conversationId, message);\\n   ```\\n\\n3. Sends an SSE event resembling:\\n\\n   ```json\\n   {\\n     \\\"type\\\": \\\"text\\\",\\n     \\\"content\\\": \\\"Assistant response\\\",\\n     \\\"isComplete\\\": true,\\n     \\\"timestamp\\\": 0\\n   }\\n   ```\\n\\n4. Includes `workflowStatus` and `workflowResult` only when they are present in `metadata`.\\n\\n### Structurally handled categories\\n\\nThe following metadata categories are persisted but not emitted as standard chat text:\\n\\n- `tool_call_formatted`\\n- `isolation_context`\\n\\n```ts\\nif (\\n  metadata?.category === 'tool_call_formatted' ||\\n  metadata?.category === 'isolation_context'\\n) {\\n  return;\\n}\\n```\\n\\nThe web UI handles these categories structurally. Contributors adding a new structurally rendered category should follow this pattern: append the data to persistence as needed, then skip the ordinary `{ type: 'text' }` SSE event.\\n\\n### Workflow results\\n\\nWhen `metadata.category === 'workflow_result'`, the adapter explicitly triggers a persistence flush after emitting the message.\\n\\nWorkflow results can arrive after the parent conversation lock is released due to background dispatch. A normal lock-release flush has already occurred in that case, so this explicit flush prevents the result from remaining buffered indefinitely.\\n\\nA failed flush is logged as:\\n\\n```text\\nworkflow_result_flush_failed\\n```\\n\\n---\\n\\n## Structured Streaming Events\\n\\n### `sendStructuredEvent()`\\n\\n```ts\\nawait adapter.sendStructuredEvent(conversationId, chunk);\\n```\\n\\n`sendStructuredEvent()` translates provider-level `MessageChunk` values into JSON SSE events that the frontend understands.\\n\\nUnsupported chunk shapes are ignored: the method returns without emitting an event.\\n\\n| `MessageChunk` condition | SSE event type | Persistence behavior |\\n|---|---|---|\\n| `chunk.type === 'tool'` and `chunk.toolName` | `tool_call` | Buffers the tool name and input. |\\n| `chunk.type === 'tool_result'` and `chunk.toolName` | `tool_result` | Buffers tool output and duration. |\\n| `chunk.type === 'result'` and `chunk.sessionId` | `session_info` | No persistence update here. |\\n| `chunk.type === 'workflow_dispatch'` | `workflow_dispatch` | No persistence update here. |\\n| `chunk.type === 'system'` | `system_status` | No persistence update here. |\\n\\n### Tool-call IDs and concurrent tools\\n\\nThe adapter must pair each `tool_result` event with its corresponding `tool_call` event. This is non-trivial when multiple tools with the same name run concurrently.\\n\\nFor each tool call, `sendStructuredEvent()`:\\n\\n1. Persists the tool call via `this.persistence.appendToolCall(...)`.\\n2. Uses `chunk.toolCallId` when the provider supplied a stable ID.\\n3. Otherwise generates an ID per conversation:\\n\\n   ```ts\\n   `${conversationId}-tool-${counter}`\\n   ```\\n\\n4. Records the start time in `runningTools`.\\n\\n`runningTools` is structured as:\\n\\n```ts\\nMap&gt;\\n```\\n\\nThe outer map is keyed by conversation; the inner map is keyed by tool call ID. This supports parallel workflow DAG nodes without one tool overwriting another tool\u2019s state.\\n\\n### Tool results and duration calculation\\n\\nFor a `tool_result` chunk, the adapter attempts to locate its running tool entry in this order:\\n\\n1. Match the stable `chunk.toolCallId`.\\n2. If unavailable or unmatched, reverse-scan active calls for the most recently started call with the same `toolName`.\\n\\nThe reverse scan provides a best-effort fallback for providers that do not return stable IDs.\\n\\nThe matched entry determines:\\n\\n- the `toolCallId` sent to the frontend;\\n- the start time used for `duration`;\\n- the entry removed from `runningTools`.\\n\\nWhen no matching tool call is found, the result is still emitted and persisted, but the SSE `toolCallId` is undefined and the duration is effectively zero. The adapter logs:\\n\\n```text\\nweb_adapter.tool_result_unmatched\\n```\\n\\nTool-result persistence failures are isolated and logged as:\\n\\n```text\\ntool_result_persist_failed\\n```\\n\\n### Example tool event sequence\\n\\nA provider that includes stable IDs produces pairable events:\\n\\n```json\\n{\\n  \\\"type\\\": \\\"tool_call\\\",\\n  \\\"toolCallId\\\": \\\"toolu_123\\\",\\n  \\\"name\\\": \\\"read_file\\\",\\n  \\\"input\\\": { \\\"path\\\": \\\"README.md\\\" },\\n  \\\"timestamp\\\": 0\\n}\\n```\\n\\n```json\\n{\\n  \\\"type\\\": \\\"tool_result\\\",\\n  \\\"toolCallId\\\": \\\"toolu_123\\\",\\n  \\\"name\\\": \\\"read_file\\\",\\n  \\\"output\\\": \\\"# Project\\\",\\n  \\\"duration\\\": 42,\\n  \\\"timestamp\\\": 0\\n}\\n```\\n\\nThe frontend can use `toolCallId` to update the existing tool card, including when concurrent calls share the same `name`.\\n\\n---\\n\\n## Conversation Lock Events\\n\\n### `emitLockEvent()`\\n\\n```ts\\nawait adapter.emitLockEvent(conversationId, locked, queuePosition);\\n```\\n\\nAPI conversation dispatch calls this method based on lock acquisition and release status.\\n\\nThe emitted SSE payload is:\\n\\n```json\\n{\\n  \\\"type\\\": \\\"conversation_lock\\\",\\n  \\\"conversationId\\\": \\\"conversation-id\\\",\\n  \\\"locked\\\": true,\\n  \\\"queuePosition\\\": 1,\\n  \\\"timestamp\\\": 0\\n}\\n```\\n\\n### Lock release cleanup\\n\\nLock release (`locked === false`) does more than emit a status event. It finalizes in-flight tool state before notifying the client that the conversation is available again:\\n\\n1. Iterates all tools still tracked in `runningTools`.\\n2. Emits an empty `tool_result` for every unfinished tool.\\n3. Persists each fallback tool result.\\n4. Removes the conversation\u2019s running-tool map.\\n5. Calls `persistence.finalizeRunningTools(conversationId)`.\\n6. Flushes persistence for the conversation.\\n7. Emits the unlocked `conversation_lock` event.\\n\\nTool completion events are deliberately emitted before the lock-release event. The frontend therefore sees all active tool cards resolve before it sees the conversation become unlocked.\\n\\nThe lock event uses `transport.emit()` directly rather than routing through another asynchronous layer, preserving that ordering.\\n\\nA failed final flush is logged with:\\n\\n```text\\nlock_release_flush_failed\\n```\\n\\n---\\n\\n## Retraction\\n\\n### `emitRetract()`\\n\\n```ts\\nawait adapter.emitRetract(conversationId);\\n```\\n\\nA retraction removes the last buffered persistence segment and notifies the browser:\\n\\n```json\\n{\\n  \\\"type\\\": \\\"retract\\\",\\n  \\\"timestamp\\\": 0\\n}\\n```\\n\\nThe ordering matters:\\n\\n```ts\\nthis.persistence.retractLastSegment(conversationId);\\nawait this.transport.emit(conversationId, event);\\n```\\n\\nPersistence is updated before the frontend event is emitted, preventing text that has been visually retracted from later being written to history.\\n\\n---\\n\\n## Workflow Event Bridging\\n\\nWorker workflows may run in a different conversation from the parent conversation that initiated them. `WebAdapter` exposes `WorkflowEventBridge` operations to relay relevant worker activity to the parent stream.\\n\\n### Bridge a worker to a parent\\n\\n```ts\\nconst cleanup = adapter.setupEventBridge(\\n  workerConversationId,\\n  parentConversationId\\n);\\n\\n// Call when workflow forwarding is no longer required.\\ncleanup();\\n```\\n\\n`setupEventBridge()` delegates to:\\n\\n```ts\\nthis.workflowBridge.bridgeWorkerEvents(workerConversationId, parentConversationId);\\n```\\n\\nThe bridge forwards compact workflow progress, status updates, and output previews to the parent conversation\u2019s SSE stream.\\n\\n### Observe output locally\\n\\nConsumers can register output callbacks for a conversation:\\n\\n```ts\\nadapter.registerOutputCallback(conversationId, (text) =&gt; {\\n  // Process emitted assistant text.\\n});\\n```\\n\\nRemove the callback when it is no longer needed:\\n\\n```ts\\nadapter.removeOutputCallback(conversationId);\\n```\\n\\n`sendMessage()` invokes `workflowBridge.emitOutput(conversationId, message)` before sending the text SSE event, enabling local previews and worker-to-parent forwarding.\\n\\n---\\n\\n## Persistence Mapping\\n\\nLike `CLIAdapter`, `WebAdapter` needs a platform-to-database conversation mapping before it can persist data for a conversation:\\n\\n```ts\\nadapter.setConversationDbId(platformConversationId, dbId);\\n```\\n\\nThis delegates to:\\n\\n```ts\\nthis.persistence.setConversationDbId(platformConversationId, dbId);\\n```\\n\\nThe web adapter\u2019s persistence scope is broader than CLI persistence:\\n\\n- normal assistant text is buffered through `appendText()`;\\n- tool calls are buffered through `appendToolCall()`;\\n- tool results are buffered through `appendToolResult()`;\\n- lifecycle points such as step transitions, lock release, workflow result delivery, and shutdown trigger flushing.\\n\\nWhen adding a new event that should survive in conversation history, update the appropriate `MessagePersistence` path rather than relying solely on SSE emission.\\n\\n---\\n\\n## Web Platform Behavior\\n\\n| Method | Return / behavior |\\n|---|---|\\n| `ensureThread(originalConversationId)` | Returns `originalConversationId`; web conversations do not have platform-native threads. |\\n| `getStreamingMode()` | Always returns `'stream'`. |\\n| `getPlatformType()` | Returns `'web'`. |\\n| `hasActiveStream(conversationId)` | Reports whether an SSE stream is registered and active. |\\n| `emitSSE(conversationId, event)` | Emits a pre-serialized SSE payload without persistence or event transformation. |\\n\\nBecause `getStreamingMode()` is always `'stream'`, callers can send incremental `MessageChunk` values through `sendStructuredEvent()` while complete text messages continue through `sendMessage()`.\\n\\n---\\n\\n## Logging and Error Handling\\n\\nAll three source files use lazy logger initialization:\\n\\n```ts\\nlet cachedLog: ReturnType | undefined;\\n\\nfunction getLog(): ReturnType {\\n  if (!cachedLog) cachedLog = createLogger('logger-name');\\n  return cachedLog;\\n}\\n```\\n\\nThis pattern defers `createLogger()` until logging is actually required. It also allows tests to mock logger creation before the logger is cached.\\n\\n| Component | Logger name |\\n|---|---|\\n| `splitIntoParagraphChunks()` | `message-splitting` |\\n| `CLIAdapter` | `cli.adapter` |\\n| `WebAdapter` | `adapter.web` |\\n\\nOperational delivery is generally prioritized over secondary persistence behavior:\\n\\n- CLI persistence failures do not stop stdout output.\\n- Web tool-result persistence failures do not stop SSE output.\\n- Web flush failures are caught and logged when triggered in background or cleanup paths.\\n- Unmatched tool results are emitted to preserve visible output even when tool pairing cannot be established.\\n\\nContributors should preserve this behavior unless a failure makes the adapter\u2019s primary delivery guarantee invalid.\\n\\n---\\n\\n## Contribution Guidelines\\n\\n### Adding a new delivery adapter\\n\\nA new platform adapter should follow the relevant interface from `@archon/core` and provide deliberate answers for:\\n\\n- How conversations map to platform identifiers.\\n- Whether the platform supports streaming or needs batch output.\\n- Whether the platform needs message splitting.\\n- Whether native threads require an `ensureThread()` implementation beyond passthrough.\\n- Which message metadata should be persisted or rendered structurally.\\n- Whether delivery and persistence failures should be independently recoverable.\\n\\nUse `splitIntoParagraphChunks()` for platforms with message limits where preserving paragraphs and line boundaries is preferable to arbitrary character splitting.\\n\\n### Adding a web structured event\\n\\nTo add support for a new `MessageChunk` type in `WebAdapter.sendStructuredEvent()`:\\n\\n1. Add a branch that validates the required chunk fields.\\n2. Construct a stable JSON event with a distinct `type`.\\n3. Persist associated data through `MessagePersistence` if it belongs in chat history.\\n4. Emit through `this.transport.emit(conversationId, event)`.\\n5. Update the frontend event consumer to handle the new event type.\\n6. Consider reconnect, lock release, and shutdown behavior if the event introduces stateful UI elements.\\n\\n### Changing tool lifecycle behavior\\n\\nTool tracking is deliberately keyed by `toolCallId`, not tool name. Do not replace the nested `Map` with a single per-conversation tool value: workflow DAGs can run tools concurrently, including multiple calls with the same name.\\n\\nWhen changing tool behavior, preserve these invariants:\\n\\n- Prefer provider-supplied `chunk.toolCallId`.\\n- Generate per-conversation fallback IDs only when no stable ID exists.\\n- Remove the matching running entry once a tool result arrives.\\n- Finalize all unresolved tool calls before an unlocked conversation event.\\n- Clear tool state when the browser stream is removed and when the adapter stops.\",\"cli-and-developer-tools\":\"# CLI and Developer Tools\\n\\n# CLI and Developer Tools\\n\\n## Homebrew Formula\\n\\n`homebrew/archon.rb` defines the Homebrew formula used to distribute the prebuilt Archon CLI as:\\n\\n```sh\\nbrew install coleam00/archon/archon\\n```\\n\\nThe formula does not build Archon from source. Instead, it downloads a release binary from the Archon GitHub releases page, verifies its SHA-256 checksum, and installs it into Homebrew\u2019s `bin` directory under the stable executable name `archon`.\\n\\n## Formula Metadata\\n\\nThe `Archon` class inherits from Homebrew\u2019s `Formula` DSL:\\n\\n```ruby\\nclass Archon &lt; Formula\\n```\\n\\nIt declares the package metadata used by Homebrew:\\n\\n| Field | Value |\\n|---|---|\\n| Description | `Remote agentic coding platform - control AI assistants from anywhere` |\\n| Homepage | `https://github.com/coleam00/Archon` |\\n| Version | `0.3.10` |\\n| License | `MIT` |\\n\\nThe version is central to release distribution. Every platform-specific download URL is constructed using:\\n\\n```ruby\\nv#{version}\\n```\\n\\nFor version `0.3.10`, this resolves to the GitHub release tag `v0.3.10`.\\n\\n## Supported Platforms\\n\\nThe formula ships prebuilt binaries for four platform and CPU combinations:\\n\\n| Operating system | CPU architecture | Release asset | Installed command |\\n|---|---|---|---|\\n| macOS | Apple Silicon / ARM | `archon-darwin-arm64` | `archon` |\\n| macOS | Intel / x64 | `archon-darwin-x64` | `archon` |\\n| Linux | ARM | `archon-linux-arm64` | `archon` |\\n| Linux | Intel / x64 | `archon-linux-x64` | `archon` |\\n\\nThe binaries are hosted at:\\n\\n```text\\nhttps://github.com/coleam00/Archon/releases/download/v/\\n```\\n\\nFor example, the macOS ARM64 release asset for the configured version is:\\n\\n```text\\nhttps://github.com/coleam00/Archon/releases/download/v0.3.10/archon-darwin-arm64\\n```\\n\\n## Installation Flow\\n\\nHomebrew evaluates the host operating system and processor type twice:\\n\\n1. In the platform blocks, to select the download URL and checksum.\\n2. In `install`, to identify the downloaded filename and rename it to `archon`.\\n\\n```mermaid\\nflowchart TD\\n    A[brew install coleam00/archon/archon] --&gt; B{Operating system}\\n    B --&gt;|macOS| C{CPU architecture}\\n    B --&gt;|Linux| D{CPU architecture}\\n    C --&gt;|ARM| E[archon-darwin-arm64]\\n    C --&gt;|Intel| F[archon-darwin-x64]\\n    D --&gt;|ARM| G[archon-linux-arm64]\\n    D --&gt;|Intel| H[archon-linux-x64]\\n    E --&gt; I[Install as archon]\\n    F --&gt; I\\n    G --&gt; I\\n    H --&gt; I\\n```\\n\\n### Download Selection\\n\\nThe formula uses Homebrew\u2019s platform DSL:\\n\\n```ruby\\non_macos do\\n  on_arm do\\n    url \\\"...\\\"\\n    sha256 \\\"...\\\"\\n  end\\n\\n  on_intel do\\n    url \\\"...\\\"\\n    sha256 \\\"...\\\"\\n  end\\nend\\n```\\n\\nAn equivalent `on_linux` block defines the Linux artifacts.\\n\\nEach artifact has an explicit `sha256` value. Homebrew verifies the downloaded file against this checksum before installation. A checksum mismatch causes the installation to fail, protecting users from corrupted or unexpectedly modified release assets.\\n\\n### Binary Installation\\n\\nThe `install` method determines the expected source filename:\\n\\n```ruby\\nbinary_name = case\\nwhen OS.mac? &amp;&amp; Hardware::CPU.arm?\\n  \\\"archon-darwin-arm64\\\"\\nwhen OS.mac? &amp;&amp; Hardware::CPU.intel?\\n  \\\"archon-darwin-x64\\\"\\nwhen OS.linux? &amp;&amp; Hardware::CPU.arm?\\n  \\\"archon-linux-arm64\\\"\\nwhen OS.linux? &amp;&amp; Hardware::CPU.intel?\\n  \\\"archon-linux-x64\\\"\\nend\\n```\\n\\nIt then installs and renames that file:\\n\\n```ruby\\nbin.install binary_name =&gt; \\\"archon\\\"\\n```\\n\\n`bin` is Homebrew\u2019s formula-specific executable directory. Homebrew exposes the resulting executable on the user\u2019s `PATH`, allowing the CLI to be invoked as:\\n\\n```sh\\narchon\\n```\\n\\nrather than by a platform-specific release filename.\\n\\n## Verification Test\\n\\nThe formula includes a Homebrew test block:\\n\\n```ruby\\ntest do\\n  assert_match version.to_s, shell_output(\\\"#{bin}/archon version\\\")\\nend\\n```\\n\\nDuring `brew test archon`, Homebrew:\\n\\n1. Runs the installed binary using its absolute formula-managed path.\\n2. Executes:\\n\\n   ```sh\\n   archon version\\n   ```\\n\\n3. Captures standard output with `shell_output`.\\n4. Asserts that the output includes the formula\u2019s configured version.\\n\\nThis verifies two important release properties:\\n\\n- The binary was installed and is executable.\\n- The installed CLI identifies itself as the version declared by the formula.\\n\\nThe test relies on the CLI supporting the exact command:\\n\\n```sh\\narchon version\\n```\\n\\nand returning a zero exit status when successful.\\n\\n## Updating the Formula for a Release\\n\\nWhen publishing a new Archon CLI version, update all release-related values together:\\n\\n1. Change the formula version:\\n\\n   ```ruby\\n   version \\\"0.3.10\\\"\\n   ```\\n\\n2. Ensure GitHub has a corresponding release tag:\\n\\n   ```text\\n   v0.3.10\\n   ```\\n\\n3. Publish all required assets with these exact names:\\n\\n   ```text\\n   archon-darwin-arm64\\n   archon-darwin-x64\\n   archon-linux-arm64\\n   archon-linux-x64\\n   ```\\n\\n4. Download each release asset and calculate its SHA-256 digest.\\n5. Replace the matching `sha256` values in each platform block.\\n6. Confirm the binary reports the same version through:\\n\\n   ```sh\\n   archon version\\n   ```\\n\\n7. Test the formula:\\n\\n   ```sh\\n   brew test archon\\n   ```\\n\\nThe formula\u2019s URLs, selected installation filename, and checksums must remain aligned with the release assets. For example, changing `version` without publishing assets under `v` causes Homebrew download failures. Updating a release binary without updating its formula checksum causes checksum validation to fail.\\n\\n## Release Asset Requirements\\n\\nThe Homebrew formula assumes release assets are raw executable files, not archives such as `.tar.gz` or `.zip` files. The selected filename is directly installed with:\\n\\n```ruby\\nbin.install binary_name =&gt; \\\"archon\\\"\\n```\\n\\nTherefore, each uploaded release asset must:\\n\\n- Be executable for its target platform.\\n- Use the exact expected filename.\\n- Be compatible with the declared operating system and architecture.\\n- Implement the `version` subcommand.\\n- Report the release version in its output.\\n\\n## Relationship to the Rest of the Codebase\\n\\nThis module is a packaging and distribution boundary rather than application runtime code. It has no internal call graph dependencies and does not invoke Archon source modules directly.\\n\\nIts contract with the rest of the project is the published CLI binary interface:\\n\\n- The release pipeline must produce binaries using the four expected asset names.\\n- Each binary must be uploaded to the GitHub release matching `v#{version}`.\\n- The binary must provide `archon version` output containing the release version.\\n- The binary must run on the platform and architecture represented by its formula block.\\n\\nBecause the formula installs a prebuilt executable, changes to the CLI\u2019s implementation do not require changes here unless they affect release naming, supported platforms, executable behavior, version reporting, or release artifact integrity.\",\"developer-documentation-and-operational-scripts\":\"# Developer Documentation and Operational Scripts\\n\\n# Developer Documentation and Operational Scripts\\n\\nThis module contains two standalone Python utilities:\\n\\n- `assets/ducc-skills/get-ugate-token/getUgateToken.py`: retrieves, caches, and manages Ugate tokens for a user.\\n- `docs/parallel-study/analyze_parallelism.py`: analyzes dependency graphs from `issues.json` files to evaluate whether parallel execution is worthwhile.\\n\\nBoth scripts use the Python standard library only. The token utility additionally invokes the external `aigate-cli` executable for authorization policy changes.\\n\\n## Module Layout\\n\\n```text\\nassets/ducc-skills/get-ugate-token/\\n\u2514\u2500\u2500 getUgateToken.py\\n\\ndocs/parallel-study/\\n\u2514\u2500\u2500 analyze_parallelism.py\\n```\\n\\n---\\n\\n## Ugate Token Utility\\n\\n### Purpose\\n\\n`getUgateToken.py` provides a command-line integration point for:\\n\\n1. Returning a previously cached Ugate token.\\n2. Saving a manually supplied token.\\n3. Requesting a manual token refresh when the user explicitly asks for one.\\n4. Enabling or disabling Ugate and email authorization through `aigate-cli policy`.\\n\\nThe script is designed for multi-user operation. Each user is identified by an email prefix supplied as the first command-line argument.\\n\\n### Invocation\\n\\n```bash\\npython3 assets/ducc-skills/get-ugate-token/getUgateToken.py \\n```\\n\\nFor example:\\n\\n```bash\\npython3 assets/ducc-skills/get-ugate-token/getUgateToken.py chenshouqin\\n```\\n\\nThe script reads the optional `USER_MESSAGE` environment variable to determine the requested operation:\\n\\n```bash\\nUSER_MESSAGE=\\\"ugate token: abc123\\\" \\\\\\npython3 assets/ducc-skills/get-ugate-token/getUgateToken.py chenshouqin\\n```\\n\\nIf the username argument is missing, the script prints an error to stderr and exits with status `1`.\\n\\n### Cache Format\\n\\nThe cache directory is:\\n\\n```python\\nCACHE_DIR = Path.home() / \\\".config\\\" / \\\"uuap\\\"\\n```\\n\\nEach username has an independent cache file:\\n\\n```text\\n~/.config/uuap/.eac_ugate_token_\\n```\\n\\nA saved cache file has the following JSON structure:\\n\\n```json\\n{\\n  \\\"token\\\": \\\"token-value\\\",\\n  \\\"permanent\\\": true\\n}\\n```\\n\\n`save_token_to_cache()` creates the parent directory when necessary and overwrites the existing file for that username.\\n\\nAlthough the cache is marked as permanent, `get_cached_token()` deliberately rejects any cache object containing an `expires_at` field. This allows older or incompatible expiring-token cache entries to be treated as invalid.\\n\\n### Request Processing Order\\n\\n`main()` processes requests in a strict order:\\n\\n1. Validate the username argument.\\n2. Read `USER_MESSAGE`.\\n3. Detect authorization policy actions.\\n4. Detect a manually supplied token.\\n5. Detect a force-refresh request.\\n6. Read the cache unless refresh was requested.\\n7. Ask the user to obtain a token manually if no usable token is available.\\n\\nThe policy branch takes priority over token handling. For example, a message containing both a policy command and token text is treated as a policy request.\\n\\n```mermaid\\nflowchart TD\\n    A[main] --&gt; B[detect_policy_action]\\n    B --&gt;|matched| C[execute_policy]\\n    B --&gt;|not matched| D[extract_manual_token]\\n    D --&gt;|token found| E[save_token_to_cache]\\n    D --&gt;|no token| F[should_force_refresh]\\n    F --&gt;|not forced| G[get_cached_token]\\n    G --&gt;|cached token| H[print token]\\n    F --&gt;|forced or cache miss| I[manual token prompt]\\n```\\n\\n### Policy Operations\\n\\n`detect_policy_action()` maps Chinese natural-language keywords to an `(action, name)` tuple:\\n\\n```python\\n(\\\"on\\\", \\\"ugate\\\")\\n(\\\"off\\\", \\\"ugate\\\")\\n(\\\"on\\\", \\\"mail\\\")\\n(\\\"off\\\", \\\"mail\\\")\\n```\\n\\nSupported logical operations are:\\n\\n| Operation | `command` | `name` |\\n|---|---|---|\\n| Enable Ugate authorization | `on` | `ugate` |\\n| Disable Ugate authorization | `off` | `ugate` |\\n| Enable email authorization | `on` | `mail` |\\n| Disable email authorization | `off` | `mail` |\\n\\nThe function checks the configured `POLICY_KEYWORDS` lists using substring matching. Matching is case-sensitive because the message is not normalized before policy detection.\\n\\n`execute_policy()` invokes:\\n\\n```bash\\naigate-cli policy -c= -n=\\n```\\n\\nIt uses:\\n\\n- `capture_output=True`\\n- `text=True`\\n- a 30-second timeout\\n\\nOn success, stdout contains a `POLICY_RESULT:`-prefixed message such as:\\n\\n```text\\nPOLICY_RESULT:\u2705 Ugate \u7528\u6237\u6388\u6743\u5df2\u5f00\u542f\\n```\\n\\nFailure cases include:\\n\\n- `aigate-cli` is not installed or not on `PATH`\\n- command timeout\\n- non-zero command exit status\\n- unexpected Python exceptions\\n\\nThe policy branch exits with `0` on success and `1` on failure.\\n\\n### Manual Token Input\\n\\n`extract_manual_token()` recognizes the following format:\\n\\n```text\\nugate token: \\nugate token\uff1a\\n```\\n\\nMatching is case-insensitive and allows either an English or Chinese colon:\\n\\n```python\\nr'ugate\\\\s+token\\\\s*[:\uff1a]\\\\s*(\\\\S.+)'\\n```\\n\\nThe extracted token is saved with `save_token_to_cache()`. The script writes a status marker to stderr and the token itself to stdout:\\n\\n```text\\nstderr: TOKEN_SAVED:Token \u5df2\u4fdd\u5b58\\nstdout: \\n```\\n\\nThe regular expression requires token content after the separator. In practice, tokens should contain at least two characters because the pattern uses `\\\\S.+`.\\n\\n### Cache Lookup and Refresh\\n\\n`should_force_refresh()` performs case-insensitive substring matching against `FORCE_REFRESH_KEYWORDS`. Examples include:\\n\\n- `\u5237\u65b0ugate`\\n- `\u91cd\u65b0\u83b7\u53d6`\\n- `\u5237\u65b0 token`\\n- `\u5ffd\u7565\u7f13\u5b58`\\n\\nA force-refresh request does not contact a token-generation API. It only skips the cache and causes the script to emit a manual acquisition prompt:\\n\\n```text\\nNEED_MANUAL_TOKEN:\u8bf7\u70b9\u51fb https://uuap.baidu.com/agent/token \u83b7\u53d6token\uff0c\u7136\u540e\u590d\u5236\u5185\u5bb9\u53d1\u9001\u7ed9\u6211\\n```\\n\\nThe process exits with status `2`.\\n\\nWithout a force-refresh request, `get_cached_token()`:\\n\\n1. Builds the username-specific path with `get_cache_file()`.\\n2. Returns `None` if the file does not exist.\\n3. Parses the JSON object.\\n4. Rejects objects containing `expires_at`.\\n5. Returns the `token` value if it is non-empty.\\n\\nMalformed JSON and missing keys are treated as cache misses. File-system errors other than those cases are not explicitly suppressed.\\n\\n### Exit Statuses\\n\\n| Status | Meaning |\\n|---:|---|\\n| `0` | Cached token returned, token saved, or policy operation succeeded |\\n| `1` | Missing username or policy operation failed |\\n| `2` | No usable token; user must obtain one manually |\\n\\n---\\n\\n## Parallelism Analysis Script\\n\\n### Purpose\\n\\n`analyze_parallelism.py` evaluates whether issue slices can benefit from parallel execution. It reads one or more `issues.json` files, interprets their `blocked_by` relationships as a dependency graph, and calculates:\\n\\n- Total slices (`N`)\\n- Number of topological layers\\n- Maximum layer width\\n- Maximum AFK-only parallelism\\n- Theoretical speedup upper bound\\n- A cross-sample P2 go/no-go recommendation\\n\\nThe script does not modify input files.\\n\\n### Invocation\\n\\nAnalyze one file:\\n\\n```bash\\npython3 docs/parallel-study/analyze_parallelism.py path/to/issues.json\\n```\\n\\nAnalyze multiple files:\\n\\n```bash\\npython3 docs/parallel-study/analyze_parallelism.py sampleA.json sampleB.json\\n```\\n\\nRecursively analyze all `issues.json` files below a directory:\\n\\n```bash\\npython3 docs/parallel-study/analyze_parallelism.py docs/parallel-study/\\n```\\n\\nAppend a machine-readable JSON summary:\\n\\n```bash\\npython3 docs/parallel-study/analyze_parallelism.py --json sampleA.json sampleB.json\\n```\\n\\nWith no arguments, `main()` prints the module docstring and returns `2`.\\n\\n### Input Format\\n\\n`load_issues()` accepts either of these top-level structures:\\n\\nAn array:\\n\\n```json\\n[\\n  {\\n    \\\"id\\\": \\\"slice-1\\\",\\n    \\\"type\\\": \\\"AFK\\\",\\n    \\\"blocked_by\\\": []\\n  }\\n]\\n```\\n\\nOr an object containing an `issues` array:\\n\\n```json\\n{\\n  \\\"issues\\\": [\\n    {\\n      \\\"id\\\": \\\"slice-1\\\",\\n      \\\"type\\\": \\\"AFK\\\",\\n      \\\"blocked_by\\\": []\\n    }\\n  ]\\n}\\n```\\n\\nEvery element must be a JSON object. Otherwise, `load_issues()` raises `ValueError`.\\n\\nRelevant fields are:\\n\\n| Field | Use |\\n|---|---|\\n| `id` | Node identifier in the dependency graph |\\n| `blocked_by` | IDs that must be resolved first |\\n| `type` | Used to distinguish `AFK` from `HITL` slices |\\n\\nIDs are converted to strings during analysis.\\n\\n### File Discovery\\n\\n`discover_paths()` expands command-line arguments as follows:\\n\\n- Directory: recursively finds `**/issues.json`\\n- Existing file: includes it directly\\n- Missing path: prints a warning to stderr and skips it\\n\\nIf no files are found, `main()` returns `1`.\\n\\nEach file is analyzed independently. A malformed file produces a per-file error, while other valid files continue to be processed. If every file fails, the script returns `1`.\\n\\n### Dependency Layering\\n\\n`topo_layers()` performs Kahn-style topological sorting:\\n\\n1. Build a dependency set for each issue.\\n2. Remove dependencies that refer to unknown IDs.\\n3. Select all nodes whose dependencies are already resolved.\\n4. Emit those nodes as one layer.\\n5. Repeat until all nodes are resolved.\\n\\nThe resulting layers represent candidate parallel execution groups. Nodes in the same layer have no remaining known dependencies on one another.\\n\\nFor example:\\n\\n```text\\nslice-a \u2500\u2500\u2510\\n          \u251c\u2500\u2500&gt; slice-c\\nslice-b \u2500\u2500\u2518\\n```\\n\\nproduces:\\n\\n```python\\n[\\n    [\\\"slice-a\\\", \\\"slice-b\\\"],\\n    [\\\"slice-c\\\"]\\n]\\n```\\n\\nUnknown `blocked_by` IDs are ignored and reported as a warning. If no nodes can be selected while unresolved nodes remain, the graph contains a dependency cycle. Resolved layers are retained, and the unresolved IDs are returned in the analysis result.\\n\\n### Metrics\\n\\n`analyze()` computes the following values.\\n\\n#### `N`\\n\\nTotal number of input issues:\\n\\n```python\\nN = len(issues)\\n```\\n\\n#### `layers`\\n\\nNumber of successfully produced topological layers. This is the serial dependency depth and acts as the critical-path length approximation.\\n\\n#### `max_width`\\n\\nLargest layer size:\\n\\n```python\\nmax_width = max(len(layer) for layer in layers)\\n```\\n\\nThis is the theoretical maximum parallelism implied by the dependency graph, regardless of slice type.\\n\\n#### `afk_parallel`\\n\\nLargest number of `AFK` issues in any one layer. Matching is case-insensitive:\\n\\n```python\\nstr(issue_type).upper() == \\\"AFK\\\"\\n```\\n\\nThis metric estimates the amount of work that could be performed automatically and concurrently without human intervention.\\n\\n#### `n_afk` and `n_hitl`\\n\\nCounts of AFK and non-AFK slices. Any type other than `AFK` is counted as HITL for reporting purposes.\\n\\n#### `speedup_ub`\\n\\nTheoretical speedup upper bound:\\n\\n```python\\nn_ranked / n_layers\\n```\\n\\nOnly nodes successfully included in topological layers contribute to `n_ranked`. This prevents cyclic, unresolved nodes from inflating the estimate. The result is rounded to two decimal places.\\n\\n#### Diagnostic fields\\n\\nThe returned metric dictionary also includes:\\n\\n- `layer_sizes`: number of nodes in each layer\\n- `unresolved`: IDs left behind by cycle detection\\n- `warn`: dangling dependency or cycle warnings\\n\\n### Verdict Logic\\n\\n`verdict()` evaluates the medians across all successfully analyzed samples. The default threshold is `2`.\\n\\nThe decision order is:\\n\\n1. **GO** if median `afk_parallel &gt;= 2`\\n2. **BORDERLINE** if median `max_width &gt;= 2` but median `afk_parallel &lt; 2`\\n3. **NO-GO** otherwise\\n\\nThis distinction is important: a wide dependency layer does not necessarily provide useful automated parallelism if most of its nodes are HITL slices.\\n\\nExample outcomes:\\n\\n```text\\nGO \u2014 AFK \u53ef\u5e76\u884c\u5ea6\u4e2d\u4f4d\u6570 2 \u2265 2\uff0cP2 \u6709\u6536\u76ca\uff0c\u53ef\u7ee7\u7eed\u3002\\n```\\n\\n```text\\nBORDERLINE \u2014 \u5c42\u5bbd\u4e2d\u4f4d\u6570 2 \u2265 2 \u4f46 AFK \u53ef\u5e76\u884c\u5ea6\u4e2d\u4f4d\u6570 1 &lt; 2...\\n```\\n\\n```text\\nNO-GO \u2014 \u5c42\u5bbd\u4e2d\u4f4d\u6570 1\u3001AFK \u53ef\u5e76\u884c\u5ea6\u4e2d\u4f4d\u6570 1 \u5747 &lt; 2...\\n```\\n\\n### Output Modes\\n\\nFor each valid sample, `fmt_sample()` prints:\\n\\n- source path\\n- total slice count\\n- AFK/HITL counts\\n- topological layer count\\n- layer-size distribution\\n- maximum layer width\\n- AFK parallelism\\n- theoretical speedup\\n- warnings, if any\\n\\nAfter all samples, `main()` prints median and range summaries for:\\n\\n- `max_width`\\n- `afk_parallel`\\n- `speedup_ub`\\n\\nWhen `--json` is supplied, it additionally emits an indented JSON object:\\n\\n```json\\n{\\n  \\\"sample_count\\\": 2,\\n  \\\"median_max_width\\\": 2,\\n  \\\"median_afk_parallel\\\": 2,\\n  \\\"median_speedup_ub\\\": 1.5,\\n  \\\"samples\\\": [\\n    {\\n      \\\"path\\\": \\\"sampleA.json\\\",\\n      \\\"N\\\": 4,\\n      \\\"layers\\\": 2,\\n      \\\"max_width\\\": 2,\\n      \\\"afk_parallel\\\": 2,\\n      \\\"n_afk\\\": 3,\\n      \\\"n_hitl\\\": 1,\\n      \\\"speedup_ub\\\": 2.0,\\n      \\\"layer_sizes\\\": [2, 2],\\n      \\\"unresolved\\\": [],\\n      \\\"warn\\\": null\\n    }\\n  ]\\n}\\n```\\n\\nThe JSON is printed after the human-readable report rather than replacing it.\\n\\n---\\n\\n## Relationship to the Rest of the Codebase\\n\\n### Ugate Integration\\n\\nThe token script is an operational boundary between the surrounding skill or agent workflow and local credential storage:\\n\\n- The caller passes the user identity as `sys.argv[1]`.\\n- The caller communicates intent through `USER_MESSAGE`.\\n- The script returns machine-detectable prefixes such as `POLICY_RESULT:`, `TOKEN_SAVED:`, and `NEED_MANUAL_TOKEN:`.\\n- Authorization changes are delegated to the external `aigate-cli` command.\\n- Tokens are persisted under the current user\u2019s home directory.\\n\\nAny caller integrating this script should preserve the distinction between stdout and stderr. The token is emitted on stdout, while status and manual-action messages are emitted on stderr.\\n\\n### Parallel Study Integration\\n\\nThe parallelism analyzer consumes `issues.json` artifacts produced by the issue-card generation workflow, referenced in the script documentation as `create-issue-cards`. Its output supports the standard development flow decision about whether P2 slice parallelism should be implemented.\\n\\nThe expected data flow is:\\n\\n```mermaid\\nflowchart LR\\n    A[create-issue-cards] --&gt; B[issues.json]\\n    B --&gt; C[discover_paths]\\n    C --&gt; D[load_issues]\\n    D --&gt; E[topo_layers]\\n    E --&gt; F[analyze]\\n    F --&gt; G[verdict]\\n```\\n\\nThe analyzer is read-only with respect to these artifacts, making it suitable for repeatable studies and CI or local experimentation.\\n\\n## Contribution Notes\\n\\n### Extending Ugate Behavior\\n\\nWhen adding a new natural-language command:\\n\\n- Add force-refresh phrases to `FORCE_REFRESH_KEYWORDS`.\\n- Add policy phrases under the appropriate key in `POLICY_KEYWORDS`.\\n- Preserve the existing policy-first processing order unless the command semantics require otherwise.\\n- Keep output prefixes stable because callers may parse them.\\n- Treat changes to cache structure as a compatibility change; `get_cached_token()` currently expects a JSON object with a `token` field.\\n\\n### Extending Parallelism Metrics\\n\\nNew metrics should generally be computed in `analyze()` and included in both:\\n\\n- `fmt_sample()` for human-readable output\\n- the `summary` object in `main()` when `--json` is enabled\\n\\nChanges to the go/no-go policy belong in `verdict()`. Keep `max_width` and `afk_parallel` separate: the former measures graph-level concurrency, while the latter measures concurrency that can proceed without human intervention.\\n\\nWhen modifying dependency handling, preserve the existing behavior of reporting dangling IDs and cycles through `warn` and `unresolved` rather than silently discarding graph problems.\",\"knowledge-management\":\"# Knowledge Management\\n\\n# Knowledge Management Module\\n\\nThe Knowledge Management module connects product-scoped knowledge spaces to three workflows:\\n\\n1. **Knowledge UI navigation** in `KnowledgePage`\\n2. **Chat routing** to knowledge-aware conversations in `knowledge-router.ts`\\n3. **Governed promotion of evaluation artifacts** through `EvaluationKnowledgeArtifactService`\\n\\nThe module is intentionally product-scoped. A `product_id` determines which knowledge space, graph, wiki, governance records, and evaluation artifacts a user or workflow operates on.\\n\\n```mermaid\\nflowchart LR\\n  Chat[Conversation message] --&gt; Router[resolveKnowledgeRoute]\\n  Router --&gt; Product[resolveProductId]\\n  Product --&gt; KnowledgeChat[Knowledge chat flow]\\n\\n  Artifact[Workflow artifact event] --&gt; Receipt[recordArtifactReceipt]\\n  Receipt --&gt; Link[Artifact knowledge link]\\n  Link --&gt; Candidate[requestCandidatePublication]\\n  Candidate --&gt; Outbox[Publication outbox]\\n  Outbox --&gt; Transport[publishCandidate]\\n  Transport --&gt; Review[approveSource]\\n```\\n\\n## Components\\n\\n| Location | Responsibility |\\n|---|---|\\n| `packages/core/src/services/evaluation-knowledge-artifact-service.ts` | Records workflow artifacts, manages their review state, and reliably delivers publication candidates through an outbox. |\\n| `packages/server/src/routes/knowledge-router.ts` | Decides whether a conversation message should be handled as a knowledge request and resolves its product space. |\\n| `packages/web/src/routes/KnowledgePage.tsx` | Provides the Knowledge Management page shell, section navigation, product switching, default redirects, and API-key dialog access. |\\n\\n---\\n\\n# Evaluation Artifact Knowledge Lifecycle\\n\\n`EvaluationKnowledgeArtifactService` governs how artifacts produced during workflow evaluation can become knowledge-base sources.\\n\\nThe service separates **artifact receipt**, **candidate delivery**, and **approval**. Receiving an artifact never automatically publishes model output to the knowledge base.\\n\\n## Lifecycle States\\n\\nArtifact knowledge links use `approval_status` and `relation_type` to represent their lifecycle.\\n\\n| Stage | `approval_status` | `relation_type` | Meaning |\\n|---|---|---|---|\\n| Received | `unreviewed` | `candidate` | The workflow emitted an artifact receipt. No knowledge publication has been requested. |\\n| Candidate requested | `publish_candidate` | `candidate` | A reviewer has requested publication and an outbox record exists or has been updated. |\\n| Approved source | `approved` | `approved_source` | A reviewer has explicitly approved the published document revision as a knowledge source. |\\n| Rejected | `rejected` | Existing relation type is retained | The candidate is not approved. Pending or failed delivery is cancelled when applicable. |\\n| Withdrawn | `withdrawn` | Existing relation type is retained | The candidate or source has been withdrawn. Pending or failed delivery is cancelled when applicable. |\\n\\nA successful external delivery does **not** automatically approve the artifact link. `deliverPendingCandidates()` marks the outbox item as `delivered`, while the link remains in `publish_candidate` until `approveSource()` is called.\\n\\n## Artifact Receipt\\n\\n### `recordArtifactReceipt()`\\n\\n```ts\\nawait service.recordArtifactReceipt({\\n  workflowRunId,\\n  traceId,\\n  nodeId,\\n  label,\\n  url,\\n  path,\\n  contentHash,\\n  gitCommit,\\n  dataClassification,\\n});\\n```\\n\\n`recordArtifactReceipt()` is the ingestion point for workflow artifacts. `workflow-trace-recorder.ts` invokes it while handling workflow events.\\n\\nIt creates or updates an evaluation artifact knowledge link with these defaults:\\n\\n```ts\\n{\\n  relation_type: 'candidate',\\n  approval_status: 'unreviewed',\\n  data_classification: 'internal',\\n  metadata: { source: 'workflow_artifact_event' },\\n}\\n```\\n\\nThe caller can override the default classification through `dataClassification`.\\n\\n### Receipt Guarantees\\n\\n- Receipt is local persistence only.\\n- Receipt does not create an outbox item.\\n- Receipt does not attach the artifact to a product.\\n- Receipt does not expose artifact content to a knowledge system.\\n- The stored record may include artifact identity and provenance fields such as `workflow_run_id`, `trace_id`, `node_id`, `artifact_url`, `artifact_path`, `content_hash`, and `git_commit`.\\n\\nThis separation is a safety boundary: workflow or model output must be reviewed before it can enter a product knowledge base.\\n\\n---\\n\\n## Requesting Candidate Publication\\n\\n### `requestCandidatePublication()`\\n\\n```ts\\nconst { link, outbox } = await service.requestCandidatePublication({\\n  artifactLinkId,\\n  productId,\\n  reviewerId,\\n  contentPreview,\\n  dataClassification,\\n  note,\\n  maxAttempts,\\n});\\n```\\n\\nThis method moves an eligible artifact link to `publish_candidate` and creates or updates an outbox record for asynchronous delivery.\\n\\n### Preconditions\\n\\nThe artifact link must exist and must not already be:\\n\\n- `approved`\\n- `withdrawn`\\n\\nAttempts to publish from either state throw an error:\\n\\n```ts\\nArtifact knowledge link cannot be published from status: \\n```\\n\\nA rejected or unreviewed link can be submitted as a candidate.\\n\\n### Stored Candidate Payload\\n\\nThe outbox payload includes:\\n\\n```ts\\n{\\n  artifact_link_id,\\n  workflow_run_id,\\n  artifact_label,\\n  artifact_url,\\n  artifact_path,\\n  content_hash,\\n  content_preview,\\n  git_commit,\\n  data_classification,\\n  product_id,\\n}\\n```\\n\\nThe payload hash is a SHA-256 hash of `JSON.stringify(payload)`, produced by `contentHash()`. The hash is supplied to `upsertEvaluationKnowledgeArtifactOutbox()` and can be used by the persistence layer to identify an equivalent payload.\\n\\n### Preview Redaction\\n\\nIf `contentPreview` is supplied, `requestCandidatePublication()` processes it through `retainedPreview()`:\\n\\n1. Empty or whitespace-only content becomes `null`.\\n2. `redactRecordWithContext({ content })` redacts sensitive values.\\n3. `toPreview()` limits the retained value to a preview representation.\\n\\nThe full `contentPreview` is not placed directly into the outbox payload. Only the redacted preview is retained.\\n\\n### Link Updates\\n\\nThe artifact link is updated with:\\n\\n```ts\\n{\\n  approval_status: 'publish_candidate',\\n  relation_type: 'candidate',\\n  product_id: input.productId,\\n  reviewed_by: input.reviewerId,\\n  review_note: input.note ?? null,\\n  data_classification: input.dataClassification,\\n  metadata: {\\n    ...link.metadata,\\n    candidate_requested_at: new Date().toISOString(),\\n  },\\n}\\n```\\n\\n`currentLinkInput()` preserves immutable or unchanged link fields while selectively applying these updates. Contributors changing link state should preserve this pattern rather than constructing partial database inputs manually.\\n\\n---\\n\\n## Delivering Candidate Publications\\n\\n### `KnowledgeArtifactCandidateTransport`\\n\\nThe service is transport-agnostic. The caller provides an implementation of:\\n\\n```ts\\nexport interface KnowledgeArtifactCandidateTransport {\\n  publishCandidate(input: {\\n    outboxId: string;\\n    artifactLinkId: string;\\n    productId: string;\\n    payload: Record;\\n  }): Promise&lt;{\\n    documentId: string;\\n    documentRevision?: string | null;\\n  }&gt;;\\n}\\n```\\n\\nThe transport owns the integration with the external knowledge-document system. It must return the external document identifier and may return a document revision.\\n\\nThe `outboxId` is supplied so a transport can implement idempotency or correlate external work with the local outbox record.\\n\\n### `deliverPendingCandidates()`\\n\\n```ts\\nconst result = await service.deliverPendingCandidates(transport);\\n```\\n\\nOptionally, a deterministic clock can be passed for workers and tests:\\n\\n```ts\\nconst result = await service.deliverPendingCandidates(transport, now);\\n```\\n\\nThe method lists up to 100 outbox records through `listEvaluationKnowledgeArtifactOutbox({ limit: 100 })` and processes eligible items.\\n\\nAn item is eligible only when all of these conditions hold:\\n\\n- Its outbox status is `pending` or `failed`.\\n- `next_attempt_at` is absent or not in the future.\\n- `attempt_count &lt; max_attempts`.\\n- The associated artifact link still has `approval_status === 'publish_candidate'`.\\n- The associated artifact link still has a `product_id`.\\n\\n### Delivery Success\\n\\nFor each successful `transport.publishCandidate()` call, the outbox row is updated to:\\n\\n```ts\\n{\\n  status: 'delivered',\\n  attempt_count: previousAttemptCount + 1,\\n  external_document_id: delivery.documentId,\\n  external_document_revision: delivery.documentRevision ?? null,\\n  delivered_at: now.toISOString(),\\n}\\n```\\n\\nThe method increments `delivered`.\\n\\n### Delivery Failure and Retry\\n\\nIf the transport rejects:\\n\\n- The failure is logged with logger namespace `evaluation.knowledge-artifact`.\\n- The outbox status becomes `failed`.\\n- The attempt count is incremented.\\n- `last_error` receives the thrown error message.\\n- A retry is scheduled five minutes after `now`, unless the maximum number of attempts has been reached.\\n\\n```ts\\n{\\n  status: 'failed',\\n  attempt_count,\\n  next_attempt_at: attemptCount &gt;= outbox.max_attempts\\n    ? null\\n    : retryAt(now),\\n  last_error: message,\\n}\\n```\\n\\n`retryAt()` applies a fixed five-minute delay. There is no exponential backoff or automatic reset of exhausted records in this service.\\n\\n### Cancelled Delivery\\n\\nBefore delivery, the worker reloads the link. If it is no longer publishable\u2014for example, it was rejected, withdrawn, or lost its product assignment\u2014the outbox item is updated to:\\n\\n```ts\\n{\\n  status: 'cancelled',\\n  attempt_count: outbox.attempt_count,\\n  last_error: 'candidate_no_longer_publishable',\\n}\\n```\\n\\nThe method increments `skipped` rather than `failed` in this case.\\n\\n### Result Counters\\n\\n`deliverPendingCandidates()` returns:\\n\\n```ts\\n{\\n  delivered: number;\\n  failed: number;\\n  skipped: number;\\n}\\n```\\n\\n`skipped` includes records that are not pending or failed, are not yet due, exhausted their retry limit, or are cancelled because the linked candidate is no longer publishable.\\n\\n---\\n\\n## Review Decisions\\n\\n### `approveSource()`\\n\\n```ts\\nawait service.approveSource({\\n  artifactLinkId,\\n  reviewerId,\\n  documentId,\\n  documentRevision,\\n  note,\\n});\\n```\\n\\n`approveSource()` is the explicit review step that converts a delivered publication candidate into an approved source.\\n\\nIt requires the link to be in `publish_candidate`. It then updates the link to:\\n\\n```ts\\n{\\n  approval_status: 'approved',\\n  relation_type: 'approved_source',\\n  document_id: documentId,\\n  document_revision: documentRevision,\\n  reviewed_by: reviewerId,\\n  review_note: note ?? null,\\n  metadata: {\\n    ...link.metadata,\\n    approved_at: new Date().toISOString(),\\n  },\\n}\\n```\\n\\nThe method does not inspect the outbox status or retrieve the external document identifiers itself. Callers must provide the `documentId` and `documentRevision` being approved. In a typical integration, these values come from the successful outbox delivery record.\\n\\n### `rejectOrWithdraw()`\\n\\n```ts\\nawait service.rejectOrWithdraw({\\n  artifactLinkId,\\n  reviewerId,\\n  reason,\\n  withdraw,\\n});\\n```\\n\\nUse `withdraw: false` or omit it to reject:\\n\\n```ts\\napproval_status: 'rejected'\\n```\\n\\nUse `withdraw: true` to withdraw:\\n\\n```ts\\napproval_status: 'withdrawn'\\n```\\n\\nBefore updating the link, the method checks for an outbox record using `getEvaluationKnowledgeArtifactOutboxByLink()`. If that record is `pending` or `failed`, it is cancelled:\\n\\n```ts\\n{\\n  status: 'cancelled',\\n  attempt_count: outbox.attempt_count,\\n  last_error: 'rejected' | 'withdrawn',\\n}\\n```\\n\\nThe link records reviewer information, the reason, and a `reviewed_at` timestamp in metadata.\\n\\n### Listing Workflow Links\\n\\n```ts\\nconst links = await service.listLinks(workflowRunId);\\n```\\n\\n`listLinks()` retrieves all artifact knowledge links associated with a workflow run:\\n\\n```ts\\nlistEvaluationArtifactKnowledgeLinks({\\n  workflow_run_id: workflowRunId,\\n});\\n```\\n\\nUse this to display workflow provenance and review state in evaluation or governance interfaces.\\n\\n---\\n\\n# Knowledge Chat Routing\\n\\n`packages/server/src/routes/knowledge-router.ts` determines whether a user message should enter a knowledge-aware chat flow.\\n\\nThe router is a decision layer only. `resolveKnowledgeRoute()` does not write database state.\\n\\n## `resolveKnowledgeRoute()`\\n\\n```ts\\nconst route = await resolveKnowledgeRoute(message, conversation);\\n```\\n\\nIt returns:\\n\\n```ts\\ninterface KnowledgeRouteResult {\\n  shouldRoute: boolean;\\n  reason: 'keyword_hit' | 'follow_up' | 'no_keyword' | 'no_product_id';\\n  productId?: string;\\n  knowledgeConversationId?: string;\\n}\\n```\\n\\nA positive result includes a `productId`. Follow-up routing additionally returns the previous `knowledgeConversationId` when available.\\n\\n## Routing Order\\n\\nThe router checks conditions in this order:\\n\\n1. **Knowledge follow-up window**\\n2. **Keyword match**\\n3. **Product resolution**\\n\\nThis ordering allows a follow-up question such as \u201cWhat about permissions?\u201d to remain in knowledge mode even if it contains none of the configured keywords.\\n\\n```mermaid\\nflowchart TD\\n  Start[resolveKnowledgeRoute] --&gt; FollowUp{In follow-up window?}\\n  FollowUp --&gt;|Yes| Product[resolveProductId]\\n  Product --&gt;|Found| FollowResult[Route: follow_up]\\n  Product --&gt;|Missing| NoProduct[Do not route: no_product_id]\\n  FollowUp --&gt;|No| Keyword{Keyword match?}\\n  Keyword --&gt;|No| NoKeyword[Do not route: no_keyword]\\n  Keyword --&gt;|Yes| Resolve[resolveProductId]\\n  Resolve --&gt;|Found| KeywordResult[Route: keyword_hit]\\n  Resolve --&gt;|Missing| NoProduct\\n```\\n\\n## Keyword Matching\\n\\n### `matchesKnowledgeKeyword()`\\n\\n```ts\\nconst matches = matchesKnowledgeKeyword(message);\\n```\\n\\nKeyword matching uses a simple substring check:\\n\\n```ts\\nKNOWLEDGE_KEYWORDS.some(kw =&gt; message.includes(kw));\\n```\\n\\nConfigured keywords are:\\n\\n- `\u77e5\u8bc6\u5e93`\\n- `\u77e5\u8bc6\u56fe\u8c31`\\n- `\u77e5\u8bc6\u95ee\u7b54`\\n- `\u6587\u6863`\\n- `\u89c4\u8303`\\n- `API`\\n- `\u63a5\u53e3`\\n- `\u8bf4\u660e`\\n- `\u914d\u7f6e`\\n- `\u600e\u4e48\u914d\u7f6e`\\n- `\u5982\u4f55\u914d\u7f6e`\\n- `\u4f7f\u7528\u65b9\u6cd5`\\n\\nMatching is not tokenized, ranked, normalized, or case-insensitive. In particular, the `API` keyword is matched according to JavaScript `String.prototype.includes()` behavior.\\n\\nWhen adding keywords, consider their false-positive rate. Broad entries such as `\u8bf4\u660e` or `\u914d\u7f6e` can route general questions into the knowledge flow.\\n\\n## Follow-Up Routing\\n\\n### `isInFollowUpWindow()`\\n\\n```ts\\nconst followUp = await isInFollowUpWindow(conversationId);\\n```\\n\\nThe function loads the 20 most recent messages:\\n\\n```ts\\nconst messages = await listMessages(conversationId, 20);\\n```\\n\\nIt then scans backwards for the most recent assistant message. A conversation is in the follow-up window only if:\\n\\n1. The latest assistant message has `mode === 'knowledge'`.\\n2. No user message occurs after that assistant message.\\n3. The assistant message is no older than 30 minutes.\\n4. The message has a `knowledge_conversation_id` for `resolveKnowledgeRoute()` to use it as a routable continuation.\\n\\nIf the latest assistant message is not a knowledge response, the function does not search farther back for an earlier knowledge response. This prevents an older knowledge exchange from overriding a newer non-knowledge interaction.\\n\\nThe routing function treats an active follow-up without a resolvable product as a non-routable result:\\n\\n```ts\\n{\\n  shouldRoute: false,\\n  reason: 'no_product_id',\\n}\\n```\\n\\n## Product Resolution\\n\\n### `resolveProductId()`\\n\\n```ts\\nconst productId = await resolveProductId(conversation);\\n```\\n\\n`resolveProductId()` derives a knowledge product space from the conversation\u2019s associated codebase or combo.\\n\\nResolution works as follows:\\n\\n1. If `conversation.codebase_id` exists, load it with `getCodebase()` and collect its name.\\n2. If `conversation.combo_id` exists, load it with `getCombo()` and collect every codebase name in `combo.codebases`.\\n3. Load all codebases sharing those names using `listCodebasesByNames()`.\\n4. Collect non-null `product_id` values.\\n5. Verify corresponding product spaces through `listProductSpacesByProductIds()`.\\n6. Return the `product_id` of the first returned product space, or `undefined` if none exist.\\n\\nUsing names rather than only the initially loaded codebase records mirrors the available-space behavior used by the knowledge-chat API flow.\\n\\n### Multi-Product Conversations\\n\\nA combo can resolve to multiple product IDs. The current implementation validates all matching product spaces but returns only `spaces[0].product_id`.\\n\\nContributors changing product selection should make the selection policy explicit rather than assuming a combo always maps to one product. The current behavior depends on the ordering returned by `listProductSpacesByProductIds()`.\\n\\n## Integration with Knowledge Chat\\n\\nThe knowledge chat proxy calls `resolveProductId()` during handling of knowledge chat requests. This keeps explicit knowledge-chat access and automatic routing aligned on product-space resolution.\\n\\nRouting logs use the `knowledge-router` logger namespace:\\n\\n- `knowledge_route_hit` for successful keyword and follow-up routing\\n- `knowledge_route_no_product_id` when a route cannot be mapped to a product space\\n\\n---\\n\\n# Knowledge Management UI\\n\\n`KnowledgePage` is the top-level web route component for the Knowledge Management experience.\\n\\nIt handles:\\n\\n- Knowledge section navigation\\n- Product-space context selection\\n- Default destination selection based on build status\\n- Navigation from chat source badges\\n- Graph entity location state passthrough\\n- Product ID copying\\n- Access to `AikuApiKeyDialog`\\n\\n## Sections\\n\\n`KnowledgePage` obtains section definitions from `knowledgeSections` and validates URL parameters with `isKnowledgeSectionId()`.\\n\\nThe sections currently visible in sub-navigation are:\\n\\n- `bootstrap`\\n- `wiki`\\n- `graph`\\n- `audit`\\n- `governance`\\n- `integrity`\\n- `evaluation`\\n- `usage`\\n\\nThe `docs` and `quality` sections remain routable because `KnowledgePage` still renders `DocsSection` and `QualitySection`, but they are not included in `VISIBLE_SECTIONS`.\\n\\n| Section ID | Component |\\n|---|---|\\n| `bootstrap` | `BootstrapSection` |\\n| `wiki` | `WikiSection` |\\n| `docs` | `DocsSection` |\\n| `graph` | `GraphPage` |\\n| `quality` | `QualitySection` |\\n| `audit` | `AuditSection` |\\n| `governance` | `GovernanceSection` |\\n| `integrity` | `IntegritySection` |\\n| `usage` | `UsageStatsSection` |\\n| `evaluation` | `EvaluationSection` |\\n\\nSection URLs are generated through `knowledgeSectionPath()`. New sections should be registered in the shared section definitions and rendered here if they need a dedicated page component.\\n\\n## Product Context\\n\\nThe page reads and updates the active product via `useProductSpaceStore()`:\\n\\n```ts\\nconst { selectedProductId, setSelectedProductId } = useProductSpaceStore();\\n```\\n\\nProduct-scoped section components receive this identifier directly:\\n\\n```tsx\\n\\n\\n\\n\\n\\n\\n\\n```\\n\\n`BootstrapSection`, `DocsSection`, and `QualitySection` are rendered without a `productId` prop in this component.\\n\\n### Navigation-Origin Product Switching\\n\\nChat source badges or other callers can navigate to the Knowledge page with location state containing:\\n\\n```ts\\n{\\n  productId: string;\\n}\\n```\\n\\n`getNavigationProductId()` extracts this value. When it differs from the selected product, `KnowledgePage` calls `setSelectedProductId()` and displays:\\n\\n```text\\n\u6b63\u5728\u5207\u6362\u4ea7\u54c1\u7a7a\u95f4...\\n```\\n\\nAfter the product changes, the page redirects to `/knowledge` unless the navigation state is a graph-location request. This allows the default redirect logic to choose the appropriate initial section for the new product.\\n\\n## Default Redirect Behavior\\n\\nWhen visiting `/knowledge` without a section, `KnowledgeDefaultRedirect` determines the destination.\\n\\n### Graph Locate Requests\\n\\nLocation state is treated as graph-location state when it has:\\n\\n```ts\\n{\\n  entityType: string;\\n  keyProps: Record;\\n  productId?: string;\\n}\\n```\\n\\n`hasGraphLocateState()` validates that shape. If it matches, the page redirects directly to the graph section and preserves the navigation state:\\n\\n```tsx\\n\\n```\\n\\nThis takes precedence over build-status checks.\\n\\n### Knowledge Build Status\\n\\nFor ordinary `/knowledge` navigation, `useKnowledgeBuildStatus(productId)` determines the initial destination:\\n\\n| Condition | Redirect |\\n|---|---|\\n| No selected product or build-status request pending | Show `\u6b63\u5728\u68c0\u67e5\u6784\u5efa\u72b6\u6001...` |\\n| Status request fails | `bootstrap` |\\n| Returned product ID does not match the selected product | `bootstrap` |\\n| Product knowledge is built | `graph` |\\n| Product knowledge is not built | `bootstrap` |\\n\\nThis makes `bootstrap` the recovery and onboarding path while sending already-built product spaces directly to the graph.\\n\\n## Product ID Copy Control\\n\\nWhen a product is selected, the top bar displays its ID and copies it through `navigator.clipboard.writeText()`.\\n\\nIf the Clipboard API path fails synchronously, `handleCopy()` falls back to a temporary `` and `document.execCommand('copy')`. The copied indicator remains visible for 1.5 seconds.\\n\\n## API Key Access\\n\\nThe top bar opens `AikuApiKeyDialog` through local `apiKeyDialogOpen` state:\\n\\n```tsx\\n\\n```\\n\\nThis dialog is available regardless of the active section.\\n\\n---\\n\\n# Contribution Guidelines\\n\\n## Preserve the Artifact Safety Boundary\\n\\nDo not change `recordArtifactReceipt()` to publish artifacts directly. Artifact receipt, candidate publication, and approval are separate operations by design:\\n\\n```text\\nworkflow event\\n  \u2192 unreviewed local receipt\\n  \u2192 reviewer-requested publication candidate\\n  \u2192 external delivery\\n  \u2192 reviewer approval as a source\\n```\\n\\nAny new publication path should retain an explicit review step and preserve redaction for retained content previews.\\n\\n## Keep Link and Outbox State Consistent\\n\\nWhen adding a transition to `EvaluationKnowledgeArtifactService`:\\n\\n- Reload the link before applying a state transition.\\n- Validate the current `approval_status`.\\n- Use `currentLinkInput()` to preserve fields not being changed.\\n- Consider whether associated `pending` or `failed` outbox work must be cancelled.\\n- Avoid marking a link `approved` solely because outbox delivery succeeded.\\n\\n## Treat Delivery as At-Least-Once Work\\n\\n`deliverPendingCandidates()` can retry failed records. Transport implementations should use the provided `outboxId` to make publication idempotent where the external system supports it.\\n\\nA worker invoking `deliverPendingCandidates()` should run regularly enough to service the fixed five-minute retry delay and should expect a maximum batch size of 100 records per invocation.\\n\\n## Keep Routing and Explicit Knowledge Chat Aligned\\n\\n`resolveProductId()` is used by both routing and knowledge-chat handling. If product association behavior changes\u2014for example, to handle multi-product combos\u2014update the shared resolver rather than implementing divergent selection logic in individual request handlers.\\n\\n## Preserve URL-State Contracts\\n\\nNavigation to the graph can depend on location state recognized by `hasGraphLocateState()`. When adding graph deep-linking behavior, preserve the required `entityType` and `keyProps` shape so the default redirect does not send the user to bootstrap or a generic graph view.\",\"observability-runtime-tracing-and-evaluation-core\":\"# Observability, Runtime Tracing, and Evaluation \u2014 core\\n\\n# Observability, Runtime Tracing, and Evaluation \u2014 Core\\n\\nThis module provides the core services for turning workflow runtime data into:\\n\\n- Runtime quality gates and release decisions\\n- Workflow, node, and skill failure attribution\\n- Evolution candidates and supervised workflow changes\\n- Golden-sample candidates extracted from completed traces\\n- Rule-based and LLM-assisted runtime intelligence summaries\\n\\nThe services are implemented under `packages/core/src/services` and persist through the database modules in `packages/core/src/db`. They are intentionally independent of server-side replay orchestration: `EvolutionService` accepts an injected `EvolutionShadowReplayRunner` rather than importing a server implementation.\\n\\n## Architecture\\n\\n```mermaid\\nflowchart LR\\n    Run[Workflow run] --&gt; Trace[Runtime trace]\\n    Trace --&gt; Eval[Evaluations]\\n    Eval --&gt; Gate[computeQualityGate]\\n    Gate --&gt; Attr[FailureAttributionService]\\n    Attr --&gt; Candidate[Evolution candidates]\\n    Trace --&gt; Golden[Golden sample candidates]\\n    Gate --&gt; Actions[Quality gate actions]\\n    Candidate --&gt; Replay[Shadow replay]\\n    Replay --&gt; Eval\\n```\\n\\nThe typical feedback loop is:\\n\\n1. A workflow run produces a runtime trace.\\n2. Automatic evaluation writes workflow, node, and skill evaluations.\\n3. `computeQualityGate()` aggregates those evaluations and runtime facts.\\n4. `EvolutionService.proposeForRun()` converts failures into actionable candidates.\\n5. A reviewer may save a patched workflow definition.\\n6. The candidate is evaluated through a source-run recheck or isolated shadow replay.\\n7. A promoted candidate publishes a new user workflow definition version.\\n\\n## Module layout\\n\\n| File | Responsibility |\\n|---|---|\\n| `quality-gate-service.ts` | Calculates quality, release, baseline, semantic, and cost decisions |\\n| `failure-attribution-service.ts` | Maps failed evaluations to workflow, node, or skill improvement proposals |\\n| `evolution-service.ts` | Manages candidate creation, patch review, evaluation, promotion, rejection, and listing |\\n| `golden-sample-candidate-service.ts` | Extracts candidate evaluation samples from traces and performs quality/duplicate checks |\\n| `runtime-intelligence.ts` | Generates structured LLM summaries from aggregated runtime intelligence |\\n\\nThe services use:\\n\\n- `../db/evaluations`\\n- `../db/runtime-traces`\\n- `../db/workflows`\\n- `../db/evolution`\\n- `../db/user-workflows`\\n- `../db/workflow-definition-versions`\\n- `../db/conversations`\\n- `../db/evaluation-benchmarks`\\n\\n## Quality gates\\n\\n### `computeQualityGate()`\\n\\n```ts\\ncomputeQualityGate({\\n  workflowRunId,\\n  baselineRunId?,\\n  thresholds?,\\n  persist?,\\n}): Promise\\n```\\n\\n`computeQualityGate()` loads the workflow run, latest evaluations, baseline comparisons, and workflow version effectiveness in parallel. It returns a `QualityGateResult` containing:\\n\\n- `decision`: `'allow' | 'warn' | 'block'`\\n- `status`: `'passed' | 'warning' | 'blocked'`\\n- Workflow identity and version\\n- Overall score\\n- Structured `reasons`\\n- Recommended or applied `actions`\\n- Thresholds used for the calculation\\n- Evaluation metadata and timestamp\\n\\nWhen `persist` is `true`, the result is stored under the workflow run metadata at:\\n\\n```ts\\nmetadata.quality_gate.result\\nmetadata.quality_gate.last_evaluated_at\\n```\\n\\nIf the workflow run does not exist, or no evaluations have been generated yet, the gate reports an `evaluation_missing` warning rather than throwing.\\n\\n### Default thresholds\\n\\n`DEFAULT_THRESHOLDS` defines the following defaults:\\n\\n| Threshold | Default | Meaning |\\n|---|---:|---|\\n| `workflow_min_score` | `70` | Minimum workflow score |\\n| `node_min_score` | `70` | Minimum node score |\\n| `semantic_min_score` | `80` | Minimum qualified semantic/Ragas score |\\n| `baseline_block_delta` | `-10` | Block if score falls by 10 or more |\\n| `baseline_warn_delta` | `-5` | Warn if score falls by 5 or more |\\n| `cost_warn_delta_ratio` | `0.5` | Warn when cost increases by at least 50% |\\n| `cost_block_delta_ratio` | `1` | Block when cost doubles |\\n| `ragas_context_recall_min` | `0.5` | Minimum qualified context recall |\\n\\nCallers can override any threshold through `thresholds`. The override applies only to the current computation.\\n\\n### Score selection\\n\\n`buildWorkflowScore()` prefers the latest deterministic workflow evaluation. If no deterministic score exists, it falls back to the latest available workflow evaluation.\\n\\nSemantic and Ragas scores are not automatically blended into the release score. They participate in gate checks only when they satisfy both:\\n\\n1. The evaluation is completed and evidence-eligible.\\n2. A matching frozen `business_anchor` benchmark suite has a valid calibration binding and an eligible report.\\n\\nThis qualification is resolved by `resolveL1CalibrationQualification()`, which uses `EvaluationCalibrationService.generateReport()`.\\n\\nUnqualified semantic evaluations produce warnings with category `evaluation_missing` and remain observational rather than release-blocking.\\n\\n### Gate reasons\\n\\nThe gate can produce reasons in these categories:\\n\\n- `score`\\n- `finding`\\n- `baseline_delta`\\n- `cost_spike`\\n- `key_node_failure`\\n- `semantic_quality`\\n- `runtime_status`\\n- `evaluation_missing`\\n\\nCritical reasons produce `decision: 'block'`. If there are no critical reasons but at least one warning, the decision is `'warn'`; otherwise it is `'allow'`.\\n\\nCritical conditions include:\\n\\n- Failed or cancelled workflow runs\\n- Workflow score below `workflow_min_score`\\n- Critical, `p0`, or `p1` findings\\n- Failed nodes or nodes with critical findings\\n- Node scores below `node_min_score`\\n- Baseline regressions at or below `baseline_block_delta`\\n- Cost increases at or above `cost_block_delta_ratio`\\n\\nQualified semantic evaluations can add warnings for low semantic score or low context recall.\\n\\n### `applyQualityGateAction()`\\n\\n```ts\\napplyQualityGateAction({\\n  workflowRunId,\\n  action,\\n  assignee?,\\n  note?,\\n  baselineRunId?,\\n}): Promise\\n```\\n\\nSupported actions are:\\n\\n- `block_release`\\n- `send_alert`\\n- `archive_history`\\n- `assign_fix`\\n\\nThe function:\\n\\n1. Computes the current gate.\\n2. Writes action metadata to the workflow run.\\n3. Recomputes and persists the gate.\\n4. Returns the refreshed gate and the applied action.\\n\\nAction state is represented in `metadata.quality_gate`, including fields such as:\\n\\n```ts\\nrelease_blocked\\nalert_sent_at\\nassigned_to\\nassigned_at\\nfix_status\\nlast_action\\nlast_action_at\\nlast_action_note\\n```\\n\\n## Failure attribution\\n\\n### `FailureAttributionService`\\n\\n`FailureAttributionService` turns evaluation evidence into an `EvolutionAttribution`:\\n\\n```ts\\ninterface EvolutionAttribution {\\n  scope: 'workflow' | 'node' | 'skill';\\n  targetKey: string;\\n  reason: string;\\n  evidence: Record;\\n  proposedPatch: Record;\\n  prediction: Record;\\n  metricsBefore: Record;\\n}\\n```\\n\\nIt does not modify the database. `EvolutionService` is responsible for persisting the returned attribution.\\n\\n### `attributeWorkflow()`\\n\\nA workflow candidate is generated unless all of the following are true:\\n\\n- The quality gate decision is `'allow'`\\n- The workflow score is at least `gate.thresholds.workflow_min_score`\\n- No critical finding exists\\n\\nThe proposed target is the workflow name. The recommendation focuses on workflow-level quality policy, failed-node prechecks, golden samples, and regression gates.\\n\\n### `attributeNode()`\\n\\nA node candidate is generated when:\\n\\n- The evaluation status is not completed, or\\n- The node score is below `node_min_score`, or\\n- A critical finding exists\\n\\nThe target is `evaluation.node_id`. The proposed patch recommends input validation, explicit error handling, retry, and fallback behavior under the node\u2019s guardrails.\\n\\n### `attributeSkill()`\\n\\nA skill candidate is generated when the skill score is below `semantic_min_score` or a critical finding exists.\\n\\nThe target key is:\\n\\n```ts\\n`${evaluation.node_id ?? 'workflow'}:${evaluation.skill_name}`\\n```\\n\\nThe proposed change focuses on skill instructions, trigger conditions, input constraints, and acceptance checks.\\n\\nCritical finding detection recognizes severity values:\\n\\n- `critical`\\n- `p0`\\n- `p1`\\n\\n## Evolution lifecycle\\n\\n### `EvolutionService.proposeForRun()`\\n\\n```ts\\nproposeForRun(workflowRunId): Promise\\n```\\n\\nThe method loads:\\n\\n- Latest workflow evaluations\\n- Latest node evaluations\\n- Latest skill evaluations\\n- A non-persisted quality gate\\n\\nIt selects the latest workflow evaluation, then deduplicates node and skill evaluations by key:\\n\\n- Node: `node_id`\\n- Skill: `${node_id ?? 'workflow'}:${skill_name}`\\n\\nEach attributable result is persisted with `evolutionDb.createEvolutionCandidate()`. Candidate records include the original trace, workflow version, evidence, proposed patch, prediction, metrics, and gate result.\\n\\nIf no workflow name can be determined from the gate or workflow evaluation, the method returns no candidates.\\n\\n### `candidatePatchedDefinition()`\\n\\n```ts\\ncandidatePatchedDefinition(candidate): string | null\\n```\\n\\nReturns `candidate.proposed_patch.patched_definition` only when it is a non-empty string. This helper is used by both shadow replay and promotion, ensuring that the same reviewed draft is executed and published.\\n\\n### `savePatchedDefinition()`\\n\\n```ts\\nsavePatchedDefinition(candidateId, definition): Promise\\n```\\n\\nThis method:\\n\\n1. Loads the candidate.\\n2. Parses the supplied definition using `parseWorkflow()`.\\n3. Rejects invalid YAML or invalid workflow definitions.\\n4. Stores the definition in `proposed_patch.patched_definition`.\\n5. Records `patched_definition_saved_at`.\\n\\nThe saved definition is the draft used by `evaluateCandidate()` and, when promoted, by `transitionCandidate()`.\\n\\n### `evaluateCandidate()`\\n\\n```ts\\nevaluateCandidate(\\n  candidateId,\\n  { shadowReplay? }\\n): Promise&lt;{\\n  candidate: EvolutionCandidateRow;\\n  experiment: EvolutionExperimentRow;\\n}&gt;\\n```\\n\\nThere are two evaluation modes.\\n\\n#### Shadow replay mode\\n\\nWhen `shadowReplay` is supplied, `evaluateCandidate()` calls the private `evaluateCandidateWithShadowReplay()` implementation.\\n\\nThe method:\\n\\n1. Loads the source workflow run.\\n2. Loads its source conversation.\\n3. Parses the reviewed patched definition, if present.\\n4. Creates a `running` evolution experiment.\\n5. Marks the candidate as `evaluating`.\\n6. Invokes the injected `EvolutionShadowReplayRunner`.\\n7. Requires the runner to return both `accepted: true` and a `workflowRunId`.\\n8. Associates the experiment with the replay run.\\n9. Returns while the experiment remains asynchronously pending evaluation.\\n\\nReplay metadata identifies the relationship between source and replay runs:\\n\\n```ts\\n{\\n  evolutionMode: 'shadow_replay',\\n  evolutionCandidateId,\\n  evolutionExperimentId,\\n  evolutionOriginalRunId,\\n  usedPatchedDefinition,\\n}\\n```\\n\\nThe automatic-evaluation path in `workflow-trace-recorder.ts` later completes the shadow replay experiment and invokes quality-gate processing.\\n\\nIf replay launch fails or is rejected:\\n\\n- The experiment is marked `failed`\\n- The candidate is returned to `proposed`\\n- The original error is rethrown\\n\\n#### Source-run gate recheck\\n\\nWithout a shadow replay runner, the service falls back to a source-run gate recheck:\\n\\n1. Mark the candidate `evaluating`.\\n2. Recompute the source run\u2019s quality gate without persistence.\\n3. Create a completed experiment with `mode: 'source_run_gate_recheck'`.\\n4. Mark the candidate `passed` unless the gate decision is `'block'`.\\n5. Store post-evaluation gate metrics.\\n\\nThis fallback does not execute the proposed patch. It reuses source-run evidence and should therefore be treated as supervised evaluation evidence, not as an independent comparison of old and new definitions.\\n\\n### `transitionCandidate()`\\n\\n```ts\\ntransitionCandidate(\\n  candidateId,\\n  status: 'rejected' | 'promoted',\\n  options?: {\\n    promotedBy?: string;\\n    ownerUserId?: string;\\n  }\\n): Promise&lt;{\\n  candidate: EvolutionCandidateRow;\\n  appliedDefinition: boolean;\\n}&gt;\\n```\\n\\nRejection simply updates the candidate status and returns `appliedDefinition: false`.\\n\\nPromotion behaves differently depending on whether a patched definition exists:\\n\\n- No patched definition: status changes to `promoted`, but no workflow definition is applied.\\n- Patched definition: the definition is validated and published.\\n\\nDefinition promotion:\\n\\n1. Rejects bundled workflows listed in `BUNDLED_WORKFLOWS`.\\n2. Parses the draft with `parseWorkflow()`.\\n3. Resolves the owner from `ownerUserId`, an existing user workflow, or `promotedBy`.\\n4. Upserts the active user workflow through `upsertUserWorkflow()`.\\n5. Records an immutable version through `recordWorkflowDefinitionVersion()`.\\n6. Stores the promoted version ID, hash, timestamp, and actor in `metrics_after`.\\n\\nPromotion requires an owner. If one cannot be resolved, it throws without applying the definition.\\n\\n### `listCandidates()`\\n\\n```ts\\nlistCandidates({\\n  workflowRunId?,\\n  scope?,\\n  status?,\\n  limit?,\\n}): Promise\\n```\\n\\nDelegates filtering to `evolutionDb.listEvolutionCandidates()`.\\n\\n## Golden-sample candidate generation\\n\\n### `GoldenSampleCandidateService`\\n\\n`GoldenSampleCandidateService` creates reviewable evaluation samples from completed workflow runs. It accepts an optional `GoldenSampleCandidateGenerator`; the default is `DeterministicTraceGoldenSampleCandidateGenerator`.\\n\\nThis injection point allows alternative extraction or generation strategies without changing persistence and quality-control behavior.\\n\\n### `generateCandidateFromRun()`\\n\\n```ts\\ngenerateCandidateFromRun(\\n  workflowRunId,\\n  options?: {\\n    scope?: 'workflow' | 'node' | 'skill';\\n    nodeId?: string | null;\\n    skillName?: string | null;\\n  }\\n): Promise\\n```\\n\\nThe method requires a completed workflow run and performs the following reads:\\n\\n1. `workflowDb.getWorkflowRun()`\\n2. `runtimeTraceDb.getLatestTraceByWorkflowRunId()`\\n3. `runtimeTraceDb.listTraceSpans()`\\n4. `runtimeTraceDb.listTraceEvents()`, limited to 2,000 events\\n5. `evaluationDb.getWorkflowVersionSnapshot()`\\n6. Existing samples through `listEvaluationGoldenSamples()`\\n\\nScope requirements:\\n\\n- `workflow`: uses the complete trace\\n- `node`: requires `nodeId`\\n- `skill`: requires `skillName`\\n\\nThe latest trace lookup also passes through runtime trace normalization and runtime policy handling. Depending on deployment configuration, this can consult event-mode, numeric, rate-map, and boolean environment settings through `getRuntimeTracePolicy()`.\\n\\nThe generated row is upserted with:\\n\\n- Workflow and version identity\\n- Node or skill scope\\n- Extracted input and expected answer\\n- Reference contexts\\n- Expected tools\\n- Ownership and visibility derived from the run\\n- `source: 'trace_candidate'`\\n- Trace, span, and event provenance in metadata\\n- Quality-control results\\n- `review_status: 'pending'`\\n\\n### Deterministic extraction\\n\\n`DeterministicTraceGoldenSampleCandidateGenerator.generate()` first calls `filterByScope()` and then extracts:\\n\\n#### Input\\n\\n`extractInput()` checks, in order:\\n\\n1. `trace.input_preview`\\n2. Trace metadata keys: `question`, `input`, `prompt`, `user_message`\\n3. Event data using the same keys\\n4. `run.user_message`\\n\\n#### Expected answer\\n\\n`extractOutput()` checks, in order:\\n\\n1. `trace.output_preview`\\n2. Trace metadata keys such as `expected_answer`, `answer`, `output`, `response`, `completion`, and `final_output`\\n3. Events in reverse order\\n4. Spans in reverse order\\n\\n#### Contexts\\n\\n`extractContexts()` gathers values from trace metadata, span attributes, and event data using:\\n\\n```ts\\ncontexts\\nreference_contexts\\nretrieved_contexts\\ndocuments\\n```\\n\\nValues are deduplicated by `uniqueNonEmpty()`.\\n\\n#### Expected tools\\n\\nTool names are collected from:\\n\\n- `span.tool_name`\\n- `event.tool_name`\\n- `event.data.tool_name`\\n\\nThe result is deduplicated and sorted.\\n\\n### Candidate quality control\\n\\n`buildCandidateQualityControl()` evaluates completeness, trace provenance, and similarity against existing samples.\\n\\nQuality issues include:\\n\\n- Input missing or shorter than eight normalized characters\\n- Expected answer missing or shorter than twelve normalized characters\\n- Missing reference contexts\\n- Missing scoped trace evidence\\n- Missing expected tools\\n- Duplicate or near-duplicate content\\n\\nContent is normalized by `normalizeText()`. A SHA-256 fingerprint is generated by `fingerprint()`. Similarity uses token or character shingles from `shingles()` and Jaccard similarity.\\n\\nSimilarity rules:\\n\\n- Samples with similarity below `0.72` are ignored.\\n- Similarity of `0.92` or higher marks the candidate as a duplicate.\\n- Up to five similar samples are retained.\\n\\nQuality penalties:\\n\\n- Critical issue: 35 points\\n- Warning: 15 points\\n- Informational issue: 5 points\\n\\nThe resulting status is:\\n\\n- `ready`\\n- `needs_review`\\n- `low_quality`\\n- `duplicate`\\n\\nThe recommendation is one of:\\n\\n- `approve_candidate`\\n- `edit_before_approval`\\n- `reject_low_quality`\\n- `reject_duplicate`\\n\\nThe complete `CandidateQualityControl` structure is stored in sample metadata, including reviewer guidance, fingerprints, cluster identity, nearest similarity, and duplicate relationship.\\n\\n## Runtime intelligence and LLM summaries\\n\\n### Provider selection\\n\\n`selectRuntimeTraceIntelligenceProvider()` resolves a provider in this order:\\n\\n1. Explicit `requestedProvider`\\n2. `envProvider`\\n3. `codebaseAssistant`\\n4. `defaultAssistant`\\n5. `'claude'`\\n\\n`resolveRuntimeTraceAssistantConfig()` selects the provider-specific assistant configuration and resolves the model from:\\n\\n1. Explicit `requestedModel`\\n2. `assistantConfig.model`\\n3. `ARCHON_TRACE_INTELLIGENCE_MODEL`\\n4. `null`\\n\\nThese helpers are useful to callers that need to display or configure the eventual provider before invoking summarization.\\n\\n### `summarizeRuntimeTraceIntelligenceWithLlm()`\\n\\n```ts\\nsummarizeRuntimeTraceIntelligenceWithLlm(\\n  input: RuntimeTraceLlmSummaryInput\\n): Promise\\n```\\n\\nThe input contains a persisted `RuntimeTraceIntelligenceRow`, a time window, optional provider/model configuration, and optional normalized trace facts.\\n\\nIf there are no root causes and no optimization actions, the function returns a skipped result without calling an LLM. The skipped result preserves rule-based recommendations.\\n\\nOtherwise it:\\n\\n1. Resolves the provider and model.\\n2. Builds a bounded prompt using `buildRuntimeTraceSummaryPrompt()`.\\n3. Limits the serialized prompt to `MAX_PROMPT_CHARS` (12,000 characters).\\n4. Calls `getAgentProvider(providerId)`.\\n5. Streams response chunks through `client.sendQuery()`.\\n6. Disables tool use with `nodeConfig: { allowed_tools: [] }`.\\n7. Disables session persistence with `persistSession: false`.\\n8. Parses JSON using `extractJsonObject()`.\\n9. Normalizes the result before returning it.\\n\\nThe prompt instructs the model to return strict JSON with failure reason, impact scope, repair suggestions, priority, confidence, and node-level suggestions. It includes only aggregated facts and explicitly avoids reconstructing unavailable prompts, tool output, or sensitive data.\\n\\n### Result states\\n\\n`RuntimeTraceLlmSummaryResult.status` is:\\n\\n- `skipped`: no significant rule-based issues were present\\n- `generated`: structured JSON was returned and normalized\\n- `failed`: provider failure or invalid JSON response\\n\\nInvalid or failed responses fall back to rule-based recommendations. LLM output is bounded and normalized:\\n\\n- Priority defaults to `'medium'`\\n- Confidence is clamped to `[0, 1]`, defaulting to `0.6` for invalid input\\n- General suggestions are limited to six entries\\n- Node suggestions are limited to eight entries\\n- Strings are trimmed and length-limited\\n\\nProvider failures are logged through `createLogger('service.runtime-intelligence')` with the `runtime_trace_intelligence.llm_failed` event.\\n\\n## Integration points\\n\\n### Automatic evaluation and replay completion\\n\\n`workflow-trace-recorder.ts` is responsible for runtime trace completion and automatic evaluation. Its evolution replay completion path uses:\\n\\n- `candidatePatchedDefinition()`\\n- `computeQualityGate()`\\n- `EvolutionService`\\n- `transitionCandidate()`\\n\\nThis allows a replay run to be evaluated by the same quality-gate logic as a normal run.\\n\\n### Database boundaries\\n\\nThe service layer does not directly manage SQL or adapter queries. Persistence is delegated to database modules:\\n\\n- Evaluation rows and golden samples: `db/evaluations.ts`\\n- Runtime traces, spans, and events: `db/runtime-traces.ts`\\n- Workflow runs and metadata: `db/workflows.ts`\\n- Evolution candidates and experiments: `db/evolution.ts`\\n- Active user workflow definitions: `db/user-workflows.ts`\\n- Immutable definition history: `db/workflow-definition-versions.ts`\\n\\n### Workflow definitions\\n\\nAll candidate definitions are validated through `parseWorkflow()`. Bundled definitions are protected from promotion; only user-owned workflow definitions can receive an evolution patch.\\n\\n## Contribution guidance\\n\\nWhen modifying this module:\\n\\n- Preserve the distinction between deterministic release scores and observational semantic scores.\\n- Keep quality-gate reasons structured; callers depend on `category`, `severity`, and `evidence`.\\n- Ensure new evaluation sources are deduplicated by their logical entity key before attribution.\\n- Keep candidate patches reviewable and validate them with `parseWorkflow()` before execution or publication.\\n- Do not make `EvolutionService` depend directly on server replay code; extend `EvolutionShadowReplayRunner` if replay inputs change.\\n- Preserve trace provenance in golden-sample metadata so reviewers can navigate back to source spans and events.\\n- Treat LLM summaries as advisory. Rule-based intelligence must remain available when providers fail or return malformed output.\\n- Add tests alongside changes; existing tests cover `EvolutionService`, `FailureAttributionService`, `computeQualityGate()`, golden-sample generation, and runtime-intelligence provider/summarization behavior.\",\"observability-runtime-tracing-and-evaluation-deepeval-evalua\":\"# Observability, Runtime Tracing, and Evaluation \u2014 deepeval-evaluator\\n\\n# Observability, Runtime Tracing, and Evaluation \u2014 `deepeval-evaluator`\\n\\n`services/deepeval-evaluator/app.py` implements a standalone FastAPI sidecar that evaluates completed workflow runs using DeepEval's LLM-as-a-judge metrics.\\n\\nThe service accepts workflow-level trace evidence\u2014question, answer, retrieval context, reference answers, identifiers, and optional node/skill metadata\u2014and returns a normalized Archon evaluation result. Its output includes an aggregate score, health classification, per-metric results, findings, evaluator provenance, and traceable sample metadata.\\n\\nAlthough request models carry node-, skill-, tool-, golden-sample-, and human-feedback-related fields, the current DeepEval scoring implementation evaluates only the workflow-level `question`, `answer`, `reference`, and `contexts`. The additional evidence is preserved as input compatibility and summarized in returned metadata.\\n\\n## Responsibilities\\n\\nThe module provides two HTTP endpoints:\\n\\n| Endpoint | Purpose |\\n|---|---|\\n| `GET /health` | Reports service readiness, configured judge model, rubric version, and metric schema version. |\\n| `POST /evaluate` | Authenticates the request, evaluates a workflow sample with DeepEval, and returns `DeepEvalEvaluationResponse`. |\\n\\nIt also owns:\\n\\n- Provider and dependency validation.\\n- Optional bearer-token authentication for evaluator callers.\\n- Translation from Archon sample payloads to `deepeval.test_case.LLMTestCase`.\\n- Construction and execution of `GEval` metrics.\\n- Normalization of DeepEval scores into a consistent `0.0`\u2013`1.0` range.\\n- Conversion of metric failures and low scores into findings.\\n- Aggregation of metric scores into a `0`\u2013`100` health score.\\n- Persistence-oriented evaluator provenance and workflow/trace metadata.\\n\\n## Service Architecture\\n\\n```mermaid\\nflowchart TD\\n    Client[Workflow / evaluation caller] --&gt; Health[GET /health]\\n    Client --&gt; Evaluate[POST /evaluate]\\n    Evaluate --&gt; Auth[validate_request_auth]\\n    Auth --&gt; Thread[asyncio.to_thread]\\n    Thread --&gt; Run[run_deepeval_evaluation]\\n    Run --&gt; Case[build_test_case]\\n    Run --&gt; Metrics[run_metrics]\\n    Metrics --&gt; GEval[DeepEval GEval]\\n    Run --&gt; Response[DeepEvalEvaluationResponse]\\n```\\n\\n`evaluate_sample()` is asynchronous, but DeepEval metric execution is delegated to a worker thread through `asyncio.to_thread(run_deepeval_evaluation, sample)`. This prevents synchronous judge-model work from blocking FastAPI's event loop.\\n\\n## Runtime Configuration\\n\\nThe service is configured exclusively through environment variables.\\n\\n| Variable | Required | Default | Use |\\n|---|---:|---|---|\\n| `OPENAI_API_KEY` | Yes for evaluation | None | Required by `validate_provider_config()` before any DeepEval metrics run. |\\n| `DEEPEVAL_EVALUATOR_TOKEN` | No | None | Enables bearer-token authentication for `POST /evaluate`. |\\n| `DEEPEVAL_LLM_MODEL` | No | `gpt-4o-mini` in reported provenance | Passed to `GEval` when set. Also returned by `/health` and result provenance. |\\n| `DEEPEVAL_THRESHOLD` | No | DeepEval default | Parsed as `float` and passed to each `GEval` metric when set. Invalid numeric values raise during metric construction. |\\n| `DEEPEVAL_RUBRIC_VERSION` | No | `deepeval-v1` | Version label persisted in evaluator provenance and reported by `/health`. |\\n\\n### Readiness behavior\\n\\n`GET /health` considers the evaluator configured only when both conditions hold:\\n\\n1. `OPENAI_API_KEY` is set.\\n2. The `deepeval` imports succeeded, meaning `GEval` is available.\\n\\nA configured instance returns:\\n\\n```json\\n{\\n  \\\"status\\\": \\\"ok\\\",\\n  \\\"provider_configured\\\": true,\\n  \\\"judge_model\\\": \\\"gpt-4o-mini\\\",\\n  \\\"rubric_version\\\": \\\"deepeval-v1\\\",\\n  \\\"metric_schema_version\\\": \\\"1\\\"\\n}\\n```\\n\\nOtherwise, it returns `\\\"status\\\": \\\"degraded\\\"` and `\\\"provider_configured\\\": false`. The health endpoint does not expose credentials.\\n\\n## Request Models\\n\\n### `DeepEvalEvaluationSample`\\n\\n`DeepEvalEvaluationSample` is the body accepted by `POST /evaluate`. It represents one workflow-run evaluation unit.\\n\\nRequired identity fields:\\n\\n| Field | Type | Meaning |\\n|---|---|---|\\n| `workflow_run_id` | `str` | Unique workflow execution identifier. Returned in response metrics. |\\n| `trace_id` | `str` | Runtime trace identifier used to correlate evaluation with observability data. |\\n| `workflow_name` | `str` | Name of the evaluated workflow. |\\n\\nPrimary evaluation fields:\\n\\n| Field | Type | Used by scoring |\\n|---|---|---:|\\n| `question` | `str \\\\| None` | Yes; becomes `LLMTestCase.input`. |\\n| `answer` | `str \\\\| None` | Yes; becomes `LLMTestCase.actual_output`. |\\n| `reference` | `str \\\\| None` | Yes when present; becomes `LLMTestCase.expected_output` and enables `reference_correctness`. |\\n| `contexts` | `list[str]` | Yes when non-empty; becomes `LLMTestCase.retrieval_context` when supported and enables `context_groundedness`. |\\n\\nTrace, feedback, and future evaluation evidence:\\n\\n| Field | Type | Current behavior |\\n|---|---|---|\\n| `workflow_version` | `str \\\\| None` | Returned as metadata. |\\n| `reference_contexts` | `list[str]` | Count returned as metadata; not supplied to DeepEval metrics. |\\n| `expected_tools` | `list[str]` | Count returned as metadata; not evaluated. |\\n| `golden_sample_id` | `str \\\\| None` | Returned as metadata and represented as `golden_sample_available`. |\\n| `human_feedback` | `list[DeepEvalHumanFeedback]` | Count returned as metadata; ratings and labels are not scored. |\\n| `nodes` | `list[DeepEvalNodeSample]` | Accepted but not evaluated or returned as per-node results. |\\n| `skills` | `list[DeepEvalSkillSample]` | Accepted but not evaluated or returned as per-skill results. |\\n\\nLists use `Field(default_factory=list)`, so omitted list-valued fields are normalized to empty lists.\\n\\n### `DeepEvalNodeSample`\\n\\n`DeepEvalNodeSample` models an individual workflow-node observation:\\n\\n- Required: `node_id`, `span_id`, `status`\\n- Optional: `node_type`, `input`, `output`, `reference`, `golden_sample_id`\\n- Evidence collections: `contexts`, `reference_contexts`, `expected_tools`\\n\\nThis model supports trace-level payloads, but `run_deepeval_evaluation()` currently performs only workflow-level evaluation.\\n\\n### `DeepEvalSkillSample`\\n\\n`DeepEvalSkillSample` models one skill invocation:\\n\\n- Required: `skill_name`\\n- Optional correlation: `node_id`\\n- Optional evaluation evidence: `input`, `output`, `reference`, contexts, expected tools, and golden sample ID.\\n\\nSkill records are currently accepted but not converted into `skill_results`.\\n\\n### `DeepEvalHumanFeedback`\\n\\n`DeepEvalHumanFeedback` carries external feedback associated with a node, skill, or workflow-level sample:\\n\\n```json\\n{\\n  \\\"rating\\\": 4,\\n  \\\"label\\\": \\\"helpful\\\",\\n  \\\"node_id\\\": \\\"answer-node\\\",\\n  \\\"skill_name\\\": null\\n}\\n```\\n\\nThe service records only `human_feedback_count` in response metadata. It does not currently blend human feedback into DeepEval scores or findings.\\n\\n## Authentication\\n\\n`validate_request_auth()` implements optional shared-token authentication.\\n\\n- If `DEEPEVAL_EVALUATOR_TOKEN` is not set, all requests are accepted without an `Authorization` header.\\n- If it is set, `POST /evaluate` requires the exact header value:\\n\\n```http\\nAuthorization: Bearer \\n```\\n\\nAny missing, malformed, or mismatched value returns:\\n\\n```json\\n{\\n  \\\"detail\\\": \\\"Invalid DeepEval evaluator token\\\"\\n}\\n```\\n\\nwith HTTP status `401`.\\n\\nThe health endpoint does not call `validate_request_auth()` and remains unauthenticated.\\n\\n## Evaluation Flow\\n\\n### 1. Receive and authenticate the sample\\n\\n`evaluate_sample()` receives a validated `DeepEvalEvaluationSample` and the optional `Authorization` header. It invokes `validate_request_auth()` before dispatching synchronous work to a thread.\\n\\n### 2. Validate evaluator dependencies and provider credentials\\n\\n`run_deepeval_evaluation()` calls `validate_provider_config()` first.\\n\\nIt returns HTTP errors in these cases:\\n\\n| Condition | Status | Detail |\\n|---|---:|---|\\n| `deepeval` could not be imported | `500` | `deepeval is not installed` |\\n| `OPENAI_API_KEY` is missing | `422` | `OPENAI_API_KEY is required for the DeepEval evaluator service.` |\\n\\nThe import is guarded so the module can load even when DeepEval is unavailable. In that case, `GEval`, `LLMTestCase`, and `LLMTestCaseParams` are set to `None`, and evaluation fails explicitly at runtime.\\n\\n### 3. Skip incomplete samples\\n\\nA workflow sample cannot be judged unless it has both a `question` and an `answer`.\\n\\nIf either is missing or falsy, `run_deepeval_evaluation()` returns a response with:\\n\\n- No top-level `score`.\\n- Default `health_status` of `\\\"unknown\\\"`.\\n- `evaluator_execution_status: \\\"skipped\\\"`.\\n- `evaluator_skip_reason: \\\"missing_question_or_answer\\\"`.\\n- `sample_count: 0`.\\n- A warning finding.\\n\\nExample skipped result:\\n\\n```json\\n{\\n  \\\"score\\\": null,\\n  \\\"health_status\\\": \\\"unknown\\\",\\n  \\\"metrics\\\": {\\n    \\\"evaluator_engine\\\": \\\"deepeval\\\",\\n    \\\"judge_model\\\": \\\"gpt-4o-mini\\\",\\n    \\\"rubric_version\\\": \\\"deepeval-v1\\\",\\n    \\\"metric_schema_version\\\": \\\"1\\\",\\n    \\\"sample_count\\\": 0,\\n    \\\"workflow_run_id\\\": \\\"run-123\\\",\\n    \\\"trace_id\\\": \\\"trace-456\\\",\\n    \\\"workflow_name\\\": \\\"support-assistant\\\",\\n    \\\"sample_has_question\\\": false,\\n    \\\"sample_has_answer\\\": true,\\n    \\\"evaluator_execution_status\\\": \\\"skipped\\\",\\n    \\\"evaluator_skip_reason\\\": \\\"missing_question_or_answer\\\"\\n  },\\n  \\\"findings\\\": [\\n    {\\n      \\\"severity\\\": \\\"warning\\\",\\n      \\\"message\\\": \\\"DeepEval skipped because the sample has no question or answer.\\\"\\n    }\\n  ],\\n  \\\"node_results\\\": [],\\n  \\\"skill_results\\\": []\\n}\\n```\\n\\nProvider configuration is validated before this skip check. Therefore, even incomplete samples require a working DeepEval installation and `OPENAI_API_KEY`.\\n\\n### 4. Build the DeepEval test case\\n\\n`build_test_case()` maps workflow-level sample data into `LLMTestCase`:\\n\\n```python\\nkwargs = {\\n    \\\"input\\\": sample.question or \\\"\\\",\\n    \\\"actual_output\\\": sample.answer or \\\"\\\",\\n}\\n```\\n\\nConditional mappings:\\n\\n- `sample.reference` becomes `expected_output`.\\n- Non-blank entries in `sample.contexts` become `retrieval_context`.\\n\\nThe function handles DeepEval version compatibility. It first attempts to construct `LLMTestCase` with `retrieval_context`; if that raises `TypeError`, it retries without that argument. This lets the evaluator run against DeepEval versions whose `LLMTestCase` constructor does not support retrieval contexts.\\n\\n### 5. Build the metric set\\n\\n`build_metrics()` always creates two `GEval` metrics:\\n\\n| Metric name | Evaluation inputs | Purpose |\\n|---|---|---|\\n| `task_completion` | `INPUT`, `ACTUAL_OUTPUT` | Checks whether the answer satisfies the request, is useful and sufficiently complete, and avoids unsupported claims. |\\n| `answer_relevancy` | `INPUT`, `ACTUAL_OUTPUT` | Checks whether the answer is relevant to the input. |\\n\\nIt conditionally adds:\\n\\n| Metric name | Enabled when | Evaluation inputs | Purpose |\\n|---|---|---|---|\\n| `reference_correctness` | `sample.reference` is truthy | `ACTUAL_OUTPUT`, `EXPECTED_OUTPUT` | Checks consistency with the expected output while allowing minor wording differences. |\\n| `context_groundedness` | `sample.contexts` is non-empty | `INPUT`, `ACTUAL_OUTPUT`, `RETRIEVAL_CONTEXT` | Checks whether the answer is supported by supplied retrieval context. |\\n\\n`make_geval()` converts the string parameter names to members of `LLMTestCaseParams`, including only parameters supported by the installed DeepEval version.\\n\\nWhen `DEEPEVAL_LLM_MODEL` is set, it attempts to pass `model=` to `GEval`. If that constructor rejects the `model` argument with `TypeError`, it retries without it. This is another DeepEval-version compatibility path.\\n\\n### 6. Run metrics independently\\n\\n`run_metrics()` executes `metric.measure(test_case)` for each metric. Each metric is isolated with its own `try`/`except`, so one failed metric does not prevent the remaining metrics from running.\\n\\nEach result has this shape:\\n\\n```json\\n{\\n  \\\"name\\\": \\\"task_completion\\\",\\n  \\\"score\\\": 0.82,\\n  \\\"reason\\\": \\\"The response directly addresses the request.\\\",\\n  \\\"success\\\": true\\n}\\n```\\n\\nWhen a metric raises an exception:\\n\\n```json\\n{\\n  \\\"name\\\": \\\"context_groundedness\\\",\\n  \\\"score\\\": null,\\n  \\\"reason\\\": \\\"error text\\\",\\n  \\\"success\\\": false\\n}\\n```\\n\\nThe exception is captured as evaluation evidence rather than propagated as an HTTP failure.\\n\\n### 7. Normalize and aggregate scores\\n\\n`normalize_score()` accepts only finite numeric values that are not booleans:\\n\\n- Values already in `0`\u2013`1` are retained.\\n- Values above `1` are interpreted as percentages and divided by `100`.\\n- Values are clamped to the inclusive range `0.0`\u2013`1.0`.\\n- Output is rounded to four decimal places.\\n- `bool`, nonnumeric, `NaN`, and infinite values produce `None`.\\n\\nExamples:\\n\\n| Raw score | Normalized score |\\n|---:|---:|\\n| `0.87321` | `0.8732` |\\n| `87.32` | `0.8732` |\\n| `125` | `1.0` |\\n| `-0.2` | `0.0` |\\n| `True` | `null` |\\n| `NaN` | `null` |\\n\\nThe top-level score is the rounded arithmetic mean of all available normalized metric scores, expressed on a `0`\u2013`100` scale:\\n\\n```python\\nscore = round(sum(numeric_scores) / len(numeric_scores) * 100)\\n```\\n\\nMetrics with `score: null` are excluded from this average. If every metric has a null score, the overall score is `None`.\\n\\n### 8. Derive health status and findings\\n\\n`health_from_score()` maps the aggregate integer score to Archon health labels:\\n\\n| Aggregate score | `health_status` |\\n|---:|---|\\n| `90`\u2013`100` | `\\\"healthy\\\"` |\\n| `70`\u2013`89` | `\\\"warning\\\"` |\\n| `0`\u2013`69` | `\\\"critical\\\"` |\\n| `null` | `\\\"unknown\\\"` |\\n\\n`findings_from_metric_results()` creates findings for any metric that:\\n\\n- has `success is False`;\\n- has `score is None`; or\\n- has a score below `0.7`.\\n\\nFinding severity is:\\n\\n| Condition | Severity |\\n|---|---|\\n| `score is None` | `critical` |\\n| `score &lt; 0.5` | `critical` |\\n| `0.5 &lt;= score &lt; 0.7` | `warning` |\\n| `success is False` with score `&gt;= 0.7` | `warning` |\\n\\nThe finding message uses the metric's `reason` when available; otherwise it falls back to ` score is below threshold.`. The response is capped at 20 findings.\\n\\n## Response Model\\n\\n`DeepEvalEvaluationResponse` is returned by `POST /evaluate`.\\n\\n| Field | Type | Meaning |\\n|---|---|---|\\n| `score` | `int \\\\| None` | Aggregate normalized metric score, represented as `0`\u2013`100`. |\\n| `health_status` | `healthy \\\\| warning \\\\| critical \\\\| unknown` | Score-derived workflow health classification. |\\n| `metrics` | `dict[str, Any]` | Metric scores, per-metric result details, evaluator provenance, and trace metadata. |\\n| `findings` | `list[dict[str, Any]]` | Low-score and failed-metric diagnostic findings. |\\n| `node_results` | `list[dict[str, Any]]` | Present for response compatibility; currently always empty. |\\n| `skill_results` | `list[dict[str, Any]]` | Present for response compatibility; currently always empty. |\\n\\n### Completed-response metrics\\n\\nA completed response includes:\\n\\n```json\\n{\\n  \\\"evaluator_mode\\\": \\\"deepeval_sidecar\\\",\\n  \\\"evaluator_execution_status\\\": \\\"completed\\\",\\n  \\\"evaluator_engine\\\": \\\"deepeval\\\",\\n  \\\"judge_model\\\": \\\"gpt-4o-mini\\\",\\n  \\\"rubric_version\\\": \\\"deepeval-v1\\\",\\n  \\\"metric_schema_version\\\": \\\"1\\\",\\n  \\\"task_completion\\\": 0.9,\\n  \\\"answer_relevancy\\\": 0.95,\\n  \\\"reference_correctness\\\": 0.88,\\n  \\\"context_groundedness\\\": 0.84,\\n  \\\"sample_count\\\": 1,\\n  \\\"workflow_run_id\\\": \\\"run-123\\\",\\n  \\\"trace_id\\\": \\\"trace-456\\\",\\n  \\\"workflow_name\\\": \\\"support-assistant\\\",\\n  \\\"workflow_version\\\": \\\"2025.03.0\\\",\\n  \\\"sample_has_question\\\": true,\\n  \\\"sample_has_answer\\\": true,\\n  \\\"sample_context_count\\\": 2,\\n  \\\"sample_has_reference\\\": true,\\n  \\\"golden_sample_available\\\": false,\\n  \\\"golden_sample_id\\\": null,\\n  \\\"reference_context_count\\\": 0,\\n  \\\"expected_tool_count\\\": 0,\\n  \\\"human_feedback_count\\\": 0,\\n  \\\"metric_names\\\": [\\n    \\\"task_completion\\\",\\n    \\\"answer_relevancy\\\",\\n    \\\"reference_correctness\\\",\\n    \\\"context_groundedness\\\"\\n  ],\\n  \\\"metric_results\\\": []\\n}\\n```\\n\\n`metric_results` contains the full ordered results, including reasons and success flags. Top-level score keys such as `task_completion` are emitted only for metrics with non-null normalized scores.\\n\\n### Evaluator provenance\\n\\n`evaluator_provenance()` supplies stable fields intended to make results reproducible and interpretable over time:\\n\\n| Field | Value |\\n|---|---|\\n| `evaluator_engine` | Always `\\\"deepeval\\\"` |\\n| `judge_model` | `DEEPEVAL_LLM_MODEL` or `\\\"gpt-4o-mini\\\"` |\\n| `rubric_version` | `DEEPEVAL_RUBRIC_VERSION` or `\\\"deepeval-v1\\\"` |\\n| `metric_schema_version` | Always `\\\"1\\\"` |\\n\\nAny metric, rubric, or output-schema change should be accompanied by an intentional version update, especially `DEEPEVAL_RUBRIC_VERSION` or `metric_schema_version`.\\n\\n## Example Evaluation Request\\n\\n```bash\\ncurl -X POST http://localhost:8000/evaluate \\\\\\n  -H 'Content-Type: application/json' \\\\\\n  -H \\\"Authorization: Bearer ${DEEPEVAL_EVALUATOR_TOKEN}\\\" \\\\\\n  -d '{\\n    \\\"workflow_run_id\\\": \\\"workflow-run-019\\\",\\n    \\\"trace_id\\\": \\\"trace-abc123\\\",\\n    \\\"workflow_name\\\": \\\"knowledge-assistant\\\",\\n    \\\"workflow_version\\\": \\\"2025.03.0\\\",\\n    \\\"question\\\": \\\"What is the retention period for audit logs?\\\",\\n    \\\"answer\\\": \\\"Audit logs are retained for 90 days.\\\",\\n    \\\"contexts\\\": [\\n      \\\"Audit logging policy: retain audit log records for 90 days.\\\",\\n      \\\"Archived audit logs are deleted after the retention window.\\\"\\n    ],\\n    \\\"reference\\\": \\\"Audit logs are retained for 90 days.\\\",\\n    \\\"golden_sample_id\\\": \\\"golden-audit-retention-01\\\",\\n    \\\"human_feedback\\\": [\\n      {\\n        \\\"rating\\\": 5,\\n        \\\"label\\\": \\\"correct\\\"\\n      }\\n    ],\\n    \\\"nodes\\\": [\\n      {\\n        \\\"node_id\\\": \\\"retrieve-policy\\\",\\n        \\\"span_id\\\": \\\"span-01\\\",\\n        \\\"node_type\\\": \\\"retrieval\\\",\\n        \\\"status\\\": \\\"completed\\\",\\n        \\\"output\\\": \\\"Retrieved audit logging policy.\\\"\\n      }\\n    ],\\n    \\\"skills\\\": [\\n      {\\n        \\\"node_id\\\": \\\"retrieve-policy\\\",\\n        \\\"skill_name\\\": \\\"policy-search\\\",\\n        \\\"input\\\": \\\"audit log retention\\\",\\n        \\\"output\\\": \\\"Audit logging policy\\\"\\n      }\\n    ]\\n  }'\\n```\\n\\nRepresentative response:\\n\\n```json\\n{\\n  \\\"score\\\": 91,\\n  \\\"health_status\\\": \\\"healthy\\\",\\n  \\\"metrics\\\": {\\n    \\\"evaluator_mode\\\": \\\"deepeval_sidecar\\\",\\n    \\\"evaluator_execution_status\\\": \\\"completed\\\",\\n    \\\"evaluator_engine\\\": \\\"deepeval\\\",\\n    \\\"judge_model\\\": \\\"gpt-4o-mini\\\",\\n    \\\"rubric_version\\\": \\\"deepeval-v1\\\",\\n    \\\"metric_schema_version\\\": \\\"1\\\",\\n    \\\"task_completion\\\": 0.91,\\n    \\\"answer_relevancy\\\": 0.95,\\n    \\\"reference_correctness\\\": 0.93,\\n    \\\"context_groundedness\\\": 0.86,\\n    \\\"sample_count\\\": 1,\\n    \\\"workflow_run_id\\\": \\\"workflow-run-019\\\",\\n    \\\"trace_id\\\": \\\"trace-abc123\\\",\\n    \\\"workflow_name\\\": \\\"knowledge-assistant\\\",\\n    \\\"workflow_version\\\": \\\"2025.03.0\\\",\\n    \\\"sample_has_question\\\": true,\\n    \\\"sample_has_answer\\\": true,\\n    \\\"sample_context_count\\\": 2,\\n    \\\"sample_has_reference\\\": true,\\n    \\\"golden_sample_available\\\": true,\\n    \\\"golden_sample_id\\\": \\\"golden-audit-retention-01\\\",\\n    \\\"reference_context_count\\\": 0,\\n    \\\"expected_tool_count\\\": 0,\\n    \\\"human_feedback_count\\\": 1,\\n    \\\"metric_names\\\": [\\n      \\\"task_completion\\\",\\n      \\\"answer_relevancy\\\",\\n      \\\"reference_correctness\\\",\\n      \\\"context_groundedness\\\"\\n    ],\\n    \\\"metric_results\\\": [\\n      {\\n        \\\"name\\\": \\\"task_completion\\\",\\n        \\\"score\\\": 0.91,\\n        \\\"reason\\\": \\\"The answer directly answers the retention question.\\\",\\n        \\\"success\\\": true\\n      }\\n    ]\\n  },\\n  \\\"findings\\\": [],\\n  \\\"node_results\\\": [],\\n  \\\"skill_results\\\": []\\n}\\n```\\n\\n## Integration with Observability and Runtime Tracing\\n\\nThe evaluator is designed to consume data assembled from workflow execution and tracing systems rather than to instrument workflows itself.\\n\\n### Trace correlation\\n\\n`workflow_run_id` and `trace_id` are required in every evaluation request and returned unchanged in `metrics`. Callers should use them to:\\n\\n- Locate the source workflow execution.\\n- Join evaluator output to spans, logs, and runtime events.\\n- Compare evaluations across workflow versions.\\n- Correlate low-scoring results with specific trace evidence.\\n\\n### Workflow-level evaluation boundary\\n\\nThe evaluation boundary is currently the complete workflow interaction:\\n\\n```text\\nquestion + final answer + optional reference + optional retrieval context\\n```\\n\\nEven though request payloads can contain `nodes` and `skills`, this module does not yet:\\n\\n- build test cases from node outputs;\\n- run node-level metrics;\\n- evaluate skill outputs;\\n- validate tool usage against `expected_tools`;\\n- compare `reference_contexts`;\\n- associate individual findings with a node or span;\\n- emit `node_results` or `skill_results`.\\n\\nContributors adding these capabilities should preserve the workflow-level result contract while populating the existing response fields.\\n\\n### Metadata preservation\\n\\n`sample_metrics()` provides lightweight observability metadata in every completed or skipped result:\\n\\n- Workflow and trace identity.\\n- Workflow version.\\n- Presence of question, answer, and reference data.\\n- Context and reference-context counts.\\n- Golden-sample availability and ID.\\n- Expected-tool count.\\n- Human-feedback count.\\n- Whether one sample was actually evaluated (`sample_count`) or skipped (`0`).\\n\\nThis metadata is intentionally descriptive rather than evaluative. It enables dashboards and downstream storage to distinguish, for example, an ungrounded response from a response for which no retrieval context was supplied.\\n\\n## Error Handling Semantics\\n\\nThe service differentiates request, configuration, and metric-level failures.\\n\\n| Failure class | Behavior |\\n|---|---|\\n| Invalid request body | FastAPI/Pydantic validation response. |\\n| Invalid bearer token | HTTP `401`. |\\n| Missing DeepEval dependency | HTTP `500`. |\\n| Missing `OPENAI_API_KEY` | HTTP `422`. |\\n| Missing question or answer | Successful response with skipped execution status and warning finding. |\\n| One metric fails | Successful response; failed metric has `score: null`, `success: false`, and a critical finding. |\\n| All metrics fail | Successful response with `score: null`, `health_status: \\\"unknown\\\"`, and findings. |\\n\\nMetric exceptions are deliberately converted into result data. This allows evaluation pipelines to retain partial scores and diagnose provider or rubric issues without losing the full workflow evaluation record.\\n\\n## Extension Guidelines\\n\\n### Adding a workflow-level metric\\n\\nAdd the metric in `build_metrics()` using `make_geval()`:\\n\\n```python\\nmetrics.append(\\n    make_geval(\\n        name=\\\"new_metric\\\",\\n        criteria=\\\"Describe the judge rubric.\\\",\\n        params=[\\\"INPUT\\\", \\\"ACTUAL_OUTPUT\\\"],\\n    )\\n)\\n```\\n\\nConsider:\\n\\n1. Use a stable, machine-readable metric name. It becomes a key in `metrics`.\\n2. Restrict `params` to fields present in the `LLMTestCase` built by `build_test_case()`.\\n3. Make conditional metrics dependent on the evidence they require.\\n4. Update `DEEPEVAL_RUBRIC_VERSION` when changing judging criteria or metric behavior.\\n5. Update `metric_schema_version` if consumers must adapt to a changed response contract.\\n\\nNo changes are required in aggregation or finding generation: `run_metrics()`, `run_deepeval_evaluation()`, and `findings_from_metric_results()` operate on the generated metric list.\\n\\n### Adding new test-case evidence\\n\\nTo use additional request fields in DeepEval:\\n\\n1. Extend `build_test_case()` to pass the evidence to `LLMTestCase`.\\n2. Handle constructor compatibility similarly to the existing `retrieval_context` fallback.\\n3. Add a corresponding conditional metric in `build_metrics()`.\\n4. Ensure the relevant `LLMTestCaseParams` member exists before including it; `make_geval()` already filters unsupported parameters.\\n5. Preserve existing workflow-level metrics when optional evidence is absent.\\n\\n### Implementing node and skill evaluation\\n\\nThe `DeepEvalNodeSample`, `DeepEvalSkillSample`, `node_results`, and `skill_results` models establish the intended extension points.\\n\\nA node- or skill-level implementation should:\\n\\n1. Iterate over `sample.nodes` or `sample.skills`.\\n2. Build a test case from the invocation-specific input, output, reference, and contexts.\\n3. Run appropriate metrics independently, preserving per-item fault isolation.\\n4. Include `node_id`, `span_id`, or `skill_name` in each emitted result for trace correlation.\\n5. Decide how per-item scores contribute to the workflow-level aggregate.\\n6. Avoid changing the meaning of existing `score` and workflow-level metric keys without a schema-version update.\\n\\n### Adjusting score thresholds\\n\\nTwo different threshold concepts exist:\\n\\n- `DEEPEVAL_THRESHOLD` is passed to `GEval` and can affect DeepEval's own `success` evaluation.\\n- `findings_from_metric_results()` independently classifies scores below `0.7` as findings and scores below `0.5` as critical.\\n\\nIf these policies are changed, align the metric-level success semantics, finding severities, dashboard expectations, and rubric versioning.\\n\\n## Implementation Notes\\n\\n- `make_geval()` and `build_test_case()` intentionally catch `TypeError` to support multiple DeepEval constructor versions.\\n- `run_metrics()` catches `Exception` per metric because external model calls can fail for provider, network, rate-limit, parsing, or DeepEval reasons. These errors are represented in the evaluation payload.\\n- `normalize_score()` explicitly rejects booleans because Python treats `bool` as a subtype of `int`.\\n- Blank context strings are removed before constructing `retrieval_context`, but `build_metrics()` enables `context_groundedness` whenever `sample.contexts` is non-empty, including a list containing only blank strings. In that case, a context-groundedness metric may be configured even though no retrieval context is successfully attached to the test case.\\n- `reference_contexts`, `expected_tools`, `human_feedback`, `nodes`, and `skills` do not affect score calculation in the current implementation.\\n\",\"observability-runtime-tracing-and-evaluation-ragas-evaluator\":\"# Observability, Runtime Tracing, and Evaluation \u2014 ragas-evaluator\\n\\n# Observability, Runtime Tracing, and Evaluation \u2014 `ragas-evaluator`\\n\\n`services/ragas-evaluator/app.py` implements a standalone FastAPI service that evaluates AI workflow executions with [Ragas](https://docs.ragas.io/) metrics.\\n\\nThe service accepts a workflow-level sample plus optional node- and skill-level samples, transforms valid samples into a Ragas dataset, invokes an OpenAI-compatible judge model, and returns:\\n\\n- An overall normalized score on a `0\u2013100` scale\\n- A derived health status\\n- Aggregate Ragas metric values\\n- Per-node and per-skill metric results\\n- Findings for metrics below configured thresholds\\n- Evaluation provenance and sample metadata for persistence alongside runtime traces\\n\\nThe module is intentionally self-contained. It does not retrieve traces itself or write results to another service; a caller is responsible for collecting workflow/runtime-tracing data, constructing `RagasEvaluationSample`, calling `POST /evaluate`, and persisting or displaying the response.\\n\\n## HTTP API\\n\\n### `GET /health`\\n\\n`health()` reports evaluator readiness and non-secret configuration.\\n\\nThe endpoint is available without authentication and does not validate that the configured judge endpoint is reachable. Its `\\\"status\\\"` only reflects whether both `OPENAI_API_KEY` and the `langchain-openai` dependency are present.\\n\\nExample response:\\n\\n```json\\n{\\n  \\\"status\\\": \\\"ok\\\",\\n  \\\"provider_configured\\\": true,\\n  \\\"judge_model\\\": \\\"gpt-4o-mini\\\",\\n  \\\"embedding_model\\\": \\\"text-embedding-3-small\\\",\\n  \\\"rubric_version\\\": \\\"ragas-v1\\\",\\n  \\\"metric_schema_version\\\": \\\"1\\\",\\n  \\\"requested_metrics\\\": [\\n    \\\"faithfulness\\\",\\n    \\\"answer_relevancy\\\",\\n    \\\"context_precision\\\",\\n    \\\"context_recall\\\"\\n  ]\\n}\\n```\\n\\nThe endpoint intentionally omits credentials such as `OPENAI_API_KEY` and `RAGAS_EVALUATOR_TOKEN`.\\n\\n### `POST /evaluate`\\n\\n`evaluate_sample()` accepts a `RagasEvaluationSample` and returns `RagasEvaluationResponse`.\\n\\nIf `RAGAS_EVALUATOR_TOKEN` is configured, callers must pass exactly:\\n\\n```http\\nAuthorization: Bearer \\n```\\n\\n`validate_request_auth()` raises HTTP `401` for a missing or mismatched authorization header. If no token is configured, endpoint authentication is disabled.\\n\\nThe async endpoint runs `run_ragas_evaluation()` in a worker thread with `asyncio.to_thread()`. This avoids blocking FastAPI's event loop while Ragas performs synchronous judge-model and embedding calls.\\n\\n```mermaid\\nflowchart TD\\n    A[POST /evaluate] --&gt; B[validate_request_auth]\\n    B --&gt; C[asyncio.to_thread]\\n    C --&gt; D[run_ragas_evaluation]\\n    D --&gt; E[Build scoped Ragas rows]\\n    E --&gt; F[Build metrics, LLM, embeddings]\\n    F --&gt; G[ragas.evaluate]\\n    G --&gt; H[Aggregate scores and findings]\\n    H --&gt; I[RagasEvaluationResponse]\\n```\\n\\n## Request Model\\n\\n`RagasEvaluationSample` represents one workflow execution and its optional traced entities.\\n\\n```python\\nclass RagasEvaluationSample(BaseModel):\\n    workflow_run_id: str\\n    trace_id: str\\n    workflow_name: str\\n    workflow_version: str | None = None\\n    question: str | None = None\\n    answer: str | None = None\\n    contexts: list[str] = Field(default_factory=list)\\n    reference_contexts: list[str] = Field(default_factory=list)\\n    reference: str | None = None\\n    expected_tools: list[str] = Field(default_factory=list)\\n    golden_sample_id: str | None = None\\n    human_feedback: list[RagasHumanFeedback] = Field(default_factory=list)\\n    nodes: list[RagasNodeSample] = Field(default_factory=list)\\n    skills: list[RagasSkillSample] = Field(default_factory=list)\\n```\\n\\n### Workflow-level fields\\n\\n| Field | Purpose |\\n|---|---|\\n| `workflow_run_id` | Identifies the evaluated workflow execution. It is required for correlation by the calling observability system but is not included in the Ragas dataset row. |\\n| `trace_id` | Identifies the associated distributed trace. Like `workflow_run_id`, it is required for external correlation rather than metric computation. |\\n| `workflow_name` | Name of the workflow being evaluated. |\\n| `workflow_version` | Optional version of the workflow definition. |\\n| `question` | Workflow input or user question. Required, together with `answer` and retrieved context, to produce a workflow Ragas row. |\\n| `answer` | Final workflow answer. Required, together with `question` and retrieved context, to produce a workflow Ragas row. |\\n| `contexts` | Retrieved context strings used by the workflow. Empty or whitespace-only strings are discarded when rows are built. |\\n| `reference` | Optional expected answer. Its presence enables reference-dependent context metrics. |\\n| `reference_contexts` | Reference context metadata. This module records its count but does not pass these values to Ragas. |\\n| `expected_tools` | Expected tool metadata. This module records its count but does not currently judge tool selection. |\\n| `golden_sample_id` | Optional identifier for a curated/golden evaluation sample. |\\n| `human_feedback` | Optional manually supplied feedback. Numeric ratings are aggregated as metadata only; they do not affect Ragas scores. |\\n| `nodes` | Runtime node samples to evaluate independently. |\\n| `skills` | Skill samples to evaluate independently. |\\n\\n### Node samples\\n\\n`RagasNodeSample` represents a traceable workflow node:\\n\\n```python\\nclass RagasNodeSample(BaseModel):\\n    node_id: str\\n    span_id: str\\n    node_type: str | None = None\\n    status: str\\n    input: str | None = None\\n    output: str | None = None\\n    contexts: list[str] = Field(default_factory=list)\\n    reference_contexts: list[str] = Field(default_factory=list)\\n    reference: str | None = None\\n    expected_tools: list[str] = Field(default_factory=list)\\n    golden_sample_id: str | None = None\\n```\\n\\nFor each node:\\n\\n- `input` falls back to the workflow `question`.\\n- `output` falls back to the workflow `answer`.\\n- Non-empty `node.contexts` take precedence over workflow `contexts`; otherwise workflow contexts are used.\\n- `node.reference` falls back to the workflow `reference`.\\n- `span_id`, golden-sample availability, reference-context count, and expected-tool count are returned as node-result metadata.\\n- `node_type` and `status` are accepted as trace context but are not used in scoring or returned result metadata by this module.\\n\\nA node is evaluated only if its resolved question, answer, and contexts are all available.\\n\\n### Skill samples\\n\\n`RagasSkillSample` represents an independently evaluable skill invocation:\\n\\n```python\\nclass RagasSkillSample(BaseModel):\\n    node_id: str | None = None\\n    skill_name: str\\n    input: str | None = None\\n    output: str | None = None\\n    contexts: list[str] = Field(default_factory=list)\\n    reference_contexts: list[str] = Field(default_factory=list)\\n    reference: str | None = None\\n    expected_tools: list[str] = Field(default_factory=list)\\n    golden_sample_id: str | None = None\\n```\\n\\nSkill fallback behavior is the same as node fallback behavior:\\n\\n- `input` \u2192 workflow `question`\\n- `output` \u2192 workflow `answer`\\n- `contexts` \u2192 workflow `contexts`\\n- `reference` \u2192 workflow `reference`\\n\\n`skill_name` is preserved in the associated `RagasEntityResult`. `node_id` can be used to associate a skill result with the node that invoked it.\\n\\n### Human feedback\\n\\n`RagasHumanFeedback` supports external human-evaluation metadata:\\n\\n```python\\nclass RagasHumanFeedback(BaseModel):\\n    rating: int | float | None = None\\n    label: str | None = None\\n    node_id: str | None = None\\n    skill_name: str | None = None\\n```\\n\\n`sample_metrics()` computes `human_rating_avg` from every numeric `rating` in the list, regardless of associated node or skill. Labels and associations are retained only in the input model; they do not influence the evaluator response.\\n\\n## Example Evaluation Request\\n\\n```json\\n{\\n  \\\"workflow_run_id\\\": \\\"run_01HVK2R3ZQ\\\",\\n  \\\"trace_id\\\": \\\"trace_8d4e32\\\",\\n  \\\"workflow_name\\\": \\\"support-answering\\\",\\n  \\\"workflow_version\\\": \\\"2025.03.1\\\",\\n  \\\"question\\\": \\\"How do I reset my account password?\\\",\\n  \\\"answer\\\": \\\"Use the password reset page, enter your email address, and follow the link sent to your inbox.\\\",\\n  \\\"contexts\\\": [\\n    \\\"Users can reset their password from the Reset Password page.\\\",\\n    \\\"A password reset email is sent to the account's registered email address.\\\"\\n  ],\\n  \\\"reference\\\": \\\"Open the password reset page and request a reset link using the registered email address.\\\",\\n  \\\"golden_sample_id\\\": \\\"support-password-reset-001\\\",\\n  \\\"human_feedback\\\": [\\n    {\\n      \\\"rating\\\": 4,\\n      \\\"label\\\": \\\"helpful\\\"\\n    }\\n  ],\\n  \\\"nodes\\\": [\\n    {\\n      \\\"node_id\\\": \\\"retrieve-policy\\\",\\n      \\\"span_id\\\": \\\"span_001\\\",\\n      \\\"node_type\\\": \\\"retriever\\\",\\n      \\\"status\\\": \\\"completed\\\",\\n      \\\"input\\\": \\\"How do I reset my account password?\\\",\\n      \\\"output\\\": \\\"Retrieved password-reset policy.\\\",\\n      \\\"contexts\\\": [\\n        \\\"Users can reset their password from the Reset Password page.\\\"\\n      ]\\n    },\\n    {\\n      \\\"node_id\\\": \\\"compose-answer\\\",\\n      \\\"span_id\\\": \\\"span_002\\\",\\n      \\\"node_type\\\": \\\"llm\\\",\\n      \\\"status\\\": \\\"completed\\\",\\n      \\\"input\\\": \\\"How do I reset my account password?\\\",\\n      \\\"output\\\": \\\"Use the password reset page and follow the emailed link.\\\",\\n      \\\"contexts\\\": [\\n        \\\"Users can reset their password from the Reset Password page.\\\",\\n        \\\"A password reset email is sent to the account's registered email address.\\\"\\n      ],\\n      \\\"reference\\\": \\\"Open the password reset page and request a reset link using the registered email address.\\\"\\n    }\\n  ],\\n  \\\"skills\\\": [\\n    {\\n      \\\"node_id\\\": \\\"compose-answer\\\",\\n      \\\"skill_name\\\": \\\"customer-support-response\\\",\\n      \\\"input\\\": \\\"How do I reset my account password?\\\",\\n      \\\"output\\\": \\\"Use the password reset page and follow the emailed link.\\\",\\n      \\\"contexts\\\": [\\n        \\\"Users can reset their password from the Reset Password page.\\\",\\n        \\\"A password reset email is sent to the account's registered email address.\\\"\\n      ]\\n    }\\n  ]\\n}\\n```\\n\\n## Evaluation Lifecycle\\n\\n### 1. Provider validation\\n\\n`run_ragas_evaluation()` begins with `validate_provider_config()`.\\n\\nThe service returns:\\n\\n| Condition | Status | Error detail |\\n|---|---:|---|\\n| `langchain_openai.ChatOpenAI` unavailable | `500` | `langchain-openai is not installed` |\\n| `OPENAI_API_KEY` missing | `422` | `OPENAI_API_KEY is required for the Ragas evaluator service.` |\\n| No Ragas metric imports available | `500` | `Ragas metrics could not be imported` |\\n\\nThis validation occurs even when a sample has no usable rows. Consequently, a request missing required sample data still needs a valid provider configuration before it can return a skipped result.\\n\\n### 2. Build scoped dataset rows\\n\\n`build_scoped_dataset_rows()` converts the input into a list of `ScopedRagasRow` values. Each row has one of three scopes:\\n\\n```python\\nRagasScope = Literal[\\\"workflow\\\", \\\"node\\\", \\\"skill\\\"]\\n```\\n\\nA `ScopedRagasRow` stores:\\n\\n- `scope`\\n- The Ragas input row\\n- Optional `node_id`\\n- Optional `skill_name`\\n- Scope-specific metadata used in entity results\\n\\n`build_dataset_row()` produces a Ragas row only when all required fields are present:\\n\\n```python\\n{\\n    \\\"question\\\": question,\\n    \\\"answer\\\": answer,\\n    \\\"contexts\\\": contexts,\\n    \\\"ground_truth\\\": reference  # only when reference is present\\n}\\n```\\n\\nRows without a non-empty question, answer, or context list are excluded.\\n\\nThe resulting row order is stable and important:\\n\\n1. Workflow row, if valid\\n2. Valid node rows in `sample.nodes` input order\\n3. Valid skill rows in `sample.skills` input order\\n\\nThis order is used to align normalized Ragas results with node and skill entities.\\n\\n### 3. Select runnable metrics\\n\\n`build_metrics(has_reference)` uses `RAGAS_METRICS` to select imported metrics.\\n\\nBy default, `requested_metric_names()` returns:\\n\\n```text\\nfaithfulness,answer_relevancy,context_precision,context_recall\\n```\\n\\nSupported names are:\\n\\n| Configuration name | Ragas metric | Requirements |\\n|---|---|---|\\n| `faithfulness` | `faithfulness` | Must be importable |\\n| `answer_relevancy` | `answer_relevancy` | Must be importable; requires embeddings |\\n| `answer_relevance` | Alias for `answer_relevancy` | Must be importable; requires embeddings |\\n| `context_precision` | `context_precision` | Must be importable and at least one dataset row must have `ground_truth` |\\n| `context_recall` | `context_recall` | Must be importable and at least one dataset row must have `ground_truth` |\\n\\nEach selected metric is `copy.deepcopy()`'d before execution. This avoids sharing potentially mutable metric instances across requests.\\n\\nReference-dependent metrics are enabled globally if **any** dataset row contains `ground_truth`. Rows without a reference may therefore participate in an evaluation run where context metrics have been selected; Ragas controls its per-row behavior.\\n\\nWhen `RAGAS_EMBEDDING_MODEL` disables embeddings, `build_metrics()` removes `answer_relevancy` and its `answer_relevance` alias before evaluation.\\n\\nIf no configured metric is runnable, the service returns a skipped response rather than calling Ragas.\\n\\n### 4. Build judge model and embeddings\\n\\n`build_llm()` constructs the LLM used by Ragas metrics.\\n\\nFor ordinary temperature values, it creates:\\n\\n```python\\nChatOpenAI(\\n    model=os.getenv(\\\"RAGAS_LLM_MODEL\\\", \\\"gpt-4o-mini\\\"),\\n    base_url=os.getenv(\\\"OPENAI_BASE_URL\\\") or None,\\n    temperature=float(temperature),\\n)\\n```\\n\\nIf `RAGAS_LLM_TEMPERATURE` is one of `\\\"\\\"`, `\\\"none\\\"`, `\\\"null\\\"`, or `\\\"omit\\\"`\u2014case-insensitive\u2014`build_llm()` uses `TemperatureOmittingChatModel` instead.\\n\\n`TemperatureOmittingChatModel` exists for OpenAI-compatible providers that reject an explicit `temperature` parameter. Its `_generate()` implementation sends only:\\n\\n```json\\n{\\n  \\\"model\\\": \\\"\\\",\\n  \\\"messages\\\": []\\n}\\n```\\n\\nand adds `\\\"stop\\\"` only when a stop sequence was provided. It posts directly to:\\n\\n```text\\n/chat/completions\\n```\\n\\nusing `urllib.request`, and adds:\\n\\n```http\\nAuthorization: Bearer \\n```\\n\\n`message_to_openai_dict()` converts LangChain message types as follows:\\n\\n| LangChain message type | OpenAI role |\\n|---|---|\\n| `system` | `system` |\\n| `human` | `user` |\\n| `ai` | `assistant` |\\n| Any other type | `user` |\\n\\nNon-string message content is JSON-serialized.\\n\\n`build_embeddings()` creates `OpenAIEmbeddings` only when selected metrics require embeddings. Currently that means `answer_relevancy` or `answer_relevance`.\\n\\n### 5. Execute and normalize Ragas output\\n\\nThe service calls:\\n\\n```python\\nevaluate(\\n    dataset,\\n    metrics=metric_names,\\n    llm=build_llm(),\\n    run_config=build_run_config(),\\n    raise_exceptions=False,\\n    show_progress=False,\\n    embeddings=embeddings,  # only when needed and enabled\\n)\\n```\\n\\n`raise_exceptions=False` asks Ragas to avoid propagating metric-level evaluation failures where supported. Transport, configuration, dataset, or library errors can still escape from `evaluate()`.\\n\\n`normalize_result_rows()` handles several result shapes:\\n\\n- Results exposing `to_pandas()`\\n- A plain dictionary\\n- Objects convertible with `dict(result)`\\n\\n`normalize_metric_record()` keeps only finite non-boolean numeric values and rounds each to four decimal places. Strings, booleans, `NaN`, infinities, and non-numeric data are discarded.\\n\\nIf Ragas produces one normalized result row for multiple dataset rows, the single row is duplicated to match the expected count. If it returns more rows than expected, extra rows are discarded. This behavior preserves alignment for `build_entity_results()`, but contributors should treat unexpected result cardinality as a possible integration issue worth investigating.\\n\\n### 6. Aggregate and classify results\\n\\n`aggregate_metric_rows()` averages each metric across all normalized rows.\\n\\n`score_from_metrics()` averages all aggregate metric values and converts the result to a percentage:\\n\\n```python\\nround(sum(metrics.values()) / len(metrics) * 100)\\n```\\n\\nNo weighting is applied. Adding or removing configured metrics changes the meaning of the overall score.\\n\\n`health_from_score()` maps the score to:\\n\\n| Overall score | `health_status` |\\n|---:|---|\\n| `&gt;= 90` | `healthy` |\\n| `70\u201389` | `warning` |\\n| `&lt; 70` | `critical` |\\n| No numeric metrics | `unknown` |\\n\\n`findings_from_metrics()` creates one finding for every metric below `0.7`:\\n\\n| Metric value | Finding severity |\\n|---:|---|\\n| `&lt; 0.5` | `critical` |\\n| `0.5\u20130.6999` | `warning` |\\n| `&gt;= 0.7` | No finding |\\n\\n## Response Model\\n\\n`RagasEvaluationResponse` has the following shape:\\n\\n```python\\nclass RagasEvaluationResponse(BaseModel):\\n    score: int | None = None\\n    health_status: HealthStatus = \\\"unknown\\\"\\n    metrics: dict[str, Any] = Field(default_factory=dict)\\n    findings: list[dict[str, Any]] = Field(default_factory=list)\\n    node_results: list[RagasEntityResult] = Field(default_factory=list)\\n    skill_results: list[RagasEntityResult] = Field(default_factory=list)\\n```\\n\\nA completed response resembles:\\n\\n```json\\n{\\n  \\\"score\\\": 82,\\n  \\\"health_status\\\": \\\"warning\\\",\\n  \\\"metrics\\\": {\\n    \\\"evaluator_engine\\\": \\\"ragas\\\",\\n    \\\"judge_model\\\": \\\"gpt-4o-mini\\\",\\n    \\\"embedding_model\\\": \\\"text-embedding-3-small\\\",\\n    \\\"rubric_version\\\": \\\"ragas-v1\\\",\\n    \\\"metric_schema_version\\\": \\\"1\\\",\\n    \\\"faithfulness\\\": 0.91,\\n    \\\"answer_relevancy\\\": 0.84,\\n    \\\"context_precision\\\": 0.78,\\n    \\\"context_recall\\\": 0.74,\\n    \\\"sample_count\\\": 4,\\n    \\\"workflow_context_count\\\": 2,\\n    \\\"node_sample_count\\\": 2,\\n    \\\"skill_sample_count\\\": 1,\\n    \\\"golden_sample_available\\\": true,\\n    \\\"golden_sample_id\\\": \\\"support-password-reset-001\\\",\\n    \\\"reference_context_count\\\": 0,\\n    \\\"expected_tool_count\\\": 0,\\n    \\\"human_feedback_count\\\": 1,\\n    \\\"human_rating_avg\\\": 4.0,\\n    \\\"metric_names\\\": [\\n      \\\"faithfulness\\\",\\n      \\\"answer_relevancy\\\",\\n      \\\"context_precision\\\",\\n      \\\"context_recall\\\"\\n    ],\\n    \\\"metric_results\\\": [\\n      {\\n        \\\"faithfulness\\\": 0.91,\\n        \\\"answer_relevancy\\\": 0.84,\\n        \\\"context_precision\\\": 0.78,\\n        \\\"context_recall\\\": 0.74\\n      }\\n    ],\\n    \\\"evaluator_execution_status\\\": \\\"completed\\\"\\n  },\\n  \\\"findings\\\": [],\\n  \\\"node_results\\\": [],\\n  \\\"skill_results\\\": []\\n}\\n```\\n\\n### Aggregate `metrics`\\n\\nThe response `metrics` object combines several categories.\\n\\n#### Evaluator provenance\\n\\n`evaluator_provenance()` produces stable fields intended for storing with evaluation results:\\n\\n| Field | Value |\\n|---|---|\\n| `evaluator_engine` | Always `\\\"ragas\\\"` |\\n| `judge_model` | `RAGAS_LLM_MODEL`, default `gpt-4o-mini` |\\n| `embedding_model` | `RAGAS_EMBEDDING_MODEL`, default `text-embedding-3-small` |\\n| `rubric_version` | `RAGAS_RUBRIC_VERSION`, default `ragas-v1` |\\n| `metric_schema_version` | Always `\\\"1\\\"` |\\n\\nThese fields identify the evaluator configuration used to generate results. They contain no secrets.\\n\\n#### Metric values and execution information\\n\\nFor completed evaluations:\\n\\n- Aggregate metrics such as `faithfulness` and `answer_relevancy`\\n- `metric_names`: resolved Ragas metric object names\\n- `metric_results`: normalized per-row Ragas metric output\\n- `evaluator_execution_status`: `\\\"completed\\\"`\\n\\nThe order of `metric_results` follows the scoped-row order: workflow, then nodes, then skills. Workflow rows do not have a dedicated entity-result list; their values contribute to aggregate scores and are available through `metric_results`.\\n\\n#### Sample metadata\\n\\n`sample_metrics()` adds:\\n\\n| Field | Meaning |\\n|---|---|\\n| `sample_count` | Number of valid scoped dataset rows actually evaluated |\\n| `workflow_context_count` | Raw count of `sample.contexts`, including any blank values |\\n| `node_sample_count` | Number of supplied node samples, whether evaluable or not |\\n| `skill_sample_count` | Number of supplied skill samples, whether evaluable or not |\\n| `golden_sample_available` | Whether workflow-level `golden_sample_id` is non-empty |\\n| `golden_sample_id` | Present only when workflow-level ID exists |\\n| `reference_context_count` | Raw workflow-level reference-context count |\\n| `expected_tool_count` | Raw workflow-level expected-tool count |\\n| `human_feedback_count` | Number of submitted human-feedback records |\\n| `human_rating_avg` | Mean of numeric submitted ratings, when at least one exists |\\n\\n### Node and skill results\\n\\n`build_entity_results()` aligns scoped rows with normalized metric rows and emits `RagasEntityResult` instances for matching scope.\\n\\n```python\\nclass RagasEntityResult(BaseModel):\\n    node_id: str | None = None\\n    skill_name: str | None = None\\n    score: int | None = None\\n    metrics: dict[str, Any] = Field(default_factory=dict)\\n    findings: list[dict[str, Any]] = Field(default_factory=list)\\n```\\n\\nNode `metrics` contain Ragas values plus:\\n\\n```json\\n{\\n  \\\"span_id\\\": \\\"span_001\\\",\\n  \\\"golden_sample_id\\\": \\\"optional-node-golden-id\\\",\\n  \\\"reference_context_count\\\": 0,\\n  \\\"expected_tool_count\\\": 0\\n}\\n```\\n\\nSkill `metrics` contain the same metadata except `span_id`, which only exists for nodes.\\n\\nThe entity `score` is computed from Ragas metric values only. Metadata fields are merged into `metrics` after scoring and do not affect scores or findings.\\n\\n## Skipped Evaluations\\n\\nThe service returns an HTTP `200` skipped response in two cases.\\n\\n### No valid workflow, node, or skill rows\\n\\nIf no scope has a usable question, answer, and retrieved context:\\n\\n```json\\n{\\n  \\\"score\\\": null,\\n  \\\"health_status\\\": \\\"unknown\\\",\\n  \\\"findings\\\": [\\n    {\\n      \\\"severity\\\": \\\"warning\\\",\\n      \\\"message\\\": \\\"Ragas evaluation skipped because no workflow, node, or skill sample contains question, answer, and contexts.\\\"\\n    }\\n  ],\\n  \\\"metrics\\\": {\\n    \\\"sample_count\\\": 0,\\n    \\\"evaluator_execution_status\\\": \\\"skipped\\\",\\n    \\\"evaluator_skip_reason\\\": \\\"missing_question_answer_or_retrieved_context\\\"\\n  }\\n}\\n```\\n\\nThe actual response also includes normal evaluator provenance and sample metadata.\\n\\n### No configured metric can run\\n\\nIf valid rows exist but `build_metrics()` returns no metric\u2014for example, all requested metrics are unavailable, or answer relevancy is the only requested metric and embeddings are disabled\u2014the response includes:\\n\\n```json\\n{\\n  \\\"metric_names\\\": [],\\n  \\\"requested_metric_names\\\": [\\\"...\\\"],\\n  \\\"evaluator_execution_status\\\": \\\"skipped\\\",\\n  \\\"evaluator_skip_reason\\\": \\\"no_configured_metric_runnable\\\"\\n}\\n```\\n\\n## Configuration\\n\\n| Environment variable | Default | Purpose |\\n|---|---|---|\\n| `OPENAI_API_KEY` | None | Required credential for the judge model and embeddings provider. |\\n| `OPENAI_BASE_URL` | None | Optional OpenAI-compatible provider base URL. In the no-temperature model path, it must provide a usable base URL because the service appends `/chat/completions`. |\\n| `RAGAS_EVALUATOR_TOKEN` | None | Optional bearer token protecting `POST /evaluate`. |\\n| `RAGAS_LLM_MODEL` | `gpt-4o-mini` | Judge model passed to `ChatOpenAI` or `TemperatureOmittingChatModel`. |\\n| `RAGAS_LLM_TEMPERATURE` | `0` | Judge temperature. Set to `none`, `null`, `omit`, or an empty value to omit the parameter entirely. Otherwise it must parse as a float. |\\n| `RAGAS_EMBEDDING_MODEL` | `text-embedding-3-small` | Embedding model for answer relevancy. |\\n| `RAGAS_METRICS` | `faithfulness,answer_relevancy,context_precision,context_recall` | Comma-separated requested metric names. Unknown names are ignored. |\\n| `RAGAS_REQUEST_TIMEOUT_SECONDS` | `120` | Request timeout used by `RunConfig` and `TemperatureOmittingChatModel`. Must parse as an integer. |\\n| `RAGAS_MAX_RETRIES` | `1` | Maximum retries passed to Ragas `RunConfig`. Must parse as an integer. |\\n| `RAGAS_RUBRIC_VERSION` | `ragas-v1` | Version label emitted as result provenance; it does not change metric logic by itself. |\\n\\n### Disabling embeddings\\n\\n`embeddings_disabled()` treats the following case-insensitive values as disabled:\\n\\n```text\\n\\\"\\\", none, null, omit, disabled, false\\n```\\n\\nFor example:\\n\\n```bash\\nRAGAS_EMBEDDING_MODEL=disabled\\n```\\n\\nThis prevents creation of `OpenAIEmbeddings` and removes answer-relevancy metrics from `build_metrics()`. Metrics not requiring embeddings remain eligible.\\n\\n## Integration with Runtime Tracing\\n\\nThis module is designed to consume data prepared from workflow observability and tracing systems:\\n\\n- Map a workflow run identifier to `workflow_run_id`.\\n- Map the trace identifier to `trace_id`.\\n- Map traced node IDs and span IDs to `RagasNodeSample.node_id` and `.span_id`.\\n- Supply the prompt/input, generated output, and retrieval contexts for each evaluable scope.\\n- Add a trusted reference answer to enable `context_precision` and `context_recall`.\\n- Preserve returned evaluator provenance with the trace so scores remain comparable across model, embedding, metric-schema, and rubric changes.\\n\\nThe module does not use `workflow_run_id`, `trace_id`, `workflow_name`, or `workflow_version` directly during metric computation. Those fields are contractually important because upstream and downstream systems use them to associate evaluation results with the original runtime execution.\\n\\nLikewise, `reference_contexts`, `expected_tools`, golden IDs, and human feedback are currently observability metadata rather than Ragas inputs. Their counts and selected identifiers make it possible for consuming systems to distinguish ordinary production evaluations from golden-test or feedback-enriched samples.\\n\\n## Extension Guidance\\n\\n### Adding a Ragas metric\\n\\nTo add a metric safely:\\n\\n1. Import it alongside the existing Ragas metric imports.\\n2. Add its configuration name and metric object to `available_metrics` in `build_metrics()`.\\n3. Update `metric_requires_embeddings()` if it needs embeddings.\\n4. Define whether it requires a reference and incorporate that condition in `build_metrics()`.\\n5. Update defaults in `requested_metric_names()` only if the metric should be enabled by default.\\n6. Confirm its input-column requirements are met by `build_dataset_row()`.\\n7. Update this module's health and score semantics if the metric is not a bounded quality value comparable to the existing `0\u20131` metrics.\\n\\nThe overall score is a simple unweighted mean. Do not add a metric with incompatible direction or scale without changing `score_from_metrics()`, `health_from_score()`, and `findings_from_metrics()`.\\n\\n### Adding trace-derived metadata\\n\\nAdditional trace metadata can be accepted in the Pydantic request models without affecting Ragas execution. To preserve it in results:\\n\\n- Add it to the relevant model.\\n- Include it in the `metadata` dict created by `build_scoped_dataset_rows()`.\\n- It will be merged into `RagasEntityResult.metrics` by `build_entity_results()`.\\n\\nAvoid adding arbitrary metadata to the Ragas row produced by `build_dataset_row()` unless the installed Ragas version supports the extra columns. The evaluator currently builds only the standard `question`, `answer`, `contexts`, and optional `ground_truth` fields.\\n\\n### Changing thresholds\\n\\nThe module uses fixed thresholds:\\n\\n- Metric finding threshold: `0.7`\\n- Critical metric threshold: `0.5`\\n- Healthy overall score threshold: `90`\\n- Warning overall score threshold: `70`\\n\\nThese values are implemented in `findings_from_metrics()` and `health_from_score()`. If they become environment-configurable, preserve the current response shape and record threshold or rubric configuration in `evaluator_provenance()` so historical results remain interpretable.\",\"observability-runtime-tracing-and-evaluation-server\":\"# Observability, Runtime Tracing, and Evaluation \u2014 server\\n\\n# Observability, Runtime Tracing, and Evaluation \u2014 Server Module\\n\\nThis module provides the server-side APIs for:\\n\\n- Capturing and querying application observability events\\n- Inspecting runtime traces, failures, costs, anomalies, and replay data\\n- Running and reviewing workflow evaluations\\n- Managing evaluation evidence, benchmarks, golden samples, and human feedback\\n- Proposing, evaluating, rejecting, and promoting supervised workflow-evolution candidates\\n- Enforcing workflow, trace, evaluation-resource, and product-space visibility\\n\\nThe implementation is organized around Hono OpenAPI route modules and a small set of shared services.\\n\\n## Module layout\\n\\n| File | Responsibility |\\n|---|---|\\n| `src/routes/api/observability.ts` | Observability event ingestion, dashboards, aggregations, and authenticated SSE streaming |\\n| `src/routes/api/runtime-traces.ts` | Runtime trace inspection, analytics, replay, pricing, migrations, alerts, and knowledge observations |\\n| `src/routes/api/evaluations.ts` | Workflow evaluation execution and querying, evaluation governance, benchmarks, golden samples, and feedback |\\n| `src/routes/api/evolution.ts` | Supervised self-evolution candidate lifecycle |\\n| `src/services/workflow-access.ts` | Shared authorization for workflow runs, traces, and evaluation resources |\\n| `src/services/evolution-replay.ts` | Boot-time bridge for the evolution shadow-replay implementation |\\n\\nAll route modules are registered from `registerApiRoutes` in `src/routes/api.ts`.\\n\\n## Architecture\\n\\n```mermaid\\nflowchart TD\\n    API[registerApiRoutes] --&gt; OBS[Observability routes]\\n    API --&gt; RT[Runtime trace routes]\\n    API --&gt; EVAL[Evaluation routes]\\n    API --&gt; EVO[Evolution routes]\\n    API --&gt; MW[API observability middleware]\\n    RT --&gt; ACCESS[workflow-access service]\\n    EVAL --&gt; ACCESS\\n    EVO --&gt; ACCESS\\n    RT --&gt; BUS[Observability / evaluation event buses]\\n    EVAL --&gt; BUS\\n```\\n\\nRoutes use `registerOpenApiRoute` with Zod-backed schemas. Database access is delegated to `@archon/core/db` modules, while higher-level operations use services such as `EvaluationService`, `EvolutionService`, and `EvaluationKnowledgeArtifactService`.\\n\\n---\\n\\n## Shared access control\\n\\n`src/services/workflow-access.ts` centralizes visibility checks for workflow-related data. Route handlers should use these functions instead of implementing per-route ownership logic.\\n\\n### Workflow actors\\n\\n`WorkflowAccessActor` contains the authenticated request identity:\\n\\n```ts\\nexport interface WorkflowAccessActor {\\n  readonly userId: string;\\n  readonly userRole: string;\\n}\\n```\\n\\nThe actor is constructed from Hono context values:\\n\\n- `c.get('userId')`\\n- `c.get('userRole')`\\n\\nThese values are expected to be populated by the application authentication middleware.\\n\\n### `canViewWorkflowRun`\\n\\n```ts\\ncanViewWorkflowRun(run, actor): Promise\\n```\\n\\nA workflow run is visible when any of the following is true:\\n\\n1. The actor has the `admin` role.\\n2. The actor owns the run through `run.owner_user_id`.\\n3. The actor is a member of `run.product_id`.\\n4. The actor created the workflow referenced by `run.workflow_record_id`.\\n5. The run has no owner, product, or workflow record.\\n\\nThe final condition preserves access to legacy or system-generated runs whose ownership fields are empty.\\n\\nMembership resolution is performed by `isProductMember`:\\n\\n- Direct membership is checked with `getProductMember`.\\n- If no direct membership exists, the user is resolved with `getUserById`.\\n- A group role is then checked with `getGroupRoleForUser`.\\n\\nWorkflow creator checks are performed by `isWorkflowCreator`, which compares the authenticated user against both:\\n\\n- `workflow.created_by === userId`\\n- `workflow.created_by === user.username`\\n\\n### `getAccessibleWorkflowRun`\\n\\n```ts\\ngetAccessibleWorkflowRun(c, runId): Promise\\n```\\n\\nThis helper loads a run with `getWorkflowRun` and returns it only if `canViewWorkflowRun` succeeds. It intentionally collapses \u201cnot found\u201d and \u201cnot authorized\u201d into `null`, allowing routes to return a consistent `404 Workflow run not found` response without revealing the existence of inaccessible runs.\\n\\nTypical route usage:\\n\\n```ts\\nconst accessDenied = await requireWorkflowRunAccess(c, runId);\\nif (accessDenied) return accessDenied;\\n```\\n\\nBoth `evaluations.ts` and `evolution.ts` define this route-level wrapper.\\n\\n### Trace visibility\\n\\n`canViewTrace` applies workflow-run visibility to a `RuntimeTraceRow`:\\n\\n- Administrators can view any trace.\\n- Traces without `workflow_run_id` are not visible to non-administrators.\\n- Otherwise, the associated workflow run is loaded and checked with `canViewWorkflowRun`.\\n\\n`filterAccessibleTraces` applies the same policy to a collection. It evaluates each trace sequentially and returns only visible rows.\\n\\n### Evaluation resource visibility\\n\\nEvaluation resources use `EvaluationResourceAccess`:\\n\\n```ts\\nexport interface EvaluationResourceAccess {\\n  readonly owner_user_id?: string | null;\\n  readonly product_id?: string | null;\\n  readonly visibility?: string | null;\\n}\\n```\\n\\n#### `canViewEvaluationResource`\\n\\nVisibility rules are:\\n\\n- Administrators can view all resources.\\n- `public` resources are visible to everyone.\\n- The owner can view the resource.\\n- Legacy private rows with no owner and no product are treated as system samples and remain visible.\\n- `product` resources require a product-space role.\\n- Other private resources are not visible to unrelated users.\\n\\n#### `canManageEvaluationResource`\\n\\nManagement is stricter than viewing:\\n\\n- Administrators can manage all resources.\\n- The owner can manage the resource.\\n- Product-scoped resources can be managed by product `admin` and `product_admin` roles.\\n- Product members without an administrative product role cannot manage them.\\n\\n#### `canUseEvaluationProduct`\\n\\nThis checks whether a user can create or target an evaluation resource in a product space. Administrators bypass the check; all other users need either direct or group-based product membership.\\n\\nThe golden-sample routes use these checks when creating, updating, approving, and rejecting samples.\\n\\n---\\n\\n# Observability\\n\\n`src/routes/api/observability.ts` provides event ingestion and operational reporting. Observability records can come from the backend, frontend, workflow execution, probes, and other producers represented by `ObservabilityEventInput`.\\n\\n## Automatic API instrumentation\\n\\n### `createApiObservabilityMiddleware`\\n\\nThis middleware measures every eligible API request:\\n\\n1. Records the start time.\\n2. Runs the downstream handler.\\n3. Captures any thrown error.\\n4. In a `finally` block, asynchronously calls `recordApiObservation`.\\n5. Re-throws the original error if one occurred.\\n\\nThe observation write is deliberately fire-and-forget:\\n\\n```ts\\nvoid recordApiObservation(c, startedAt, thrownError).catch(...)\\n```\\n\\nA failure to write observability data is logged at debug level and does not replace or alter the original API response.\\n\\n### Excluded paths\\n\\n`shouldSkipApiObservation` excludes paths that would create noise or recursion:\\n\\n- `/api/observability`\\n- `/api/stream`\\n- `/api/auth`\\n- `/api/openapi`\\n- `/api/health`\\n\\n### `recordApiObservation`\\n\\nThis function derives an `ObservabilityEventInput` from the request context:\\n\\n- `source: 'backend'`\\n- `event_type: 'api_call'` for successful and non-server-error responses\\n- `event_type: 'backend_error'` for thrown errors or status codes `&gt;= 500`\\n- Severity:\\n  - `critical` for thrown errors or server errors\\n  - `warning` for other 4xx responses\\n  - `info` otherwise\\n- HTTP method, path, status, and duration\\n- Error name and message when an `Error` was thrown\\n- User ID, resolved username, and user role\\n- A feature area inferred by `inferFeatureAreaFromPath`\\n\\nThe username is resolved by `resolveUsername`, which prefers `real_name` and falls back to `username`.\\n\\nFeature-area inference includes:\\n\\n| Path prefix | Area |\\n|---|---|\\n| `/api/conversations`, `/api/messages` | `chat` |\\n| `/api/workflows` | `workflow` |\\n| `/api/evaluations`, `/api/runtime` | `evaluation` |\\n| `/api/knowledge` | `knowledge` |\\n| `/api/settings`, `/api/config` | `settings` |\\n| `/api/dashboard` | `dashboard` |\\n| `/api/ui-replay`, `/api/debug-session` | `diagnostics` |\\n| Other paths | `unknown` |\\n\\nAfter persistence through `observabilityDb.createObservabilityEvents`, the created event is published through `getObservabilityEventBus()` as `observability_event_created`.\\n\\n## Event ingestion\\n\\n### `POST /api/observability/events`\\n\\nThis endpoint accepts a batch validated by `createObservabilityEventsBodySchema`.\\n\\nFor each event:\\n\\n- The route preserves the submitted fields.\\n- `source` defaults to `'frontend'` when omitted.\\n- The authenticated request user and resolved username are passed to the database layer.\\n\\nThe response includes:\\n\\n```json\\n{\\n  \\\"events\\\": [],\\n  \\\"accepted\\\": 0\\n}\\n```\\n\\nThe route publishes an `observability_batch_created` event containing the accepted count and serialized event payloads.\\n\\n## Event query endpoints\\n\\n### `GET /api/observability/events`\\n\\n`listObservabilityEventsRoute` supports:\\n\\n- Relative windows, capped at 92 days\\n- Explicit `startAt` and `endAt`\\n- Pagination through `limit` and `offset`\\n- Source, event type, and severity filters\\n- Feature area\\n- Product, codebase, user, and workflow-name filters\\n\\nWindow parsing is handled by `parseObservabilityWindowMinutes`:\\n\\n- Default: 60 minutes\\n- Minimum: 1 minute\\n- Maximum: `92 * 24 * 60` minutes\\n\\nLimits are normalized through `parseRuntimeLimit`.\\n\\n### `GET /api/observability/events/{id}`\\n\\nLoads a single event with `observabilityDb.getObservabilityEvent`. Missing IDs and missing records return `404`.\\n\\n### `GET /api/observability/errors`\\n\\nUses `observabilityDb.listObservabilityErrorPage` to combine frontend, backend, and workflow errors. In addition to common time and identity filters, it accepts:\\n\\n- `featureArea`\\n- `stabilityCategory`\\n- Product and codebase\\n- User and workflow name\\n- Pagination\\n\\n### SLA and dashboard endpoints\\n\\n- `GET /api/observability/sla`\\n  - Returns time-bucketed stability data from `listObservabilitySlaBuckets`.\\n- `GET /api/observability/sla-dashboard`\\n  - Returns a combined dashboard snapshot from `listObservabilitySlaDashboard`.\\n  - Optional sections include error details, workflow-node errors, and user activity.\\n- `GET /api/observability/traffic`\\n  - Loads traffic buckets and a traffic summary in parallel.\\n- `GET /api/observability/probe-targets`\\n  - Aggregates active probe history by target.\\n- `GET /api/observability/workflow-node-errors`\\n  - Reports workflow-node failures from traces and frontend observations.\\n- `GET /api/observability/user-activity`\\n  - Aggregates page, action, idle, dwell, and error activity.\\n\\nWorkflow-node filters support node types:\\n\\n- `command`\\n- `skill`\\n- `bash`\\n- `other`\\n\\nRoot-cause filters include categories such as `node_stalled`, `provider_stream`, `sandbox_lifecycle`, `workflow_logic`, and `control_plane_timeout`.\\n\\nThe `executionFailures` flag changes workflow-node error behavior. When enabled, the route includes all non-cancelled workflow failures rather than restricting the query to workflow-only node failures.\\n\\n## Observability SSE stream\\n\\n### `GET /api/stream/__observability__`\\n\\nThe stream requires an authenticated JWT. The token may be supplied through:\\n\\n- `Authorization: Bearer `\\n- `token` query parameter\\n\\n`authorizeAuthenticatedStream` verifies the token with `verifyToken` and confirms that the user still exists with `getUserById`.\\n\\nOnce authorized, the route:\\n\\n1. Sends an initial heartbeat.\\n2. Subscribes to `getObservabilityEventBus()`.\\n3. Writes each event to the SSE stream.\\n4. Sends a heartbeat every 30 seconds.\\n5. Unsubscribes on abort and during cleanup.\\n\\nThe stream serializes events through `observabilityStreamEventPayload`, which includes correlation fields such as:\\n\\n- `workflow_run_id`\\n- `trace_id`\\n- `span_id`\\n- `node_id`\\n- `skill_name`\\n- `tool_name`\\n\\nThis allows a live observability consumer to correlate API events with runtime traces and workflow execution.\\n\\n---\\n\\n# Runtime tracing\\n\\n`src/routes/api/runtime-traces.ts` exposes runtime trace data and operational tooling. The route module integrates several core databases:\\n\\n- `runtimeTraceDb`\\n- `workflowDb`\\n- `workflowEventDb`\\n- `conversationDb`\\n- `codebaseDb`\\n- `envVarDb`\\n- `messageDb`\\n- `knowledgeObservationDb`\\n- `knowledgeSyncJobDb`\\n\\nIt also integrates workflow discovery, local workflow execution, runtime pricing, and replay support.\\n\\n## Trace query and analytics endpoints\\n\\nThe route definitions cover the following API areas.\\n\\n### Trace inspection\\n\\n- `GET /api/runtime/traces`\\n  - Lists recent runtime traces.\\n- `GET /api/runtime/traces/{traceId}`\\n  - Returns trace detail with spans and events.\\n- `GET /api/runtime/traces/{traceId}/replay-manifest`\\n  - Builds a replay manifest from a failed trace.\\n- `POST /api/runtime/traces/{traceId}/replay`\\n  - Replays a failed workflow trace locally without isolation.\\n\\nTrace access is enforced with `canViewTrace` or `filterAccessibleTraces`.\\n\\n### Health and failure analysis\\n\\n- `GET /api/runtime/traces/health`\\n  - Evaluates trace health over a time window.\\n- `GET /api/runtime/traces/stale-runs`\\n  - Lists stale or orphaned workflow traces for manual reconciliation.\\n- `GET /api/runtime/traces/failure-aggregates`\\n  - Aggregates failures by node, tool, span, or event type.\\n- `GET /api/runtime/traces/anomalies`\\n  - Detects trace anomalies.\\n- `GET /api/runtime/traces/reliability`\\n  - Ranks workflow, provider, and model reliability.\\n\\n### Performance and usage\\n\\n- `GET /api/runtime/traces/workflow-aggregates`\\n  - Aggregates workflow node and tool duration percentiles.\\n- `GET /api/runtime/traces/slow-node-trends`\\n  - Returns slow span percentile trends by time bucket.\\n- `GET /api/runtime/traces/usage-aggregates`\\n  - Aggregates token and cost usage by provider and model.\\n- `GET /api/runtime/traces/cost-trends`\\n  - Returns token and cost trends by time bucket.\\n\\n### Runtime intelligence\\n\\n- `GET /api/runtime/traces/intelligence`\\n  - Combines trace health, anomalies, and optimization suggestions.\\n- `POST /api/runtime/traces/intelligence/summarize`\\n  - Optionally generates an LLM summary of runtime intelligence.\\n\\nThe runtime trace module builds structured LLM facts through `buildRuntimeTraceLlmFacts`. Values are normalized with `stringValue`, while configuration structures are guarded with `isRecord` and selected through `pickDefinedConfig`.\\n\\n### Pricing\\n\\n- `GET /api/runtime/traces/pricing`\\n  - Returns the runtime model price catalog and overrides.\\n- `PUT /api/runtime/traces/pricing`\\n  - Updates price overrides.\\n\\nThe handlers use:\\n\\n- `getRuntimePriceCatalog`\\n- `getRuntimePriceOverrides`\\n- `setRuntimePriceOverrides`\\n\\n### Alerting\\n\\n- `GET /api/runtime/traces/alerts/preview`\\n  - Previews alerts for a time window.\\n- `GET /api/runtime/traces/alerts`\\n  - Lists persisted alert history.\\n- `POST /api/runtime/traces/alerts/{alertId}/status`\\n  - Updates an alert status.\\n- `GET /api/runtime/traces/alert-rules`\\n  - Lists alert rules.\\n- `PUT /api/runtime/traces/alert-rules/{ruleId}`\\n  - Updates an alert rule.\\n\\n### Schema migrations\\n\\n- `GET /api/runtime/traces/schema-migrations/summary`\\n- `GET /api/runtime/traces/schema-migrations`\\n- `POST /api/runtime/traces/schema-migrations/run`\\n\\nThese endpoints expose runtime trace schema migration state, history, and batch upgrades for older trace records.\\n\\n### Archives\\n\\n- `GET /api/runtime/traces/archives`\\n- `GET /api/runtime/traces/archives/{archiveId}`\\n- `GET /api/runtime/traces/archives/compare`\\n- `GET /api/runtime/traces/archives/{archiveId}/download`\\n\\nArchive routes inspect JSON trace snapshots and compare two archived snapshots.\\n\\n## Replay manifests\\n\\nReplay manifest construction is centered around `buildReplayManifestContextForTrace`.\\n\\nThe function gathers the context needed to reproduce or inspect a workflow run, including:\\n\\n- The source workflow run\\n- Conversation and message snapshots\\n- Workflow events\\n- Discovered workflow definitions\\n- Codebase information\\n- Codebase environment variables\\n- Execution replay context\\n- Log pointers\\n- Artifact pointers\\n- Assistant configuration overrides\\n\\nRelevant helper functions include:\\n\\n- `buildWorkflowReplaySnapshot`\\n- `toReplayMessageSnapshot`\\n- `parseMessageMetadata`\\n- `buildExecutionReplayContext`\\n- `buildLogPointers`\\n- `buildArtifactPointers`\\n- `buildProviderConfigSnapshots`\\n- `buildNodeConfigSnapshots`\\n- `buildToolInputSummaries`\\n- `buildToolInputPreview`\\n- `describeRedactedValue`\\n\\nThe helper names reflect an important implementation property: replay metadata is summarized and redacted rather than exposing raw tool inputs or secret configuration values. Log and artifact pointers are derived through `getRunLogPath` and `getRunArtifactsPath`.\\n\\nThe manifest gathers related database data through calls such as:\\n\\n- `getConversationById`\\n- `listMessages`\\n- `listWorkflowEvents`\\n- `getWorkflowRun`\\n- `getCodebase`\\n- `getCodebaseEnvVars`\\n\\nIt also uses `discoverWorkflowsWithConfig` to resolve workflow definitions available to the server.\\n\\n## Local replay\\n\\n`POST /api/runtime/traces/{traceId}/replay` invokes local workflow execution. The replay path uses:\\n\\n- `discoverWorkflowsWithConfig`\\n- `loadConfig`\\n- Built-in provider registration\\n- `createWorkflowRun`\\n- `sendMessage`\\n- `sendStructuredEvent`\\n- Codebase and environment-variable lookup\\n- Conversation lookup through `findConversationByPlatformId`\\n\\nThe local execution path can reach built-in providers such as `CodexProvider` and `ClaudeProvider`. It also uses workflow discovery behavior that distinguishes bundled defaults through `isBinaryBuild`.\\n\\nReplay execution returns a dispatch-style response extended with:\\n\\n- `workflowRunId`\\n- `replayTraceId`\\n\\nReplay is intentionally local and non-isolated according to the route summary. Callers should treat it as an operational debugging tool rather than a sandbox boundary.\\n\\n## Knowledge observations\\n\\nThe runtime route also exposes body-free knowledge telemetry:\\n\\n- `GET /api/runtime/knowledge/overview`\\n- `GET /api/runtime/knowledge/retrievals`\\n- `GET /api/runtime/knowledge/sync-funnel`\\n\\nThese handlers use knowledge observation and knowledge-sync database modules. Access checks are performed through `knowledgeObservationAccessError` and `isProductSpaceMember`, so product-scoped knowledge observations are not returned to users without the required product-space membership.\\n\\n---\\n\\n# Evaluation APIs\\n\\n`src/routes/api/evaluations.ts` is the evaluation orchestration and governance layer. It combines:\\n\\n- `EvaluationService`\\n- Evaluation database modules\\n- `EvaluationBenchmarkService`\\n- `EvaluationCalibrationService`\\n- `EvaluationKnowledgeArtifactService`\\n- `GoldenSampleCandidateService`\\n- Quality-gate functions\\n- The evaluation event bus\\n\\n## Workflow evaluation reads\\n\\nThe following endpoints query evaluation projections associated with a workflow run:\\n\\n- `GET /api/evaluations/workflows`\\n- `GET /api/evaluations/workflows/{runId}`\\n- `GET /api/evaluations/workflows/{runId}/nodes`\\n- `GET /api/evaluations/workflows/{runId}/skills`\\n- `GET /api/evaluations/workflows/{runId}/snapshot`\\n- `GET /api/evaluations/jobs`\\n- `GET /api/evaluations/jobs/{jobId}/runs`\\n\\nWorkflow-scoped rows are filtered through `getAccessibleWorkflowRun`. For list endpoints containing many rows, `filterWorkflowScopedRows` caches access decisions per `workflow_run_id` to avoid repeated authorization lookups.\\n\\nThe `latestOnly` query flag switches between complete history and latest evaluation projections.\\n\\nThe snapshot endpoint loads workflow, node, and skill evaluations in parallel and returns:\\n\\n```json\\n{\\n  \\\"workflow_evaluations\\\": [],\\n  \\\"node_evaluations\\\": [],\\n  \\\"skill_evaluations\\\": []\\n}\\n```\\n\\n## Manual evaluator execution\\n\\nThe following endpoints execute a manual evaluation for a workflow run:\\n\\n- `POST /api/evaluations/workflows/{runId}/deterministic`\\n- `POST /api/evaluations/workflows/{runId}/semantic`\\n- `POST /api/evaluations/workflows/{runId}/ragas`\\n- `POST /api/evaluations/workflows/{runId}/promptfoo`\\n\\nAll four routes first require workflow-run access, then call:\\n\\n```ts\\nrunEvaluationForResponse(runId, evaluatorType)\\n```\\n\\n### `runEvaluationForResponse`\\n\\nThe execution flow is:\\n\\n1. Emit `evaluation_started`.\\n2. Instantiate `EvaluationService`.\\n3. Call the evaluator-specific method:\\n   - `runDeterministicEvaluation`\\n   - `runSemanticEvaluation`\\n   - `runRagasEvaluation`\\n   - `runPromptfooEvaluation`\\n4. Persist an immutable evaluation run with `recordManualEvaluationRun`.\\n5. Emit `evaluation_updated`.\\n6. Emit `evaluation_completed`.\\n7. Return workflow, node, and skill evaluation results.\\n\\nFailures are logged with `evaluation_run_failed` and returned as HTTP `422`.\\n\\n### `recordManualEvaluationRun`\\n\\nThis function creates a durable job and run record around the service result.\\n\\nIt loads, in parallel:\\n\\n- The workflow run\\n- The workflow version snapshot\\n- A new evaluation job\\n\\nIt derives:\\n\\n- Evaluation status\\n- Applicability\\n- Input hash\\n- Trace snapshot hash\\n- Evaluator engine, mode, and version\\n- Optional dataset, rubric, and judge-model metadata\\n- Workflow and node/skill counts\\n- Trace provenance\\n- The projected workflow evaluation ID\\n\\n`metricString`, `nullableMetricString`, and `hashEvaluationInput` normalize evaluator output and provide stable provenance metadata.\\n\\nThe lifecycle is:\\n\\n```text\\nevaluation job: running\\n        |\\n        v\\nrecord immutable evaluation run\\n        |\\n        v\\ncomplete evaluation job:\\n  completed -&gt; completed\\n  failed/skipped -&gt; partial\\n```\\n\\n## Comparison, readiness, and evidence\\n\\n- `GET /api/evaluations/workflows/{runId}/compare`\\n  - Compares a workflow evaluation with an optional `baselineRunId`.\\n- `GET /api/evaluations/workflows/{runId}/capability-readiness`\\n  - Calls `computeEvaluationCapabilityReadiness`.\\n- `GET /api/evaluations/workflows/{runId}/evidence-coverage`\\n  - Returns redacted evaluation-evidence coverage.\\n- `GET /api/evaluations/workflows/{runId}/knowledge-artifacts`\\n  - Lists knowledge-governance links associated with workflow artifacts.\\n\\nAll workflow-scoped endpoints require access to the referenced workflow run.\\n\\n## Aggregates and version effectiveness\\n\\nTwo administrative reporting endpoints are intentionally non-disclosing for non-admin users:\\n\\n- `GET /api/evaluations/aggregates`\\n- `GET /api/evaluations/version-effectiveness`\\n\\nA non-admin receives an empty result rather than an authorization error:\\n\\n```json\\n{\\n  \\\"workflow\\\": [],\\n  \\\"nodes\\\": [],\\n  \\\"skills\\\": [],\\n  \\\"trends\\\": []\\n}\\n```\\n\\nor:\\n\\n```json\\n{\\n  \\\"versions\\\": []\\n}\\n```\\n\\nAdministrators can query by codebase, product, workflow name, workflow version, knowledge mode, time window, bucket count, and result limit.\\n\\n## Quality gates\\n\\n- `GET /api/evaluations/workflows/{runId}/quality-gate`\\n  - Computes and persists a quality gate using `computeQualityGate`.\\n- `POST /api/evaluations/workflows/{runId}/quality-gate/actions`\\n  - Applies a governance action with `applyQualityGateAction`.\\n\\nActions may include an assignee, note, and baseline run ID. Both routes enforce workflow-run visibility.\\n\\n## Knowledge artifact governance\\n\\nThe following routes are administrator-only:\\n\\n- `POST /api/evaluations/knowledge-artifacts/{linkId}/publish-candidate`\\n- `POST /api/evaluations/knowledge-artifacts/{linkId}/approve-source`\\n- `POST /api/evaluations/knowledge-artifacts/{linkId}/review`\\n\\nThey use `EvaluationKnowledgeArtifactService` to:\\n\\n- Queue a reviewed artifact as an AI-Ku candidate\\n- Record an explicitly approved external source revision\\n- Reject or withdraw a candidate\\n\\nThe route passes the authenticated user ID as `reviewerId`, preserving reviewer provenance.\\n\\n## Benchmark suites\\n\\nBenchmark administration is also restricted to administrators:\\n\\n- `GET /api/evaluations/benchmarks`\\n- `POST /api/evaluations/benchmarks/import`\\n- `GET /api/evaluations/benchmarks/{suiteId}/calibration`\\n\\n`EvaluationBenchmarkService.importSuite` validates and imports an isolated suite. The request can select dry-run and freeze behavior. Invalid validation results are returned as HTTP `400`.\\n\\n`EvaluationCalibrationService.generateReport` creates a calibration report for a suite and rubric version.\\n\\n## Golden samples\\n\\nGolden sample routes:\\n\\n- `GET /api/evaluations/golden-samples`\\n- `POST /api/evaluations/golden-samples`\\n- `POST /api/evaluations/golden-samples/{sampleId}/approve`\\n- `POST /api/evaluations/golden-samples/{sampleId}/reject`\\n- `POST /api/evaluations/workflows/{runId}/golden-sample-candidate`\\n\\n### Creation and update behavior\\n\\nThe upsert route finds an existing sample by its logical key:\\n\\n- Workflow name\\n- Workflow version\\n- Node ID\\n- Skill name\\n- Sample key\\n\\nIf an existing resource is found, `canManageEvaluationResource` must succeed. For new product-scoped samples, `canUseEvaluationProduct` is required.\\n\\nNew records receive defaults for:\\n\\n- `owner_user_id`\\n- `visibility`\\n- `dataset_version`\\n- `source`\\n- `created_by`\\n- `updated_by`\\n\\nAudit metadata records whether the action was a create or update and identifies the actor.\\n\\n### Review behavior\\n\\nApproval and rejection update review metadata, including:\\n\\n- Review status\\n- Reviewer note\\n- Review timestamp\\n- Reviewer ID\\n- Audit action\\n\\nBoth operations require management access to the existing sample.\\n\\n### Candidate generation\\n\\n`GoldenSampleCandidateService.generateCandidateFromRun` derives a candidate from an accessible workflow run. The optional request body can limit generation by:\\n\\n- `scope`\\n- `node_id`\\n- `skill_name`\\n\\nThe route accepts an optional JSON body and returns `400` when the body is present but invalid.\\n\\n## Human feedback\\n\\n- `GET /api/evaluations/human-feedback`\\n- `POST /api/evaluations/human-feedback`\\n\\nListing applies both query-level visibility filters and `filterWorkflowScopedRows`.\\n\\nWhen feedback is created:\\n\\n- The workflow run must be accessible.\\n- `product_id` is inherited from the run.\\n- `owner_user_id` and `created_by` are set to the authenticated user.\\n- Visibility is `product` when the run has a product, otherwise `private`.\\n- Audit metadata records the API source and actor.\\n\\n---\\n\\n# Evolution candidate APIs\\n\\n`src/routes/api/evolution.ts` implements supervised self-evolution. Candidate records are always scoped back to their originating workflow run.\\n\\n## Candidate lifecycle endpoints\\n\\n- `GET /api/evaluations/evolution/candidates`\\n- `GET /api/evaluations/evolution/candidates/{candidateId}`\\n- `POST /api/evaluations/evolution/runs/{runId}/propose`\\n- `POST /api/evaluations/evolution/candidates/{candidateId}/evaluate`\\n- `POST /api/evaluations/evolution/candidates/{candidateId}/reject`\\n- `POST /api/evaluations/evolution/candidates/{candidateId}/promote`\\n- `PUT /api/evaluations/evolution/candidates/{candidateId}/patched-definition`\\n\\n`filterAccessibleCandidates` caches run visibility decisions by `workflow_run_id`, matching the approach used by evaluation list endpoints.\\n\\n### Proposal\\n\\n`POST .../runs/{runId}/propose` requires access to the source run and calls:\\n\\n```ts\\nnew EvolutionService().proposeForRun(runId)\\n```\\n\\n### Evaluation\\n\\n`POST .../candidates/{candidateId}/evaluate` loads and authorizes the candidate, then calls `EvolutionService.evaluateCandidate`.\\n\\nCandidate evaluation can use a shadow replay runner supplied by `buildCandidateShadowReplayRunner`.\\n\\n### Rejection\\n\\nRejection transitions the candidate with:\\n\\n```ts\\ntransitionCandidate(candidateId, 'rejected')\\n```\\n\\n### Promotion\\n\\nPromotion is administrator-only. It transitions the candidate to `promoted`, passing:\\n\\n- `promotedBy`\\n- `ownerUserId`\\n\\nThe response includes both the transitioned candidate and the applied definition. Errors indicating invalid or bundled definitions are mapped to `400`; other failures return `500`.\\n\\n### Patched definitions\\n\\nSaving a human-reviewed definition draft is administrator-only. The body is validated by `evolutionPatchedDefinitionBodySchema`, then passed to:\\n\\n```ts\\nEvolutionService.savePatchedDefinition(candidateId, definition)\\n```\\n\\nInvalid definition errors return `400`.\\n\\n## Shadow replay bridge\\n\\n`src/services/evolution-replay.ts` contains a process-local runner registry:\\n\\n```ts\\nlet shadowReplayRunner: EvolutionShadowReplayRunner | null = null;\\n```\\n\\nIt exposes:\\n\\n- `setEvolutionShadowReplayRunner`\\n- `getEvolutionShadowReplayRunner`\\n\\nThe runtime-trace route registers the actual runner during boot:\\n\\n```text\\nregisterRuntimeTraceRoutes\\n  -&gt; setEvolutionShadowReplayRunner\\n```\\n\\nThe evolution route later retrieves it through `getEvolutionShadowReplayRunner`.\\n\\nThis separation exists because the local replay implementation depends on the web adapter closure available in `runtime-traces.ts`. The evolution route should not construct that adapter independently.\\n\\n### `buildCandidateShadowReplayRunner`\\n\\nThis wrapper adds database-backed workflow resolution:\\n\\n1. Retrieve the boot-registered base runner.\\n2. If the candidate input already contains `modifiedWorkflow`, preserve it.\\n3. Otherwise, load all user workflows with `listAllUserWorkflows`.\\n4. Find the workflow by name.\\n5. Parse its stored definition with `parseWorkflow`.\\n6. Use the parsed workflow when parsing succeeds.\\n7. Delegate to the base runner with the resolved definition.\\n\\nThis is required because user workflows stored in the database are not visible to file-based workflow discovery.\\n\\n---\\n\\n# Route implementation conventions\\n\\n## OpenAPI and validation\\n\\nEach endpoint defines a `createRoute` descriptor with:\\n\\n- HTTP method\\n- Path\\n- OpenAPI tag and summary\\n- Zod request schemas\\n- Response schemas and documented error responses\\n\\nHandlers are registered through `registerOpenApiRoute`. Request bodies should be read with `getValidatedBody` unless the route intentionally supports an optional body, as in golden-sample candidate generation and runtime replay.\\n\\n## Limits and windows\\n\\nRuntime and observability list endpoints normalize pagination and time ranges with shared helpers:\\n\\n- `parseRuntimeLimit`\\n- `parseRuntimeWindowMinutes`\\n- `parseObservabilityWindowMinutes`\\n- `parseOffset`\\n\\nDo not pass raw query-string values directly to database list methods when a shared parser exists.\\n\\n## Error handling\\n\\nHandlers generally follow this pattern:\\n\\n```ts\\ntry {\\n  // load, authorize, and perform operation\\n} catch (error) {\\n  getLog().error({ err: error }, 'operation_failed');\\n  return apiError(c, 500, 'Operation failed');\\n}\\n```\\n\\nExpected validation or domain failures are mapped to `400` or `422` where the route contract specifies them. Authorization failures for workflow resources commonly return `404` to avoid exposing inaccessible records.\\n\\n## Event buses\\n\\nTwo event-bus integrations are important:\\n\\n- `getObservabilityEventBus`\\n  - Publishes persisted observability events and batches.\\n  - Feeds `/api/stream/__observability__`.\\n- `getEvaluationEventBus`\\n  - Publishes `evaluation_started`, `evaluation_updated`, and `evaluation_completed`.\\n\\nWhen adding a new lifecycle operation, preserve the existing event ordering and include correlation identifiers such as `workflowRunId` and `traceId` when available.\\n\\n## Logging\\n\\nAll route modules use lazy logger initialization with `createLogger`. Lazy initialization is intentional: it allows tests to install mocks before the logger is created.\\n\\nNotable logger names include:\\n\\n- `api`\\n- `api.evolution`\\n- `api.observability`\\n\\nOperational failures should include the relevant run, trace, candidate, evaluator, or path identifiers in structured log fields.\",\"observability-runtime-tracing-and-evaluation-web\":\"# Observability, Runtime Tracing, and Evaluation \u2014 web\\n\\n# Observability, Runtime Tracing, and Evaluation \u2014 Web\\n\\n## Overview\\n\\nThe web observability and evaluation module is implemented primarily by:\\n\\n- `packages/web/src/routes/EvaluationSlaPage.tsx`\\n- `packages/web/src/hooks/useObservabilitySSE.ts`\\n- `packages/web/src/lib/api.ts`\\n- `packages/web/src/lib/observability.ts`\\n\\n`EvaluationSlaPage` is the main observability dashboard for evaluating runtime health and workflow execution quality. It combines:\\n\\n- SLA and stability metrics\\n- API and frontend error events\\n- Workflow node failures\\n- User activity and workflow correctness\\n- Domain and endpoint active probes\\n- Runtime traces and workflow run links\\n- URL-persisted filters, sorting, pagination, and drill-down state\\n- Server-sent event (SSE) updates with query invalidation\\n- Client-side fallback aggregation when dashboard workflow data is incomplete\\n\\nThe user-facing labels are primarily Chinese, and all dashboard date input and display behavior is based on the `Asia/Shanghai` time zone.\\n\\n## Responsibilities\\n\\n`EvaluationSlaPage` coordinates four observability views:\\n\\n1. **Stability**\\n   - Overall SLA\\n   - Environment stability\\n   - System stability\\n   - Workflow stability\\n\\n2. **Traffic**\\n   - Page views (PV)\\n   - Unique users (UV)\\n   - Actions\\n   - API errors\\n\\n3. **Active probing**\\n   - Current-domain API and page health\\n   - Availability and HTTP status\\n   - Historical success rates and latency\\n\\n4. **Evaluation and diagnosis**\\n   - Environment and system error groups\\n   - Workflow failure groups\\n   - Root-cause suggestions\\n   - User activity and workflow correctness\\n   - Links to workflow runs and traces\\n\\nThe page also acts as a bridge between observability data and runtime tracing. Error and activity rows link to workflow run pages, while trace links use `workflowTraceHref()` to navigate to the workflow console with a `traceId`.\\n\\n## Runtime data flow\\n\\n```mermaid\\nflowchart LR\\n    Page[EvaluationSlaPage]\\n    API[listObservabilitySlaDashboard]\\n    Errors[listObservabilityErrorPage]\\n    WorkflowErrors[listObservabilityWorkflowNodeErrors]\\n    Activity[User activity]\\n    SSE[useObservabilitySSE]\\n    QueryCache[React Query cache]\\n    UI[SLA, traffic, probes, details]\\n\\n    Page --&gt; API\\n    Page --&gt; Errors\\n    Page --&gt; WorkflowErrors\\n    Page --&gt; Activity\\n    Page --&gt; UI\\n    SSE --&gt; QueryCache\\n    QueryCache --&gt; Page\\n```\\n\\n### Initial loading\\n\\n`EvaluationSlaPage`:\\n\\n1. Parses the current URL with `parseSlaUrlState()`.\\n2. Builds an `ObservabilityQuery` from the selected time range and filters.\\n3. Loads the SLA dashboard through `listObservabilitySlaDashboard()`.\\n4. Loads error and workflow-failure details only when their panels or drill-down state requires them.\\n5. Loads workflow names through `listWorkflowsV2()` only when the workflow filter is opened or a workflow is already selected.\\n6. Reads active probe state through `useActiveProbeTargetsSnapshot()`.\\n7. Reads API availability through `useApiAvailability()`.\\n\\nThe dashboard query uses 12 time buckets and defaults to a one-hour quick range. React Query data is considered stale after `OBSERVABILITY_QUERY_STALE_MS` (30 seconds).\\n\\n### Live updates\\n\\nThe page calls `useObservabilitySSE()`. When an observability update is received, the SSE hook schedules invalidation through:\\n\\n1. `scheduleObservabilityInvalidation()`\\n2. `invalidateSlaUpdatedQueries()`\\n\\nThis causes relevant React Query data to refresh without requiring a full page reload. If the SSE stream is unavailable, the SLA dashboard uses a fallback polling interval of `SLA_LIVE_FALLBACK_REFETCH_INTERVAL_MS` (60 seconds).\\n\\n## URL state\\n\\nThe dashboard persists user navigation state in query parameters. This allows filters, pagination, sorting, and selected chart buckets to survive reloads and be shared as links.\\n\\nThe internal state shape is `SlaUrlState`:\\n\\n```ts\\ninterface SlaUrlState {\\n  windowMinutes: number;\\n  timeMode: 'quick' | 'custom';\\n  startDate: string;\\n  endDate: string;\\n  workflowRootCauseFilter: WorkflowRootCauseFilter;\\n  slaProductId: string;\\n  slaWorkflowName: string;\\n  workflowFailureDetailsPage: number;\\n  workflowFailureSort: WorkflowFailureSort;\\n  failureDetailType: SlaFailureDetailSelection;\\n  selectedBucketRange: SlaBucketDrilldownRange | null;\\n}\\n```\\n\\nSupported URL parameters are:\\n\\n| Parameter | Purpose |\\n| --- | --- |\\n| `productId` | Product scope |\\n| `workflowName` | Workflow filter |\\n| `timeMode` | `quick` or `custom` |\\n| `windowMinutes` | Quick-range duration |\\n| `startDate` | Custom range start date |\\n| `endDate` | Custom range end date |\\n| `rootCause` | Workflow root-cause filter |\\n| `failurePage` | Workflow failure detail page |\\n| `detailType` | Selected failure panel: environment, system, workflow, user operation, or execution |\\n| `sortKey` | Workflow failure sort field |\\n| `sortDir` | `asc` or `desc` |\\n| `bucketStart` | Selected SLA bucket start |\\n| `bucketEnd` | Selected SLA bucket end |\\n\\n### Parsing\\n\\n`parseSlaUrlState()` validates and normalizes URL values:\\n\\n- Invalid dates are replaced with a default six-day range ending today.\\n- Invalid quick ranges fall back to `DEFAULT_SLA_WINDOW_MINUTES`.\\n- Invalid root-cause filters become `all`.\\n- Invalid failure detail types become `null`.\\n- Invalid pagination values become page `0`.\\n- Sort direction defaults according to `defaultWorkflowFailureSortDirection()`.\\n\\n`parseSlaUrlState()` delegates to:\\n\\n- `parseWindowMinutesParam()`\\n- `parseWorkflowRootCauseFilterParam()`\\n- `parseWorkflowFailureSort()`\\n- `parseBucketDrilldownRange()`\\n\\n`parseBucketDrilldownRange()` only returns a selection when both timestamps form a valid, positive-length range.\\n\\n### Serialization\\n\\n`buildSlaSearchParams()` removes all managed parameters from the current `URLSearchParams` and writes only non-default state. For example:\\n\\n- The default one-hour quick range is omitted.\\n- The default workflow failure sort (`latest_at`, descending) is omitted.\\n- The `all` root-cause filter is omitted.\\n- Page `0` is omitted.\\n\\nUnrelated query parameters are preserved.\\n\\n`shouldDeferSlaUrlWriteForExternalChange()` prevents an external URL change from being immediately overwritten when its parsed state differs from the current in-memory state. This is important when browser navigation or another component changes the search string.\\n\\n## Time handling\\n\\nThe module deliberately separates browser-local time from dashboard time.\\n\\n### Beijing date inputs\\n\\n- `toBeijingDateInputValue()` formats a `Date` as `YYYY-MM-DD` in `Asia/Shanghai`.\\n- `startOfBeijingDateIso()` converts a date input to midnight Beijing time and returns an ISO timestamp.\\n- `endOfBeijingDateIso()` converts a date input to `23:59:59.999` Beijing time.\\n- `customRangeDays()` validates a custom range and returns its inclusive day span.\\n\\nCustom ranges are limited to `MAX_SLA_RANGE_DAYS` (92 days).\\n\\n### Display formatting\\n\\n`parseBeijingDisplayDate()` accepts:\\n\\n- UTC SQL-style timestamps such as `YYYY-MM-DD HH:mm:ss`\\n- ISO timestamps with an explicit time zone\\n- Timestamps without an explicit zone, which are normalized through `ensureUtc()`\\n\\n`formatBeijingTime()` and `formatBeijingListTime()` format timestamps as month/day and hour/minute in Beijing time. The distinction between the two functions is semantic; both currently use the same display formatting path.\\n\\nAxis labels are generated by `slaXAxisLabels()` and `trafficXAxisLabels()`:\\n\\n- Ranges up to two days show `HH:mm`.\\n- Ranges up to eight days show `MM/DD HH:mm`.\\n- Longer ranges show `MM/DD`.\\n- At most six labels are generated.\\n\\n## SLA aggregation\\n\\n### Server-provided summaries\\n\\n`summarySlaBucketsForCards()` aggregates data from `ObservabilitySlaBucketResponse[]` and produces an `SlaCardSummary`.\\n\\nOnly buckets recognized by `hasSlaBucketData()` contribute to card calculations. Empty buckets, including idle buckets with no observability activity, do not produce misleading summary values.\\n\\nThe summary includes:\\n\\n- `overall_sla`\\n- `environment_stability`\\n- `system_stability`\\n- `workflow_stability`\\n- Environment, system, API, and workflow counts\\n- API success rate\\n- Workflow execution success rate\\n- Workflow user-configuration health\\n\\nPercentages are calculated with `percentFromCounts()`, rounded to one decimal place, and constrained to the range 0\u2013100.\\n\\n### Stability semantics\\n\\nThe dashboard separates failures into three categories:\\n\\n- **Environment**\\n  - External gateways and upstream dependencies\\n  - HTTP 429, 502, 503, 504, and 529\\n  - Known gateway, network, provider, timeout, and upstream error phrases\\n\\n- **System**\\n  - Platform or application behavior\\n  - Frontend failures\\n  - API failures not classified as environment failures\\n  - Sandbox and container quota failures\\n\\n- **Workflow**\\n  - Workflow node or business-logic failures\\n  - Failures not otherwise classified as environment or system issues\\n\\n`eventStabilityCategory()` applies classification in this order:\\n\\n1. Explicit `metadata.stability_category`, when it is `environment`, `system`, or `workflow`\\n2. `isEnvironmentErrorEvent()`\\n3. `isSystemErrorEvent()`\\n4. `workflow_node_error` event type\\n5. System as the default category\\n\\nError attribution uses `eventTextForAttribution()` to combine error class, message, paths, HTTP status, and serialized metadata into a lowercase searchable string.\\n\\nFrontend fetch failures are identified separately by `isFrontendFetchFailureEvent()`. These events are excluded from fallback SLA error aggregation because a browser-side transport failure should not be counted as a duplicate backend incident.\\n\\n### Overall SLA\\n\\n`overall_sla` is the arithmetic average of the available environment, system, and workflow stability values. Missing categories are excluded rather than treated as zero.\\n\\n`cumulativeSlaChartBuckets()` transforms chart values into cumulative values. Each chart bucket summarizes all data from the beginning of the selected range through that bucket, while preserving the original bucket boundaries.\\n\\n## Client-side SLA fallback\\n\\nThe dashboard can reconstruct SLA buckets from visible detail rows when the backend dashboard response lacks sufficient workflow metrics.\\n\\n`fallbackSlaBucketsFromVisibleRows()` accepts:\\n\\n- Existing dashboard buckets\\n- The dashboard range\\n- Error events\\n- Workflow node error groups\\n- User activity rows\\n\\nThe fallback process is:\\n\\n1. Validate the dashboard range.\\n2. Create mutable buckets with `createMutableClientSlaBuckets()`.\\n3. Assign visible rows to buckets using `fallbackBucketIndex()`.\\n4. Apply each row type:\\n   - `applyErrorEventToFallbackBucket()`\\n   - `applyWorkflowErrorToFallbackBucket()`\\n   - `applyUserActivityToFallbackBucket()`\\n5. Convert mutable buckets to API-compatible responses with `finalizeFallbackBuckets()`.\\n6. Prefer existing backend workflow metrics when they are already present.\\n7. Merge only missing or lower-fidelity workflow failure data with `mergeWorkflowFallbackBucket()`.\\n\\nThe fallback intentionally avoids replacing authoritative backend data unless it has evidence that the backend response is missing workflow metrics or under-counting workflow failures.\\n\\n### Workflow exclusions\\n\\nWorkflow runs can be excluded from workflow stability denominators for reasons such as:\\n\\n- Environment failures\\n- User configuration or operation failures\\n- Cancelled runs\\n\\nThis distinction supports separate metrics for:\\n\\n- Workflow stability\\n- Execution success rate\\n- User-configuration health\\n\\n## Traffic aggregation\\n\\n`TrafficCurve` renders traffic metrics from `ObservabilityTrafficBucketResponse[]`.\\n\\n`summarizeTrafficBuckets()` calculates:\\n\\n- Total page views\\n- Maximum unique-user count across buckets\\n- Total actions\\n- Total user-facing errors\\n- Total API calls and API errors\\n- Probe count and successful probes\\n- Weighted average probe duration\\n\\n`applyExactTrafficSummary()` replaces PV and UV values with exact totals from `ObservabilityTrafficSummaryResponse` when the backend provides them. This avoids approximating unique users by summing bucket-level values.\\n\\n`trafficMaxValue()` determines the chart scale using the largest PV, UV, action, or API-error bucket and adds 15% headroom. `trafficLineChartPoints()` converts each traffic series into SVG polyline coordinates.\\n\\n## Active domain probes\\n\\n`DomainProbePanel` combines two forms of health information:\\n\\n### Real-time state\\n\\n`useActiveProbeTargetsSnapshot()` subscribes to the external active-probe store through `useSyncExternalStore()`:\\n\\n- `subscribeActiveProbeTargets`\\n- `getActiveProbeTargetsSnapshot`\\n\\nEach target reports:\\n\\n- Health: unknown, healthy, warning, or critical\\n- Availability: unknown, available, or unavailable\\n- HTTP status\\n- Duration\\n- Last checked time\\n- Optional status message\\n\\nThe panel summarizes target status by severity:\\n\\n1. Any critical target \u2192 critical\\n2. Otherwise, any warning target \u2192 warning\\n3. Otherwise, any checked target \u2192 healthy\\n4. Otherwise, unknown\\n\\n### Historical state\\n\\nThe page receives probe history from observability data and normalizes it with `summarizeDomainProbeTargetHistories()`.\\n\\nEvery target in `ACTIVE_PROBE_TARGETS` receives a row, including targets with no history. Historical metrics include:\\n\\n- Probe count\\n- Healthy and available counts\\n- Health and availability rates\\n- Average duration\\n- Latest timestamp\\n- Latest HTTP status and duration\\n\\nThe panel also uses `useApiAvailability()` for current-domain availability and displays the last success and failure times.\\n\\n## Workflow failure analysis\\n\\n### Root-cause inference\\n\\n`inferWorkflowRootCauseInsight()` provides deterministic, text-based root-cause guidance. It searches the combined text generated by `workflowErrorText()` and returns:\\n\\n- A display label\\n- A diagnostic summary\\n- A confidence score\\n- A visual tone\\n\\nThe matching order is significant. More specific patterns are checked first:\\n\\n1. Control-plane or workflow-run status connection timeout\\n2. Missing workflow command configuration\\n3. Missing runtime dependency or CLI\\n4. Sandbox lifecycle failure\\n5. Node stalled or idle timeout\\n6. Provider streaming failure\\n7. Explicit environment category\\n8. Explicit system category\\n9. Bash/script node failure\\n10. Generic workflow logic failure\\n\\n`workflowNodeTypeGroup()` classifies nodes as:\\n\\n- `command`\\n- `skill`\\n- `bash`\\n- `other`\\n\\nThis classification is used both in root-cause fallback logic and in the workflow failure table.\\n\\n### Sorting\\n\\n`WorkflowFailureDetailsTable` supports sorting by:\\n\\n- `latest_at`\\n- `workflow_name`\\n- `node_id`\\n- `root_cause`\\n- `count`\\n\\n`nextWorkflowFailureSort()` selects the default direction when changing columns and toggles direction when clicking the active column.\\n\\n`sortWorkflowFailureDetails()`:\\n\\n1. Compares numeric fields for `count` and `latest_at`.\\n2. Compares localized text for workflow, node, and root-cause fields.\\n3. Uses latest timestamp as a tie-breaker.\\n4. Uses the error group ID as the final deterministic tie-breaker.\\n\\n### Trace and run links\\n\\n`workflowTraceHref(traceId)` returns:\\n\\n```text\\n/console/workflows?traceId=\\n```\\n\\nThe failure and error tables link to:\\n\\n- `/workflows/runs/` for run details\\n- `/console/workflows?traceId=` for trace inspection\\n\\nThese links allow contributors to move from an aggregated failure group to the concrete runtime execution.\\n\\n## User activity and evaluation\\n\\n`ActivityRow` renders `ObservabilityUserActivityResponse` records and exposes evaluation-oriented fields:\\n\\n- User, product, and codebase\\n- Route path\\n- Workflow name and run\\n- Trace and run links\\n- Workflow status\\n- Failed node and node type\\n- Failure category and failure message\\n- Workflow duration\\n- Workflow correctness\\n- Feature area\\n- Action and error counts\\n- Idle time\\n- Last activity time\\n\\nWorkflow correctness is rendered by:\\n\\n- `workflowCorrectText()`\\n- `workflowCorrectTone()`\\n\\nThe three correctness states are:\\n\\n- `true`: correct\\n- `false`: abnormal\\n- `null`: pending confirmation\\n\\n`ActivityRow` treats a row as having a workflow failure when it has a failed node, an explicit incorrect result, or a failure/error status. If a workflow failed but no node details were collected, it displays \u201cfailure node pending collection\u201d and directs the user to runtime logs.\\n\\n## Query builders\\n\\nThe module keeps query construction in exported helper functions so that pagination and filters remain consistent across the page and tests.\\n\\n### `buildSlaDashboardQuery()`\\n\\nCreates the dashboard query with:\\n\\n- Time window and date range\\n- Product, codebase, user, and workflow scope\\n- 12 buckets\\n- Default limits for error, workflow failure, and activity data\\n- Detail sections disabled by default\\n\\nThe dashboard initially requests summary data and enables detailed sections only when needed.\\n\\n### `buildUserActivityQuery()`\\n\\nAdds activity pagination and filters:\\n\\n- `limit`\\n- `offset`\\n- Feature area\\n- Workflow correctness\\n- Search text\\n\\nThe `all` filter values are converted to `undefined`, allowing the API to omit those filters.\\n\\n### `buildWorkflowFailureDetailsQuery()`\\n\\nAdds workflow failure pagination and optional filters:\\n\\n- Root cause\\n- User-operation-only mode\\n- Execution-failure mode\\n\\n### `buildObservabilityErrorDetailsQuery()`\\n\\nAdds error detail pagination and a required stability category. It is restricted to environment or system details; workflow failures use `buildWorkflowFailureDetailsQuery()`.\\n\\n### `shouldLoadSlaWorkflowOptions()`\\n\\nAvoids loading workflow names until the workflow filter is opened, unless a workflow name is already selected in URL state.\\n\\n## Main UI components\\n\\n### `EvaluationSlaPage`\\n\\nThe page-level coordinator. It owns:\\n\\n- Search parameter synchronization\\n- Date and quick-window controls\\n- Product and workflow filters\\n- Query construction and React Query calls\\n- Detail panel selection\\n- Chart bucket selection\\n- Pagination and sorting\\n- Active probe state\\n- Loading, empty, and fallback behavior\\n\\n### `MetricCard`\\n\\nReusable metric card that accepts a title, value, description, optional icon, and tone:\\n\\n- `neutral`\\n- `good`\\n- `warning`\\n- `danger`\\n\\n### `SlaCurve`\\n\\nRenders the four stability series as SVG polylines:\\n\\n- User-perceived overall SLA\\n- Environment\\n- System\\n- Workflow\\n\\nEach bucket has a keyboard-accessible hit area. Selecting a bucket stores a `SlaBucketDrilldownRange` and opens the corresponding failure details.\\n\\n### `TrafficCurve`\\n\\nRenders PV, UV, Action, and API-error series on a shared SVG chart.\\n\\n### `DomainProbePanel`\\n\\nDisplays active probe health, historical probe metrics, and target-level details.\\n\\n### `ObservabilityErrorDetailsTable`\\n\\nDisplays grouped environment or system errors with:\\n\\n- Beijing timestamp\\n- Stability attribution\\n- Source and scope\\n- API or page target\\n- Raw error\\n- Duration\\n- Run and trace links\\n\\n### `WorkflowFailureDetailsTable`\\n\\nDisplays grouped workflow failures with:\\n\\n- Workflow and node\\n- Node type and failure type\\n- Inferred root cause and confidence\\n- Original error and next action\\n- Occurrence count\\n- Run and trace links\\n- Root-cause filtering\\n- Sortable columns\\n- Pagination\\n\\n### `ActivityRow`\\n\\nRenders one user activity and evaluation record inside the activity table.\\n\\n## Constants and limits\\n\\nImportant module-level limits include:\\n\\n| Constant | Value | Meaning |\\n| --- | ---: | --- |\\n| `ERROR_PAGE_SIZE` | 10 | Error detail rows per page |\\n| `WORKFLOW_FAILURE_DETAIL_PAGE_SIZE` | 10 | Workflow failure rows per page |\\n| `ACTIVITY_PAGE_SIZE` | 10 | Activity rows per page |\\n| `MAX_SLA_RANGE_DAYS` | 92 | Maximum custom range |\\n| `OBSERVABILITY_QUERY_STALE_MS` | 30,000 ms | React Query stale period |\\n| `SLA_LIVE_FALLBACK_REFETCH_INTERVAL_MS` | 60,000 ms | Fallback refresh interval |\\n| `SLA_AXIS_LABEL_COUNT` | 6 | Maximum chart axis labels |\\n| `SLA_CHART_WIDTH` | 720 | SVG chart width |\\n| `SLA_CHART_HEIGHT` | 180 | SLA chart height |\\n| `DEFAULT_SLA_WINDOW_MINUTES` | 60 | Default quick range |\\n\\nQuick ranges are based on `WINDOWS` plus:\\n\\n- 1 month: 30 days\\n- 1 quarter: 92 days\\n\\n## Error attribution maintenance\\n\\nThe frontend attribution rules must remain aligned with backend SLA rules. The relevant constants are:\\n\\n- `ENVIRONMENT_ERROR_PATTERNS`\\n- `SYSTEM_ERROR_PATTERNS`\\n- `ENVIRONMENT_ERROR_STATUS_CODES`\\n- `FRONTEND_FETCH_FAILURE_PATTERNS`\\n\\nWhen adding a new backend classification rule, update the corresponding frontend pattern or status-code set if the table and fallback aggregation must display the same category as the SLA cards.\\n\\nAvoid adding overly generic patterns. The source intentionally excludes generic `timeout` and `exited with code` matches to prevent configuration or script failures from being incorrectly classified as environment incidents.\\n\\n## Testing surface\\n\\n`EvaluationSlaPage.test.ts` directly covers the module\u2019s exported pure functions, including:\\n\\n- URL parsing and serialization\\n- Beijing date conversion\\n- Custom range validation\\n- SLA and traffic chart coordinates\\n- Axis label generation\\n- SLA bucket summaries\\n- Cumulative chart buckets\\n- Fallback bucket reconstruction\\n- Traffic summary correction\\n- Error category attribution\\n- Workflow root-cause inference\\n- Workflow failure sorting\\n- Query builders\\n- Trace URL generation\\n- Workflow option loading decisions\\n\\nWhen changing aggregation or URL behavior, update the corresponding pure-function tests before modifying page-level behavior. Pure helpers such as `summarizeSlaBucketsForCards()`, `fallbackSlaBucketsFromVisibleRows()`, `eventStabilityCategory()`, and `sortWorkflowFailureDetails()` are the preferred extension points for business logic because they can be tested without rendering the full dashboard.\",\"observability-runtime-tracing-and-evaluation\":\"# Observability, Runtime Tracing, and Evaluation\\n\\n# Observability, Runtime Tracing, and Evaluation\\n\\nThis module group turns workflow execution data into operational insight, evaluation evidence, and controlled workflow improvements.\\n\\nIt combines:\\n\\n- Core services for trace analysis, quality gates, failure attribution, golden-sample discovery, and workflow evolution\\n- Server APIs for capturing, querying, evaluating, replaying, and governing runtime data\\n- A web dashboard for monitoring SLA health, failures, traces, and workflow activity\\n- Optional DeepEval and Ragas sidecars for LLM-as-a-judge evaluation\\n\\n## How the sub-modules fit together\\n\\nThe [core module](core.md) contains the domain services and persistence-facing logic. It is intentionally independent of server replay orchestration: `EvolutionService` receives an injected `EvolutionShadowReplayRunner`, allowing the server to provide replay behavior without coupling core services to server implementations.\\n\\nThe [server module](server.md) exposes this functionality through Hono OpenAPI routes. It handles observability events, runtime traces, evaluations, evidence, benchmarks, golden samples, human feedback, and supervised evolution candidates. Server routes also enforce visibility for workflows, traces, evaluation resources, and product spaces.\\n\\nThe [web module](web.md) provides the primary operational view through `EvaluationSlaPage`. It combines server data with URL-persisted filters and drill-down state to connect aggregate SLA metrics to error events, failed workflow nodes, runtime traces, and workflow runs. `useObservabilitySSE` supports live observability updates.\\n\\nThe [DeepEval evaluator](deepeval-evaluator.md) and [Ragas evaluator](ragas-evaluator.md) are standalone FastAPI sidecars. They receive completed workflow evidence and return normalized evaluation results, including scores, health classifications, metric findings, provenance, and sample metadata for persistence by the server.\\n\\n```mermaid\\nflowchart LR\\n    R[Workflow runtime] --&gt; T[Runtime traces and observability events]\\n    T --&gt; S[Server APIs]\\n    S --&gt; W[Web dashboard]\\n    T --&gt; E1[DeepEval evaluator]\\n    T --&gt; E2[Ragas evaluator]\\n    E1 --&gt; S\\n    E2 --&gt; S\\n    S --&gt; C[Core services]\\n    C --&gt; G[Quality gates]\\n    C --&gt; GS[Golden-sample candidates]\\n    C --&gt; EV[Evolution candidates]\\n    EV --&gt; RP[Shadow replay]\\n    RP --&gt; G\\n```\\n\\n## Cross-module workflows\\n\\n### Runtime monitoring and investigation\\n\\n1. Workflow execution produces observability events and runtime traces.\\n2. Server routes capture and expose traces, failures, costs, anomalies, and replay data.\\n3. `EvaluationSlaPage` aggregates these results into SLA and stability metrics.\\n4. Users drill from traffic or error summaries into workflow runs, node failures, and trace details.\\n5. Access checks such as `canViewTrace` and `filterAccessibleTraces` limit results to permitted workflows and product spaces.\\n\\n### Automatic evaluation\\n\\nCompleted traces can be sent to either evaluator sidecar:\\n\\n- DeepEval evaluates workflow-level evidence with LLM-as-a-judge metrics.\\n- Ragas builds scoped datasets from workflow, node, and skill samples, then returns aggregate and scoped metric results.\\n\\nThe resulting normalized evidence is returned to the server with evaluator provenance and sample metadata. Runtime evaluation can then invoke `computeQualityGate`, which reads the workflow run and applies configured quality and calibration requirements.\\n\\n### Quality gates and release decisions\\n\\n`QualityGateService` converts runtime and evaluation evidence into pass, fail, or otherwise actionable quality decisions. These decisions can be used to:\\n\\n- Identify unhealthy workflow runs\\n- Block or qualify releases\\n- Provide evidence for supervised workflow changes\\n- Compare candidate behavior against baseline behavior\\n\\n### Evolution with shadow replay\\n\\nA workflow run can be proposed as an evolution candidate through `EvolutionService`. The candidate is evaluated with an injected shadow replay runner, which executes the patched workflow definition without coupling replay implementation to core.\\n\\nReplay results are recorded through the runtime trace machinery, and the candidate is compared using quality gates before it can be reviewed or promoted. Server APIs manage the candidate lifecycle, including proposal, evaluation, rejection, and promotion.\\n\\nThe server-side replay path discovers workflow configuration and registered providers before executing the workflow locally. This allows replay to use the same workflow and provider infrastructure as normal execution while remaining isolated from production behavior.\\n\\n### Golden-sample discovery\\n\\nCompleted runs can produce golden-sample candidates through the core `GoldenSampleCandidateService`. It extracts usable trace evidence, removes duplicate or empty values, and applies candidate quality-control metadata. The server makes these candidates available for review and persistence alongside evaluation evidence.\\n\\nTogether, golden samples and human feedback provide durable reference material for future evaluations, benchmark management, and supervised workflow evolution.\",\"other-adapters\":\"# Other \u2014 adapters\\n\\n# Other \u2014 adapters\\n\\n`@archon/adapters` provides the platform boundary between Archon\u2019s core orchestration and external chat or source-control systems.\\n\\nThe package contains adapters for:\\n\\n- **Chat platforms**\\n  - Slack (`SlackAdapter`)\\n  - Telegram (`TelegramAdapter`)\\n  - Community Discord (`DiscordAdapter`)\\n- **Forge platforms**\\n  - GitHub\\n  - Community Gitea\\n  - Community GitLab\\n- **Shared utilities**\\n  - Message splitting for platforms with output-size limits\\n\\nAdapters implement `IPlatformAdapter` from `@archon/core` where applicable. They translate platform-specific incoming events into Archon message handling, route outbound responses back to the source conversation, enforce optional allowlists, and manage platform lifecycle concerns.\\n\\n## Package Layout\\n\\n```text\\npackages/adapters/src/\\n\u251c\u2500\u2500 chat/\\n\u2502   \u251c\u2500\u2500 slack/\\n\u2502   \u2514\u2500\u2500 telegram/\\n\u251c\u2500\u2500 community/\\n\u2502   \u251c\u2500\u2500 chat/\\n\u2502   \u2502   \u2514\u2500\u2500 discord/\\n\u2502   \u2514\u2500\u2500 forge/\\n\u2502       \u251c\u2500\u2500 gitea/\\n\u2502       \u2514\u2500\u2500 gitlab/\\n\u251c\u2500\u2500 forge/\\n\u2502   \u2514\u2500\u2500 github/\\n\u2514\u2500\u2500 utils/\\n    \u2514\u2500\u2500 message-splitting.ts\\n```\\n\\nCommunity adapters have explicit package export paths:\\n\\n```ts\\nimport { GiteaAdapter } from '@archon/adapters/community/forge/gitea';\\nimport { GitLabAdapter } from '@archon/adapters/community/forge/gitlab';\\n```\\n\\nEach adapter directory follows the same broad pattern:\\n\\n```text\\nplatform/\\n\u251c\u2500\u2500 adapter.ts       # SDK integration and platform behavior\\n\u251c\u2500\u2500 auth.ts          # Allowlist or webhook verification helpers\\n\u251c\u2500\u2500 types.ts         # Platform event/context types, when needed\\n\u251c\u2500\u2500 index.ts         # Public barrel export\\n\u2514\u2500\u2500 *.test.ts        # Unit coverage\\n```\\n\\n## Architecture\\n\\nAdapters sit at the edge of the system. Chat adapters receive events through SDK listeners or polling, while forge adapters receive webhook payloads through server HTTP routes.\\n\\n```mermaid\\nflowchart LR\\n  Platform[Chat or Forge Platform] --&gt; Adapter[Platform Adapter]\\n  Adapter --&gt; Auth[Authorization / Signature Checks]\\n  Adapter --&gt; Core[@archon/core]\\n  Core --&gt; Adapter\\n  Adapter --&gt; Platform\\n\\n  Adapter --&gt; Git[@archon/git]\\n  Adapter --&gt; Paths[@archon/paths]\\n  Adapter --&gt; DB[Core Codebase / Conversation DB]\\n```\\n\\n### Runtime Responsibilities\\n\\n| Concern | Chat adapters | Forge adapters |\\n|---|---|---|\\n| Incoming transport | Socket Mode, gateway events, or polling | HTTP webhook payload |\\n| Access control | User-ID allowlist | Webhook verification and user allowlist |\\n| Conversation identity | Channel, chat, thread, or message-derived ID | Repository and issue/PR-derived ID |\\n| Outbound response | Send a message or thread reply | Post an issue or pull-request comment |\\n| Repository preparation | Not applicable | Clone, sync, register, and inspect repository |\\n| Lifecycle | `start()` / `stop()` | Initialization plus webhook handling |\\n\\nThe server creates adapters, registers message handlers for chat platforms, starts their event listeners, and exposes webhook routes for forge platforms. Error handling elsewhere in the server can call the adapter\u2019s `sendMessage()` method to return failures to the originating platform.\\n\\n## Shared Adapter Contract\\n\\nThe adapters use `IPlatformAdapter` from `@archon/core`. Exact platform event types differ, but implementations consistently expose the following behavior:\\n\\n- `sendMessage(conversationId, message, metadata?)`: send a response to a platform conversation.\\n- `getStreamingMode()`: return either `'stream'` or `'batch'`.\\n- `getPlatformType()`: identify the adapter platform.\\n- `ensureThread(originalConversationId, messageContext?)`: resolve or create an appropriate reply thread when a platform supports threads.\\n- `start()` and `stop()`: connect and disconnect platform resources.\\n\\nChat adapters additionally expose:\\n\\n```ts\\nonMessage(handler)\\n```\\n\\nThe handler must be registered before `start()`. Incoming platform events are converted into the adapter\u2019s native message context and passed to this handler asynchronously.\\n\\n## Chat Adapters\\n\\n## Slack: `SlackAdapter`\\n\\n`SlackAdapter` uses `@slack/bolt` in Socket Mode.\\n\\n```ts\\nconst adapter = new SlackAdapter(botToken, appToken, 'batch');\\n\\nadapter.onMessage(async event =&gt; {\\n  // event is SlackMessageEvent\\n});\\n\\nawait adapter.start();\\n```\\n\\n### Constructor\\n\\n```ts\\nnew SlackAdapter(\\n  botToken: string,\\n  appToken: string,\\n  mode: 'stream' | 'batch' = 'batch'\\n)\\n```\\n\\nSlack defaults to `'batch'` streaming mode.\\n\\nThe adapter initializes a Bolt `App` configured with:\\n\\n- `socketMode: true`\\n- the provided bot token\\n- the provided app-level token\\n- `LogLevel.INFO`\\n\\n`getApp()` returns the underlying Bolt `App` for integration or platform-specific setup.\\n\\n### Incoming Messages\\n\\n`start()` registers two Bolt handlers:\\n\\n- `app_mention`: handles messages in channels where the bot is mentioned.\\n- `message`: handles direct messages only, identified by `channel_type === 'im'`.\\n\\nChannel messages are intentionally ignored by the generic `message` handler because channel interaction must go through `app_mention`. Direct-message bot events are ignored to prevent response loops.\\n\\nIncoming events are represented as:\\n\\n```ts\\ninterface SlackMessageEvent {\\n  text: string;\\n  user: string;\\n  channel: string;\\n  ts: string;\\n  thread_ts?: string;\\n}\\n```\\n\\n### Conversation and Thread IDs\\n\\nSlack thread routing uses a compound conversation ID:\\n\\n```text\\nchannel:threadTimestamp\\n```\\n\\n`getConversationId(event)` behaves as follows:\\n\\n- For an event with `thread_ts`, return `channel:thread_ts`.\\n- For a new non-thread channel message, return `channel:ts`.\\n\\nThe latter is intentional: passing this ID into `sendMessage()` causes the adapter to use the original message timestamp as `thread_ts`, so responses become thread replies even for an initial channel mention.\\n\\n```ts\\nconst conversationId = adapter.getConversationId(event);\\n// C123:1234567890.000001\\n\\nawait adapter.sendMessage(conversationId, 'Response');\\n```\\n\\n`ensureThread()` is a no-op because the conversation-ID convention already encodes the correct thread destination.\\n\\nRelated helpers:\\n\\n- `isThread(event)`: true when `thread_ts` is defined and differs from `ts`.\\n- `getParentConversationId(event)`: returns `channel:thread_ts` for replies, otherwise `null`.\\n- `fetchThreadHistory(event)`: fetches up to 100 messages from a Slack thread and formats them in chronological order.\\n\\nThread history formats bot messages as `[Bot]: ...` and user messages as `&lt;@USER_ID&gt;: ...`. API failures are logged and produce an empty history instead of failing the caller.\\n\\n### Mention and URL Normalization\\n\\n`stripBotMention(text)` removes one leading Slack user mention and normalizes Slack\u2019s wrapped URL syntax:\\n\\n```ts\\nadapter.stripBotMention('&lt;@U1234ABCD&gt; /clone ');\\n// \\\"/clone https://github.com/org/repo\\\"\\n```\\n\\nIt supports both:\\n\\n```text\\n\\n\\n```\\n\\nOnly a leading mention is removed. Remaining mentions are preserved.\\n\\n### Outbound Formatting\\n\\nSlack markdown blocks have a maximum length of 12,000 characters. `sendMessage()`:\\n\\n1. Parses the conversation ID into a channel and optional thread timestamp.\\n2. Sends short messages through `sendWithMarkdownBlock()`.\\n3. Splits oversized output with `splitIntoParagraphChunks()`.\\n4. Sends chunks sequentially to preserve response ordering.\\n\\nThe primary Slack payload uses a `markdown` block:\\n\\n```ts\\n{\\n  channel,\\n  thread_ts,\\n  blocks: [\\n    {\\n      type: 'markdown',\\n      text: message,\\n    },\\n  ],\\n  text: fallbackText,\\n}\\n```\\n\\nFallback text is truncated to 150 characters with `...` when necessary. If Slack rejects the markdown block, `sendWithMarkdownBlock()` retries as a plain text message.\\n\\n### Slack Authorization\\n\\nThe optional `SLACK_ALLOWED_USER_IDS` environment variable controls access:\\n\\n```bash\\nSLACK_ALLOWED_USER_IDS=U1234ABCD,W5678EFGH\\n```\\n\\n`parseAllowedUserIds()` accepts comma-separated Slack IDs matching:\\n\\n```text\\n[UW][A-Z0-9]+\\n```\\n\\n`isSlackUserAuthorized(userId, allowedIds)` implements two modes:\\n\\n- An empty allowlist means **open access**.\\n- A populated allowlist requires an exact user-ID match.\\n\\nUnauthorized channel mentions and DMs are silently rejected after an informational log entry.\\n\\n---\\n\\n## Telegram: `TelegramAdapter`\\n\\n`TelegramAdapter` uses the grammY SDK and Telegram long polling.\\n\\n```ts\\nconst adapter = new TelegramAdapter(token);\\n\\nadapter.onMessage(async context =&gt; {\\n  // context is TelegramMessageContext\\n});\\n\\nawait adapter.start();\\n```\\n\\n### Constructor\\n\\n```ts\\nnew TelegramAdapter(\\n  token: string,\\n  mode: 'stream' | 'batch' = 'stream'\\n)\\n```\\n\\nTelegram defaults to `'stream'` mode.\\n\\n`getBot()` exposes the underlying grammY `Bot` instance.\\n\\n### Incoming Messages\\n\\n`start()` registers a grammY `message:text` handler. It ignores updates with no text and forwards valid messages to the registered handler as:\\n\\n```ts\\ninterface TelegramMessageContext {\\n  conversationId: string;\\n  message: string;\\n  userId: number | undefined;\\n}\\n```\\n\\n`getConversationId(ctx)` uses `ctx.chat.id` converted to a string. It throws `Error('No chat in context')` when `ctx.chat` is missing.\\n\\nTelegram chats are persistent conversations and do not require thread creation:\\n\\n```ts\\nawait adapter.ensureThread('12345');\\n// \\\"12345\\\"\\n```\\n\\n### Polling Startup and Conflict Retries\\n\\nTelegram only permits one active `getUpdates` polling connection per bot token. `TelegramAdapter.start()` retries startup failures containing `409` up to three times.\\n\\nThe default retry delay is 60 seconds:\\n\\n```ts\\nawait adapter.start();\\n\\n// Useful in tests or controlled environments:\\nawait adapter.start({ retryDelayMs: 0 });\\n```\\n\\nThe adapter uses grammY\u2019s `onStart` callback to distinguish successful startup from the eventual completion of the long-polling process. Pending messages are dropped at startup through `drop_pending_updates: true`, preventing stale commands from being processed after downtime or restarts.\\n\\nNon-409 startup errors are propagated immediately. Runtime errors after startup are logged.\\n\\n### Telegram Authorization\\n\\nThe adapter supports either environment variable:\\n\\n```bash\\nTELEGRAM_ALLOWED_USER_IDS=123456789,987654321\\n# or\\nTELEGRAM_ALLOWED_USERS=123456789,987654321\\n```\\n\\n`TELEGRAM_ALLOWED_USER_IDS` takes precedence when both are set.\\n\\n`parseAllowedUserIds()` accepts positive integer IDs only. `isUserAuthorized()` permits all users when the parsed list is empty, and otherwise requires a matching numeric ID.\\n\\n### MarkdownV2 Formatting\\n\\nTelegram has a 4,096-character message limit and a strict MarkdownV2 parser. `sendMessage()` uses the following strategy:\\n\\n1. Messages at or below 4,096 characters are passed to `sendFormattedChunk()`.\\n2. Longer messages are split on paragraph boundaries with `splitIntoParagraphChunks()`.\\n3. Each normal-sized chunk is converted from GitHub-flavored Markdown to Telegram MarkdownV2.\\n4. If Telegram rejects the formatted message, the adapter retries using `stripMarkdown(chunk)`.\\n5. If an individual chunk is still too long after paragraph splitting, formatting is removed and the text is split by lines.\\n\\nThis preserves formatting where possible while ensuring the adapter can still send unusual or oversized AI output.\\n\\n### Markdown Utilities\\n\\n`chat/telegram/markdown.ts` contains the Telegram formatting helpers.\\n\\n| Function | Purpose |\\n|---|---|\\n| `convertToTelegramMarkdown(markdown)` | Converts GitHub-flavored Markdown using `telegramify-markdown`, then fixes remaining `**bold**` sequences. |\\n| `escapeMarkdownV2(text)` | Escapes all MarkdownV2 special characters. Used as a conversion fallback. |\\n| `isAlreadyEscaped(text)` | Detects whether text appears to contain MarkdownV2 escapes. |\\n| `stripMarkdown(markdown)` | Removes common Markdown markup while preserving readable content. |\\n\\n`convertToTelegramMarkdown()` uses the `escape` conversion strategy. If `telegramify-markdown` throws, it logs the failure and returns a MarkdownV2-escaped version of the original text.\\n\\n`stripMarkdown()` preserves the contents of code blocks and inline code, removes heading and emphasis markers, and turns links into readable text:\\n\\n```text\\n[Archon](https://example.com)\\n```\\n\\nbecomes:\\n\\n```text\\nArchon (https://example.com)\\n```\\n\\n---\\n\\n## Discord: `DiscordAdapter`\\n\\n`DiscordAdapter` is a community chat adapter built on `discord.js` v14.\\n\\n```ts\\nconst adapter = new DiscordAdapter(token);\\n\\nadapter.onMessage(async message =&gt; {\\n  // message is a discord.js Message\\n});\\n\\nawait adapter.start();\\n```\\n\\n### Constructor and Client\\n\\n```ts\\nnew DiscordAdapter(\\n  token: string,\\n  mode: 'stream' | 'batch' = 'stream'\\n)\\n```\\n\\nThe adapter configures the Discord client with intents required for guilds, messages, message content, direct messages, and partial channels.\\n\\n`getClient()` returns the underlying `discord.js` `Client`.\\n\\n### Incoming Events\\n\\n`start()` registers a `MessageCreate` listener before calling `client.login(token)`.\\n\\nThe listener:\\n\\n1. Ignores bot-authored messages to avoid loops.\\n2. Checks the author against `DISCORD_ALLOWED_USER_IDS`.\\n3. Invokes the registered handler when authorized.\\n\\nUnlike Slack, the adapter forwards authorized Discord messages to its handler without requiring mention filtering internally. Consumers may use `isBotMentioned()` and `stripBotMention()` to apply channel-command semantics.\\n\\n### Conversation, Mentions, and Threads\\n\\n`getConversationId(message)` returns `message.channelId`.\\n\\nFor a Discord thread, `channelId` is the thread\u2019s own ID, so thread messages naturally remain isolated from parent-channel conversation state.\\n\\nHelpers include:\\n\\n- `isBotMentioned(message)`: checks whether the current client user appears in `message.mentions`.\\n- `isThread(message)`: delegates to `message.channel.isThread()`.\\n- `getParentChannelId(message)`: returns `message.channel.parentId` for thread messages.\\n- `stripBotMention(message)`: removes all occurrences of the current bot\u2019s `&lt;@BOT_ID&gt;` and `&lt;@!BOT_ID&gt;` mentions.\\n- `fetchThreadHistory(message)`: fetches up to 100 thread messages, reverses Discord\u2019s newest-first result, and returns oldest-first formatted lines.\\n\\n### Thread Creation\\n\\n`ensureThread(originalConversationId, messageContext?)` creates a Discord thread for a guild channel message when necessary.\\n\\nBehavior:\\n\\n- No `messageContext`: return the supplied ID unchanged.\\n- Existing thread: return the existing thread channel ID.\\n- Direct message: return the supplied ID unchanged.\\n- Guild channel message: create a thread from the triggering message.\\n- Thread creation failure: log the failure and fall back to the original channel ID.\\n\\nThread creation is deduplicated with `pendingThreads`, keyed by:\\n\\n```text\\nchannelId:messageId\\n```\\n\\nConcurrent calls for the same source message share one creation promise, preventing duplicate Discord threads.\\n\\nThread names come from the mention-stripped message content:\\n\\n- Whitespace is normalized.\\n- Empty content becomes `Bot Response`.\\n- Content of 100 characters or fewer is retained.\\n- Longer content is truncated to 97 characters and suffixed with `...`.\\n\\nThreads use `ThreadAutoArchiveDuration.OneDay` and are created with the reason `Bot response thread`.\\n\\n### Outbound Messages\\n\\nDiscord limits messages to 2,000 characters.\\n\\n`sendMessage()` fetches the destination channel, verifies that it is sendable, and either:\\n\\n- sends a short message directly, or\\n- splits a long message using `splitIntoParagraphChunks(message, 1900)` and sends chunks in order.\\n\\nIf the channel is unavailable or not sendable, the adapter logs the condition and returns without throwing.\\n\\n### Discord Authorization\\n\\nThe optional allowlist uses:\\n\\n```bash\\nDISCORD_ALLOWED_USER_IDS=123456789,987654321\\n```\\n\\n`parseAllowedUserIds()` accepts numeric-string Discord snowflakes. `isDiscordUserAuthorized()` allows all users when no valid IDs are configured; otherwise it requires a non-empty exact match.\\n\\n## Forge Adapters\\n\\nForge adapters connect Archon to repository-hosting systems through webhooks. They have more responsibilities than chat adapters because they also prepare local repositories and associate them with Archon codebase records.\\n\\nAvailable implementations include:\\n\\n- GitHub under `forge/github`\\n- Gitea under `community/forge/gitea`\\n- GitLab under `community/forge/gitlab`\\n\\nThe server constructs each adapter and starts it as part of server initialization. It is also responsible for exposing the appropriate HTTP webhook endpoint and passing the raw request payload and verification header/token to the adapter.\\n\\n## Forge Webhook Lifecycle\\n\\nAlthough platform details differ, the webhook flow follows the same architecture:\\n\\n```mermaid\\nsequenceDiagram\\n  participant F as Forge\\n  participant S as Server Route\\n  participant A as Forge Adapter\\n  participant G as Git / Codebase Services\\n  participant C as @archon/core\\n\\n  F-&gt;&gt;S: Webhook payload\\n  S-&gt;&gt;A: handleWebhook(payload, signature/token)\\n  A-&gt;&gt;A: Verify and parse event\\n  A-&gt;&gt;G: Prepare repository and codebase\\n  A-&gt;&gt;C: handleMessage(...)\\n  C--&gt;&gt;A: Response\\n  A--&gt;&gt;F: Post issue/PR comment\\n```\\n\\nTypical processing includes:\\n\\n1. Verify the webhook signature or GitLab token.\\n2. Parse the platform event and ignore unsupported event types.\\n3. Identify the repository, issue or pull request, sender, and action.\\n4. Check user authorization.\\n5. Build a stable conversation ID.\\n6. Acquire the conversation lock to serialize processing for that conversation.\\n7. Create or reuse the codebase record for the repository.\\n8. Clone or synchronize the local repository.\\n9. Load repository-defined command metadata where present.\\n10. Call `handleMessage()` from `@archon/core`.\\n11. Post responses back as issue or pull-request comments.\\n12. Run cleanup behavior for closed conversations where supported.\\n\\n### Integration with `@archon/git`\\n\\nForge adapters use `@archon/git` to prepare repositories. Known calls include:\\n\\n- `cloneRepository()`\\n- `syncRepository()`\\n- `addSafeDirectory()`\\n- `toRepoPath()`\\n- `toBranchName()`\\n- `isWorktreePath()`\\n\\nRepository setup must distinguish between:\\n\\n- a repository path that already exists and should be synchronized;\\n- a missing path that should be cloned;\\n- inaccessible paths, which should produce actionable errors;\\n- stale worktree paths that must be repaired before codebase reuse.\\n\\n### Integration with Core Persistence\\n\\nForge adapters use core codebase and conversation services to map remote repositories to local workspaces. Their code paths interact with operations such as:\\n\\n- `findCodebaseByRepoUrl()`\\n- `createCodebase()`\\n- `updateCodebase()`\\n- `getCodebaseCommands()`\\n- `updateCodebaseCommands()`\\n- conversation creation and update operations\\n\\nThis mapping is important: a webhook\u2019s repository identity must resolve to the same Archon codebase over subsequent issue or pull-request events.\\n\\n### Repository Commands\\n\\nForge adapters can inspect configured command folders using `getCommandFolderSearchPaths()` from `@archon/paths`.\\n\\nWhen a command folder exists, markdown command files are added to codebase command metadata. The adapter searches configured locations and loads command definitions from the first available command directory.\\n\\n## Gitea Adapter Behavior\\n\\n`GiteaAdapter` is available from:\\n\\n```ts\\nimport { GiteaAdapter } from '@archon/adapters/community/forge/gitea';\\n```\\n\\nIt accepts the Gitea server URL, token, webhook secret, conversation lock manager, and bot identity/configuration values as constructor inputs.\\n\\nThe adapter supports webhook verification, event parsing, repository preparation, issue and pull-request context construction, comment-history lookup, and comment posting.\\n\\n### Event Parsing and Context\\n\\nThe adapter identifies issue, pull request, and issue-comment events, including whether an issue comment belongs to a pull request. It also recognizes close and merge states for cleanup-oriented flows.\\n\\nIt builds richer prompts for issue and PR comments:\\n\\n- Issue context includes issue number, title, author, body, labels, state, and a `tea issue view ` hint.\\n- Pull-request context includes number, title, author, body, state, changed-file count, additions/deletions, and a `tea pr view ` hint.\\n\\nIf structured issue or pull-request data is unavailable, the adapter falls back to the raw comment text.\\n\\n### Comment History\\n\\n`fetchCommentHistory(owner, repo, number)` requests Gitea issue comments and formats entries as:\\n\\n```text\\nauthor: comment text\\n```\\n\\nMissing author or body values are rendered safely. API failures degrade to an empty array, allowing the caller to proceed without history.\\n\\n### Repository Preparation\\n\\n`ensureRepoReady()` handles both existing and missing local clones:\\n\\n- Existing repositories may be synchronized with the configured default branch.\\n- Missing repositories are cloned from the Gitea URL and then marked as safe Git directories.\\n- Clone errors are translated into more useful cases such as missing/private repositories or authentication failures.\\n\\n## GitHub and GitLab Adapter Behavior\\n\\nGitHub and GitLab adapters follow the same forge responsibilities: receive and validate webhooks, prepare repositories, route messages through core orchestration, and post responses back to the originating issue or pull request.\\n\\nThe GitHub adapter additionally participates in conversation cleanup when a conversation closes, via `onConversationClosed()`. Its webhook processing also uses linked issue information through `getLinkedIssueNumbers()` where applicable.\\n\\nThe GitLab adapter verifies incoming webhook tokens through `verifyWebhookToken()` and uses the shared paragraph splitting utility when posting long comments.\\n\\n## Shared Message Splitting\\n\\n`splitIntoParagraphChunks()` is used by Slack, Telegram, Discord, GitHub, and GitLab adapters to avoid platform message limits.\\n\\nAdapters supply a conservative platform-specific chunk size rather than the exact hard maximum:\\n\\n| Adapter | Platform limit | Split threshold used by adapter |\\n|---|---:|---:|\\n| Slack | 12,000 Markdown block characters | 11,500 |\\n| Telegram | 4,096 characters | 3,896 |\\n| Discord | 2,000 characters | 1,900 |\\n\\nThis safety margin leaves room for formatting expansion, API behavior, or fallback formatting.\\n\\nCallers send chunks sequentially with `await`, preserving the ordering of generated responses.\\n\\n## Logging\\n\\nAdapters create loggers through `createLogger()` from `@archon/paths`.\\n\\nThey use a lazy module-level logger pattern:\\n\\n```ts\\nlet cachedLog: ReturnType | undefined;\\n\\nfunction getLog(): ReturnType {\\n  if (!cachedLog) cachedLog = createLogger('adapter.example');\\n  return cachedLog;\\n}\\n```\\n\\nThis has two purposes:\\n\\n1. Logger creation is deferred until it is needed.\\n2. Tests can mock `createLogger()` before the adapter initializes it.\\n\\nLog events use structured context for relevant values such as message length, conversation IDs, retry attempts, thread IDs, and masked user IDs. Errors are generally logged at the adapter boundary while recoverable behavior falls back safely:\\n\\n- Slack markdown failure falls back to plain text.\\n- Telegram MarkdownV2 failure falls back to stripped text.\\n- Thread-history API failure returns no history.\\n- Discord thread creation failure falls back to the original channel.\\n- Forge comment-history failures return an empty context where appropriate.\\n\\n## Security and Access Control\\n\\nAllowlist behavior is intentionally consistent across chat adapters:\\n\\n- No configured valid IDs means **open access**.\\n- A non-empty configured list means **only listed users are accepted**.\\n- Missing sender IDs are rejected when a whitelist is active.\\n- Unauthorized requests are logged with partially masked identifiers and are otherwise silently ignored.\\n\\nEnvironment variable names are platform-specific:\\n\\n| Platform | Environment variable |\\n|---|---|\\n| Slack | `SLACK_ALLOWED_USER_IDS` |\\n| Telegram | `TELEGRAM_ALLOWED_USER_IDS` or `TELEGRAM_ALLOWED_USERS` |\\n| Discord | `DISCORD_ALLOWED_USER_IDS` |\\n\\nForge adapters add webhook authenticity verification before event processing. GitHub and Gitea verify signatures; GitLab uses webhook-token verification.\\n\\n## Adding an Adapter\\n\\nNew chat adapters should use `DiscordAdapter` as the primary reference. New forge adapters should follow the GitHub adapter\u2019s repository and webhook lifecycle.\\n\\nA chat adapter should:\\n\\n1. Implement `IPlatformAdapter`.\\n2. Define a native incoming context type if the platform SDK type is not appropriate.\\n3. Store a handler registered by `onMessage()`.\\n4. Apply optional authorization before dispatching the handler.\\n5. Implement platform-specific conversation and thread semantics.\\n6. Split outgoing responses for platform limits.\\n7. Use a lazy `getLog()` helper.\\n8. Be registered by the server before `start()` is called.\\n\\nA forge adapter should additionally:\\n\\n1. Verify webhook authenticity.\\n2. Parse and filter supported event types.\\n3. Create stable conversation IDs.\\n4. Use the conversation lock manager around orchestration.\\n5. Prepare the repository and associated codebase.\\n6. Handle close or merge cleanup paths where relevant.\\n7. Post core responses as comments.\\n\\n## Testing\\n\\nThe package test script separates some test files into distinct `bun test` invocations. This is required because Bun\u2019s `mock.module()` is process-global and cannot be reliably undone with `mock.restore()`.\\n\\nWhen adding tests that mock modules such as `@archon/paths`, `@archon/git`, or `@archon/core`, ensure they do not share a test process with incompatible mocks. Add a dedicated `bun test` invocation in `packages/adapters/package.json` when needed.\\n\\nTests should cover:\\n\\n- streaming-mode defaults and overrides;\\n- platform type;\\n- allowlist parsing and authorization behavior;\\n- conversation ID and thread semantics;\\n- formatting and oversized-message behavior;\\n- API failure fallbacks;\\n- startup and shutdown;\\n- webhook verification and event parsing for forge adapters;\\n- concurrent thread creation where the platform supports threads.\\n\\nUse mocked SDK clients for adapter tests and retain the lazy logger pattern so logger mocks intercept initialization correctly.\",\"other-agents-md\":\"# Other \u2014 AGENTS.md\\n\\n# AGENTS.md \u2014 Contributor and AI Agent Operating Guide\\n\\n`AGENTS.md` defines the repository-wide development contract for Archon, a remote AI programming platform built with Bun, TypeScript, and SQLite or PostgreSQL. It is guidance rather than executable code: it establishes architectural boundaries, implementation conventions, validation requirements, release practices, and mandatory GitNexus-assisted change analysis.\\n\\nThe file applies to human contributors and automated coding agents working anywhere in the repository.\\n\\n## Purpose and Scope\\n\\nArchon enables remote control of AI coding assistants through Slack, Telegram, and GitHub. The codebase uses a platform-neutral core and platform adapters to provide a consistent conversation and workflow model.\\n\\n`AGENTS.md` governs:\\n\\n- TypeScript, schema, logging, and error-handling conventions\\n- Workflow, command, and platform-extension boundaries\\n- Test isolation and CI validation expectations\\n- Git, pull request, release, and generated-artifact workflows\\n- Safe repository navigation and impact analysis through GitNexus\\n\\nFor project architecture, use [`docs/architecture.md`](docs/architecture.md). For command-line commands, API endpoints, workflow syntax, and configuration, use [`docs/cli-reference.md`](docs/cli-reference.md).\\n\\n## Architectural Constraints\\n\\nThe project is deliberately designed as a single-user development tool. Contributors should not introduce multi-tenant behavior, tenant-scoped abstractions, or enterprise authorization complexity without a concrete approved requirement.\\n\\nPlatform-specific behavior must remain behind the existing adapter boundary:\\n\\n- `IPlatformAdapter` defines platform-facing operations.\\n- `IAgentProvider` defines AI-agent-provider behavior.\\n- `IDatabase` defines database access.\\n- `IWorkflowStore` defines workflow persistence behavior.\\n\\nNew behavior should extend an appropriate narrow interface rather than adding unrelated methods to an existing interface. For example, Slack-, Telegram-, and GitHub-specific message handling belongs in an `IPlatformAdapter` implementation, not in orchestration code.\\n\\n```mermaid\\nflowchart LR\\n    Slack[Slack adapter] --&gt; Adapter[IPlatformAdapter]\\n    Telegram[Telegram adapter] --&gt; Adapter\\n    GitHub[GitHub adapter] --&gt; Adapter\\n    Adapter --&gt; Core[Session and workflow core]\\n    Core --&gt; Agent[IAgentProvider]\\n    Core --&gt; Store[IWorkflowStore]\\n    Store --&gt; DB[IDatabase]\\n```\\n\\nThe adapter layer allows the core workflow and session logic to operate independently of the originating communication platform.\\n\\n## Engineering Principles\\n\\n### Keep implementation scope small\\n\\nFollow KISS and YAGNI:\\n\\n- Prefer direct, readable control flow over speculative abstractions.\\n- Do not add configuration keys, feature flags, or interface methods without a current use case.\\n- Explicitly reject unsupported paths rather than creating incomplete or misleading support.\\n- Extract shared utilities only after a stable pattern has appeared at least three times.\\n\\n### Fail early and visibly\\n\\nErrors must remain local, explicit, and actionable:\\n\\n- Throw clear errors for invalid or unsupported states.\\n- Do not silently swallow errors.\\n- Document intentional fallback behavior in code comments.\\n- For database updates, verify `rowCount`; an `updateX` operation should throw when no matching row exists.\\n\\n### Preserve lifecycle ownership\\n\\nA process must not autonomously mark work as failed or cancelled across process boundaries merely because a timer has elapsed. A process cannot reliably distinguish active work in another process from orphaned work.\\n\\nThis rule protects workflow and session state from false cancellation or failure. See the lifecycle guidance near `packages/cli/src/cli.ts:256-258` and issue `#1216`.\\n\\n### Maintain determinism and reversibility\\n\\nChanges should be:\\n\\n- Deterministic in tests and validation.\\n- Compatible with `bun run validate`, which maps directly to CI expectations.\\n- Narrow enough to understand and revert.\\n- Accompanied by a known rollback path when they affect higher-risk behavior.\\n\\n## TypeScript and Schema Requirements\\n\\n### Type safety\\n\\nUse strict TypeScript throughout:\\n\\n- Fully annotate function signatures.\\n- Avoid `any`.\\n- Use SDK-provided types directly rather than duplicating them.\\n- Define interfaces for important abstractions.\\n\\nFor example, import agent SDK types rather than creating parallel approximations:\\n\\n```typescript\\nimport { query, type Options } from '@anthropic-ai/Codex-agent-sdk';\\n\\nconst options: Options = {\\n  cwd,\\n  permissionMode: 'bypassPermissions',\\n};\\n\\nquery({ prompt, options });\\n```\\n\\nDo not create replacement option interfaces or bypass type checking with `as any`.\\n\\n### Zod schemas\\n\\nAll Zod schemas follow a consistent source, naming, and inference model.\\n\\n| Rule | Requirement |\\n|---|---|\\n| Zod import | Import `z` from `@hono/zod-openapi`, not directly from `zod`. |\\n| Schema naming | Use camelCase names with a descriptive suffix, such as `workflowRunSchema`. |\\n| Type derivation | Use `z.infer`; do not write duplicate parallel interfaces. |\\n| API route schemas | Place in `packages/server/src/routes/schemas/`, organized as one file per domain. |\\n| Workflow engine schemas | Place in `packages/workflows/src/schemas/`, one file per concern, and re-export through `index.ts`. |\\n| API route registration | New or modified API routes must use `registerOpenApiRoute(createRoute({...}), handler)`. |\\n| Enum-derived values | Derive `TRIGGER_RULES` and `WORKFLOW_HOOK_EVENTS` from schema `.options`; do not maintain duplicate arrays. |\\n| DAG validation | `loader.ts` validates nodes with `dagNodeSchema.safeParse()`. |\\n\\nThis policy makes API documentation, runtime validation, and TypeScript types derive from one authoritative schema definition.\\n\\n## Commands, Workflows, and Resolution\\n\\n### Repository and global content\\n\\nArchon loads commands and workflows from project and user-home locations:\\n\\n| Content | Project location | Global location |\\n|---|---|---|\\n| Commands | `.archon/commands/` | `~/.archon/commands/` |\\n| Workflows | `.archon/workflows/` | `~/.archon/workflows/` |\\n\\nWorkflow discovery is recursive. Commands are plain text or Markdown files invoked through `command:` workflow nodes.\\n\\nLoading precedence is:\\n\\n1. Bundled defaults\\n2. Global user content\\n3. Project-local content\\n\\nProject-local definitions therefore override global and bundled definitions.\\n\\nBundled defaults live in:\\n\\n- `.archon/commands/defaults/`\\n- `.archon/workflows/defaults/`\\n\\nAfter adding, removing, or editing bundled defaults, run:\\n\\n```bash\\nbun run generate:bundled\\n```\\n\\n### Workflow-name matching\\n\\n`resolveWorkflowName()` in `router.ts` resolves workflow names through four ordered fallbacks:\\n\\n1. Exact match\\n2. Case-insensitive match\\n3. Suffix match\\n4. Substring match\\n\\nContributors changing workflow routing should preserve this order unless the intended behavior change is explicit and tested.\\n\\n### Slash commands\\n\\nThe deterministic slash commands do not require AI interpretation:\\n\\n- `/help`\\n- `/status`\\n- `/reset`\\n- `/workflow`\\n- `/register-project`\\n- `/update-project`\\n- `/remove-project`\\n- `/commands`\\n- `/init`\\n- `/worktree`\\n\\nThe `/workflow` command supports:\\n\\n- `list`\\n- `run`\\n- `status`\\n- `cancel`\\n- `resume`\\n- `abandon`\\n- `approve`\\n- `reject`\\n\\n## GitHub Mention Handling\\n\\nGitHub `@archon` mention detection is intentionally narrow:\\n\\n- Parse mentions only from Issue and Pull Request **comments**.\\n- Do not parse mentions from Issue or Pull Request descriptions.\\n- Handle only the `issue_comment` GitHub event.\\n\\nThis constraint prevents unintentional execution from static issue or pull-request content.\\n\\n## Logging and Error Handling\\n\\n### Structured logging\\n\\nCreate loggers with `createLogger()` from `@archon/paths`:\\n\\n```typescript\\nimport { createLogger } from '@archon/paths';\\n\\nconst log = createLogger('orchestrator');\\n```\\n\\nUse event names in this form:\\n\\n```text\\n{domain}.{action}_{state}\\n```\\n\\nOperations must pair lifecycle events consistently:\\n\\n- `_started` with `_completed`\\n- `_started` with `_failed`\\n\\nFor example:\\n\\n```typescript\\nlog.info({ conversationId, codebaseId }, 'session.create_started');\\nlog.error({ conversationId, error: err.message, err }, 'session.create_failed');\\n```\\n\\nNever log:\\n\\n- API keys\\n- Tokens\\n- User message content\\n- Personally identifiable information\\n\\nIf a token must be correlated during troubleshooting, mask it:\\n\\n```typescript\\ntoken.slice(0, 8) + '...'\\n```\\n\\n### Isolation and Git-related failures\\n\\nErrors from Git or isolation setup must be classified with `classifyIsolationError()` from `@archon/isolation` before they are shown to a user:\\n\\n```typescript\\ntry {\\n  // isolation creation logic\\n} catch (error) {\\n  const err = error as Error;\\n  const userMessage = classifyIsolationError(err);\\n\\n  log.error({ err, codebaseId }, 'isolation_creation_failed');\\n  await platform.sendMessage(conversationId, userMessage);\\n}\\n```\\n\\nThis preserves detailed diagnostics in logs while returning a user-oriented, classified error through the active `IPlatformAdapter`.\\n\\n## Testing and Validation\\n\\n### Test isolation\\n\\nBun\u2019s `mock.module()` is process-global and irreversible. `mock.restore()` does not undo it.\\n\\nTherefore:\\n\\n- Prefer `spyOn()` for modules also mocked by other test files.\\n- Restore spies with `spy.mockRestore()`.\\n- Do not run `bun test` from the repository root.\\n- Run all repository tests through `bun run test`, which executes packages in isolated processes.\\n- A new test using `mock.module()` must run in its own independent `bun test` invocation.\\n\\nThe standard commands are:\\n\\n```bash\\nbun run test\\nbun test --watch\\n```\\n\\n`bun test --watch` is appropriate for a single package during local development. It is not a replacement for repository-wide isolated test execution.\\n\\n### Linting and formatting\\n\\nRun:\\n\\n```bash\\nbun run type-check\\nbun run lint\\nbun run lint:fix\\nbun run format\\nbun run format:check\\n```\\n\\nESLint warnings are treated as failures in CI through `--max-warnings 0`. Fix warnings rather than suppressing them. The only permitted exception is an external SDK type defect, and that suppression must include a comment explaining why it is necessary.\\n\\n### Required pre-PR validation\\n\\nBefore opening or updating a pull request, run:\\n\\n```bash\\nbun run validate\\n```\\n\\nThis validates:\\n\\n1. `check:bundled`\\n2. `check:bundled-skill`\\n3. Type checking\\n4. Linting\\n5. Formatting\\n6. Tests\\n\\nAll checks must pass for CI to succeed.\\n\\n## Development Commands\\n\\n### Local development\\n\\n```bash\\nbun run dev\\nbun run dev:server\\nbun run dev:web\\n```\\n\\n- `bun run dev` starts the server and Web UI with hot reload.\\n- `bun run dev:server` starts only the backend on port `3090`.\\n- `bun run dev:web` starts only the frontend on port `5173`.\\n\\nTo regenerate frontend API types, start the server first and run:\\n\\n```bash\\nbun --filter @archon/web generate:types\\n```\\n\\n### Database setup\\n\\nSQLite is the default and requires no setup:\\n\\n```text\\n~/.archon/archon.db\\n```\\n\\nFor PostgreSQL, define `DATABASE_URL` in `.env`, then apply the combined migration:\\n\\n```bash\\npsql $DATABASE_URL &lt; migrations/000_combined.sql\\n```\\n\\n## Git, Pull Requests, and Releases\\n\\n### Safe Git operations\\n\\nUse `@archon/git` functions for Git operations when available. If direct Git invocation is required, use `execFileAsync`; do not use shell-based `exec`.\\n\\nNever run:\\n\\n```bash\\ngit clean -fd\\n```\\n\\nTo discard tracked-file changes, use:\\n\\n```bash\\ngit checkout .\\n```\\n\\nThe prohibition protects untracked local files, generated assets, and developer work that may not be recoverable.\\n\\n### Pull request requirements\\n\\nEvery pull request must use `.github/PULL_REQUEST_TEMPLATE.md`.\\n\\nWhen creating a PR with `gh pr create`, explicitly provide the template body. The PR description must associate the relevant issue using:\\n\\n```text\\nCloses #\\n```\\n\\n### Releases\\n\\nUse the release skill rather than manually managing release steps:\\n\\n```text\\n/release\\n/release minor\\n/release major\\n```\\n\\nVersions are maintained in the root `package.json`. Release notes belong in `CHANGELOG.md` and must follow Keep a Changelog formatting.\\n\\n## GitNexus Change-Safety Workflow\\n\\nThe repository is indexed in GitNexus as `doarchon`. GitNexus provides symbol relationships, execution flows, and impact analysis that contributors must use before modifying implementation symbols.\\n\\n`AGENTS.md` itself has no runtime calls, incoming callers, or execution flows. Its GitNexus requirements apply to changes made to the code modules governed by this document.\\n\\n### Before editing a function, class, or method\\n\\nRun upstream impact analysis:\\n\\n```text\\ngitnexus_impact({ target: \\\"symbolName\\\", direction: \\\"upstream\\\" })\\n```\\n\\nReport the result to the user, including:\\n\\n- Direct callers\\n- Affected processes or execution flows\\n- Risk level\\n\\nIf the result is `HIGH` or `CRITICAL`, warn the user before proceeding.\\n\\nDo not edit a function, class, or method without this analysis.\\n\\n### During exploration and debugging\\n\\nUse GitNexus queries before broad text searches when learning unfamiliar behavior:\\n\\n```text\\ngitnexus_query({ query: \\\"concept\\\" })\\n```\\n\\nUse full symbol context when a specific function or class is central to the task:\\n\\n```text\\ngitnexus_context({ name: \\\"symbolName\\\" })\\n```\\n\\nIf GitNexus reports that its index is stale, refresh it before relying on the results:\\n\\n```bash\\nnpx gitnexus analyze\\n```\\n\\n### Before committing\\n\\nRun:\\n\\n```text\\ngitnexus_detect_changes()\\n```\\n\\nConfirm that changed symbols and affected execution flows match the intended scope. Do not commit if the detected impact reveals unexpected behavior changes.\\n\\n### Refactoring and renaming\\n\\nNever rename symbols through find-and-replace. Use:\\n\\n```text\\ngitnexus_rename\\n```\\n\\nThis preserves call-graph awareness and reduces the risk of incomplete references.\\n\\n## Contributor Checklist\\n\\nBefore submitting a change:\\n\\n- [ ] The change respects existing narrow interfaces such as `IPlatformAdapter`, `IAgentProvider`, `IDatabase`, and `IWorkflowStore`.\\n- [ ] New schemas use `z` from `@hono/zod-openapi` and derive types with `z.infer`.\\n- [ ] Modified API routes use `registerOpenApiRoute(createRoute({...}), handler)`.\\n- [ ] Logging follows `{domain}.{action}_{state}` and does not expose secrets, user content, or PII.\\n- [ ] Database updates verify `rowCount`.\\n- [ ] Tests do not create cross-file `mock.module()` contamination.\\n- [ ] Bundled command or workflow changes were followed by `bun run generate:bundled`.\\n- [ ] `bun run validate` passes.\\n- [ ] GitNexus impact analysis was completed before editing implementation symbols.\\n- [ ] `gitnexus_detect_changes()` was run before committing.\\n- [ ] The PR uses the repository template and includes `Closes #`.\",\"other-auth-service\":\"# Other \u2014 auth-service\\n\\n# Other \u2014 `auth-service`\\n\\n## Overview\\n\\n`auth-service` is a small Node.js authentication sidecar intended for use with Caddy\u2019s `forward_auth` mechanism. It provides cookie-based authentication logic and exposes reusable helpers for:\\n\\n- Validating redirect targets with `isSafeRedirect`\\n- Signing authentication cookie values with `signCookie`\\n- Verifying signed cookies with `verifyCookie`\\n\\nThe service is packaged as a production-oriented Docker image and runs on port `9000`.\\n\\n## Module layout\\n\\n```text\\nauth-service/\\n\u251c\u2500\u2500 Dockerfile\\n\u251c\u2500\u2500 package.json\\n\u251c\u2500\u2500 server.js       # Runtime server and authentication helpers\\n\u2514\u2500\u2500 test.js         # Direct assertions for helper functions\\n```\\n\\n`server.js` is the application entry point and is also imported by `test.js` so its helper functions can be tested directly.\\n\\n## Architecture\\n\\nThe service is designed to sit alongside an HTTP proxy such as Caddy. Caddy can forward authentication checks to this service before allowing access to protected routes.\\n\\n```mermaid\\nflowchart LR\\n    Client --&gt; Caddy\\n    Caddy --&gt;|forward_auth| Auth[\\\"auth-service\\\\n:9000\\\"]\\n    Auth --&gt;|allow or deny| Caddy\\n    Caddy --&gt; Application\\n```\\n\\nThe call-graph data does not identify an incoming caller for the running service. The documented integration point is the intended Caddy `forward_auth` deployment described by the package metadata.\\n\\n## Runtime and deployment\\n\\n### Docker image\\n\\nThe `Dockerfile` uses:\\n\\n```dockerfile\\nFROM node:22-alpine\\n```\\n\\nThe container:\\n\\n1. Sets `/app` as the working directory.\\n2. Copies `package.json`.\\n3. Installs production dependencies with:\\n\\n   ```sh\\n   npm install --omit=dev --no-package-lock\\n   ```\\n\\n4. Copies `server.js`.\\n5. Switches to the built-in non-root `node` user.\\n6. Exposes port `9000`.\\n7. Starts the service with:\\n\\n   ```sh\\n   node server.js\\n   ```\\n\\nThe application should therefore be configured to listen on port `9000` inside the container.\\n\\n### Local execution\\n\\nInstall dependencies and start the service from the `auth-service` directory:\\n\\n```sh\\nnpm install\\nnpm start\\n```\\n\\nThe `start` script resolves to:\\n\\n```sh\\nnode server.js\\n```\\n\\nThe package is marked `\\\"private\\\": true`, indicating that it is intended for deployment within this codebase rather than publication as an npm package.\\n\\n## Authentication helpers\\n\\n### `signCookie(value)`\\n\\n`signCookie` produces a signed cookie representation for the supplied value.\\n\\nThe tests establish that the generated format is:\\n\\n```text\\n.\\n```\\n\\nThe signature is generated using an HMAC-SHA-256 operation. The test suite constructs compatible signatures using:\\n\\n```js\\ncreateHmac('sha256', secret)\\n  .update(value)\\n  .digest('base64url')\\n```\\n\\nA normal round trip is expected to preserve the original value:\\n\\n```js\\nconst signed = signCookie('authenticated');\\nconst value = verifyCookie(signed);\\n\\n// value === 'authenticated'\\n```\\n\\nThe signing secret is obtained by `server.js`; callers do not pass it to `signCookie`.\\n\\n### `verifyCookie(cookie)`\\n\\n`verifyCookie` validates a signed cookie and returns the original unsigned value when the signature is valid.\\n\\nIt returns `null` for invalid input, including:\\n\\n- A tampered signature\\n- A value without the separating dot\\n- An empty string\\n- A signature generated using a different secret\\n\\nExample:\\n\\n```js\\nconst signed = signCookie('authenticated');\\nconst authenticatedValue = verifyCookie(signed);\\n\\nif (authenticatedValue !== null) {\\n  // The cookie signature is valid.\\n}\\n```\\n\\nVerification uses a timing-safe comparison, as indicated by the test module\u2019s use of Node\u2019s `timingSafeEqual` API and the security-sensitive nature of the helper.\\n\\n### Cookie format considerations\\n\\nThe cookie format is deliberately simple:\\n\\n```text\\nvalue.signature\\n```\\n\\nAny code changing the format must update both `signCookie` and `verifyCookie`, as well as the corresponding assertions in `test.js`. Changes to the configured signing secret invalidate existing cookies signed with the previous secret.\\n\\n## Redirect validation\\n\\n### `isSafeRedirect(path)`\\n\\n`isSafeRedirect` accepts only redirect targets that are rooted paths on the current application origin.\\n\\nThe following values are considered safe:\\n\\n```text\\n/\\n/dashboard\\n/api/health\\n/api/v1/resource\\n```\\n\\nThe following values are rejected:\\n\\n```text\\n//evil.com\\n/\\\\evil.com\\nhttps://evil.com\\nhttp://evil.com\\njavascript://\\n//\\n(empty string)\\nrelative/no-leading-slash\\n```\\n\\nThis prevents common open-redirect patterns, including:\\n\\n- Absolute URLs\\n- Protocol-relative URLs\\n- Backslash-based host interpretation\\n- Non-path schemes\\n- Relative paths that do not begin with `/`\\n\\nTypical usage is to validate a return or redirect path before using it in an authentication flow:\\n\\n```js\\nif (isSafeRedirect(returnPath)) {\\n  // Use returnPath as the redirect target.\\n}\\n```\\n\\nCallers should continue to treat redirect values as untrusted input even after validation.\\n\\n## Dependencies\\n\\nThe runtime dependency declared in `package.json` is:\\n\\n```json\\n\\\"bcryptjs\\\": \\\"^2.4.3\\\"\\n```\\n\\nThe supplied test file does not directly exercise `bcryptjs`. Any password hashing or comparison behavior implemented in `server.js` should use the dependency according to the service\u2019s authentication requirements.\\n\\nThe application otherwise relies on Node.js built-in modules, including cryptographic functionality used by the cookie-signing tests.\\n\\n## Testing\\n\\nRun the helper tests with:\\n\\n```sh\\nnode test.js\\n```\\n\\nor, from the repository root:\\n\\n```sh\\nnode auth-service/test.js\\n```\\n\\nThe test file imports these functions from `server.js`:\\n\\n```js\\nconst {\\n  isSafeRedirect,\\n  signCookie,\\n  verifyCookie\\n} = require('./server.js');\\n```\\n\\nThe test coverage verifies:\\n\\n- Accepted and rejected redirect paths\\n- Successful cookie signing and verification\\n- Detection of modified signatures\\n- Rejection of malformed cookie values\\n- Rejection of cookies signed with the wrong secret\\n\\nA successful run prints:\\n\\n```text\\nisSafeRedirect: all assertions passed\\nsignCookie/verifyCookie: all assertions passed\\nAll tests passed.\\n```\\n\\n## Contribution guidance\\n\\nWhen modifying this module:\\n\\n- Preserve the `value.signature` cookie format unless all consumers are updated.\\n- Keep invalid cookie verification failures represented by `null`, matching the current contract.\\n- Do not weaken `isSafeRedirect`; absolute, protocol-relative, backslash-based, and non-rooted targets must remain rejected.\\n- Keep the container running as the non-root `node` user.\\n- Ensure changes to `server.js` remain compatible with the direct imports used by `test.js`.\\n- Run `node test.js` before committing changes.\\n\\nThe repository call-graph data identifies `test.js` as the module\u2019s test entry point and records an integration reference to `components/workflows/WorkflowBuilder.tsx`. No runtime incoming calls are identified for `auth-service`; its operational connection is the proxy-side `forward_auth` deployment described in `package.json`.\",\"other-auth\":\"# Other \u2014 auth\\n\\n# `@archon/auth`\\n\\n`@archon/auth` provides authentication, authorization, identity-provider clients, and authentication-related database access for the Archon application.\\n\\nThe module supports:\\n\\n- Local JWT authentication\\n- UUAP/UGate token authentication\\n- Hono middleware for authenticated and admin-only routes\\n- UUAP ticket and session validation\\n- UIC user and email-group search\\n- Department-member lookup\\n- Persistent users, UGate tokens, and iCafe space configuration\\n\\n## Package exports\\n\\n```text\\n@archon/auth                 Main public API\\n@archon/auth/jwt             JWT helpers\\n@archon/auth/middleware      Hono authentication middleware\\n@archon/auth/db              Authentication database helpers\\n@archon/auth/uuap/client     UuapClient\\n@archon/auth/uic/client      UICClient\\n@archon/auth/deptmember/client\\n                             Department-member client\\n```\\n\\nThe package root (`src/index.ts`) exports:\\n\\n- UUAP types and errors\\n- `signToken`, `verifyToken`, and `JwtInvalidError`\\n- `requireAuth` and `requireAdmin`\\n- Database interfaces and helpers\\n\\nThe UUAP, UIC, and department-member clients must be imported from their explicit subpaths.\\n\\n---\\n\\n## Authentication architecture\\n\\nAuthentication is accepted from either a local JWT or a UUAP/UGate token. Both paths populate Hono context values used by downstream handlers:\\n\\n```ts\\nc.get('userId');   // Internal remote_agent_users.id\\nc.get('userRole'); // 'admin' | 'user'\\n```\\n\\n```mermaid\\nflowchart TD\\n    Request[Incoming request] --&gt; Test{Test auth enabled?}\\n    Test --&gt;|Valid X-Test-User| TestUser[ensureTestUser]\\n    Test --&gt;|No| Detect[Detect UGate or Bearer token]\\n    Detect --&gt; UGate{UGate token?}\\n    UGate --&gt;|Yes| VerifyUGate[Verify HS256 and UUAP session]\\n    VerifyUGate --&gt; User[findOrCreateUser]\\n    UGate --&gt;|No or fallback| Local[verifyToken]\\n    Local --&gt; Existing[getUserById]\\n    TestUser --&gt; Context[Set userId and userRole]\\n    User --&gt; Context\\n    Existing --&gt; Context\\n    Context --&gt; Next[Continue Hono chain]\\n```\\n\\n### UGate authentication\\n\\n`requireAuth` and `requireAdmin` use `authenticateUgateToken` internally. The flow is:\\n\\n1. Read and decode the candidate token to identify UGate claims.\\n2. Verify the token signature with `UUAP_SECRET_KEY`, restricted to `HS256`.\\n3. Require both `pToken` and `sToken` claims.\\n4. Call `UuapClient.verifySession(pToken, sToken, { apiToken: true })`.\\n5. Persist or update the UUAP user through `findOrCreateUser`.\\n6. Set `userId` to the internal database UUID and `userRole` to the persisted role.\\n\\nA validly signed token without `pToken` or `sToken` is rejected. It is not treated as a local JWT.\\n\\nUGate tokens can be supplied through:\\n\\n- `Ugate-Token`\\n- `X-Ugate-Token`\\n- `Authorization`\\n\\nAn `Authorization` token is considered a UGate token when its decoded payload contains both `pToken` and `sToken`. The `Bearer ` prefix is removed when present.\\n\\n### Local JWT authentication\\n\\nLocal JWTs are signed and verified by `signToken` and `verifyToken`.\\n\\n`authenticateLocalJwt`:\\n\\n1. Verifies the token with `verifyToken`.\\n2. Sets `userId` from the token payload.\\n3. Looks up the user with `getUserById`.\\n4. Sets `userRole` to the database role, or `'user'` if no database row exists.\\n\\n`requireAdmin` passes `{ requireUser: true }`, so a local JWT must refer to an existing database user before it can authorize an admin request.\\n\\n### Fallback behavior\\n\\nIf a UGate token fails and the request also has an `Authorization` header beginning with `Bearer `, the middleware attempts local JWT authentication using that Bearer token.\\n\\nThis allows a request with an incidental or invalid UGate header to continue using a valid local JWT.\\n\\nIf there is no Bearer token to fall back to:\\n\\n- Authentication errors produce `401 Unauthorized`.\\n- Unexpected non-authentication errors are rethrown.\\n\\n---\\n\\n## Hono middleware\\n\\n### `requireAuth`\\n\\n```ts\\nimport { requireAuth } from '@archon/auth/middleware';\\n\\napp.use('/protected/*', requireAuth);\\n```\\n\\n`requireAuth` accepts:\\n\\n- A local JWT in `Authorization: Bearer `\\n- A UGate token in `Ugate-Token` or `X-Ugate-Token`\\n- A UGate token in `Authorization`, with or without the `Bearer ` prefix when it has UGate claims\\n\\nOn success, it sets:\\n\\n```ts\\nc.set('userId', user.id);\\nc.set('userRole', user.role);\\n```\\n\\nOn missing or invalid credentials, it returns:\\n\\n```json\\n{ \\\"error\\\": \\\"Unauthorized\\\" }\\n```\\n\\nwith status `401`.\\n\\n### `requireAdmin`\\n\\n```ts\\nimport { requireAdmin } from '@archon/auth/middleware';\\n\\napp.use('/admin/*', requireAdmin);\\n```\\n\\n`requireAdmin` performs authentication and then requires:\\n\\n```ts\\nc.get('userRole') === 'admin'\\n```\\n\\nA successfully authenticated non-admin receives:\\n\\n```json\\n{ \\\"error\\\": \\\"Forbidden\\\" }\\n```\\n\\nwith status `403`.\\n\\nFor local JWTs, the referenced user must exist in `remote_agent_users`. For UGate tokens, the user is upserted before the role check.\\n\\n`requireAdmin` is intended to run as the route-level authorization middleware. It can be used independently because it contains the authentication logic required for both token types.\\n\\n### Test authentication\\n\\nWhen:\\n\\n```text\\nTEST_AUTH_ENABLED=true\\n```\\n\\nthe middleware recognizes:\\n\\n```http\\nX-Test-User: admin\\n```\\n\\nor:\\n\\n```http\\nX-Test-User: user\\n```\\n\\nThe request bypasses UUAP authentication, calls `ensureTestUser`, and sets the corresponding context values.\\n\\nThis behavior is intended only for local development and tests. It must not be enabled in production.\\n\\nFor `requireAdmin`:\\n\\n- `X-Test-User: admin` succeeds.\\n- `X-Test-User: user` returns `403`.\\n- Other requests continue through normal authentication.\\n\\n---\\n\\n## JWT helpers\\n\\n### `signToken(userId)`\\n\\n```ts\\nimport { signToken } from '@archon/auth';\\n\\nconst token = signToken(userId);\\n```\\n\\nCreates a JWT containing:\\n\\n```ts\\n{ userId }\\n```\\n\\nConfiguration:\\n\\n| Variable | Default | Description |\\n|---|---|---|\\n| `JWT_SECRET` | Required | Signing and verification secret |\\n| `JWT_EXPIRES_IN` | `7d` | `jsonwebtoken` expiration value |\\n| `TEST_AUTH_ENABLED` | unset | Enables a local test-only fallback secret |\\n\\nIf `JWT_SECRET` is missing, `signToken` throws unless `TEST_AUTH_ENABLED === 'true'`. With test authentication enabled, the module uses the built-in local test secret.\\n\\n### `verifyToken(token)`\\n\\n```ts\\nimport { verifyToken } from '@archon/auth';\\n\\nconst { userId } = verifyToken(token);\\n```\\n\\nReturns:\\n\\n```ts\\n{ userId: string }\\n```\\n\\nInvalid, expired, or incorrectly signed tokens throw `JwtInvalidError` with the message:\\n\\n```text\\nInvalid or expired JWT token\\n```\\n\\nThe function intentionally normalizes all JWT verification failures into `JwtInvalidError`.\\n\\n---\\n\\n## UUAP client\\n\\n`UuapClient` communicates with UUAP using signed form-encoded requests.\\n\\n```ts\\nimport { UuapClient } from '@archon/auth/uuap/client';\\n\\nconst client = new UuapClient({\\n  baseUrl: 'https://uuap.baidu.com',\\n  appKey,\\n  secretKey,\\n  pTokenName: 'UUAP_P_TOKEN',\\n});\\n```\\n\\n`UuapConfig.pTokenName` is part of the configuration type, although the current client methods do not directly use it.\\n\\n### `exchangeTicket(ticket)`\\n\\nExchanges a CAS ticket for an S_TOKEN through:\\n\\n```text\\nPOST {baseUrl}/sTokenDecrypt\\n```\\n\\nThe request includes a SHA-256 signature derived from:\\n\\n```text\\nappKey + ticket + timestamp + secretKey\\n```\\n\\nFailures throw `UuapTicketError`.\\n\\n### `verifySession(pToken, sToken, options?)`\\n\\nValidates a UUAP session through:\\n\\n```text\\nPOST {baseUrl}/session/validate\\n```\\n\\nReturns:\\n\\n```ts\\n{\\n  username: string;\\n  name: string;\\n  email: string;\\n}\\n```\\n\\nWith:\\n\\n```ts\\n{ apiToken: true }\\n```\\n\\nthe request includes:\\n\\n- `apiToken=true`\\n- A random `sRandom` value\\n- A sorted-parameter SHA-256 signature\\n\\nThis option is used by UGate authentication.\\n\\nFailures, including UUAP business code `204`, throw `UuapSessionError`.\\n\\n---\\n\\n## User database helpers\\n\\n`src/db.ts` uses the shared `pool` from `@archon/core/db/connection`.\\n\\n### Database records\\n\\n`DbUser` corresponds to `remote_agent_users`:\\n\\n```ts\\ninterface DbUser {\\n  id: string;\\n  uuap_id: string;\\n  username: string;\\n  real_name: string | null;\\n  email: string | null;\\n  role: 'admin' | 'user';\\n  created_at: string;\\n  last_login: string;\\n}\\n```\\n\\n`DbUgateToken` corresponds to `remote_agent_ugate_tokens`:\\n\\n```ts\\ninterface DbUgateToken {\\n  username: string;\\n  token: string;\\n  icafe_space: string | null;\\n  updated_at: string;\\n}\\n```\\n\\n### `findOrCreateUser(input)`\\n\\nLooks up a user by `uuapId`.\\n\\nFor an existing user, it updates:\\n\\n- `last_login`\\n- `real_name`\\n- `email`\\n- `role`\\n\\nFor a new user, it creates a UUID with `randomUUID()` and inserts the complete row.\\n\\nThe returned object reflects the current login data even when the update query does not return a row.\\n\\n```ts\\nconst user = await findOrCreateUser({\\n  uuapId: uuapUser.username,\\n  username: uuapUser.username,\\n  realName: uuapUser.name || null,\\n  email: uuapUser.email || null,\\n});\\n```\\n\\n### Role derivation\\n\\nRoles are derived from email addresses by `deriveRole`.\\n\\nThe admin email set is built once when `db.ts` is loaded:\\n\\n- If `ADMIN_USERNAMES` is set, it is parsed as a comma-separated username list.\\n- Otherwise, `DEV_ADMIN_USERNAMES` is used.\\n- Each username is converted to `@baidu.com`.\\n\\nExample:\\n\\n```text\\nADMIN_USERNAMES=zhangsan,lisi\\n```\\n\\nproduces admin emails:\\n\\n```text\\nzhangsan@baidu.com\\nlisi@baidu.com\\n```\\n\\nAny email not in the set receives the `'user'` role. A later UUAP login can therefore change a user's role as the configured admin list changes.\\n\\nBecause the set is initialized at module load time, changes to `ADMIN_USERNAMES` require process restart.\\n\\n### Lookup functions\\n\\n```ts\\ngetUserById(id): Promise\\ngetUserByUsername(username): Promise\\n```\\n\\nBoth return `null` when no matching row exists.\\n\\nThese helpers are used throughout route authorization and identity resolution, including product spaces, workflows, knowledge APIs, observability, conversations, and server startup.\\n\\n### `ensureTestUser(role)`\\n\\nIdempotently inserts or updates one of two synthetic users:\\n\\n```ts\\nawait ensureTestUser('admin');\\nawait ensureTestUser('user');\\n```\\n\\nThe fixtures use:\\n\\n```text\\n__test_admin__ / admin\\n__test_user__  / user\\n```\\n\\nThe operation uses `ON CONFLICT (uuap_id)` and updates `last_login` when the fixture already exists. It is intended to be called only when test authentication is enabled.\\n\\n---\\n\\n## UGate token persistence\\n\\nThe database helpers store tokens by UUAP username.\\n\\n### `upsertUgateToken(username, token)`\\n\\nInserts a token or updates the existing token and `updated_at` value.\\n\\n```ts\\nawait upsertUgateToken('alice', token);\\n```\\n\\n### `getUgateTokenByUsername(username)`\\n\\nReturns the token string, or `null` when no row exists.\\n\\n### `deleteUgateTokenByUsername(username)`\\n\\nDeletes the token row and returns:\\n\\n- `true` when a row was deleted\\n- `false` when no matching row existed\\n\\n### `listAllUgateTokens()`\\n\\nReturns all stored tokens ordered by username:\\n\\n```ts\\nconst tokens = await listAllUgateTokens();\\n```\\n\\nThe function returns a new array rather than exposing the database result array directly.\\n\\nThis is used by `syncUgateTokensToFiles` to synchronize stored credentials to the application\u2019s external token representation.\\n\\n### `hasUgateToken(username)`\\n\\nChecks whether a token row exists without returning the token value.\\n\\n---\\n\\n## iCafe space helpers\\n\\nThe `remote_agent_ugate_tokens.icafe_space` column stores an iCafe space `prefixCode` associated with a username.\\n\\n```ts\\ngetIcafeSpace(username): Promise\\nsetIcafeSpace(username, space): Promise\\n```\\n\\n`setIcafeSpace` accepts `null` to clear the configured space:\\n\\n```ts\\nawait setIcafeSpace('alice', null);\\n```\\n\\nIt updates only an existing UGate token row. It does not create a row when the username has no stored token.\\n\\n---\\n\\n## Department-member client\\n\\nThe department-member client provides a typed wrapper around:\\n\\n```text\\nGET /deptmember/get_dept_member_data\\n```\\n\\n### `DeptMember`\\n\\n```ts\\ninterface DeptMember {\\n  name: string;\\n  dept: string;\\n  deptChain: string;\\n  employmentStatus: string;\\n  email: string;\\n}\\n```\\n\\n### `HttpDeptMemberClient`\\n\\n```ts\\nimport {\\n  HttpDeptMemberClient,\\n} from '@archon/auth/deptmember/client';\\n\\nconst client = new HttpDeptMemberClient(\\n  'http://deptmember.example.test',\\n  10_000\\n);\\n```\\n\\n`getMembersByEmails(emails)`:\\n\\n1. Trims and lowercases each email.\\n2. Removes empty values.\\n3. Deduplicates the list.\\n4. URL-encodes the comma-separated email query.\\n5. Aborts the request after the configured timeout.\\n6. Validates the response envelope and each member record.\\n7. Maps the upstream `status` property to `employmentStatus`.\\n\\nAn empty normalized email list returns `[]` without making a request.\\n\\nErrors are reported as `DeptMemberClientError` and include categories such as:\\n\\n- Request timeout\\n- Request failure\\n- Non-2xx HTTP status\\n- Invalid JSON\\n- Business error\\n- Invalid response or member record\\n\\nError messages do not echo requested email addresses.\\n\\n### `getDeptMemberClient()`\\n\\nReturns a configured `DeptMemberClient` or `null`.\\n\\nConfiguration:\\n\\n| Variable | Default |\\n|---|---|\\n| `DEPTMEMBER_BASE_URL` | `http://10.175.100.158:8888` |\\n\\nThe factory removes a trailing slash from the base URL. The client is used by personnel-profile synchronization and UI components that resolve department information.\\n\\n---\\n\\n## UIC client\\n\\n`UICClient` wraps UUAP User Information Center APIs using signed JSON POST requests.\\n\\n```ts\\nimport { UICClient, getUICClient } from '@archon/auth/uic/client';\\n```\\n\\n### Configuration\\n\\n`getUICClient()` lazily creates a singleton using:\\n\\n| Variable | Default |\\n|---|---|\\n| `UUAP_HOST` | `https://uuap.baidu.com/uic` |\\n| `UUAP_APP_KEY` | `''` |\\n| `UUAP_SECRET_KEY` | `''` |\\n\\nThe singleton captures environment values when first requested. Tests or callers changing these variables must reset the process/module state or construct `UICClient` directly.\\n\\n### Signing\\n\\nEach request includes:\\n\\n- `appKey`\\n- Unix-second `timestamp`\\n- Random 32-character hexadecimal `sRandom`\\n- `sign`\\n\\nThe signature sorts non-null parameters by key, concatenates their values, appends the secret key, and hashes the result with SHA-256.\\n\\n### User search\\n\\n```ts\\ngetUsersByNameBlurPrefix(namePrefix, returnSize = 10)\\ngetUsersByUsernameBlurPrefix(usernamePrefix, returnSize = 10)\\n```\\n\\nBoth methods:\\n\\n- Require a non-empty prefix.\\n- Require `returnSize` between `1` and `50`.\\n- Return `UicRawUser[]`.\\n- Throw on HTTP or UIC business errors.\\n\\nUsername-prefix search is preferred because name-prefix search can return duplicate names.\\n\\n### Email groups\\n\\n```ts\\ngetEmailGroupsByBlurPrefix(emailGroupPrefix, returnSize = 10)\\n```\\n\\nValidates the prefix and result size in the same way as user search, then returns `UicRawEmailGroup[]`.\\n\\n```ts\\ngetMailGroupMembers(groupEmail)\\n```\\n\\nReturns the usernames in an email group. This method is intentionally fault-tolerant: HTTP errors, malformed responses, and network failures all return `[]` and log a warning.\\n\\n### `search(keyword, limit = 20)`\\n\\nRuns three searches concurrently:\\n\\n- Username prefix\\n- Name prefix\\n- Email-group prefix\\n\\nIt uses `Promise.allSettled`, so one failed branch does not discard successful results.\\n\\nResult behavior:\\n\\n1. Username matches are added first.\\n2. Name matches are appended after deduplicating by username.\\n3. Group matches are appended as `type: 'group'`.\\n4. The final result is truncated to `limit`.\\n5. Each UIC request is capped at a query size of `20`.\\n\\nReturned values use the normalized shape:\\n\\n```ts\\ninterface UicSearchResult {\\n  username: string;\\n  displayName: string;\\n  email: string;\\n  type: 'user' | 'group';\\n}\\n```\\n\\n---\\n\\n## Environment variables\\n\\nAuthentication-related configuration is read from process environment variables.\\n\\n| Variable | Purpose |\\n|---|---|\\n| `JWT_SECRET` | Secret for local JWT signing and verification |\\n| `JWT_EXPIRES_IN` | Local JWT lifetime; defaults to `7d` |\\n| `TEST_AUTH_ENABLED` | Enables synthetic test-user authentication and JWT fallback secret |\\n| `ADMIN_USERNAMES` | Comma-separated UUAP usernames treated as admins |\\n| `UUAP_BASE_URL` | UUAP endpoint base URL for middleware validation |\\n| `UUAP_HOST` | UIC endpoint base URL |\\n| `UUAP_APP_KEY` | UUAP/UIC application key |\\n| `UUAP_SECRET_KEY` | UUAP/UIC signing and token-verification secret |\\n| `UUAP_P_TOKEN_NAME` | P_TOKEN cookie name; defaults to `UUAP_P_TOKEN` |\\n| `DEPTMEMBER_BASE_URL` | Department-member service base URL |\\n| `AUTH_DEBUG_HEADERS` | Set to `false` to disable authentication header debug logging |\\n\\n`UUAP_APP_KEY` and `UUAP_SECRET_KEY` are required when validating UGate tokens. The middleware throws a configuration error if either is absent.\\n\\n### Sensitive logging\\n\\n`logAuthDebugHeaders` logs all request headers by default unless `AUTH_DEBUG_HEADERS=false`. This can expose credentials in logs and should be disabled in production:\\n\\n```text\\nAUTH_DEBUG_HEADERS=false\\n```\\n\\nThe middleware also logs diagnostic UGate claim metadata. It does not log the raw token value, but claim-derived metadata should still be treated as sensitive.\\n\\n---\\n\\n## Error handling conventions\\n\\n| Error | Meaning |\\n|---|---|\\n| `JwtInvalidError` | Local or UGate JWT is invalid, expired, or structurally unsuitable |\\n| `UuapTicketError` | CAS ticket exchange failed |\\n| `UuapSessionError` | UUAP session validation failed |\\n| `DeptMemberClientError` | Department-member request or response was invalid |\\n| Generic UIC `Error` | UIC HTTP or business-level failure |\\n\\nThe middleware maps authentication failures to HTTP responses:\\n\\n- `401 Unauthorized`: missing or invalid credentials\\n- `403 Forbidden`: valid credentials for a non-admin user on an admin route\\n\\nUnexpected database, configuration, or infrastructure errors are generally allowed to propagate rather than being silently converted to unauthorized responses.\\n\\n---\\n\\n## Testing and contribution notes\\n\\nThe package uses Bun tests:\\n\\n```bash\\nbun test src/\\nbun x tsc --noEmit\\n```\\n\\nDatabase tests mock `@archon/core/db/connection` before importing `db.ts` or `middleware.ts`. This ordering is required because Bun\u2019s `mock.module()` is process-global and module imports capture the mocked connection.\\n\\nHTTP clients accept injectable or replaceable fetch implementations in tests:\\n\\n- `HttpDeptMemberClient` accepts `fetchFn` in its constructor.\\n- `UuapClient` and `UICClient` use `globalThis.fetch`, which tests replace temporarily.\\n\\nWhen adding authentication behavior:\\n\\n1. Preserve the distinction between local JWTs and UGate tokens.\\n2. Require both `pToken` and `sToken` for UGate validation.\\n3. Keep local JWT fallback limited to `Authorization: Bearer ...`.\\n4. Set both `userId` and `userRole` consistently.\\n5. Use `findOrCreateUser` for UUAP-backed identities so login timestamps and roles remain synchronized.\\n6. Avoid logging raw tokens or sensitive request headers.\\n7. Add tests for missing credentials, invalid signatures, provider failures, and fallback behavior.\",\"other-auto-heal-txt\":\"# Other \u2014 auto-heal.txt\\n\\n# `auto-heal.txt`\\n\\n## Purpose\\n\\n`auto-heal.txt` is a text-only module containing the literal text:\\n\\n```text\\nauto-heal patch\\n```\\n\\nIt does not implement auto-healing behavior, define configuration, or provide executable logic.\\n\\n## Contents\\n\\nThe file contains a single line:\\n\\n```text\\nauto-heal patch\\n```\\n\\nNo additional sections, metadata, commands, or structured data are present.\\n\\n## Execution and API Surface\\n\\nThis module has no executable code and exposes no functions, classes, or other callable APIs.\\n\\n- **Internal calls:** None\\n- **Outgoing calls:** None\\n- **Incoming calls:** None\\n- **Execution flows:** None detected\\n\\nThe file is therefore inert unless another part of the codebase explicitly reads it as a text resource.\\n\\n## Integration\\n\\nNo references or integration points are defined within the module. In particular, the file does not:\\n\\n- Register an auto-healing mechanism\\n- Apply a patch\\n- Invoke scripts or commands\\n- Configure a service\\n- Import or depend on other modules\\n\\nAny behavior associated with the phrase `auto-heal patch` would need to be implemented by external tooling or code that discovers and interprets this file. That behavior is not specified by the module itself.\\n\\n## Contribution Notes\\n\\nChanges to this file alter its text content only. If the file is intended to act as a marker or sentinel, consumers should be updated in tandem with any changes to the expected contents.\",\"other-bunfig-coverage-toml\":\"# Other \u2014 bunfig.coverage.toml\\n\\n# `bunfig.coverage.toml`\\n\\n`bunfig.coverage.toml` configures Bun\u2019s test runner for repository-wide test execution with code coverage enabled. It establishes the test root, loads the shared test setup module before tests run, and writes coverage reports in text and LCOV formats.\\n\\n## Configuration\\n\\n```toml\\n[test]\\nroot = \\\"./packages\\\"\\npreload = [\\\"./packages/core/src/test/setup.ts\\\"]\\ncoverage = true\\ncoverageDir = \\\"coverage\\\"\\ncoverageReporter = [\\\"text\\\", \\\"lcov\\\"]\\n```\\n\\nAll settings are contained in Bun\u2019s `[test]` configuration section.\\n\\n## Test root\\n\\n```toml\\nroot = \\\"./packages\\\"\\n```\\n\\nThe test runner treats `./packages` as the root directory for test discovery and execution. This allows tests located across the repository\u2019s packages to be run through a single configuration.\\n\\nThe path is relative to the location from which Bun resolves this configuration.\\n\\n## Shared test setup\\n\\n```toml\\npreload = [\\\"./packages/core/src/test/setup.ts\\\"]\\n```\\n\\nBun loads `./packages/core/src/test/setup.ts` before executing the test files.\\n\\nThe preload module is the repository-wide initialization point for test behavior. It can establish shared globals, configure test-specific environment state, install mocks, or perform other setup required by tests in multiple packages. Because it is configured centrally, individual test files do not need to import this setup module manually.\\n\\nChanges to the preload file can affect every test run that uses this configuration.\\n\\n## Coverage collection\\n\\n```toml\\ncoverage = true\\n```\\n\\nCoverage instrumentation and collection are enabled for test execution. Running Bun tests with this configuration produces coverage data in addition to normal test results.\\n\\nCoverage is generated from the code exercised by the tests discovered under the configured `root`.\\n\\n## Coverage output directory\\n\\n```toml\\ncoverageDir = \\\"coverage\\\"\\n```\\n\\nCoverage artifacts are written to the `coverage` directory. The directory name is intentionally shared by the configured reporters, so text output and LCOV data are generated as part of the same coverage run.\\n\\nThe directory may need to be excluded from source control if the repository does not already ignore generated coverage output.\\n\\n## Coverage reporters\\n\\n```toml\\ncoverageReporter = [\\\"text\\\", \\\"lcov\\\"]\\n```\\n\\nTwo report formats are enabled:\\n\\n- `text` \u2014 provides a human-readable coverage summary in the test command\u2019s output.\\n- `lcov` \u2014 produces machine-readable LCOV data suitable for coverage tools, IDE integrations, and CI reporting systems.\\n\\nUsing both formats supports local inspection through the terminal and automated processing through external tooling.\\n\\n## Relationship to the codebase\\n\\nThis module is configuration-only. It does not define functions, classes, or runtime logic, and it has no internal or outgoing calls.\\n\\nIts connection to the rest of the codebase is through Bun\u2019s test runner:\\n\\n1. Bun reads the `[test]` settings.\\n2. Tests are discovered relative to `./packages`.\\n3. `packages/core/src/test/setup.ts` is preloaded.\\n4. Tests execute with coverage enabled.\\n5. Text and LCOV reports are written under `coverage`.\\n\\nThe preload file is the only source-code module referenced directly by this configuration. The rest of the relationship is indirect: package tests are affected by the test root, and coverage tooling consumes the generated reports.\\n\\n## Typical usage\\n\\nUse this configuration when running the repository\u2019s Bun test suite with coverage enabled. The exact command depends on how the repository invokes Bun and selects `bunfig.coverage.toml`; once loaded, the settings apply automatically to the test run.\\n\\nA successful run should provide:\\n\\n- Test discovery across the `packages` directory\\n- Shared initialization from `packages/core/src/test/setup.ts`\\n- A terminal coverage summary\\n- LCOV coverage output in `coverage`\",\"other-bunfig-toml\":\"# Other \u2014 bunfig.toml\\n\\n# `bunfig.toml`\\n\\nRepository-level Bun configuration for the Remote Agentic Coding Platform.\\n\\nThis file configures how Bun discovers and runs tests, initializes the test environment, and writes coverage reports. It does not contain application logic or call other modules directly; Bun reads it automatically when commands such as `bun test` run from the repository context.\\n\\n## Test Configuration\\n\\n```toml\\n[test]\\nroot = \\\"./packages\\\"\\npreload = [\\\"./packages/core/src/test/setup.ts\\\", \\\"allure-bun/setup\\\"]\\ncoverage = true\\ncoverageDir = \\\"coverage\\\"\\ncoverageReporter = [\\\"text\\\", \\\"lcov\\\"]\\n```\\n\\nThe `[test]` table applies these settings to Bun's test runner.\\n\\n## Test Discovery Root\\n\\n```toml\\nroot = \\\"./packages\\\"\\n```\\n\\nBun searches for tests only beneath the repository's `packages/` directory.\\n\\nThis restriction is intentional: the repository may contain workspace or worktree directories that include copied test files. Without a constrained root, `bun test` could discover and execute duplicate tests from those locations.\\n\\n### Implications for contributors\\n\\n- Place package tests under `packages/` so Bun can discover them.\\n- Tests stored outside `packages/` are not found by the default test configuration.\\n- Do not broaden `root` without checking workspace and worktree layouts, since duplicate discovery is the reason for this setting.\\n\\n## Test Preloads\\n\\n```toml\\npreload = [\\n  \\\"./packages/core/src/test/setup.ts\\\",\\n  \\\"allure-bun/setup\\\"\\n]\\n```\\n\\nBun loads each preload before executing discovered test files.\\n\\n### `./packages/core/src/test/setup.ts`\\n\\nThis repository-owned setup module lives in `@archon/core`. It provides shared test initialization for the monorepo.\\n\\nBecause it is configured as a preload rather than imported by individual test files, every test run receives the same baseline environment. Shared test behavior should generally be configured here when it must apply consistently across packages.\\n\\n### `allure-bun/setup`\\n\\nThis preload is supplied by the `allure-bun` package. It initializes Allure integration before tests execute, allowing test results and related metadata to be captured for reporting.\\n\\nKeep this entry available whenever Allure-compatible test output is required. Removing it may allow tests to run while preventing the expected Allure setup from occurring.\\n\\n## Coverage Reporting\\n\\n```toml\\ncoverage = true\\ncoverageDir = \\\"coverage\\\"\\ncoverageReporter = [\\\"text\\\", \\\"lcov\\\"]\\n```\\n\\nCoverage collection is enabled by default for Bun test runs.\\n\\n| Setting | Value | Effect |\\n|---|---|---|\\n| `coverage` | `true` | Collects coverage while tests execute. |\\n| `coverageDir` | `\\\"coverage\\\"` | Writes generated coverage artifacts to the repository-level `coverage/` directory. |\\n| `coverageReporter` | `[\\\"text\\\", \\\"lcov\\\"]` | Produces terminal-readable coverage output and LCOV data. |\\n\\nThe two reporters serve different consumers:\\n\\n- **`text`** provides a summary in test command output for local development and CI logs.\\n- **`lcov`** creates machine-readable coverage data for coverage tooling, CI integrations, and report processors.\\n\\nGenerated files in `coverage/` are test artifacts rather than source files and should normally remain untracked unless repository policy explicitly requires otherwise.\\n\\n## Runtime Sequence\\n\\n```mermaid\\nflowchart TD\\n    A[\\\"bun test\\\"] --&gt; B[\\\"Read bunfig.toml\\\"]\\n    B --&gt; C[\\\"Discover tests under packages/\\\"]\\n    B --&gt; D[\\\"Preload core test setup\\\"]\\n    B --&gt; E[\\\"Preload allure-bun/setup\\\"]\\n    C --&gt; F[\\\"Execute tests\\\"]\\n    D --&gt; F\\n    E --&gt; F\\n    F --&gt; G[\\\"Write text and LCOV coverage\\\"]\\n```\\n\\nBun reads the configuration, loads the preloads, discovers tests under `packages/`, executes them, and emits coverage output to `coverage/`.\\n\\n## Maintenance Guidelines\\n\\nWhen modifying this file:\\n\\n- Keep `root = \\\"./packages\\\"` unless the test layout changes and duplicate discovery has been addressed.\\n- Use preload entries only for initialization that must happen before every test file.\\n- Ensure local preload paths remain valid after moving shared test infrastructure.\\n- Keep coverage reporters aligned with CI and reporting-tool expectations.\\n- Validate changes with `bun test`, particularly after changing preload modules or discovery settings.\",\"other-caddyfile-example\":\"# Other \u2014 Caddyfile.example\\n\\n# Caddyfile.example\\n\\n`Caddyfile.example` is a Caddy reverse-proxy configuration template for Archon deployments. It terminates HTTPS, routes incoming requests to the Archon application container, optionally protects private routes with authentication, and applies common security and compression settings.\\n\\nThe template is intended to be copied or mounted as the active Caddy configuration and parameterized through environment variables.\\n\\n## Configuration Overview\\n\\nThe site address is configured with:\\n\\n```caddy\\n{$DOMAIN} {\\n\\t...\\n}\\n```\\n\\nSet `DOMAIN` in `.env` to the public hostname, for example:\\n\\n```dotenv\\nDOMAIN=archon.example.com\\n```\\n\\nFor local testing, replace `{$DOMAIN}` with `:80` or `localhost`.\\n\\nCaddy automatically manages TLS certificates through Let's Encrypt when `DOMAIN` resolves to the deployment and the required ports are reachable.\\n\\nThe application is reached through the Docker Compose service named `app`:\\n\\n```caddy\\nreverse_proxy app:{$PORT:3000}\\n```\\n\\n`PORT` defaults to `3000` when it is not set.\\n\\n## Request Routing\\n\\nRoutes are evaluated in the order defined in the site block.\\n\\n```mermaid\\nflowchart TD\\n    Request[Incoming request] --&gt; Public{Webhook or health path?}\\n    Public --&gt;|Yes| App[app:PORT]\\n    Public --&gt;|No| Auth{Authentication configuration}\\n    Auth --&gt;|Form auth| AuthService[auth-service:AUTH_SERVICE_PORT]\\n    Auth --&gt;|Basic auth| Basic[Basic authentication]\\n    Auth --&gt;|None| App\\n    AuthService --&gt; App\\n    App --&gt; Stream{API stream path?}\\n    Stream --&gt;|Yes| Flush[Streaming proxy]\\n    Stream --&gt;|No| Normal[Standard proxy]\\n```\\n\\n### Public paths\\n\\nThe following routes always bypass authentication:\\n\\n```caddy\\nhandle /webhooks/* {\\n\\treverse_proxy app:{$PORT:3000}\\n}\\n\\nhandle /api/health {\\n\\treverse_proxy app:{$PORT:3000}\\n}\\n```\\n\\nThese routes are intended for external webhook providers and health checks. They are declared before the authentication configuration so that authentication does not prevent delivery or monitoring.\\n\\n- `/webhooks/*` matches all webhook endpoints.\\n- `/api/health` matches the application health endpoint.\\n\\n## Authentication Options\\n\\nThe file documents three mutually exclusive modes:\\n\\n1. Form-based authentication\\n2. Basic authentication\\n3. No authentication\\n\\nThe default active configuration is **no authentication**. Enable only one authentication method at a time.\\n\\n### Option A: Form-based authentication\\n\\nThe form-authentication block is commented out by default. It requires the `auth-service` container and the `auth` Docker Compose profile:\\n\\n```sh\\ndocker compose --profile cloud --profile auth up -d\\n```\\n\\nBefore enabling it, configure:\\n\\n- `AUTH_USERNAME`\\n- `AUTH_PASSWORD_HASH`\\n- `COOKIE_SECRET`\\n\\nThe login and logout routes are proxied to the authentication service:\\n\\n```caddy\\nhandle /login {\\n\\treverse_proxy auth-service:{$AUTH_SERVICE_PORT:9000}\\n}\\n\\nhandle /logout {\\n\\treverse_proxy auth-service:{$AUTH_SERVICE_PORT:9000}\\n}\\n```\\n\\nProtected requests use Caddy's `forward_auth` directive:\\n\\n```caddy\\nforward_auth auth-service:{$AUTH_SERVICE_PORT:9000} {\\n\\turi /verify\\n\\tcopy_headers X-Auth-User\\n}\\n```\\n\\nCaddy asks `auth-service` to verify the request at `/verify`. On successful verification, the `X-Auth-User` response header is copied into the proxied request before forwarding it to `app`.\\n\\nTo activate this mode:\\n\\n1. Uncomment the form-authentication block.\\n2. Comment out the active no-auth `handle` block.\\n3. Ensure the `auth` Compose profile is running.\\n4. Set the authentication variables in `.env`.\\n\\nThe form-auth block has dedicated handling for server-sent events (SSE), described below.\\n\\n### Option B: Basic authentication\\n\\nBasic authentication does not require an additional container. The template defines a matcher for all routes except the public paths:\\n\\n```caddy\\n@protected not path /webhooks/* /api/health\\n```\\n\\nThe `CADDY_BASIC_AUTH` environment variable is then expanded into the configuration:\\n\\n```caddy\\n{$CADDY_BASIC_AUTH:}\\n```\\n\\nA typical value is:\\n\\n```dotenv\\nCADDY_BASIC_AUTH=basicauth @protected { admin $2a$14$ }\\n```\\n\\nGenerate a password hash with:\\n\\n```sh\\ndocker run caddy caddy hash-password --plaintext 'YOUR_PASSWORD'\\n```\\n\\nBecause the matcher excludes `/webhooks/*` and `/api/health`, those endpoints remain publicly accessible while all other routes require Basic authentication.\\n\\nThe Basic authentication configuration is active in the template, but it has no effect when `CADDY_BASIC_AUTH` is unset because the environment expansion defaults to an empty value.\\n\\n### No authentication\\n\\nThe no-auth handler is active by default:\\n\\n```caddy\\nhandle {\\n\\t@sse path /api/stream/*\\n\\treverse_proxy @sse app:{$PORT:3000} {\\n\\t\\tflush_interval -1\\n\\t}\\n\\treverse_proxy app:{$PORT:3000}\\n}\\n```\\n\\nTo use form authentication, comment out this entire block after enabling the form-auth block. When no authentication is required, all non-public requests are sent directly to `app`.\\n\\n## Server-Sent Events\\n\\nThe application stream endpoint is matched separately:\\n\\n```caddy\\n@sse path /api/stream/*\\nreverse_proxy @sse app:{$PORT:3000} {\\n\\tflush_interval -1\\n}\\n```\\n\\n`flush_interval -1` disables normal response buffering for matching requests. This allows SSE events to reach clients as soon as the application emits them instead of waiting for a larger response buffer or periodic flush.\\n\\nThe same behavior is present in both:\\n\\n- The default no-auth handler.\\n- The form-authentication handler.\\n\\nThis keeps streaming behavior consistent regardless of the selected authentication mode.\\n\\n## Upstream Service Configuration\\n\\nThe template uses Docker Compose service names for internal routing:\\n\\n| Upstream | Purpose | Default port |\\n|---|---|---:|\\n| `app` | Archon application | `3000` |\\n| `auth-service` | Optional form-authentication service | `9000` |\\n\\nCaddy resolves these service names on the Docker network. The service names must therefore match the corresponding Docker Compose services.\\n\\nEnvironment substitutions use Caddy's placeholder syntax with defaults:\\n\\n```caddy\\n{$PORT:3000}\\n{$AUTH_SERVICE_PORT:9000}\\n{$CADDY_BASIC_AUTH:}\\n```\\n\\nThis means:\\n\\n- `PORT` uses `3000` when unset.\\n- `AUTH_SERVICE_PORT` uses `9000` when unset.\\n- `CADDY_BASIC_AUTH` uses an empty value when unset.\\n\\n## Security Headers\\n\\nThe global `header` block adds response security headers:\\n\\n```caddy\\nheader {\\n\\tX-Content-Type-Options nosniff\\n\\tX-Frame-Options DENY\\n\\tReferrer-Policy strict-origin-when-cross-origin\\n\\tStrict-Transport-Security \\\"max-age=31536000; includeSubDomains\\\"\\n\\t-Server\\n}\\n```\\n\\nThe headers provide the following protections:\\n\\n- `X-Content-Type-Options nosniff` prevents browsers from MIME-sniffing responses.\\n- `X-Frame-Options DENY` prevents the application from being embedded in frames.\\n- `Referrer-Policy strict-origin-when-cross-origin` limits referrer information sent to other origins.\\n- `Strict-Transport-Security` instructs browsers to use HTTPS for the site and its subdomains for one year.\\n- `-Server` removes Caddy's `Server` response header.\\n\\nBecause HSTS includes `includeSubDomains`, use this configuration only when all relevant subdomains are intended to support HTTPS.\\n\\n## Compression\\n\\nResponses are compressed with:\\n\\n```caddy\\nencode gzip zstd\\n```\\n\\nCaddy negotiates the supported encoding with the client. Compression reduces response size for normal HTTP traffic. The SSE route has separate proxy flushing behavior so that compression and proxy buffering do not unnecessarily delay stream events.\\n\\n## Access Logging\\n\\nCaddy writes access logs to standard output using the console format:\\n\\n```caddy\\nlog {\\n\\toutput stdout\\n\\tformat console\\n}\\n```\\n\\nThis is suitable for Docker deployments, where container logs can be collected by Docker or the host's logging system.\\n\\n## Relationship to the Rest of the Deployment\\n\\nThis file does not contain application logic or Caddy extensions. It has no internal function calls or code-level dependencies. Its integration points are deployment services and environment configuration:\\n\\n- The `app` Docker Compose service receives normal application and stream traffic.\\n- The optional `auth-service` Docker Compose service handles form authentication.\\n- `.env` supplies the domain, upstream ports, and optional Basic authentication rule.\\n- `docs/docker.md` provides password-hash generation guidance for form authentication.\\n- Docker Compose profiles control whether the cloud and authentication services are started.\\n\\nWhen modifying this file, keep the following contracts intact:\\n\\n1. Preserve unauthenticated access to `/webhooks/*` if external webhook delivery depends on it.\\n2. Preserve unauthenticated access to `/api/health` for health monitoring.\\n3. Keep `flush_interval -1` for `/api/stream/*` unless the application no longer uses SSE.\\n4. Ensure the selected authentication block matches the services and environment variables enabled in Docker Compose.\\n5. Keep upstream service names aligned with the Compose service definitions.\",\"other-ci-yml\":\"# Other \u2014 ci.yml\\n\\n# Other \u2014 `ci.yml`\\n\\n## Purpose\\n\\n`ci.yml` defines the CI configuration for the project. It selects the default build profile, specifies the container image used by build agents, enables task reuse, invokes the project build script, and publishes the generated `output/` directory as a release artifact.\\n\\nThe file also declares an image registration profile for making the CI image available to the build system.\\n\\n## Global configuration\\n\\n```yaml\\nGlobal:\\n  version: 2.0\\n  group_email: huabinhong@baidu.com\\n```\\n\\n| Field | Description |\\n|---|---|\\n| `version` | CI configuration format version, set to `2.0`. |\\n| `group_email` | Global contact or notification address for the CI configuration. |\\n\\nThe global email is specified as `group_email`. The `image_register` profile uses the profile-level key `group_mail`, which is distinct from the global key and should be preserved according to the CI platform\u2019s schema.\\n\\n## Default profile\\n\\n```yaml\\nDefault:\\n  profile: [build]\\n```\\n\\nThe `build` profile is the default profile used when no profile is explicitly selected. This makes the standard CI operation an agent-based build using the configured container image and build command.\\n\\n## Profiles\\n\\n### `image_register`\\n\\n```yaml\\n- profile:\\n  name: image_register\\n  mode: IMAGE_REGISTER\\n  group_mail: huabinhong@baidu.com\\n  images:\\n    - image: iregistry.baidu-int.com/tianniu/doarchon_ci:1778147784207\\n```\\n\\nThe `image_register` profile registers the CI container image:\\n\\n```text\\niregistry.baidu-int.com/tianniu/doarchon_ci:1778147784207\\n```\\n\\nKey properties:\\n\\n- `name: image_register` identifies the profile.\\n- `mode: IMAGE_REGISTER` indicates that the profile performs image registration rather than a source build.\\n- `group_mail` identifies the profile-specific contact address.\\n- `images` contains the image registry entry to register.\\n\\nThis profile is not selected by default. It must be invoked explicitly by the CI system when image registration is required.\\n\\n### `build`\\n\\n```yaml\\n- profile:\\n  name: build\\n  mode: AGENT\\n  environment:\\n    image: iregistry.baidu-int.com/tianniu/doarchon_ci:1778147784207\\n  check:\\n    - reuse: TASK\\n      enable: true\\n  build:\\n    command: sh scripts/build.sh\\n  artifacts:\\n    release: true\\n    paths:\\n      - output/\\n```\\n\\nThe `build` profile is the primary project build configuration.\\n\\n#### Execution environment\\n\\n```yaml\\nenvironment:\\n  image: iregistry.baidu-int.com/tianniu/doarchon_ci:1778147784207\\n```\\n\\nThe CI agent runs in the project-specific container image registered by the `image_register` profile. Keeping the same image reference in both profiles ensures that the image being registered is also the image used for builds.\\n\\n#### Task reuse\\n\\n```yaml\\ncheck:\\n  - reuse: TASK\\n    enable: true\\n```\\n\\nTask reuse is enabled for the build profile. The CI system may reuse eligible task results instead of repeating work, depending on its task-cache and invalidation rules.\\n\\n#### Build command\\n\\n```yaml\\nbuild:\\n  command: sh scripts/build.sh\\n```\\n\\nThe build delegates to `scripts/build.sh`. This YAML file does not define the build steps themselves; contributors who need to change compilation, testing, packaging, or other build behavior should inspect or modify that script.\\n\\nThe command is executed through `sh`, so the script must be compatible with the shell environment provided by the configured CI image.\\n\\n#### Release artifacts\\n\\n```yaml\\nartifacts:\\n  release: true\\n  paths:\\n    - output/\\n```\\n\\nThe build marks release artifact publication as enabled and publishes the `output/` directory.\\n\\nThe build process must therefore create the expected deliverables under:\\n\\n```text\\noutput/\\n```\\n\\nFiles outside this directory are not listed as release artifacts by this configuration.\\n\\n## Build flow\\n\\n```mermaid\\nflowchart TD\\n    A[CI selects default profile] --&gt; B[Use build profile]\\n    B --&gt; C[Start AGENT with CI image]\\n    C --&gt; D[Run sh scripts/build.sh]\\n    D --&gt; E[Publish output/ as release artifacts]\\n```\\n\\n## Relationship to the codebase\\n\\n`ci.yml` has no internal function or class calls and does not directly import or invoke application modules. Its primary connection to the repository is the build entry point:\\n\\n```text\\nscripts/build.sh\\n```\\n\\nThat script is the executable boundary between the CI platform and the rest of the codebase. Any source compilation, tests, packaging, or artifact generation performed by CI is controlled by the script and the commands it calls.\\n\\nThe configuration also establishes an external dependency on the Baidu internal registry image:\\n\\n```text\\niregistry.baidu-int.com/tianniu/doarchon_ci:1778147784207\\n```\\n\\nBoth the image registration and build execution profiles reference this image. Updating the build environment requires updating the image reference consistently in both locations.\\n\\n## Contributor guidance\\n\\n- Keep the `build` profile as the default unless the repository\u2019s standard CI entry point changes.\\n- When changing build behavior, inspect `scripts/build.sh` before modifying this file.\\n- Ensure release outputs continue to be written under `output/`.\\n- Update the image reference in both `image_register.images[].image` and `build.environment.image` when moving to a new CI image.\\n- Treat `image_register` as an explicit operational profile; it is not automatically run by the default build.\\n- Preserve the CI schema keys and casing, including the distinction between `group_email` and `group_mail`.\",\"other-claude-md\":\"# Other \u2014 CLAUDE.md\\n\\n# Other \u2014 `CLAUDE.md`\\n\\n## Purpose\\n\\n`CLAUDE.md` is the repository-level development guide for the remote intelligent programming platform. It provides conventions and operational rules for contributors and AI coding assistants working in the codebase.\\n\\nThe file does not define runtime code, exported functions, classes, or an execution flow. Instead, it establishes:\\n\\n- The project\u2019s architecture and technology baseline\\n- TypeScript, schema, API, database, and logging conventions\\n- Git and release procedures\\n- Development, testing, validation, and packaging commands\\n- Boundaries for extending platform adapters, agents, databases, and workflows\\n- GitNexus requirements for code exploration, impact analysis, and safe refactoring\\n\\nFor detailed architecture and command/API references, it links to:\\n\\n- [`docs/architecture.md`](docs/architecture.md)\\n- [`docs/cli-reference.md`](docs/cli-reference.md)\\n\\n## Project Context\\n\\nThe project is a single-user remote programming platform. It allows users to control AI programming assistants remotely through:\\n\\n- Slack\\n- Telegram\\n- GitHub\\n\\nThe platform uses:\\n\\n- Bun\\n- TypeScript\\n- SQLite by default\\n- PostgreSQL as an alternative\\n- Claude Code SDK\\n- Codex SDK\\n\\nThe codebase is organized around platform-independent session behavior and platform-specific adapters. Platform integrations implement `IPlatformAdapter`, while other major extension points include:\\n\\n- `IAgentProvider`\\n- `IDatabase`\\n- `IWorkflowStore`\\n\\nThe project intentionally avoids multi-tenant complexity and favors narrow, explicit interfaces.\\n\\n## Design Principles\\n\\n### Single-user scope\\n\\nThe system is designed as a single-person development tool. New features should not introduce multi-tenant abstractions, permissions models, or configuration complexity without a concrete use case.\\n\\n### Platform independence\\n\\nShared session behavior should remain independent of Slack, Telegram, or GitHub. Platform-specific behavior belongs in implementations of `IPlatformAdapter`.\\n\\n### Type safety\\n\\nTypeScript is strict throughout the repository:\\n\\n- Every function must have complete type annotations.\\n- `any` is prohibited.\\n- Major abstractions require interfaces.\\n- Existing SDK types should be reused instead of duplicated.\\n\\nWhen working with the Claude Agent SDK, import its types directly:\\n\\n```typescript\\nimport { query, type Options } from '@anthropic-ai/claude-agent-sdk';\\n\\nconst options: Options = {\\n  cwd,\\n  permissionMode: 'bypassPermissions',\\n};\\n```\\n\\nDo not create parallel local interfaces or bypass type checking with casts such as `as any`.\\n\\n### Simple, local control flow\\n\\nThe project follows KISS and YAGNI:\\n\\n- Prefer direct control flow.\\n- Keep error paths visible and local.\\n- Do not add configuration keys, interface methods, or feature flags without a concrete requirement.\\n- Unsupported behavior should fail explicitly instead of being silently or partially implemented.\\n- Extract shared utilities only after a stable pattern has appeared at least three times.\\n\\nModules should follow SRP and ISP. Extend behavior through existing narrow interfaces rather than adding unrelated methods to them.\\n\\n### Explicit failure\\n\\nErrors should be detected early and reported clearly:\\n\\n- Do not silently swallow exceptions.\\n- Intentional fallback behavior must be documented with a comment.\\n- Otherwise, throw an explicit error.\\n- Database update helpers such as `updateX` must throw when no row matches.\\n- Database updates should verify `rowCount`.\\n\\nA process must not independently change lifecycle state across a process boundary when it cannot distinguish \u201cstill running elsewhere\u201d from \u201corphaned.\u201d In particular, timers must not guess that work should be marked failed or cancelled. The relevant reference is `packages/cli/src/cli.ts:256-258` and issue `#1216`.\\n\\n### Determinism and reversibility\\n\\nChanges should be:\\n\\n- Deterministic and reproducible\\n- Small in scope\\n- Easy to validate\\n- Easy to roll back\\n\\nTests must be deterministic, and `bun run validate` must correspond directly to the checks expected by CI.\\n\\n## Zod and OpenAPI Conventions\\n\\nSchemas use `z` imported from `@hono/zod-openapi`, not directly from `zod`.\\n\\n```typescript\\nimport { z } from '@hono/zod-openapi';\\n```\\n\\n### Naming and type inference\\n\\nSchema names use camelCase with a descriptive suffix, such as:\\n\\n```typescript\\nworkflowRunSchema\\n```\\n\\nTypes must always be derived from schemas:\\n\\n```typescript\\ntype WorkflowRun = z.infer;\\n```\\n\\nDo not write a separate interface that mirrors a Zod schema.\\n\\n### Schema locations\\n\\nUse the following locations:\\n\\n- API route schemas: `packages/server/src/routes/schemas/`\\n  - Keep schemas grouped by domain.\\n- Workflow engine schemas: `packages/workflows/src/schemas/`\\n  - Keep schemas grouped by concern.\\n  - Re-export all schemas from `index.ts`.\\n\\n### OpenAPI routes\\n\\nAll new or modified API routes must use:\\n\\n```typescript\\nregisterOpenApiRoute(createRoute({...}), handler);\\n```\\n\\nThis keeps route definitions, validation, and OpenAPI metadata consistent.\\n\\n### Derived constants\\n\\n`TRIGGER_RULES` and `WORKFLOW_HOOK_EVENTS` must be derived from the corresponding schema `.options` values. They must not be duplicated as ordinary arrays, which could drift from schema validation.\\n\\n### Workflow node validation\\n\\n`loader.ts` validates workflow nodes using:\\n\\n```typescript\\ndagNodeSchema.safeParse()\\n```\\n\\nNew workflow loading behavior should preserve this validation boundary.\\n\\n## Git and Release Workflow\\n\\n### Branches\\n\\n- `main` is the release branch and must never receive direct commits.\\n- `dev` is the working branch.\\n\\nAll changes should go through pull requests.\\n\\n### Pull requests\\n\\nEvery pull request must use `.github/PULL_REQUEST_TEMPLATE.md`.\\n\\nWhen using `gh pr create`, explicitly copy the template content into the PR body. Link the associated issue with:\\n\\n```text\\nCloses #\\n```\\n\\n### Releases\\n\\nUse the `/release` skill:\\n\\n- `/release` for a patch release\\n- `/release minor` for a minor release\\n- `/release major` for a major release\\n\\nRelease metadata is maintained in:\\n\\n- `CHANGELOG.md`, using Keep a Changelog format\\n- The version field in the root `package.json`\\n\\n### Git operations\\n\\nUse functions from `@archon/git` for Git operations. If direct process execution is necessary, use `execFileAsync`, not `exec`.\\n\\nNever run:\\n\\n```bash\\ngit clean -fd\\n```\\n\\nUse the safer alternative:\\n\\n```bash\\ngit checkout .\\n```\\n\\n## Development Commands\\n\\n### Start development services\\n\\n```bash\\nbun run dev\\n```\\n\\nStarts the server and Web UI with hot reload.\\n\\n```bash\\nbun run dev:server\\n```\\n\\nStarts only the backend on port `3090`.\\n\\n```bash\\nbun run dev:web\\n```\\n\\nStarts only the frontend on port `5173`.\\n\\n### Generate frontend API types\\n\\nThe server must be running on port `3090`:\\n\\n```bash\\nbun --filter @archon/web generate:types\\n```\\n\\n### Tests\\n\\nRun all package tests in isolated processes:\\n\\n```bash\\nbun run test\\n```\\n\\nRun a package\u2019s tests in watch mode:\\n\\n```bash\\nbun test --watch\\n```\\n\\nDo not run `bun test` from the repository root. Use `bun run test`, which runs each package in its own process.\\n\\n#### `mock.module()` isolation\\n\\nBun\u2019s `mock.module()` is process-global and irreversible. `mock.restore()` does not undo it; see [oven-sh/bun#7823](https://github.com/oven-sh/bun/issues/7823).\\n\\nTest guidance:\\n\\n- Use `spyOn()` when mocking modules that are also mocked by other files.\\n- Restore spies with `spy.mockRestore()`.\\n- Any new test file using `mock.module()` must run in a separate `bun test` invocation.\\n\\nThis prevents mocks from leaking between tests and causing order-dependent failures.\\n\\n### Type checking, linting, and formatting\\n\\n```bash\\nbun run type-check\\nbun run lint &amp;&amp; bun run lint:fix\\nbun run format &amp;&amp; bun run format:check\\n```\\n\\nESLint runs with `--max-warnings 0` in CI. Fix warnings and errors rather than bypassing them with `eslint-disable`.\\n\\nAn exception is permitted for incorrect external SDK types, but the code must include a comment explaining why the exception is necessary.\\n\\n### Pre-PR validation\\n\\nRun:\\n\\n```bash\\nbun run validate\\n```\\n\\nValidation covers:\\n\\n1. `check:bundled`\\n2. `check:bundled-skill`\\n3. `type-check`\\n4. `lint`\\n5. `format`\\n6. Tests\\n\\nAll six checks must pass for CI to succeed.\\n\\n## Database and Migration Rules\\n\\nSQLite is the default database and requires no configuration:\\n\\n```text\\n~/.archon/archon.db\\n```\\n\\nPostgreSQL is enabled by setting `DATABASE_URL` in `.env`. Apply migrations with:\\n\\n```bash\\npsql $DATABASE_URL &lt; migrations/000_combined.sql\\n```\\n\\n### Immutable migrations\\n\\nOnce committed, migration files must never be edited:\\n\\n- `000_combined.sql`\\n- Any existing `NNN_*.sql` file\\n\\nSchema changes require a new migration with the next sequence number, for example:\\n\\n```text\\n024_add_workflow_index.sql\\n```\\n\\nAfter `000_combined.sql`, the migration runner applies outstanding incremental migrations in numeric order.\\n\\nThis preserves reproducibility for existing installations and prevents previously applied migrations from changing meaning.\\n\\n## Bundled Defaults\\n\\nDefault commands and workflows are packaged from:\\n\\n- `.archon/commands/defaults/`\\n- `.archon/workflows/defaults/`\\n\\nAfter adding, removing, or modifying files in either directory, regenerate bundled assets:\\n\\n```bash\\nbun run generate:bundled\\n```\\n\\nBundled output should be kept synchronized with the source defaults before validation or release.\\n\\n## Logging\\n\\nCreate loggers through `@archon/paths`:\\n\\n```typescript\\nimport { createLogger } from '@archon/paths';\\n\\nconst log = createLogger('orchestrator');\\n```\\n\\nEvent names use the format:\\n\\n```text\\n{domain}.{action}_{state}\\n```\\n\\nStart and terminal events should be paired:\\n\\n- `{action}_started` with `{action}_completed`\\n- `{action}_started` with `{action}_failed`\\n\\nExample:\\n\\n```typescript\\nlog.info(\\n  { conversationId, codebaseId },\\n  'session.create_started',\\n);\\n\\nlog.error(\\n  { conversationId, error: err.message, err },\\n  'session.create_failed',\\n);\\n```\\n\\nNever log:\\n\\n- API keys\\n- Tokens\\n- User message contents\\n- Personally identifiable information\\n\\nTokens may be masked when necessary:\\n\\n```typescript\\ntoken.slice(0, 8) + '...'\\n```\\n\\n## Error Handling and Isolation\\n\\nGit and isolation failures should use `classifyIsolationError()` from `@archon/isolation` to produce a user-facing message.\\n\\nTypical handling:\\n\\n```typescript\\ntry {\\n  // Isolation creation logic\\n} catch (error) {\\n  const err = error as Error;\\n  const userMessage = classifyIsolationError(err);\\n\\n  log.error(\\n    { err, codebaseId },\\n    'isolation_creation_failed',\\n  );\\n\\n  await platform.sendMessage(conversationId, userMessage);\\n}\\n```\\n\\nThe implementation should preserve both sides of the error:\\n\\n- Log the original error for diagnostics.\\n- Send the classified, safe message to the platform user.\\n- Do not expose secrets or internal details in the user-facing message.\\n\\n## Command and Workflow System\\n\\n### Repository commands\\n\\nRepository commands are plain text or Markdown files stored in:\\n\\n```text\\n.archon/commands/\\n```\\n\\nThey are invoked by `command:` workflow nodes.\\n\\n### Workflow YAML\\n\\nWorkflow definitions are stored in:\\n\\n```text\\n.archon/workflows/\\n```\\n\\nWorkflow discovery is recursive. Node types and variable substitution rules are documented in [`docs/cli-reference.md`](docs/cli-reference.md).\\n\\n### Home-directory scope and precedence\\n\\nGlobal commands and workflows are stored under:\\n\\n```text\\n~/.archon/commands/\\n~/.archon/workflows/\\n```\\n\\nLoading precedence is:\\n\\n```text\\nbundled &lt; global &lt; project\\n```\\n\\nProject definitions therefore override global definitions, and global definitions override bundled defaults.\\n\\n### Workflow name resolution\\n\\n`resolveWorkflowName()` in `router.ts` resolves workflow names using four fallback levels:\\n\\n1. Exact match\\n2. Case-insensitive match\\n3. Suffix match\\n4. Substring match\\n\\nChanges to workflow routing should preserve this deterministic order.\\n\\n## Deterministic Slash Commands\\n\\nThe following commands do not invoke AI:\\n\\n```text\\n/help\\n/status\\n/reset\\n/workflow\\n/register-project\\n/update-project\\n/remove-project\\n/commands\\n/init\\n/worktree\\n```\\n\\n`/workflow` supports these subcommands:\\n\\n```text\\nlist\\nrun\\nstatus\\ncancel\\nresume\\nabandon\\napprove\\nreject\\n```\\n\\nCommand implementations should keep deterministic command handling separate from AI-driven session behavior.\\n\\n## GitHub Mention Handling\\n\\n`@archon` mentions are parsed only from Issue and pull request comments.\\n\\nThey are not parsed from:\\n\\n- Issue descriptions\\n- Pull request descriptions\\n\\nThe supported GitHub event is:\\n\\n```text\\nissue_comment\\n```\\n\\nChanges to GitHub event handling must retain these scope restrictions to avoid unintentionally triggering workflows from unsupported content.\\n\\n## GitNexus-Assisted Development\\n\\nThe repository is indexed by GitNexus as `doarchon`. The index contains symbols, relationships, and execution-flow information used for code navigation and impact assessment.\\n\\nIf GitNexus reports that the index is stale, refresh it with:\\n\\n```bash\\nnpx gitnexus analyze\\n```\\n\\n### Required exploration workflow\\n\\nBefore changing a function, class, or method:\\n\\n1. Run `gitnexus_impact({target: \\\"symbolName\\\", direction: \\\"upstream\\\"})`.\\n2. Review direct callers, affected processes, and risk level.\\n3. Warn about HIGH or CRITICAL risk before proceeding.\\n4. Make the change only after understanding its blast radius.\\n\\nFor unfamiliar behavior, use:\\n\\n```text\\ngitnexus_query({query: \\\"concept\\\"})\\n```\\n\\nThis returns execution-flow-oriented results rather than requiring broad text searches.\\n\\nFor complete context around a symbol, use:\\n\\n```text\\ngitnexus_context({name: \\\"symbolName\\\"})\\n```\\n\\nThis exposes callers, callees, and participating execution flows.\\n\\n### Required pre-commit check\\n\\nBefore committing, run:\\n\\n```text\\ngitnexus_detect_changes()\\n```\\n\\nConfirm that the changed symbols and execution flows match the intended scope.\\n\\n### GitNexus resources\\n\\nUseful repository resources include:\\n\\n- `gitnexus://repo/doarchon/context`\\n- `gitnexus://repo/doarchon/clusters`\\n- `gitnexus://repo/doarchon/processes`\\n- `gitnexus://repo/doarchon/process/{name}`\\n\\nRelated skill guides are located under:\\n\\n```text\\n.claude/skills/gitnexus/\\n```\\n\\nRelevant guides include:\\n\\n- `gitnexus-exploring/SKILL.md`\\n- `gitnexus-impact-analysis/SKILL.md`\\n- `gitnexus-debugging/SKILL.md`\\n- `gitnexus-refactoring/SKILL.md`\\n- `gitnexus-guide/SKILL.md`\\n- `gitnexus-cli/SKILL.md`\\n\\n## Contributor Checklist\\n\\nBefore opening a pull request:\\n\\n1. Keep changes on `dev`; do not commit directly to `main`.\\n2. Reuse existing interfaces such as `IPlatformAdapter`, `IAgentProvider`, `IDatabase`, and `IWorkflowStore`.\\n3. Use SDK-provided types instead of duplicate interfaces or `any`.\\n4. Place new schemas in the appropriate schema directory and derive types with `z.infer`.\\n5. Register API routes with `registerOpenApiRoute(createRoute({...}), handler)`.\\n6. Add a new migration instead of modifying an existing migration.\\n7. Regenerate bundled defaults when `.archon/commands/defaults/` or `.archon/workflows/defaults/` changes.\\n8. Preserve logging, privacy, and explicit error-handling conventions.\\n9. Run `bun run validate`.\\n10. Run `gitnexus_detect_changes()` and verify the affected scope.\\n11. Use `.github/PULL_REQUEST_TEMPLATE.md` and include `Closes #` where applicable.\",\"other-cli\":\"# Other \u2014 cli\\n\\n# Other \u2014 CLI\\n\\nThe `@archon/cli` package provides two command-line entry points:\\n\\n- `archon` / `aiflow`: the full local Archon CLI, implemented by `src/cli.ts`\\n- `aiflow`: the platform-only CLI, implemented by `src/cli-platform.ts`\\n\\nThe package is an ES module and is executed with Bun. Its platform client communicates with the online aiflow service through the Apigo gateway; the full CLI additionally initializes Archon configuration, providers, local workflow execution, isolation environments, telemetry, and database services.\\n\\n## Package entry points\\n\\n```json\\n{\\n  \\\"bin\\\": {\\n    \\\"aiflow\\\": \\\"./src/cli-platform.ts\\\",\\n    \\\"archon\\\": \\\"./src/cli.ts\\\"\\n  }\\n}\\n```\\n\\n| Entry point | Purpose |\\n|---|---|\\n| `src/cli-platform.ts` | Small, online-only aiflow client. Supports `platform`, `version`, and `help`. |\\n| `src/cli.ts` | Full Archon CLI. Supports local workflow execution and operational commands in addition to platform functionality. |\\n\\nThe platform entry point intentionally does not import the local engine, database, providers, worktree isolation, or server runtime. This keeps compiled binaries small and allows the platform CLI to run without a local Archon repository or database.\\n\\n## Architecture\\n\\n```mermaid\\nflowchart TD\\n    A[cli-platform.ts] --&gt; B[run]\\n    B --&gt; C[platformCommand]\\n    C --&gt; D[Resource handler]\\n    D --&gt; E[createAiflowClient]\\n    E --&gt; F[resolveUgateToken]\\n    E --&gt; G[AiflowClient]\\n    G --&gt; H[Apigo aiflow API]\\n\\n    I[cli.ts] --&gt; J[Local command handlers]\\n    I --&gt; C\\n    J --&gt; K[Core, workflows, isolation, providers]\\n```\\n\\n## Platform CLI execution\\n\\n`src/cli-platform.ts` exports:\\n\\n- `run(args: string[]): Promise`\\n- `isVersionRequest(args: string[]): boolean`\\n\\nWhen run as a Bun executable, it invokes:\\n\\n```ts\\nrun(process.argv.slice(2))\\n  .then(code =&gt; process.exit(code))\\n```\\n\\nWhen imported by tests, the `import.meta.main` guard prevents automatic execution.\\n\\n### Argument parsing\\n\\n`run()` uses Node\u2019s `parseArgs` with:\\n\\n- `allowPositionals: true`\\n- `strict: false`\\n- `--cwd`, defaulting to `process.cwd()`\\n- repeated `--file` and `--node-supplement` flags\\n- platform-specific string flags such as `--workflow`, `--codebase`, `--message`, and `--product`\\n\\nThe parsed values are converted into `PlatformCommandOptions`:\\n\\n```ts\\ninterface PlatformCommandOptions {\\n  baseUrl?: string;\\n  ugate?: string;\\n  json: boolean;\\n  cwd: string;\\n  values: Record;\\n}\\n```\\n\\n`--base-url` takes precedence over `AIFLOW_BASE_URL`. The supplied `cwd` is normalized with `resolve()` before it is passed to command handlers.\\n\\n### Top-level dispatch\\n\\n`run()` handles these cases before platform dispatch:\\n\\n- no arguments: prints top-level usage and returns `0`\\n- `--version`, `-V`, `-version`, or a lone `-v`: invokes `versionCommand()`\\n- `version`: invokes `versionCommand()`\\n- `help` or `--help`: prints top-level usage\\n- `platform --help`: invokes `printPlatformUsage()`\\n- anything other than `platform`: prints usage and returns `1`\\n\\nFor platform commands, `run()` calls:\\n\\n```ts\\nplatformCommand(positionals.slice(1), options)\\n```\\n\\nErrors escaping the top-level dispatch are printed as `\u9519\u8bef: ...` and produce exit code `1`.\\n\\n## Platform resource routing\\n\\n`platformCommand()` receives the resource and action separately:\\n\\n```text\\naiflow platform   [arguments]\\n```\\n\\nIt resolves a handler using `resolveHandler()` and passes the action, remaining positionals, and parsed options to that handler.\\n\\nSupported resources are:\\n\\n- `space`\\n- `codebase`\\n- `combo`\\n- `conversation`\\n- `workflow`\\n- `run`\\n- `token`\\n\\nUnknown or missing resources cause `printPlatformUsage()` to be called and return exit code `1`.\\n\\nEach handler returns a numeric exit code rather than terminating the process. `platformCommand()` catches command-level errors, including `AiflowApiError`, prints the message, and returns `1`.\\n\\n## Platform commands\\n\\n### `spaceCommand`\\n\\nImplemented in `src/aiflow/commands/space.ts`.\\n\\n| Action | API operation |\\n|---|---|\\n| `list` | `GET /api/product-spaces` |\\n| `get ` | `GET /api/product-spaces/:product_id` |\\n| `create --name  [--description ]` | `POST /api/product-spaces` |\\n\\n`list` renders the `spaces` response property using:\\n\\n```text\\nproduct_id, name, description, member_count, my_role\\n```\\n\\n`create` requires `--name`.\\n\\n### `codebaseCommand`\\n\\nImplemented in `src/aiflow/commands/codebase.ts`.\\n\\n| Action | API operation |\\n|---|---|\\n| `list [--product ]` | `GET /api/codebases?product_id=...` |\\n| `get ` | `GET /api/codebases/:id` |\\n| `add  [--product ]` | `POST /api/codebases` |\\n\\n`codebaseCommand()` classifies an `add` target before constructing the request body:\\n\\n- URL containing `://`, or beginning with `git@` \u2192 `{ url }`\\n- local path beginning with `/`, `~`, or `.` \u2192 `{ path }`\\n- icode-style `owner/repo` or `owner/group/repo` \u2192 `{ icode_repo }`\\n- all other values \u2192 `{ path }`\\n\\nThe `--path` flag takes precedence over the positional target. `--product` adds `product_id` to the request body.\\n\\nFor key-value output, `default_cwd` and `ai_assistant_type` are removed by `codebaseKvView()`.\\n\\n### `comboCommand`\\n\\nImplemented in `src/aiflow/commands/combo.ts`.\\n\\n| Action | API operation |\\n|---|---|\\n| `list [--product ]` | `GET /api/combos?product_id=...` |\\n| `get ` | `GET /api/combos/:id` |\\n\\nList output uses the columns:\\n\\n```text\\nid, name, description\\n```\\n\\n### `conversationCommand`\\n\\nImplemented in `src/aiflow/commands/conversation.ts`.\\n\\n| Action | API operation |\\n|---|---|\\n| `list [--product ]` | `GET /api/conversations?productId=...` |\\n| `get ` | `GET /api/conversations/:id` |\\n| `create --codebase  ...` | `POST /api/conversations` |\\n| `create --combo  ...` | `POST /api/conversations` |\\n| `send  --message ` | `POST /api/conversations/:id/message` |\\n| `messages  [--limit ]` | `GET /api/conversations/:id/messages` |\\n\\n`create` requires either `--codebase` or `--combo`. Optional values are mapped to the API body as:\\n\\n```ts\\n{\\n  codebaseId,\\n  comboId,\\n  message,\\n  productId\\n}\\n```\\n\\n`send` supports repeated `--file` flags. Files are loaded with `loadUploadFiles()` and sent as multipart form data through `AiflowClient.postForm()`. Without attachments, it uses JSON with `AiflowClient.post()`.\\n\\nMessage list output uses:\\n\\n```text\\nid, role, content, created_at\\n```\\n\\n### `platformWorkflowCommand`\\n\\nImplemented in `src/aiflow/commands/workflow.ts`.\\n\\n| Action | API operation |\\n|---|---|\\n| `list [--product ]` | `GET /api/workflows-v2?productId=...` |\\n| `get ` | `GET /api/workflows-v2/:id` |\\n\\nThe v2 workflow response is expected to contain a flat `workflows` array. List output uses:\\n\\n```text\\nid, name, scope, description\\n```\\n\\nWhen no product is supplied, the API request omits `productId`.\\n\\n### `runCommand`\\n\\nImplemented in `src/aiflow/commands/run.ts`.\\n\\n#### Triggering runs\\n\\n```text\\naiflow platform run trigger \\\\\\n  --workflow  \\\\\\n  --codebase  \\\\\\n  --message \\n```\\n\\nTriggering is deliberately two-phase:\\n\\n1. `POST /api/conversations` creates a conversation associated with the codebase.\\n2. `POST /api/workflows//runs` starts the workflow using the returned `conversationId`.\\n\\nIf `--branch` is present, it is attached to the conversation:\\n\\n```ts\\n{\\n  codebaseId,\\n  branches: {\\n    [codebaseId]: branch\\n  }\\n}\\n```\\n\\nThe run request includes `message`, `conversationId`, and `codebaseId`. Optional `--workflow-id` and `--product` values map to `workflowId` and `productId`.\\n\\nAttachments cause the second request to use `postForm()` instead of `post()`.\\n\\n#### Run inspection and control\\n\\n| Action | API operation |\\n|---|---|\\n| `status ` | `GET /api/workflows/runs/:run-id` |\\n| `result ` | `GET /api/workflows/runs/:run-id/result` |\\n| `cancel ` | `POST /api/workflows/runs/:run-id/cancel` |\\n| `pause ` | `POST /api/workflows/runs/:run-id/user-pause` |\\n| `resume ` | State-dependent; see below |\\n| `approve ` | `POST /api/workflows/runs/:run-id/approve` |\\n| `reject ` | `POST /api/workflows/runs/:run-id/reject` |\\n| `clarify  --message ` | `POST /api/workflows/runs/:run-id/clarify` |\\n\\n#### Pause behavior\\n\\n`pause` accepts an explicit `--node`. If omitted, `resolveRunningNodeId()` fetches the run detail and calculates the active node by:\\n\\n1. collecting `node_started` events\\n2. collecting `node_completed` and `node_failed` events\\n3. selecting a started node that has not finished\\n\\nIf the detail request fails or no active node is found, it uses:\\n\\n```text\\n__user_pause__\\n```\\n\\n`--supplement` is included as `supplement` in the pause request.\\n\\n#### Resume behavior\\n\\n`resume` first calls `fetchRunDetail()` and routes based on the run\u2019s status and approval metadata:\\n\\n- paused with `approval.type === \\\"user_pause\\\"`:\\n  - `POST /api/workflows/runs/:run-id/approve`\\n  - `--supplement` or `--message` becomes `comment`\\n- failed:\\n  - `POST /api/workflows/runs/:run-id/breakpoint-retry`\\n  - optional node supplements are sent as `nodeSupplements`\\n- all other states:\\n  - `POST /api/workflows/runs/:run-id/resume`\\n\\nNode supplements use the syntax:\\n\\n```text\\n--node-supplement =\\n```\\n\\n`parseNodeSupplements()` converts them into:\\n\\n```ts\\n[\\n  {\\n    nodeId: 'node-id',\\n    supplement: 'text'\\n  }\\n]\\n```\\n\\nMalformed entries without a non-empty node ID are ignored.\\n\\n#### Clarification and attachments\\n\\n`clarify` requires both a run ID and `--message`. Like conversation sending and run triggering, it selects JSON or multipart transport based on whether `--file` was supplied.\\n\\n### `tokenCommand`\\n\\nImplemented in `src/aiflow/commands/token.ts`.\\n\\n```text\\naiflow platform token status\\n```\\n\\nThe command calls:\\n\\n```text\\nGET /api/settings/comate-auth-token\\n```\\n\\nThe server response contains `configured` and a masked token value. The CLI does not print the masked value. It reports:\\n\\n```json\\n{\\n  \\\"registered\\\": true,\\n  \\\"registration_url\\\": \\\"https://ai-flow.baidu-int.com\\\"\\n}\\n```\\n\\nIn human-readable mode, an unregistered token produces a registration hint.\\n\\n## Authentication\\n\\n`resolveUgateToken()` in `src/aiflow/auth.ts` resolves the token in this order:\\n\\n1. `explicitToken`, normally supplied through `--ugate`\\n2. `AIFLOW_UGATE_TOKEN`\\n3. UUAP cache file under `~/.config/uuap`\\n4. automatic discovery when the cache directory contains exactly one token file\\n\\nThe cache file naming convention is:\\n\\n```text\\n~/.config/uuap/.eac_ugate_token_\\n```\\n\\nThe username is resolved in this order:\\n\\n1. `ResolveUgateOptions.username`\\n2. the prefix of `git config user.email`\\n3. the sole cached token filename, if exactly one exists\\n\\nFor example, `ftx@baidu.com` maps to username `ftx`.\\n\\nCached files are expected to contain JSON such as:\\n\\n```json\\n{\\n  \\\"token\\\": \\\"...\\\",\\n  \\\"permanent\\\": true\\n}\\n```\\n\\nA file containing `expires_at` is treated as invalid. If no usable token is found, `resolveUgateToken()` throws an error that explains the supported configuration mechanisms.\\n\\n## HTTP client\\n\\n`src/aiflow/client.ts` contains the platform HTTP layer.\\n\\n### `AiflowClient`\\n\\n```ts\\nnew AiflowClient({\\n  baseUrl?: string,\\n  token: string\\n})\\n```\\n\\nThe default base URL is:\\n\\n```text\\nhttps://apigo.baidu-int.com/aide/aiflow\\n```\\n\\nThe constructor removes a trailing slash from `baseUrl`.\\n\\nAvailable methods:\\n\\n- `get(path, query?)`\\n- `post(path, body?)`\\n- `postForm(path, fields, files)`\\n- `patch(path, body?)`\\n\\nAll requests include:\\n\\n```http\\nUgate-Token: \\n```\\n\\nJSON request bodies also include:\\n\\n```http\\nContent-Type: application/json\\n```\\n\\n`postForm()` builds a `FormData` body, appends defined fields, and appends every file under the `files` field. It deliberately does not set `Content-Type`; the runtime must supply the multipart boundary.\\n\\n### Query handling\\n\\n`withQuery()` converts a query object into URL parameters and omits entries whose value is `undefined`.\\n\\nFor example:\\n\\n```ts\\nclient.get('/api/conversations', {\\n  product_id: 'p1',\\n  cursor: undefined\\n});\\n```\\n\\nproduces:\\n\\n```text\\n/api/conversations?product_id=p1\\n```\\n\\n### Response parsing and errors\\n\\n`request()` delegates response parsing to `parseBody()`:\\n\\n- empty response \u2192 `null`\\n- valid JSON \u2192 parsed JSON value\\n- invalid JSON \u2192 response text\\n\\nNetwork failures are wrapped with a message containing the configured service URL and an internal-network hint.\\n\\nNon-2xx responses produce an `AiflowApiError` containing:\\n\\n- `status`\\n- `body`\\n- formatted `message`\\n\\nFor HTTP 401 responses, the message additionally suggests that the UGate token may have expired.\\n\\n`platformCommand()` catches these errors so command handlers can remain focused on request construction and output formatting.\\n\\n### `createAiflowClient()`\\n\\n`createAiflowClient()` combines authentication and client construction:\\n\\n```ts\\nconst client = await createAiflowClient({\\n  baseUrl: opts.baseUrl,\\n  explicitToken: opts.ugate,\\n  cwd: opts.cwd\\n});\\n```\\n\\nThis is the common initialization path used by all platform resource handlers.\\n\\n## File uploads\\n\\n`src/aiflow/file-upload.ts` provides upload preparation utilities:\\n\\n- `toStringArray(value)` normalizes a single string or repeated flag value to `string[]`\\n- `loadUploadFiles(cwd, rawPaths)` resolves and loads files\\n- `loadUploadFile()` validates an individual path and creates a Bun `File`\\n\\nRelative paths are resolved against the command\u2019s `cwd`. Nonexistent paths and directories throw:\\n\\n```text\\n\u9644\u4ef6\u4e0d\u5b58\u5728\u6216\u4e0d\u662f\u6587\u4ef6: \\n```\\n\\nThe resulting `File` uses the source basename and detected MIME type.\\n\\n## Output formatting\\n\\n`src/aiflow/format.ts` centralizes output behavior.\\n\\n### `printResult()`\\n\\n`printResult()` chooses output based on `opts.json`:\\n\\n- JSON mode: pretty-printed original response\\n- table mode: `formatTable()` when table configuration is provided\\n- key-value mode: `formatKeyValue()` when `kv` configuration is provided\\n- fallback: pretty-printed JSON\\n\\n### `formatTable()`\\n\\n`formatTable(rows, columns)` renders an aligned, fixed-width table. Missing, `null`, and `undefined` values are displayed as empty cells. Nested objects are JSON-stringified. Empty input returns:\\n\\n```text\\n(\u65e0\u6570\u636e)\\n```\\n\\n### `formatKeyValue()`\\n\\n`formatKeyValue(obj)` writes one field per line:\\n\\n```text\\nid: s1\\nname: demo\\nmeta: {\\\"a\\\":1}\\n```\\n\\nResource handlers select columns explicitly so output remains stable even when the API returns additional fields.\\n\\n## Full CLI initialization\\n\\n`src/cli.ts` is the full local CLI entry point. Its startup sequence is intentionally ordered.\\n\\n1. `@archon/paths/strip-cwd-env-boot` is imported first to remove Bun-auto-loaded CWD environment variables before modules read configuration.\\n2. `loadArchonEnv(process.cwd())` loads Archon-owned environment files.\\n3. `initMcpServers()` initializes configured MCP servers.\\n4. Claude authentication defaults are applied when explicit Claude tokens are absent.\\n5. Built-in and community providers are registered with:\\n   - `registerBuiltinProviders()`\\n   - `registerCommunityProviders()`\\n6. Command modules are imported and dispatched.\\n7. On shutdown, telemetry and server-related cleanup are finalized.\\n\\nThe full CLI includes local commands such as workflow execution, isolation management, setup, skill installation, chat, validation, serving, diagnostics, and token utilities. Local commands interact with packages including:\\n\\n- `@archon/core`\\n- `@archon/workflows`\\n- `@archon/isolation`\\n- `@archon/providers`\\n- `@archon/server`\\n- `@archon/git`\\n- `@archon/paths`\\n\\nUnlike `cli-platform.ts`, the full CLI validates repository context for commands that require a Git repository. `--cwd` can be used to select a different working directory.\\n\\n## `CLIAdapter`\\n\\n`CLIAdapter` in `src/adapters/cli-adapter.ts` adapts workflow or chat output to terminal behavior.\\n\\nIts contract includes:\\n\\n- default streaming mode: `batch`\\n- optional `streamingMode: 'stream'`\\n- `getStreamingMode()`\\n- `getPlatformType()`, returning `'cli'`\\n- `ensureThread()`, which passes through the supplied conversation ID\\n- `start()` and `stop()`, both no-ops\\n- `sendMessage()`, which writes assistant content to `console.log`\\n\\nThe adapter can associate an external conversation ID with a database conversation ID using:\\n\\n```ts\\nadapter.setConversationDbId(conversationId, conversationDbId);\\n```\\n\\nWhen a mapping exists, `sendMessage()` persists the assistant message through `addMessage()`:\\n\\n```ts\\naddMessage(conversationDbId, 'assistant', content, metadata)\\n```\\n\\nOnly persistent metadata fields are forwarded. Workflow status/result and workflow dispatch metadata are retained; transient fields such as `segment` are omitted. Persistence failures are logged with `warn` and do not prevent terminal output or cause `sendMessage()` to reject.\\n\\n## Bundled skills\\n\\n`src/bundled-skill.ts` statically imports the Archon skill files using text import attributes and exports them through:\\n\\n```ts\\nBUNDLED_SKILL_FILES: Record\\n```\\n\\nThe map preserves paths relative to `.claude/skills/archon/`, including:\\n\\n- `SKILL.md`\\n- examples\\n- guides\\n- command references\\n- workflow references\\n- troubleshooting and configuration references\\n\\nStatic imports allow compiled binaries to install or expose these resources without reading the source repository at runtime.\\n\\n## Testing and contribution workflow\\n\\nThe package uses Bun tests and TypeScript type checking.\\n\\n```bash\\nbun run --cwd packages/cli test\\nbun run --cwd packages/cli type-check\\n```\\n\\nThe test script groups tests by area:\\n\\n- CLI parsing and adapters\\n- local commands\\n- platform command handlers\\n- authentication and HTTP client behavior\\n- output formatting\\n- file uploads\\n\\nPlatform command tests generally mock `createAiflowClient()` and verify:\\n\\n- required argument validation\\n- HTTP method and path\\n- query parameter names\\n- request body shape\\n- multipart selection\\n- output behavior\\n- exit codes\\n\\nWhen adding a platform resource:\\n\\n1. Add the handler under `src/aiflow/commands/`.\\n2. Route it from `resolveHandler()` in `src/aiflow/platform.ts`.\\n3. Add its usage text to `printPlatformUsage()`.\\n4. Use `createAiflowClient()` rather than constructing authentication independently.\\n5. Use `printResult()` for consistent JSON, table, and key-value output.\\n6. Add handler tests that mock the client and assert exact API requests.\\n7. Preserve nonzero exit codes for invalid actions or missing required arguments.\\n\\nWhen changing shared platform behavior, update the relevant tests for `run()`, `platformCommand()`, `AiflowClient`, `resolveUgateToken()`, and the formatting helpers.\",\"other-core\":\"# Other \u2014 core\\n\\n# Other \u2014 core\\n\\n`@archon/core` is the shared application-core package for Archon. It contains the server-side primitives used by handlers, orchestration, workflows, services, scheduling, and API layers:\\n\\n- Configuration loading, merging, validation, persistence, and safe client projection.\\n- Database connection and adapter abstractions for PostgreSQL and SQLite.\\n- Domain persistence modules for conversations, workflows, traces, evaluations, scheduling, environments, and product-space data.\\n- Runtime tracing, policy, redaction, event emission, and evaluation support.\\n- Orchestration, command handling, workflow execution integration, and state transitions.\\n- Shared operational utilities such as locking, worktree synchronization, path validation, port allocation, and error formatting.\\n\\nThe package is TypeScript-first and runs directly under Bun. Its package exports provide focused subpath imports rather than requiring consumers to import internal files.\\n\\n## Package entry points\\n\\n```ts\\nimport { loadConfig } from '@archon/core/config';\\nimport { getDatabase } from '@archon/core/db';\\nimport { PostgresAdapter, SqliteAdapter } from '@archon/core/db';\\nimport { dispatchBackgroundWorkflow } from '@archon/core/orchestrator';\\nimport { CommandHandler } from '@archon/core/handlers';\\nimport { createRuntimeEmitter } from '@archon/core/runtime';\\n```\\n\\nAvailable package areas include:\\n\\n| Import path | Purpose |\\n| --- | --- |\\n| `@archon/core` | Main package entry point |\\n| `@archon/core/config` | YAML configuration types and loader |\\n| `@archon/core/db` | Database connection, adapters, and persistence operations |\\n| `@archon/core/operations` | Higher-level workflow and isolation operations |\\n| `@archon/core/workflows` | Workflow integration and persistence adapters |\\n| `@archon/core/orchestrator` | Conversation and background workflow orchestration |\\n| `@archon/core/handlers` | Command handling and clone-related handlers |\\n| `@archon/core/notifications/*` | Notification integrations, including Infoflow |\\n| `@archon/core/runtime` | Runtime IDs, costs, trace bus, policies, redaction, and emitters |\\n| `@archon/core/services/*` | Evaluation, quality, evolution, cleanup, intelligence, and related services |\\n| `@archon/core/scheduling/*` | Scheduled task execution and sandbox scheduling |\\n| `@archon/core/state/*` | Session and interaction state transitions |\\n| `@archon/core/utils/*` | Shared filesystem, locking, command, networking, and error helpers |\\n\\n---\\n\\n## Architecture and dependencies\\n\\n`@archon/core` coordinates infrastructure-facing behavior while delegating specialized responsibilities to workspace packages:\\n\\n- `@archon/providers` owns provider registration and provider-specific defaults.\\n- `@archon/workflows` owns workflow definitions and execution-facing abstractions.\\n- `@archon/git` provides Git and worktree primitives.\\n- `@archon/isolation` and `@archon/sandbox` provide isolated execution environments.\\n- `@archon/paths` provides Archon filesystem locations and structured logging.\\n\\nThe core package is commonly called from server routes, chat adapters, and background workers. In turn, core modules persist state, resolve configuration, invoke workflow infrastructure, and emit observable runtime events.\\n\\n```mermaid\\nflowchart LR\\n  Client[Server routes / chat adapters] --&gt; Core[@archon/core]\\n  Core --&gt; Config[config]\\n  Core --&gt; DB[db]\\n  Core --&gt; Orchestrator[orchestrator]\\n  Orchestrator --&gt; Workflows[@archon/workflows]\\n  Core --&gt; Runtime[runtime]\\n  Core --&gt; Providers[@archon/providers]\\n  Core --&gt; Isolation[git / isolation / sandbox]\\n```\\n\\n---\\n\\n# Configuration\\n\\nThe configuration subsystem is exported from `@archon/core/config`.\\n\\n```ts\\nimport {\\n  loadConfig,\\n  loadGlobalConfig,\\n  loadRepoConfig,\\n  updateGlobalConfig,\\n  toSafeConfig,\\n} from '@archon/core/config';\\n```\\n\\nConfiguration is split into three type levels:\\n\\n- `GlobalConfig`: user-level settings in `~/.archon/config.yaml`.\\n- `RepoConfig`: repository-level settings in `/.archon/config.yaml`.\\n- `MergedConfig`: fully resolved server-side configuration.\\n- `SafeConfig`: intentionally restricted configuration suitable for a web client.\\n\\n## Resolution order\\n\\n`loadConfig(repoPath?)` resolves settings in strict precedence order:\\n\\n1. Built-in defaults from `getDefaults()`.\\n2. Global YAML configuration from `loadGlobalConfig()`.\\n3. Repository YAML configuration from `loadRepoConfig(repoPath)`, if a repository path is supplied.\\n4. Environment variable overrides from `applyEnvOverrides()`.\\n\\nLater layers override earlier layers.\\n\\n```mermaid\\nflowchart LR\\n  Defaults[getDefaults] --&gt; Global[loadGlobalConfig]\\n  Global --&gt; Repo[loadRepoConfig]\\n  Repo --&gt; Env[applyEnvOverrides]\\n  Env --&gt; Price[setRuntimePriceOverrides]\\n  Price --&gt; Result[MergedConfig]\\n```\\n\\n`loadConfig()` also performs provider bootstrap before reading provider-dependent settings:\\n\\n```ts\\nregisterBuiltinProviders();\\nregisterCommunityProviders();\\n```\\n\\nThis ensures that default assistant validation and dynamically registered provider defaults operate against a populated provider registry.\\n\\n## Loading global configuration\\n\\n`loadGlobalConfig(forceReload = false)` reads `getArchonConfigPath()`, normally `~/.archon/config.yaml`.\\n\\nBehavior:\\n\\n- Caches the parsed result in `cachedGlobalConfig`.\\n- Returns the cached value unless `forceReload` is `true`.\\n- When the file does not exist (`ENOENT`), calls `createDefaultConfig()` to create a commented starter configuration and returns `{}`.\\n- Logs malformed YAML, permission failures, and other read failures with structured event names:\\n  - `config_invalid_yaml`\\n  - `config_permission_denied`\\n  - `config_load_error`\\n\\nUse `clearConfigCache()` in tests or when a caller must invalidate the in-memory global-config cache.\\n\\n```ts\\nclearConfigCache();\\n\\nconst config = await loadGlobalConfig(true);\\n```\\n\\n## Loading repository configuration\\n\\n`loadRepoConfig(repoPath)` reads:\\n\\n```text\\n/.archon/config.yaml\\n```\\n\\nUnlike global configuration, a missing repository configuration file is expected and does not create a file. It returns `{}` for `ENOENT`.\\n\\nRepository configuration controls project-scoped behavior such as:\\n\\n- Default `assistant`.\\n- Per-provider assistant defaults.\\n- Command discovery settings.\\n- Default command and workflow loading.\\n- Worktree base branch and local worktree path.\\n- Documentation directory.\\n- Environment variables passed to workflow execution.\\n\\n## Defaults\\n\\n`getDefaults()` is internal, but defines the baseline behavior reflected by `MergedConfig`:\\n\\n| Setting | Default |\\n| --- | --- |\\n| `botName` | `\\\"Archon\\\"` |\\n| `assistant` | First built-in registered provider, otherwise `\\\"claude\\\"` |\\n| `streaming.telegram` | `\\\"stream\\\"` |\\n| `streaming.discord` | `\\\"batch\\\"` |\\n| `streaming.slack` | `\\\"batch\\\"` |\\n| `concurrency.maxConversations` | `10` |\\n| `commands.autoLoad` | `true` |\\n| `defaults.copyDefaults` | `true` |\\n| `defaults.loadDefaultCommands` | `true` |\\n| `defaults.loadDefaultWorkflows` | `true` |\\n| `infoflowEnabled` | `true` |\\n| `sandboxEnabledByDefault` | `false` |\\n\\nThe defaults map is provider-aware. `getDefaults()` always creates `claude` and `codex` entries and then adds `{}` entries for every other registered provider. New community providers therefore appear without requiring a core-package code change.\\n\\n## Assistant defaults and provider registration\\n\\n`AssistantDefaults` is a provider-keyed map. It includes typed convenience fields for built-ins:\\n\\n```ts\\nconfig.assistants.claude.model;\\nconfig.assistants.codex.model;\\nconfig.assistants.codex.modelReasoningEffort;\\nconfig.assistants.codex.webSearchMode;\\n```\\n\\nCommunity providers use the generic index signature inherited from `ProviderDefaultsMap`.\\n\\n`mergeAssistantDefaults(base, overrides)` is designed to preserve every registered provider slot and shallow-merge each provider\u2019s object independently. This is important because global and repository layers may configure different keys for the same provider.\\n\\nFor example, a global model and repository web-search setting combine:\\n\\n```yaml\\n# ~/.archon/config.yaml\\nassistants:\\n  codex:\\n    model: gpt-5.2-codex\\n    modelReasoningEffort: medium\\n```\\n\\n```yaml\\n# /.archon/config.yaml\\nassistants:\\n  codex:\\n    webSearchMode: live\\n```\\n\\nThe resulting `config.assistants.codex` contains all three values.\\n\\n## Assistant validation\\n\\nBoth global `defaultAssistant` and repository `assistant` values are validated with `isRegisteredProvider()`.\\n\\nInvalid provider IDs cause `loadConfig()` to reject with an error that includes the available provider IDs. This is intentional fail-fast behavior; configuration must not silently select an invalid provider.\\n\\nThe same validation applies to `DEFAULT_AI_ASSISTANT`.\\n\\n## Environment overrides\\n\\n`applyEnvOverrides()` mutates the resolved `MergedConfig` with the highest-precedence values.\\n\\n### General settings\\n\\n| Environment variable | Result |\\n| --- | --- |\\n| `BOT_DISPLAY_NAME` | Overrides `botName` |\\n| `DEFAULT_AI_ASSISTANT` | Overrides `assistant`; must be registered |\\n| `MAX_CONCURRENT_CONVERSATIONS` | Sets a positive integer concurrency limit |\\n| `TELEGRAM_STREAMING_MODE` | Accepts `stream` or `batch` |\\n| `DISCORD_STREAMING_MODE` | Accepts `stream` or `batch` |\\n| `SLACK_STREAMING_MODE` | Accepts `stream` or `batch` |\\n\\n### Per-provider models\\n\\nFor every registered provider, `loadConfig()` checks:\\n\\n```text\\n_MODEL\\n```\\n\\nExamples:\\n\\n```text\\nCLAUDE_MODEL=claude-opus-4-8\\nCODEX_MODEL=gpt-5.3-codex\\n```\\n\\nA non-blank value is trimmed and stored in:\\n\\n```ts\\nconfig.assistants[providerId].model\\n```\\n\\nThese overrides apply to conversation defaults. Workflow runs resolve their model from workflow YAML, unless that workflow definition omits a model.\\n\\n### Infoflow\\n\\nInfoflow configuration is environment-only. `config.infoflow` exists only when both `INFOFLOW_AK` and `INFOFLOW_SK` are supplied.\\n\\n| Environment variable | `MergedConfig.infoflow` field |\\n| --- | --- |\\n| `INFOFLOW_AK` | `ak` |\\n| `INFOFLOW_SK` | `sk` |\\n| `INFOFLOW_BASE_URL` | `baseUrl`, defaulting to `https://apiin.im.baidu.com` |\\n| `INFOFLOW_TOKEN_BASE_URL` | `tokenBaseUrl` |\\n| `INFOFLOW_GROUP_BASE_URL` | `groupBaseUrl` |\\n| `INFOFLOW_CHECK_TOKEN` | `checkToken` |\\n| `INFOFLOW_ENCODING_AES_KEY` | `encodingAesKey` |\\n| `INFOFLOW_TIMEOUT_SECONDS` | `timeoutSeconds` |\\n\\nSet either of the following to disable Infoflow notifications:\\n\\n```text\\nINFOFLOW_ENABLED=false\\nINFOFLOW_ENABLED=0\\n```\\n\\nThis sets `config.infoflowEnabled` to `false`.\\n\\n### E2B sandbox settings\\n\\nGlobal YAML may define `sandbox`, while environment variables override individual values:\\n\\n| Environment variable | Sandbox field |\\n| --- | --- |\\n| `E2B_API_KEY` | `apiKey` |\\n| `E2B_DOMAIN` | `domain` |\\n| `E2B_TEMPLATE` | `template` |\\n| `E2B_TIMEOUT_MS` | `timeoutMs` |\\n| `ARCHON_EXTERNAL_URL` | `envs.ARCHON_EXTERNAL_URL` |\\n| `ARCHON_FRONTEND_URL` | `envs.ARCHON_FRONTEND_URL` |\\n\\n`ARCHON_EXTERNAL_URL` is the backend address reachable from the sandbox. `ARCHON_FRONTEND_URL` is the user-facing frontend address used for displayed links.\\n\\nSet either value below to enable sandboxing by default for new conversations:\\n\\n```text\\nSANDBOX_ENABLED_BY_DEFAULT=true\\nSANDBOX_ENABLED_BY_DEFAULT=1\\n```\\n\\n## Repository-only propagated fields\\n\\n`mergeRepoConfig()` projects several repository settings into top-level `MergedConfig` fields consumed by workflow execution:\\n\\n| Repo YAML field | Merged field | Intended use |\\n| --- | --- | --- |\\n| `worktree.baseBranch` | `baseBranch` | `$BASE_BRANCH` workflow substitution |\\n| `docs.path` | `docsPath` | `$DOCS_DIR` workflow substitution |\\n| `env` | `envVars` | Per-project execution environment |\\n\\n`worktree.baseBranch` and `docs.path` are trimmed. Blank values are ignored; an ignored blank documentation path emits `config.docs_path_whitespace_ignored`.\\n\\n`envVars` is merged from repository configuration. Workflow execution may merge database-managed environment variables on top of it.\\n\\nExample repository configuration:\\n\\n```yaml\\nassistant: codex\\n\\nworktree:\\n  baseBranch: develop\\n  path: .worktrees\\n\\ndocs:\\n  path: packages/docs-web/src/content/docs\\n\\nenv:\\n  API_BASE: https://api.example.com\\n  FEATURE_FLAG: enabled\\n\\ncommands:\\n  folder: .archon/custom-commands\\n  autoLoad: true\\n```\\n\\n## Updating global configuration\\n\\n`updateGlobalConfig(updates)` reads the current global configuration, merges selected top-level fields, serializes YAML with `Bun.YAML.stringify()`, and writes it to the global config path.\\n\\n```ts\\nawait updateGlobalConfig({\\n  defaultAssistant: 'codex',\\n  assistants: {\\n    codex: {\\n      model: 'gpt-5.3-codex',\\n      modelReasoningEffort: 'medium',\\n    },\\n  },\\n});\\n```\\n\\nIt merges:\\n\\n- `botName`\\n- `defaultAssistant`\\n- `assistants`\\n- `trace`\\n- `streaming`\\n- `concurrency`\\n\\nThe function creates the parent directory when necessary, clears `cachedGlobalConfig` after a successful write, logs completion as `config.update_completed`, and rethrows write errors after logging them.\\n\\n## Safe configuration for web clients\\n\\nNever serialize `MergedConfig` directly to a web client. Use `toSafeConfig(config)`.\\n\\n```ts\\nconst config = await loadConfig(repoPath);\\nconst safeConfig = toSafeConfig(config);\\n```\\n\\n`toSafeConfig()` excludes server-internal or sensitive information, including:\\n\\n- `paths`\\n- `commands`\\n- `baseBranch`\\n- `docsPath`\\n- `envVars`\\n- `infoflow`\\n- `sandbox`\\n- `sandboxEnabledByDefault`\\n\\nAssistant defaults use an explicit allowlist rather than a denylist:\\n\\n```ts\\nconst SAFE_ASSISTANT_FIELDS = {\\n  claude: ['model'],\\n  codex: ['model', 'modelReasoningEffort', 'webSearchMode'],\\n  pi: ['model'],\\n};\\n```\\n\\nThis means unknown provider defaults are hidden by default, even when the provider itself appears in the returned `assistants` map. When adding a provider field that is safe to surface in the UI, it must be explicitly added to `SAFE_ASSISTANT_FIELDS`.\\n\\n---\\n\\n# Database abstraction\\n\\nThe database adapter layer is exported from `@archon/core/db`.\\n\\n```ts\\nimport {\\n  PostgresAdapter,\\n  SqliteAdapter,\\n  postgresDialect,\\n  sqliteDialect,\\n} from '@archon/core/db';\\nimport type { IDatabase, QueryResult, SqlDialect } from '@archon/core/db';\\n```\\n\\nThe adapter boundary allows the persistence modules to use a common query shape while supporting PostgreSQL in deployed environments and SQLite for local or embedded deployments.\\n\\n## `IDatabase` contract\\n\\nAdapters implement `IDatabase`, whose essential operations are:\\n\\n```ts\\ninterface IDatabase {\\n  query(sql: string, params?: unknown[]): Promise&gt;;\\n\\n  withSession(\\n    fn: (\\n      query: (sql: string, params?: unknown[]) =&gt; Promise&gt;\\n    ) =&gt; Promise\\n  ): Promise;\\n\\n  withTransaction(\\n    fn: (\\n      query: (sql: string, params?: unknown[]) =&gt; Promise&gt;\\n    ) =&gt; Promise\\n  ): Promise;\\n\\n  close(): Promise;\\n}\\n```\\n\\n`QueryResult` normalizes driver-specific responses:\\n\\n```ts\\n{\\n  rows: T[];\\n  rowCount: number;\\n}\\n```\\n\\n`rowCount` is always numeric. In particular, `PostgresAdapter` converts PostgreSQL\u2019s nullable `rowCount` to `0`.\\n\\n### Query usage\\n\\n```ts\\nconst result = await db.query&lt;{ id: string; name: string }&gt;(\\n  'SELECT id, name FROM remote_agent_codebases WHERE id = $1',\\n  [codebaseId]\\n);\\n\\nconst codebase = result.rows[0];\\n```\\n\\nUse `$1`, `$2`, and similar positional placeholders in persistence code. The SQLite adapter translates them to SQLite-compatible bindings.\\n\\n## Sessions and transactions\\n\\nUse `withSession()` when multiple queries must use one physical connection but do not require atomicity. This is particularly relevant for database-specific session state or connection-bound operations.\\n\\n```ts\\nawait db.withSession(async query =&gt; {\\n  const result = await query&lt;{ value: number }&gt;('SELECT 42 AS value');\\n  return result.rows[0].value;\\n});\\n```\\n\\nUse `withTransaction()` for atomic work:\\n\\n```ts\\nawait db.withTransaction(async query =&gt; {\\n  await query(\\n    'UPDATE remote_agent_workflow_runs SET status = $1 WHERE id = $2',\\n    ['running', workflowRunId]\\n  );\\n\\n  await query(\\n    'INSERT INTO remote_agent_workflow_events (workflow_run_id, event_type) VALUES ($1, $2)',\\n    [workflowRunId, 'started']\\n  );\\n});\\n```\\n\\nThe PostgreSQL implementation guarantees client release in all paths. It issues:\\n\\n- `BEGIN` before the callback.\\n- `COMMIT` when the callback resolves.\\n- `ROLLBACK` when the callback throws.\\n\\nIf rollback itself fails, the rollback failure is logged as `db.postgres_transaction_rollback_failed`; the original callback error is still rethrown.\\n\\n---\\n\\n## PostgreSQL: `PostgresAdapter`\\n\\n`PostgresAdapter` wraps `pg.Pool`.\\n\\n```ts\\nconst db = new PostgresAdapter(process.env.DATABASE_URL!);\\n```\\n\\n### Pool configuration\\n\\nThe adapter configures the pool with:\\n\\n- `max`: from `resolvePoolMax()`.\\n- `idleTimeoutMillis: 0`.\\n- `connectionTimeoutMillis: 10000`.\\n\\n`resolvePoolMax()` reads `DATABASE_POOL_MAX`:\\n\\n```ts\\nconst poolMax = resolvePoolMax();\\n```\\n\\nRules:\\n\\n- Default: `30`.\\n- Valid values: positive integers.\\n- Invalid, zero, negative, or non-numeric values fall back to `30`.\\n\\nThe relatively high default addresses core execution paths where one message or scheduled workflow can result in many database operations. A small pool can leave lightweight incoming requests waiting behind long-running background work.\\n\\n### Timestamp handling\\n\\nThe module configures `pg` type parsers for PostgreSQL timestamp types:\\n\\n- OID `1114` (`timestamp`)\\n- OID `1184` (`timestamptz`)\\n\\nBoth are preserved as raw strings:\\n\\n```ts\\ntypes.setTypeParser(1114, (value: string) =&gt; value);\\ntypes.setTypeParser(1184, (value: string) =&gt; value);\\n```\\n\\nThis avoids an implicit conversion to local-time `Date` objects. The application stores UTC wall-clock timestamps and must not shift them before downstream SLA and UI formatting logic runs.\\n\\n### Pool errors\\n\\nPool-level errors are logged as:\\n\\n```text\\ndb.postgres_pool_connection_failed\\n```\\n\\nThe event handler logs rather than throws. Individual query callers receive their own query failures.\\n\\n---\\n\\n## SQLite: `SqliteAdapter`\\n\\n`SqliteAdapter` uses Bun\u2019s `bun:sqlite` implementation.\\n\\n```ts\\nconst db = new SqliteAdapter('/path/to/archon.db');\\n```\\n\\nOn construction, it:\\n\\n1. Creates the database directory if it does not exist.\\n2. Opens the SQLite database.\\n3. Enables WAL journal mode.\\n4. Sets `PRAGMA busy_timeout = 5000`.\\n5. Enables foreign keys with `PRAGMA foreign_keys = ON`.\\n6. Initializes and reconciles the schema.\\n\\nWAL mode and the busy timeout reduce `SQLITE_BUSY` failures under parallel workflow execution.\\n\\n### Placeholder conversion\\n\\nCore persistence code uses PostgreSQL-style positional placeholders:\\n\\n```sql\\nSELECT * FROM remote_agent_codebases WHERE id = $1\\n```\\n\\n`SqliteAdapter` converts them to SQLite bindings before preparing statements.\\n\\nDo not put placeholder-shaped text such as `$3` inside SQL comments. Placeholder conversion is lexical and can interpret those comment values as real placeholders, causing a binding-count mismatch.\\n\\n```sql\\n-- Avoid this: $3 is interpreted as a placeholder\\nSELECT * FROM example WHERE id = $1 -- $3\\n```\\n\\n### SQLite `RETURNING` behavior\\n\\nSQLite supports `INSERT ... RETURNING`, including upserts:\\n\\n```sql\\nINSERT INTO remote_agent_isolation_environments (...)\\nVALUES (...)\\nON CONFLICT (...)\\nDO UPDATE SET ...\\nRETURNING *\\n```\\n\\nThe adapter does not support `RETURNING` on `UPDATE` or `DELETE`; such statements fail explicitly. Contributors should use a separate select when that behavior is required under the cross-database abstraction.\\n\\n### SQLite schema compatibility\\n\\nSQLite initialization includes migration and reconciliation logic for pre-existing local databases. It handles schema evolution such as:\\n\\n- Evaluation tables and their indexes.\\n- SLA and runtime trace typed fields.\\n- Workflow-run original-start timestamps.\\n- Isolation and sandbox schema adjustments.\\n- Workflow version snapshots.\\n- Commands table migration from product-only to dual product/system scope.\\n\\nThis makes `SqliteAdapter` responsible for both fresh schema initialization and compatibility with historical local database layouts.\\n\\n---\\n\\n## SQL dialect helpers\\n\\n`SqlDialect` isolates SQL fragments that differ between PostgreSQL and SQLite. Each adapter exposes a dialect object as `.sql`:\\n\\n```ts\\ndb.sql.now();\\ndb.sql.jsonMerge('metadata', 1);\\n```\\n\\n### PostgreSQL dialect\\n\\n`postgresDialect` provides:\\n\\n| Method | PostgreSQL output |\\n| --- | --- |\\n| `generateUuid()` | JavaScript `crypto.randomUUID()` |\\n| `now()` | `NOW()` |\\n| `jsonMerge('metadata', 1)` | `metadata || $1::jsonb` |\\n| `jsonArrayContains('tags', 'labels', 1)` | `tags-&gt;'labels' ? $1` |\\n| `nowMinusDays(1)` | `NOW() - ($1 || ' days')::INTERVAL` |\\n| `daysSince('created_at')` | `EXTRACT(EPOCH FROM (NOW() - created_at)) / 86400` |\\n\\nThe helpers expect trusted SQL identifiers for `column` and `path`; they interpolate those arguments directly. Do not pass user-controlled values as identifiers. Use query parameters for untrusted values.\\n\\n### JSON merge semantics\\n\\nSQLite `json_patch()` recursively preserves unspecified nested fields. This matters when replacing nested metadata such as workflow approval forms.\\n\\nTo remove an old nested field, set it to `null` in the patch:\\n\\n```ts\\nconst patch = JSON.stringify({\\n  approval: {\\n    nodeId: 'collect-clarify',\\n    iteration: 2,\\n    inputSchema: null,\\n  },\\n});\\n```\\n\\nWithout `inputSchema: null`, a prior `inputSchema` may survive a recursive JSON merge and display a stale approval form.\\n\\n---\\n\\n# Runtime, observability, and evaluation integration\\n\\nThe core runtime area contains the cross-cutting infrastructure used to create, normalize, redact, persist, and evaluate execution traces.\\n\\nA typical runtime emission flow is:\\n\\n```mermaid\\nflowchart LR\\n  Emitter[Runtime emitter] --&gt; Policy[Runtime trace policy]\\n  Emitter --&gt; Bus[trace-bus emit]\\n  Emitter --&gt; Event[createTraceEvent]\\n  Event --&gt; DB[(runtime trace tables)]\\n  Emitter --&gt; Redaction[redactRecordWithContext]\\n```\\n\\nKey execution behavior includes:\\n\\n- Runtime emitters call `getRuntimeTracePolicy()` to determine trace behavior.\\n- `event()` normalizes event types through `normalizeRuntimeEventType()` and persists events with `createTraceEvent()`.\\n- Completion, failure, and cancellation share `finishWithStatus()`.\\n- `finishWithStatus()` redacts outbound records through `redactRecordWithContext()`.\\n- Evaluation evidence capture uses `redactEvaluationEvidence()` and `toPreview()` to avoid retaining unsafe or excessively large raw content.\\n- Runtime pricing overrides configured through `trace.priceOverrides` are propagated by `loadConfig()` through `setRuntimePriceOverrides()`.\\n\\nThe database includes persistence for trace records, spans, trace events, observability events, evaluation outputs, evidence coverage, benchmark suites, benchmark runs, golden samples, human feedback, and evaluation knowledge-artifact outbox processing.\\n\\n---\\n\\n# Orchestration and workflow integration\\n\\nThe orchestrator coordinates conversation updates and workflow dispatch. It relies on core database operations to persist state before and during execution.\\n\\nFor example, background workflow dispatch updates conversations through the database layer. Workflow and server-side callers may also invoke `loadConfig()` while resolving workflow YAML, allowing repository settings to influence workflow discovery and substitution.\\n\\nConfiguration values consumed by workflow paths include:\\n\\n- `baseBranch` for `$BASE_BRANCH`.\\n- `docsPath` for `$DOCS_DIR`.\\n- `envVars` for project-scoped execution environment.\\n- Assistant defaults for conversation-oriented provider selection.\\n- Runtime trace price overrides for cost and observability reporting.\\n\\nThe workflow store adapter bridges core persistence and `@archon/workflows`. It constructs dependencies that may use sandbox operations such as file listing, reading file bytes, and running scripts.\\n\\n---\\n\\n# Contribution guidelines\\n\\n## Keep configuration layering explicit\\n\\nWhen adding a configuration field, decide which layer owns it:\\n\\n- Add user-wide preferences to `GlobalConfig`.\\n- Add project-specific behavior to `RepoConfig`.\\n- Add resolved behavior to `MergedConfig`.\\n- Add only deliberately safe fields to `SafeConfig`.\\n\\nThen update the appropriate merge function:\\n\\n- `mergeGlobalConfig()`\\n- `mergeRepoConfig()`\\n- `applyEnvOverrides()`\\n- `toSafeConfig()`\\n\\nDo not accidentally expose a server-only setting merely because it exists in `MergedConfig`.\\n\\n## Preserve provider extensibility\\n\\nProvider registration is dynamic. Avoid adding per-provider branching unless a behavior is intrinsically provider-specific.\\n\\nWhen working with assistant defaults:\\n\\n- Use `mergeAssistantDefaults()` rather than replacing the full map.\\n- Do not assume only `claude` and `codex` exist.\\n- Add a field to `SAFE_ASSISTANT_FIELDS` only after confirming it is appropriate for web clients.\\n- Keep provider parsing and validation inside `@archon/providers` where possible.\\n\\n## Maintain database portability\\n\\nPersistence code should use `IDatabase` and `SqlDialect` helpers rather than assuming PostgreSQL-only syntax.\\n\\nBefore adding SQL:\\n\\n- Verify PostgreSQL and SQLite behavior.\\n- Use `$N` placeholders in application SQL.\\n- Avoid `$N` text inside SQL comments because SQLite placeholder conversion is not SQL-comment aware.\\n- Prefer `withTransaction()` for multi-write state transitions.\\n- Consider existing SQLite migrations when changing a persisted schema.\\n\\n## Preserve error behavior\\n\\nConfiguration failures have intentional semantics:\\n\\n- Missing files are non-fatal.\\n- Invalid YAML is logged and treated as an empty configuration layer.\\n- Unknown providers are fatal configuration errors.\\n- Permission and write failures are logged and rethrown where the caller must act.\\n\\nDatabase transaction behavior also preserves the original failure, even if rollback fails. Avoid changing this behavior without ensuring callers can still diagnose the actual operation that failed.\",\"other-db-governance\":\"# Other \u2014 db-governance\\n\\n# DB \u4e8b\u4ef6\u6570\u636e\u6cbb\u7406\u6a21\u5757\\n\\n`scripts/db-governance` \u662f\u9762\u5411 PostgreSQL 17 \u7684\u4e8b\u4ef6\u6570\u636e\u751f\u547d\u5468\u671f\u6cbb\u7406\u6a21\u5757\uff0c\u7528\u4e8e\u63a7\u5236\u751f\u4ea7\u5e93 `aiflow_prod` \u4e2d\u4e09\u7c7b\u9ad8\u589e\u957f\u4e8b\u4ef6\u8868\u7684\u5b58\u50a8\u91cf\uff1a\\n\\n- `remote_agent_observability_events`\\n- `remote_agent_trace_events`\\n- `remote_agent_workflow_events`\\n\\n\u6a21\u5757\u91c7\u7528 **92 \u5929\u4fdd\u7559\u7a97\u53e3**\uff0c\u8d85\u8fc7\u7a97\u53e3\u7684\u6570\u636e\u76f4\u63a5\u5220\u9664\uff0c\u4e0d\u8fdb\u884c\u5f52\u6863\u300292 \u5929\u4e0e SLA canonical rollup \u7684\u6700\u5927\u67e5\u8be2\u7a97\u53e3\u4fdd\u6301\u4e00\u81f4\uff0c\u56e0\u6b64\u4e8b\u4ef6\u6e90\u6570\u636e\u81f3\u5c11\u9700\u8981\u4fdd\u7559 92 \u5929\uff0c\u4ee5\u4fbf\u540e\u7eed SLA \u810f\u6570\u636e\u91cd\u5efa\u80fd\u591f\u8bfb\u53d6\u5b8c\u6574\u6e90\u6570\u636e\u3002\\n\\n\u8be5\u6a21\u5757\u4e0d\u63d0\u4f9b\u5e94\u7528\u5c42\u51fd\u6570\u6216\u670d\u52a1\u63a5\u53e3\uff0c\u6240\u6709\u64cd\u4f5c\u901a\u8fc7 `psql` \u6267\u884c SQL \u811a\u672c\u5b8c\u6210\u3002\\n\\n## \u6cbb\u7406\u6d41\u7a0b\\n\\n```mermaid\\nflowchart LR\\n    P[00_preflight\u53ea\u8bfb\u68c0\u67e5] --&gt; S1[01-03\u5728\u7ebf\u6362\u8868]\\n    S1 --&gt; V[04_verify\u53ea\u8bfb\u9a8c\u8bc1]\\n    V --&gt; O[\u89c2\u5bdf\u8bfb\u5199\u7a33\u5b9a\u6027]\\n    O --&gt; D[05_drop_old\u786e\u8ba4\u540e\u5220\u9664]\\n    P --&gt; R[10_rolling_cleanup\u6279\u91cf\u5220\u9664]\\n    R --&gt; R\\n```\\n\\n\u6a21\u5757\u5305\u542b\u4e24\u4e2a\u6e05\u7406\u9636\u6bb5\uff1a\\n\\n1. **\u9636\u6bb5\u4e00\uff1a\u6362\u8868\u7626\u8eab**\\n   - \u521b\u5efa\u4ec5\u5305\u542b\u8fd1 92 \u5929\u6570\u636e\u7684 `_new` \u8868\u3002\\n   - \u5728\u65b0\u8868\u4e0a\u91cd\u5efa\u4e3b\u952e\u3001\u7d22\u5f15\u3001\u51fa\u5411\u5916\u952e\u548c\u89e6\u53d1\u5668\u3002\\n   - \u5728\u77ed\u4e8b\u52a1\u4e2d\u5207\u6362\u8868\u540d\u3002\\n   - \u539f\u8868\u6539\u540d\u4e3a `_old`\uff0c\u6682\u4e0d\u5220\u9664\u3002\\n2. **\u9636\u6bb5\u4e8c\uff1a\u5728\u7ebf\u6279\u5220**\\n   - \u4f7f\u7528\u5c0f\u6279\u91cf `DELETE` \u5220\u9664\u8d85\u8fc7 92 \u5929\u7684\u6570\u636e\u3002\\n   - \u9002\u5408\u6362\u8868\u5b8c\u6210\u540e\u7684\u65e5\u5e38\u7a33\u6001\u7ef4\u62a4\u3002\\n   - \u53ef\u91cd\u590d\u6267\u884c\uff0c\u76f4\u5230\u5f85\u5220\u884c\u6570\u4e3a\u96f6\u3002\\n\\n## \u524d\u7f6e\u6761\u4ef6\\n\\n### \u5ba2\u6237\u7aef\u548c\u8fde\u63a5\\n\\n\u811a\u672c\u8981\u6c42\u4f7f\u7528 PostgreSQL 17 \u7684 `psql` \u5ba2\u6237\u7aef\u3002\u8fde\u63a5\u4fe1\u606f\u901a\u8fc7\u73af\u5883\u53d8\u91cf\u63d0\u4f9b\uff1a\\n\\n```bash\\nexport PGHOST=\\nexport PGPORT=\\nexport PGUSER=\\nexport PGDATABASE=aiflow_prod\\n```\\n\\n\u5bc6\u7801\u5e94\u901a\u8fc7 `~/.pgpass` \u6216\u4ea4\u4e92\u5f0f\u8f93\u5165\u63d0\u4f9b\uff0c\u4e0d\u8981\u5c06\u660e\u6587\u5bc6\u7801\u5199\u5165\u811a\u672c\u3001\u547d\u4ee4\u884c\u6216 shell \u5386\u53f2\u3002\\n\\n### \u6743\u9650\u548c\u6267\u884c\u7a97\u53e3\\n\\n`01_shrink_observability_events.sql`\u3001`02_shrink_trace_events.sql`\u3001`03_shrink_workflow_events.sql`\u3001`05_drop_old_tables.sql` \u548c `10_rolling_cleanup.sql` \u90fd\u4f1a\u4fee\u6539\u6570\u636e\u6216\u6570\u636e\u5e93\u5bf9\u8c61\uff0c\u9700\u8981\u76f8\u5e94\u7684\u6570\u636e\u5e93\u6743\u9650\u3002\\n\\n\u9636\u6bb5\u4e00\u6d89\u53ca\u8868\u5207\u6362\u548c `ACCESS EXCLUSIVE` \u9501\uff0c\u5e94\u5b89\u6392\u5728\u4f4e\u5cf0\u671f\u6267\u884c\u3002\u867d\u7136\u6570\u636e\u590d\u5236\u548c\u7d22\u5f15\u521b\u5efa\u4e0d\u9501\u539f\u8868\uff0c\u4f46\u6700\u7ec8\u6362\u8868\u4e8b\u52a1\u4ecd\u4f1a\u963b\u585e\u76ee\u6807\u8868\u4e0a\u7684\u5e76\u53d1\u8bbf\u95ee\uff0c\u76f4\u5230\u4e8b\u52a1\u63d0\u4ea4\u3002\\n\\n## \u811a\u672c\u6e05\u5355\\n\\n| \u811a\u672c | \u7c7b\u578b | \u4f5c\u7528 |\\n|---|---|---|\\n| `00_preflight.sql` | \u53ea\u8bfb | \u68c0\u67e5\u6570\u636e\u5e93\u5927\u5c0f\u3001\u4e09\u8868\u4f53\u79ef\u3001\u4fdd\u7559/\u5f85\u5220\u6570\u636e\u3001\u5916\u952e\u3001\u7d22\u5f15\u548c\u89e6\u53d1\u5668 |\\n| `01_shrink_observability_events.sql` | \u5199\u64cd\u4f5c | \u91cd\u5efa `remote_agent_observability_events` |\\n| `02_shrink_trace_events.sql` | \u5199\u64cd\u4f5c | \u91cd\u5efa `remote_agent_trace_events` |\\n| `03_shrink_workflow_events.sql` | \u5199\u64cd\u4f5c | \u91cd\u5efa `remote_agent_workflow_events` |\\n| `04_verify_after_shrink.sql` | \u53ea\u8bfb | \u9a8c\u8bc1\u6362\u8868\u540e\u7684\u884c\u6570\u3001\u7d22\u5f15\u3001\u89e6\u53d1\u5668\u3001\u5916\u952e\u548c `_old` \u8868 |\\n| `05_drop_old_tables.sql` | \u5199\u64cd\u4f5c | \u5728\u660e\u786e\u786e\u8ba4\u540e\u5220\u9664\u4e09\u5f20 `_old` \u8868 |\\n| `10_rolling_cleanup.sql` | \u5199\u64cd\u4f5c | \u6309\u6279\u6b21\u5220\u9664\u4e09\u5f20\u4e3b\u8868\u4e2d\u7684\u8fc7\u671f\u4e8b\u4ef6\u5e76\u6267\u884c `VACUUM (ANALYZE)` |\\n\\n## \u6807\u51c6\u6267\u884c\u987a\u5e8f\\n\\n### 1. \u6267\u884c\u524d\u68c0\u67e5\\n\\n```bash\\npsql -f scripts/db-governance/00_preflight.sql\\n```\\n\\n\u786e\u8ba4\u4ee5\u4e0b\u4fe1\u606f\uff1a\\n\\n- \u5f53\u524d\u6570\u636e\u5e93\u5927\u5c0f\u3002\\n- \u4e09\u5f20\u76ee\u6807\u8868\u7684\u603b\u5927\u5c0f\u3001heap \u5927\u5c0f\u548c\u7d22\u5f15\u5927\u5c0f\u3002\\n- \u6309\u4fdd\u7559\u7a97\u53e3\u8ba1\u7b97\u7684 `keep` \u548c `del` \u884c\u6570\u3002\\n- \u662f\u5426\u5b58\u5728\u5f15\u7528\u4e09\u5f20\u4e8b\u4ef6\u8868\u7684\u53cd\u5411\u5916\u952e\u3002\\n- \u5f53\u524d\u7d22\u5f15 DDL\u3002\\n- \u5f53\u524d\u975e\u5185\u90e8\u89e6\u53d1\u5668\u5b9a\u4e49\u3002\\n- \u5f53\u524d\u4e09\u5f20\u8868\u4e0a\u7684\u51fa\u5411\u5916\u952e\u5b9a\u4e49\u3002\\n\\n`\u53cd\u5411\u5916\u952e`\u68c0\u67e5\u7ed3\u679c\u5e94\u4e3a\u7a7a\u3002\u5982\u679c\u5176\u4ed6\u8868\u901a\u8fc7\u5916\u952e\u5f15\u7528\u76ee\u6807\u4e8b\u4ef6\u8868\uff0c\u76f4\u63a5\u6362\u8868\u53ef\u80fd\u88ab\u4f9d\u8d56\u5173\u7cfb\u963b\u585e\uff0c\u5fc5\u987b\u5148\u8bc4\u4f30\u6216\u5904\u7406\u8fd9\u4e9b\u4f9d\u8d56\u3002\\n\\n### 2. \u6267\u884c\u9636\u6bb5\u4e00\u6362\u8868\\n\\n\u6309\u4ee5\u4e0b\u987a\u5e8f\u6267\u884c\uff1a\\n\\n```bash\\npsql -f scripts/db-governance/01_shrink_observability_events.sql\\npsql -f scripts/db-governance/02_shrink_trace_events.sql\\npsql -f scripts/db-governance/03_shrink_workflow_events.sql\\n```\\n\\n\u6bcf\u4e2a\u811a\u672c\u90fd\u542f\u7528\uff1a\\n\\n```sql\\n\\\\set ON_ERROR_STOP on\\n\\\\set retention_days 92\\n```\\n\\n\u4efb\u4f55 SQL \u9519\u8bef\u90fd\u4f1a\u505c\u6b62\u5f53\u524d\u811a\u672c\uff0c\u907f\u514d\u7ee7\u7eed\u6267\u884c\u540e\u7eed\u6362\u8868\u6b65\u9aa4\u3002\\n\\n\u6bcf\u5f20\u8868\u7684\u6362\u8868\u8fc7\u7a0b\u90fd\u662f\uff1a\\n\\n1. \u5220\u9664\u9057\u7559\u7684 `\n_new` \u4e34\u65f6\u8868\u3002\\n2. \u4f7f\u7528 `LIKE ... INCLUDING ...` \u521b\u5efa\u65b0\u8868\u7ed3\u6784\u3002\\n3. \u5c06\u4fdd\u7559\u7a97\u53e3\u5185\u7684\u6570\u636e\u5199\u5165\u65b0\u8868\u3002\\n4. \u521b\u5efa\u4e3b\u952e\u3001\u7d22\u5f15\u5e76\u6267\u884c `ANALYZE`\u3002\\n5. \u521b\u5efa\u51fa\u5411\u5916\u952e\u3002\\n6. \u9501\u5b9a\u539f\u8868\u5e76\u5728\u4e8b\u52a1\u5185\u5b8c\u6210\u8868\u540d\u5207\u6362\u3002\\n7. \u5728\u65b0\u4e3b\u8868\u4e0a\u91cd\u5efa\u89e6\u53d1\u5668\u3002\\n8. \u4fdd\u7559\u539f\u8868\u4e3a `\n_old`\u3002\\n\\n### 3. \u9a8c\u8bc1\u6362\u8868\u7ed3\u679c\\n\\n```bash\\npsql -f scripts/db-governance/04_verify_after_shrink.sql\\n```\\n\\n\u8be5\u811a\u672c\u662f\u53ea\u8bfb\u9a8c\u8bc1\uff0c\u4e0d\u4f1a\u4fee\u6539\u6570\u636e\u5e93\u3002\u91cd\u70b9\u68c0\u67e5\uff1a\\n\\n- \u4e3b\u8868\u5f53\u524d\u884c\u6570\u3002\\n- \u4e3b\u8868\u4e2d\u8d85\u8fc7 92 \u5929\u7684\u6570\u636e\u5e94\u4e3a\u96f6\u3002\\n- \u7d22\u5f15\u6570\u91cf\uff1a\\n  - `remote_agent_observability_events`\uff1a20\\n  - `remote_agent_trace_events`\uff1a16\\n  - `remote_agent_workflow_events`\uff1a5\\n- \u89e6\u53d1\u5668\u6570\u91cf\uff1a\\n  - observability\uff1a1\\n  - trace\uff1a1\\n  - workflow\uff1a2\\n- \u51fa\u5411\u5916\u952e\u6570\u91cf\uff1a\\n  - observability\uff1a5\\n  - trace\uff1a2\\n  - workflow\uff1a1\\n- \u4e09\u5f20 `_old` \u8868\u4ecd\u7136\u5b58\u5728\u3002\\n\\n\u9664\u6570\u636e\u5e93\u68c0\u67e5\u5916\uff0c\u8fd8\u5e94\u89c2\u5bdf\u5e94\u7528\u8bfb\u5199\u3001\u4e8b\u4ef6\u5199\u5165\u3001SLA rollup \u548c\u76f8\u5173\u67e5\u8be2\u662f\u5426\u6b63\u5e38\u3002\u53ea\u6709\u5728\u89c2\u5bdf\u7a97\u53e3\u7ed3\u675f\u4e14\u786e\u8ba4\u65e0\u5f02\u5e38\u540e\uff0c\u624d\u80fd\u5220\u9664 `_old` \u8868\u3002\\n\\n### 4. \u5220\u9664\u65e7\u8868\\n\\n\u9ed8\u8ba4\u6267\u884c\u4e0d\u4f1a\u5220\u9664\u4efb\u4f55\u8868\uff1a\\n\\n```bash\\npsql -f scripts/db-governance/05_drop_old_tables.sql\\n```\\n\\n\u786e\u8ba4\u6362\u8868\u7ed3\u679c\u540e\uff0c\u663e\u5f0f\u4f20\u5165 `confirmed=yes`\uff1a\\n\\n```bash\\npsql -v confirmed=yes \\\\\\n  -f scripts/db-governance/05_drop_old_tables.sql\\n```\\n\\n\u811a\u672c\u53ea\u6709\u5728 `confirmed` \u7cbe\u786e\u7b49\u4e8e `yes` \u65f6\u624d\u6267\u884c\uff1a\\n\\n```sql\\nDROP TABLE IF EXISTS remote_agent_observability_events_old;\\nDROP TABLE IF EXISTS remote_agent_trace_events_old;\\nDROP TABLE IF EXISTS remote_agent_workflow_events_old;\\n```\\n\\n\u5220\u9664\u5b8c\u6210\u540e\uff0c\u811a\u672c\u8f93\u51fa\u5f53\u524d\u6570\u636e\u5e93\u5927\u5c0f\u3002`DROP TABLE` \u4f1a\u91ca\u653e\u8868\u53ca\u5176\u7d22\u5f15\u5360\u7528\u7684\u7a7a\u95f4\uff1b\u4e0e\u6279\u91cf `DELETE` \u4e0d\u540c\uff0c\u7a7a\u95f4\u56de\u6536\u6548\u679c\u901a\u5e38\u66f4\u76f4\u63a5\u3002\\n\\n## \u5404\u76ee\u6807\u8868\u7684\u4fdd\u7559\u89c4\u5219\\n\\n| \u8868 | \u65f6\u95f4\u5217 | \u4fdd\u7559\u6761\u4ef6 |\\n|---|---|---|\\n| `remote_agent_observability_events` | `occurred_at` | `occurred_at &gt;= now() - 92 days` |\\n| `remote_agent_trace_events` | `created_at` | `created_at &gt;= now() - 92 days` |\\n| `remote_agent_workflow_events` | `created_at` | `created_at &gt;= now() - 92 days` |\\n\\n\u4e09\u4e2a\u811a\u672c\u90fd\u4f7f\u7528 PostgreSQL \u7684 `make_interval` \u6784\u9020\u65f6\u95f4\u7a97\u53e3\uff1a\\n\\n```sql\\nnow() - make_interval(days =&gt; :retention_days)\\n```\\n\\n\u4fdd\u7559\u5929\u6570\u7531\u5404\u811a\u672c\u9876\u90e8\u7684 `\\\\set retention_days 92` \u63a7\u5236\u3002\u4e0d\u5f97\u5c06\u5176\u8bbe\u7f6e\u4e3a\u5c0f\u4e8e SLA \u6700\u5927\u56de\u7b97\u7a97\u53e3\u7684\u503c\uff0c\u5426\u5219 SLA dirty bucket \u91cd\u5efa\u53ef\u80fd\u56e0\u7f3a\u5c11\u539f\u59cb\u4e8b\u4ef6\u800c\u4ea7\u751f\u4e0d\u5b8c\u6574\u7ed3\u679c\u3002\\n\\n## \u9636\u6bb5\u4e00\uff1a\u6362\u8868\u5b9e\u73b0\u7ec6\u8282\\n\\n### \u65b0\u8868\u521b\u5efa\u548c\u6570\u636e\u590d\u5236\\n\\n\u4ee5 `remote_agent_observability_events` \u4e3a\u4f8b\uff1a\\n\\n```sql\\nCREATE TABLE remote_agent_observability_events_new\\n  (LIKE remote_agent_observability_events\\n     INCLUDING DEFAULTS\\n     INCLUDING CONSTRAINTS\\n     INCLUDING COMMENTS\\n     INCLUDING STORAGE);\\n\\nINSERT INTO remote_agent_observability_events_new\\nSELECT *\\nFROM remote_agent_observability_events\\nWHERE occurred_at &gt;= now() - make_interval(days =&gt; :retention_days);\\n```\\n\\n\u6570\u636e\u590d\u5236\u9636\u6bb5\u4e0d\u9501\u5b9a\u539f\u8868\uff0c\u5e94\u7528\u53ef\u4ee5\u7ee7\u7eed\u8bfb\u5199\u539f\u8868\u3002\u65b0\u8868\u4e0d\u4f1a\u5728\u704c\u6570\u9636\u6bb5\u521b\u5efa\u4e1a\u52a1\u89e6\u53d1\u5668\uff0c\u907f\u514d\u590d\u5236\u5386\u53f2\u6570\u636e\u65f6\u89e6\u53d1 SLA \u810f\u6807\u8bb0\u903b\u8f91\u3002\\n\\n### \u4e3b\u952e\u548c\u7d22\u5f15\\n\\n\u6bcf\u4e2a\u65b0\u8868\u5148\u4f7f\u7528\u4e34\u65f6\u540d\u79f0\u521b\u5efa\u4e3b\u952e\u548c\u7d22\u5f15\uff0c\u4f8b\u5982\uff1a\\n\\n```sql\\nALTER TABLE remote_agent_trace_events_new\\n  ADD CONSTRAINT remote_agent_trace_events_pkey__new PRIMARY KEY (id);\\n```\\n\\n\u7d22\u5f15\u540c\u6837\u4f7f\u7528 `__new` \u540e\u7f00\u3002\u6362\u8868\u6210\u529f\u540e\uff0c\u518d\u5c06\u8fd9\u4e9b\u5bf9\u8c61\u91cd\u547d\u540d\u4e3a\u6b63\u5f0f\u540d\u79f0\u3002\u8fd9\u6837\u53ef\u4ee5\uff1a\\n\\n- \u4fdd\u6301\u5e94\u7528\u548c\u67e5\u8be2\u4f9d\u8d56\u7684\u8868\u540d\u4e0d\u53d8\u3002\\n- \u4fdd\u6301\u73b0\u6709\u7d22\u5f15\u540d\u79f0\u4e0d\u53d8\u3002\\n- \u907f\u514d\u65b0\u65e7\u8868\u540c\u65f6\u5360\u7528\u76f8\u540c\u7684\u7d22\u5f15\u540d\u79f0\u3002\\n- \u8ba9 `04_verify_after_shrink.sql` \u80fd\u6309\u89c4\u8303\u540d\u79f0\u9a8c\u8bc1\u7d22\u5f15\u3002\\n\\n\u65b0\u8868\u521b\u5efa\u7d22\u5f15\u540e\u4f1a\u6267\u884c\uff1a\\n\\n```sql\\nANALYZE \n_new;\\n```\\n\\n\u4ee5\u4fbf\u6362\u8868\u540e\u67e5\u8be2\u4f18\u5316\u5668\u7acb\u5373\u83b7\u5f97\u65b0\u8868\u7edf\u8ba1\u4fe1\u606f\u3002\\n\\n### `remote_agent_observability_events`\\n\\n\u8be5\u8868\u91cd\u5efa\uff1a\\n\\n- \u4e3b\u952e `remote_agent_observability_events_pkey`\\n- 10 \u4e2a\u5355\u5217\u6216\u7ec4\u5408\u67e5\u8be2\u7d22\u5f15\\n- \u591a\u4e2a\u9762\u5411\u6d3b\u52a8\u3001\u6d41\u91cf\u3001\u63a2\u9488\u548c\u9519\u8bef\u67e5\u8be2\u7684\u8986\u76d6\u7d22\u5f15\\n- 4 \u4e2a\u6761\u4ef6\u7d22\u5f15\uff0c\u5305\u62ec\uff1a\\n  - \u524d\u7aef active probe API \u8c03\u7528\\n  - `page_view` \u548c `action` \u4ea4\u4e92\u4e8b\u4ef6\\n  - API/\u540e\u7aef/\u524d\u7aef/\u5de5\u4f5c\u6d41\u8282\u70b9\u9519\u8bef\u4fe1\u53f7\\n  - \u524d\u7aef API \u8c03\u7528\u4e2d `http_status IS NULL`\\n\\n\u65b0\u8868\u521b\u5efa 5 \u4e2a\u51fa\u5411\u5916\u952e\uff1a\\n\\n- `product_id` \u2192 `remote_agent_product_spaces(product_id)`\uff0c`ON DELETE SET NULL`\\n- `codebase_id` \u2192 `remote_agent_codebases(id)`\uff0c`ON DELETE SET NULL`\\n- `conversation_id` \u2192 `remote_agent_conversations(id)`\uff0c`ON DELETE SET NULL`\\n- `workflow_run_id` \u2192 `remote_agent_workflow_runs(id)`\uff0c`ON DELETE SET NULL`\\n- `trace_id` \u2192 `remote_agent_traces(id)`\uff0c`ON DELETE SET NULL`\\n\\n\u6362\u8868\u540e\u521b\u5efa\u89e6\u53d1\u5668\uff1a\\n\\n```sql\\nCREATE TRIGGER trg_observability_events_sla_dirty\\n  AFTER INSERT OR UPDATE ON remote_agent_observability_events\\n  FOR EACH ROW\\n  EXECUTE FUNCTION remote_agent_mark_sla_rollup_dirty();\\n```\\n\\n### `remote_agent_trace_events`\\n\\n\u8be5\u8868\u91cd\u5efa 15 \u4e2a\u4e1a\u52a1\u7d22\u5f15\u548c\u4e00\u4e2a\u4e3b\u952e\uff0c\u5171 16 \u4e2a\u7d22\u5f15\u3002\u7d22\u5f15\u8986\u76d6\uff1a\\n\\n- trace \u4e0e\u521b\u5efa\u65f6\u95f4\u67e5\u8be2\\n- \u4e8b\u4ef6\u7c7b\u578b\\n- workflow run\\n- conversation\\n- provider\u3001model\\n- node\u3001skill\\n- \u5931\u8d25\u4e8b\u4ef6\\n- SLA \u5931\u8d25\u4e8b\u4ef6\\n- usage \u6570\u636e\u4e8b\u4ef6\\n\\n\u5176\u4e2d\u90e8\u5206\u7d22\u5f15\u662f\u6761\u4ef6\u7d22\u5f15\uff1a\\n\\n```sql\\nCREATE INDEX ...\\n  WHERE is_sla_failure;\\n\\nCREATE INDEX ...\\n  WHERE has_usage_data;\\n```\\n\\n\u65b0\u8868\u521b\u5efa 2 \u4e2a\u51fa\u5411\u5916\u952e\uff1a\\n\\n- `trace_id` \u2192 `remote_agent_traces(id)`\uff0c`ON DELETE CASCADE`\\n- `span_id` \u2192 `remote_agent_trace_spans(id)`\uff0c`ON DELETE SET NULL`\\n\\n\u6362\u8868\u540e\u521b\u5efa\uff1a\\n\\n```sql\\nCREATE TRIGGER trg_trace_events_sla_dirty\\n  AFTER INSERT OR UPDATE ON remote_agent_trace_events\\n  FOR EACH ROW\\n  EXECUTE FUNCTION remote_agent_mark_sla_rollup_dirty();\\n```\\n\\n### `remote_agent_workflow_events`\\n\\n\u8be5\u8868\u91cd\u5efa 4 \u4e2a\u4e1a\u52a1\u7d22\u5f15\u548c\u4e00\u4e2a\u4e3b\u952e\uff0c\u5171 5 \u4e2a\u7d22\u5f15\uff1a\\n\\n- `workflow_run_id`\\n- `event_type`\\n- `(event_type, created_at DESC, workflow_run_id)`\\n- `(workflow_run_id, event_type, created_at DESC)`\\n\\n\u65b0\u8868\u521b\u5efa 1 \u4e2a\u51fa\u5411\u5916\u952e\uff1a\\n\\n- `workflow_run_id` \u2192 `remote_agent_workflow_runs(id)`\uff0c`ON DELETE CASCADE`\\n\\n\u8be5\u8868\u7684 SLA \u810f\u6807\u8bb0\u5206\u4e3a\u63d2\u5165\u548c\u66f4\u65b0\u4e24\u4e2a\u89e6\u53d1\u5668\uff1a\\n\\n```sql\\nCREATE TRIGGER trg_workflow_failure_events_sla_dirty\\n  AFTER INSERT ON remote_agent_workflow_events\\n  FOR EACH ROW\\n  WHEN (new.event_type IN ('node_failed', 'workflow_failed'))\\n  EXECUTE FUNCTION remote_agent_mark_sla_rollup_dirty();\\n```\\n\\n```sql\\nCREATE TRIGGER trg_workflow_failure_events_update_sla_dirty\\n  AFTER UPDATE OF workflow_run_id, event_type, data, created_at\\n  ON remote_agent_workflow_events\\n  FOR EACH ROW\\n  WHEN (\\n    new.event_type IN ('node_failed', 'workflow_failed')\\n    OR old.event_type IN ('node_failed', 'workflow_failed')\\n  )\\n  EXECUTE FUNCTION remote_agent_mark_sla_rollup_dirty();\\n```\\n\\n\u53ea\u6709\u5931\u8d25\u76f8\u5173\u5de5\u4f5c\u6d41\u4e8b\u4ef6\u624d\u4f1a\u89e6\u53d1\u5bf9\u5e94\u7684 SLA dirty \u6807\u8bb0\u903b\u8f91\u3002\\n\\n## \u8868\u5207\u6362\u548c\u9501\u884c\u4e3a\\n\\n\u6362\u8868\u7684\u5173\u952e\u4e8b\u52a1\u7ed3\u6784\u5982\u4e0b\uff1a\\n\\n```sql\\nBEGIN;\\nLOCK TABLE remote_agent_&lt;...&gt;_events IN ACCESS EXCLUSIVE MODE;\\n\\nALTER TABLE remote_agent_&lt;...&gt;_events\\n  RENAME TO remote_agent_&lt;...&gt;_events_old;\\n\\nALTER TABLE remote_agent_&lt;...&gt;_events_new\\n  RENAME TO remote_agent_&lt;...&gt;_events;\\n\\n-- \u91cd\u547d\u540d\u4e3b\u952e\u548c\u7d22\u5f15\\n-- \u521b\u5efa\u6b63\u5f0f\u8868\u89e6\u53d1\u5668\\n\\nCOMMIT;\\n```\\n\\n\u6570\u636e\u590d\u5236\u3001\u7d22\u5f15\u521b\u5efa\u3001\u7edf\u8ba1\u4fe1\u606f\u6536\u96c6\u548c\u5916\u952e\u521b\u5efa\u90fd\u5728\u6362\u8868\u4e8b\u52a1\u4e4b\u5916\u5b8c\u6210\u3002`ACCESS EXCLUSIVE` \u9501\u4ec5\u7528\u4e8e\u6700\u540e\u7684\u5bf9\u8c61\u5207\u6362\uff0c\u56e0\u6b64\u9501\u6301\u6709\u65f6\u95f4\u4e3b\u8981\u53d6\u51b3\u4e8e `ALTER TABLE`\u3001\u5bf9\u8c61\u91cd\u547d\u540d\u548c\u89e6\u53d1\u5668\u521b\u5efa\uff0c\u800c\u4e0d\u662f\u5386\u53f2\u6570\u636e\u91cf\u3002\\n\\n\u6267\u884c\u8005\u4ecd\u9700\u786e\u4fdd\uff1a\\n\\n- \u6ca1\u6709\u957f\u65f6\u95f4\u8fd0\u884c\u7684\u67e5\u8be2\u6301\u6709\u76ee\u6807\u8868\u9501\u3002\\n- \u6ca1\u6709\u957f\u4e8b\u52a1\u963b\u585e `LOCK TABLE`\u3002\\n- \u5e94\u7528\u8fde\u63a5\u6c60\u80fd\u591f\u5904\u7406\u77ed\u6682\u7b49\u5f85\u6216\u91cd\u8bd5\u3002\\n- \u4e09\u5f20\u8868\u6700\u597d\u5206\u5f00\u6267\u884c\uff0c\u4ee5\u4fbf\u5355\u8868\u51fa\u73b0\u95ee\u9898\u65f6\u5bb9\u6613\u5b9a\u4f4d\u3002\\n\\n## \u9636\u6bb5\u4e8c\uff1a\u6eda\u52a8\u6279\u91cf\u6e05\u7406\\n\\n```bash\\npsql -f scripts/db-governance/10_rolling_cleanup.sql\\n```\\n\\n\u9ed8\u8ba4\u53c2\u6570\u4e3a\uff1a\\n\\n```sql\\n\\\\set retention_days 92\\n\\\\set batch_size 50000\\n```\\n\\n\u6bcf\u6b21\u6267\u884c\u5206\u522b\u4ece\u4e09\u5f20\u4e3b\u8868\u6700\u591a\u5220\u9664 50,000 \u884c\uff1a\\n\\n```sql\\nDELETE FROM remote_agent_trace_events\\nWHERE ctid IN (\\n  SELECT ctid\\n  FROM remote_agent_trace_events\\n  WHERE created_at &lt; now() - make_interval(days =&gt; :retention_days)\\n  LIMIT :batch_size\\n);\\n```\\n\\n\u6e05\u7406\u903b\u8f91\u4f7f\u7528 `ctid` \u5b9a\u4f4d\u672c\u6279\u8981\u5220\u9664\u7684\u884c\u3002\u5b50\u67e5\u8be2\u6ca1\u6709\u6307\u5b9a\u6392\u5e8f\uff0c\u56e0\u6b64\u6bcf\u6279\u5220\u9664\u7684\u5177\u4f53\u884c\u4e0d\u4fdd\u8bc1\u6309\u65f6\u95f4\u987a\u5e8f\uff0c\u4f46\u91cd\u590d\u6267\u884c\u6700\u7ec8\u4f1a\u6e05\u9664\u6240\u6709\u6ee1\u8db3\u8fc7\u671f\u6761\u4ef6\u7684\u884c\u3002\\n\\n\u811a\u672c\u4f1a\u5728\u4e09\u5f20\u8868\u5220\u9664\u540e\u7edf\u8ba1\u5269\u4f59\u5f85\u5220\u884c\u6570\uff1a\\n\\n```text\\nremaining_del = 0\\n```\\n\\n\u8868\u793a\u5bf9\u5e94\u8868\u5f53\u524d\u6ca1\u6709\u8d85\u8fc7\u4fdd\u7559\u7a97\u53e3\u7684\u6570\u636e\u3002\u82e5\u4ecd\u5927\u4e8e\u96f6\uff0c\u5e94\u91cd\u590d\u6267\u884c\u811a\u672c\uff1a\\n\\n```bash\\npsql -f scripts/db-governance/10_rolling_cleanup.sql\\n```\\n\\n### \u6e05\u7406\u540e\u7684\u7a7a\u95f4\u5904\u7406\\n\\n\u811a\u672c\u6700\u540e\u6267\u884c\uff1a\\n\\n```sql\\nVACUUM (ANALYZE) remote_agent_observability_events;\\nVACUUM (ANALYZE) remote_agent_trace_events;\\nVACUUM (ANALYZE) remote_agent_workflow_events;\\n```\\n\\n\u8fd9\u4f1a\uff1a\\n\\n- \u56de\u6536\u5df2\u5220\u9664\u884c\u5230 PostgreSQL \u7684\u53ef\u590d\u7528\u7a7a\u95f4\u3002\\n- \u66f4\u65b0\u67e5\u8be2\u7edf\u8ba1\u4fe1\u606f\u3002\\n- \u9632\u6b62\u8868\u6301\u7eed\u81a8\u80c0\u3002\\n\\n\u666e\u901a `VACUUM` \u901a\u5e38\u4e0d\u4f1a\u5c06\u7a7a\u95f4\u76f4\u63a5\u5f52\u8fd8\u7ed9\u64cd\u4f5c\u7cfb\u7edf\u3002\u5982\u679c\u76ee\u6807\u662f\u7acb\u523b\u7f29\u5c0f\u7269\u7406\u6587\u4ef6\uff0c\u5f53\u524d\u6a21\u5757\u6ca1\u6709\u6267\u884c `VACUUM FULL` \u6216\u5728\u7ebf\u8868\u91cd\u5199\uff1b\u9636\u6bb5\u4e00\u7684\u6362\u8868\u6d41\u7a0b\u66f4\u9002\u5408\u76f4\u63a5\u91ca\u653e\u65e7\u8868\u5360\u7528\u7684\u7a7a\u95f4\u3002\\n\\n## \u4e0e\u5176\u4ed6\u6570\u636e\u5e93\u5bf9\u8c61\u7684\u8fde\u63a5\\n\\n\u8be5\u6a21\u5757\u4e0d\u4f9d\u8d56\u5e94\u7528\u5c42\u8c03\u7528\u56fe\uff0c\u4e5f\u6ca1\u6709\u6a21\u5757\u5185\u51fd\u6570\u8c03\u7528\u3002\u5b83\u901a\u8fc7 PostgreSQL \u5bf9\u8c61\u8fde\u63a5\u5230\u5176\u4ed6\u6570\u636e\u6a21\u578b\u3002\\n\\n### \u5916\u952e\u4f9d\u8d56\\n\\n| \u4e8b\u4ef6\u8868 | \u5f15\u7528\u5bf9\u8c61 | \u5220\u9664\u884c\u4e3a |\\n|---|---|---|\\n| `remote_agent_observability_events` | `remote_agent_product_spaces(product_id)` | `SET NULL` |\\n| `remote_agent_observability_events` | `remote_agent_codebases(id)` | `SET NULL` |\\n| `remote_agent_observability_events` | `remote_agent_conversations(id)` | `SET NULL` |\\n| `remote_agent_observability_events` | `remote_agent_workflow_runs(id)` | `SET NULL` |\\n| `remote_agent_observability_events` | `remote_agent_traces(id)` | `SET NULL` |\\n| `remote_agent_trace_events` | `remote_agent_traces(id)` | `CASCADE` |\\n| `remote_agent_trace_events` | `remote_agent_trace_spans(id)` | `SET NULL` |\\n| `remote_agent_workflow_events` | `remote_agent_workflow_runs(id)` | `CASCADE` |\\n\\n`00_preflight.sql` \u4f1a\u68c0\u67e5\u662f\u5426\u6709\u5176\u4ed6\u8868\u53cd\u5411\u5f15\u7528\u8fd9\u4e09\u5f20\u4e8b\u4ef6\u8868\u3002\u8be5\u68c0\u67e5\u5fc5\u987b\u4e3a\u7a7a\uff0c\u6216\u8005\u7531 DBA \u660e\u786e\u8bc4\u4f30\u5176\u5f71\u54cd\u540e\u518d\u6267\u884c\u6362\u8868\u3002\\n\\n### SLA \u810f\u6807\u8bb0\\n\\n\u4e09\u5f20\u8868\u7684\u6362\u8868\u811a\u672c\u90fd\u4f1a\u5728\u6b63\u5f0f\u8868\u4e0a\u91cd\u65b0\u521b\u5efa\u4e0e SLA rollup \u76f8\u5173\u7684\u89e6\u53d1\u5668\u3002\u8fd9\u4e9b\u89e6\u53d1\u5668\u8c03\u7528\u73b0\u6709\u6570\u636e\u5e93\u51fd\u6570\uff1a\\n\\n```sql\\nremote_agent_mark_sla_rollup_dirty()\\n```\\n\\n\u65b0\u8868\u704c\u5165\u5386\u53f2\u6570\u636e\u65f6\u4e0d\u4f1a\u521b\u5efa\u89e6\u53d1\u5668\uff1b\u89e6\u53d1\u5668\u53ea\u5728\u6362\u8868\u5b8c\u6210\u540e\u6062\u590d\uff0c\u56e0\u6b64\u5386\u53f2\u590d\u5236\u4e0d\u4f1a\u4ea7\u751f\u989d\u5916\u7684 dirty \u6807\u8bb0\u3002\u6362\u8868\u540e\u7684\u65b0\u5199\u5165\u548c\u76f8\u5173\u66f4\u65b0\u4f1a\u7ee7\u7eed\u89e6\u53d1\u539f\u6709 SLA rollup \u673a\u5236\u3002\\n\\n### \u4e0d\u6d89\u53ca\u7684\u5bf9\u8c61\\n\\n\u672c\u6a21\u5757\u660e\u786e\u4e0d\u5904\u7406\uff1a\\n\\n- `messages`\\n- `sessions`\\n- `commands_copy`\\n- \u5176\u4ed6\u975e\u4e8b\u4ef6\u7c7b\u5bf9\u8c61\\n- \u4e8b\u4ef6\u8868\u5206\u533a\u6539\u9020\\n- \u81ea\u52a8\u8c03\u5ea6\u914d\u7f6e\\n- \u5386\u53f2\u6570\u636e\u5f52\u6863\\n\\n## \u56de\u6eda\\n\\n### \u9636\u6bb5\u4e00\u56de\u6eda\\n\\n\u5728\u6267\u884c `05_drop_old_tables.sql` \u4e4b\u524d\uff0c\u539f\u8868\u4ecd\u4ee5 `_old` \u540d\u79f0\u5b8c\u6574\u4fdd\u7559\uff0c\u6362\u8868\u64cd\u4f5c\u539f\u5219\u4e0a\u53ef\u9006\u3002\\n\\n`01_shrink_observability_events.sql` \u6587\u4ef6\u672b\u5c3e\u5305\u542b\u624b\u52a8\u56de\u6eda\u793a\u4f8b\uff0c\u57fa\u672c\u6b65\u9aa4\u662f\uff1a\\n\\n1. \u9501\u5b9a\u5f53\u524d\u6b63\u5f0f\u8868\u3002\\n2. \u5c06\u5f53\u524d\u65b0\u8868\u6539\u540d\u4e3a `_new`\u3002\\n3. \u5c06 `_old` \u8868\u6539\u56de\u6b63\u5f0f\u8868\u540d\u3002\\n4. \u6309\u9700\u6062\u590d\u4e3b\u952e\u548c\u7d22\u5f15\u540d\u79f0\u3002\\n5. \u63d0\u4ea4\u4e8b\u52a1\u3002\\n\\n\u56de\u6eda\u524d\u5e94\u5148\u505c\u6b62\u6216\u534f\u8c03\u5e94\u7528\u5199\u5165\uff0c\u5e76\u786e\u8ba4\u5f53\u524d\u6b63\u5f0f\u8868\u4e0e `_old` \u8868\u7684\u5bf9\u8c61\u540d\u79f0\u72b6\u6001\u3002\u56de\u6eda\u5757\u662f\u6ce8\u91ca\u5185\u5bb9\uff0c\u4e0d\u4f1a\u81ea\u52a8\u6267\u884c\u3002\\n\\n### \u9636\u6bb5\u4e8c\u56de\u6eda\\n\\n`10_rolling_cleanup.sql` \u7684\u5220\u9664\u4e0d\u53ef\u9006\u3002\u8be5\u811a\u672c\u53ea\u5220\u9664\u8d85\u8fc7 92 \u5929\u7684\u6570\u636e\uff1b\u5982\u679c\u5386\u53f2\u6570\u636e\u6b64\u524d\u6ca1\u6709\u5f52\u6863\u6216\u4e8b\u5b9e\u8868\u526f\u672c\uff0c\u5220\u9664\u540e\u65e0\u6cd5\u901a\u8fc7\u672c\u6a21\u5757\u6062\u590d\u3002\\n\\n### `05_drop_old_tables.sql` \u540e\\n\\n\u4e00\u65e6\u6267\u884c\uff1a\\n\\n```bash\\npsql -v confirmed=yes -f scripts/db-governance/05_drop_old_tables.sql\\n```\\n\\n\u4e09\u5f20 `_old` \u8868\u5c06\u88ab\u5220\u9664\uff0c\u9636\u6bb5\u4e00\u7684\u5feb\u901f\u8868\u7ea7\u56de\u6eda\u8def\u5f84\u4e0d\u518d\u53ef\u7528\u3002\u540e\u7eed\u6062\u590d\u53ea\u80fd\u4f9d\u8d56\u6570\u636e\u5e93\u5907\u4efd\u6216\u5176\u4ed6\u5916\u90e8\u526f\u672c\u3002\\n\\n## \u53c2\u6570\u8c03\u6574\\n\\n### \u4fdd\u7559\u5929\u6570\\n\\n\u6bcf\u4e2a\u811a\u672c\u72ec\u7acb\u8bbe\u7f6e\uff1a\\n\\n```sql\\n\\\\set retention_days 92\\n```\\n\\n\u5982\u679c\u9700\u8981\u53d8\u66f4\u4fdd\u7559\u7b56\u7565\uff0c\u5fc5\u987b\u540c\u6b65\u8bc4\u4f30\uff1a\\n\\n- SLA canonical rollup \u7684\u6700\u5927\u67e5\u8be2\u7a97\u53e3\u3002\\n- dirty bucket \u91cd\u5efa\u6240\u9700\u7684\u6e90\u4e8b\u4ef6\u8303\u56f4\u3002\\n- \u4e09\u5f20\u8868\u7684\u7a7a\u95f4\u589e\u957f\u901f\u5ea6\u3002\\n- `00_preflight.sql`\u3001`01`\u3001`02`\u3001`03`\u3001`04` \u548c `10` \u4e2d\u7684\u53c2\u6570\u662f\u5426\u4e00\u81f4\u3002\\n\\n\u4e0d\u80fd\u53ea\u4fee\u6539\u5355\u4e2a\u811a\u672c\uff0c\u5426\u5219\u9884\u68c0\u67e5\u3001\u6362\u8868\u3001\u9a8c\u8bc1\u548c\u65e5\u5e38\u6e05\u7406\u53ef\u80fd\u4f7f\u7528\u4e0d\u540c\u7684\u4fdd\u7559\u7a97\u53e3\u3002\\n\\n### \u6279\u5927\u5c0f\\n\\n\u4ec5 `10_rolling_cleanup.sql` \u4f7f\u7528\uff1a\\n\\n```sql\\n\\\\set batch_size 50000\\n```\\n\\n\u589e\u5927\u6279\u5927\u5c0f\u53ef\u4ee5\u51cf\u5c11\u811a\u672c\u8fd0\u884c\u6b21\u6570\uff0c\u4f46\u4f1a\u589e\u52a0\u5355\u6b21\u5220\u9664\u7684\u9501\u7ade\u4e89\u3001WAL \u4ea7\u751f\u91cf\u3001\u4e8b\u52a1\u65f6\u95f4\u548c vacuum \u538b\u529b\u3002\u751f\u4ea7\u73af\u5883\u5e94\u6839\u636e\u4e8b\u4ef6\u5199\u5165\u91cf\u548c\u4f4e\u5cf0\u7a97\u53e3\u8c03\u6574\u3002\\n\\n## \u8fd0\u7ef4\u6ce8\u610f\u4e8b\u9879\\n\\n- \u6267\u884c\u9636\u6bb5\u4e00\u524d\u5fc5\u987b\u4fdd\u5b58 `00_preflight.sql` \u7684\u8f93\u51fa\uff0c\u5c24\u5176\u662f\u7d22\u5f15\u3001\u89e6\u53d1\u5668\u548c\u5916\u952e DDL\u3002\\n- \u6bcf\u4e2a\u6362\u8868\u811a\u672c\u5e94\u72ec\u7acb\u6267\u884c\u5e76\u68c0\u67e5\u8f93\u51fa\uff0c\u4e0d\u5efa\u8bae\u5c06\u4e09\u4e2a\u811a\u672c\u62fc\u63a5\u4e3a\u4e0d\u53ef\u89c2\u6d4b\u7684\u5355\u6b21\u547d\u4ee4\u3002\\n- \u5982\u679c\u6362\u8868\u5931\u8d25\uff0c\u5148\u68c0\u67e5\u662f\u5426\u5b58\u5728\u6b8b\u7559\u7684 `\n_new`\u3001\u9501\u7b49\u5f85\u6216\u5bf9\u8c61\u540d\u79f0\u51b2\u7a81\uff0c\u518d\u51b3\u5b9a\u91cd\u8bd5\u3002\\n- \u672a\u901a\u8fc7 `04_verify_after_shrink.sql` \u65f6\uff0c\u4e0d\u5f97\u6267\u884c `05_drop_old_tables.sql`\u3002\\n- \u89c2\u5bdf\u671f\u5185\u5e94\u91cd\u70b9\u68c0\u67e5\u4e8b\u4ef6\u5199\u5165\u3001\u4e8b\u4ef6\u67e5\u8be2\u3001SLA rollup\u3001workflow failure \u5904\u7406\u548c trace \u67e5\u8be2\u3002\\n- `05_drop_old_tables.sql` \u9ed8\u8ba4\u5b89\u5168\u8df3\u8fc7\u5220\u9664\uff1b\u53ea\u6709\u663e\u5f0f\u4f20\u5165 `-v confirmed=yes` \u624d\u4f1a\u6267\u884c\u7834\u574f\u6027\u64cd\u4f5c\u3002\\n- \u9636\u6bb5\u4e8c\u53ef\u901a\u8fc7 crontab \u6216 Kubernetes CronJob \u8c03\u5ea6\uff0c\u4f46\u5f53\u524d\u6a21\u5757\u672c\u8eab\u4e0d\u5305\u542b\u8c03\u5ea6\u914d\u7f6e\u3002\\n- \u5982\u679c\u4e8b\u4ef6\u91cf\u6301\u7eed\u589e\u957f\uff0c\u672a\u6765\u53ef\u8003\u8651\u5c06 `remote_agent_observability_events` \u6539\u9020\u4e3a\u6309 `occurred_at` \u7684\u6708\u5ea6 range \u5206\u533a\u8868\uff0c\u5e76\u901a\u8fc7\u5220\u9664\u5206\u533a\u66ff\u4ee3\u6279\u91cf\u5220\u9664\u3002\",\"other-deepeval-evaluator\":\"# Other \u2014 deepeval-evaluator\\n\\n# Archon DeepEval Evaluator\\n\\nThe `deepeval-evaluator` module is a standalone FastAPI sidecar for evaluating Archon workflow traces with DeepEval GEval metrics. Archon sends a question-and-answer pair, along with trace context, to the evaluator service and persists the returned evaluation result.\\n\\nThe service is intentionally isolated from the main application. It can be deployed independently with Docker Compose and addressed through the `ARCHON_DEEPEVAL_EVALUATOR_URL` setting.\\n\\n## Responsibilities\\n\\nThe evaluator service:\\n\\n- Exposes a readiness endpoint at `GET /health`.\\n- Accepts evaluation requests at `POST /evaluate`.\\n- Evaluates Archon workflow traces using DeepEval GEval metrics.\\n- Uses a configurable judge model and GEval threshold.\\n- Records the configured rubric version with each result.\\n- Marks requests with missing questions or answers as skipped.\\n- Leaves HTTP and provider failures as errors so the Archon application can persist them as failed evaluations.\\n- Protects the evaluation endpoint with an optional bearer token.\\n\\nThe service does not appear to contain an internal call graph or application-to-application calls beyond its HTTP interface. Its runtime dependency on DeepEval and the configured judge provider is supplied through the Python package and environment configuration.\\n\\n## Architecture\\n\\n```mermaid\\nflowchart LR\\n    A[Archon application] --&gt;|POST /evaluate| E[deepeval-evaluator]\\n    A --&gt;|GET /health| E\\n    E --&gt; G[DeepEval GEval]\\n    G --&gt; J[Configured judge model]\\n    E --&gt;|Evaluation result or error| A\\n```\\n\\nThe evaluator is deployed as a sidecar rather than embedded directly in the Archon application. This keeps DeepEval and its model-provider dependencies isolated and allows the evaluator to be scaled or configured independently.\\n\\n## HTTP API\\n\\n### `GET /health`\\n\\nReturns service readiness information without exposing credentials.\\n\\nThe response includes:\\n\\n- Readiness status.\\n- Configured judge model.\\n- Rubric version.\\n- Metric schema version.\\n\\nUse this endpoint for container health checks and operational diagnostics. It is also useful for verifying that the evaluator is running with the expected evaluation configuration.\\n\\n### `POST /evaluate`\\n\\nEvaluates an Archon trace using DeepEval GEval metrics.\\n\\nThe request is expected to contain the trace data required by the evaluator, including at least:\\n\\n- A question.\\n- An answer.\\n- The workflow trace or related evaluation context.\\n\\nIf the question or answer is missing, the evaluator does not treat the request as a service failure. Instead, it returns an evaluation result with:\\n\\n```text\\nevaluator_execution_status=skipped\\n```\\n\\nHTTP failures and provider failures remain errors. The Archon application is responsible for handling these failures and persisting them with a failed evaluation status.\\n\\nThe exact request and response schemas are implemented in `app.py`; callers should use the deployed service contract rather than relying on DeepEval\u2019s internal object model.\\n\\n## Configuration\\n\\n### Archon application configuration\\n\\nSet the evaluator endpoint in the Archon application:\\n\\n```bash\\nARCHON_DEEPEVAL_EVALUATOR_URL=http://deepeval-evaluator:8000/evaluate\\n```\\n\\nIf the evaluator requires authentication, configure the matching token in the Archon application:\\n\\n```bash\\nARCHON_DEEPEVAL_EVALUATOR_TOKEN=...\\n```\\n\\nThe Archon token must correspond to the evaluator\u2019s `DEEPEVAL_EVALUATOR_TOKEN`.\\n\\n### Evaluator configuration\\n\\n| Variable | Required | Description |\\n|---|---:|---|\\n| `DEEPEVAL_EVALUATOR_TOKEN` | No | Bearer token required by the evaluator. |\\n| `DEEPEVAL_LLM_MODEL` | No | Judge model passed to DeepEval. |\\n| `DEEPEVAL_RUBRIC_VERSION` | No | Immutable rubric or prompt version persisted with every result. |\\n| `DEEPEVAL_THRESHOLD` | No | GEval threshold. If unset, DeepEval\u2019s metric default is used. |\\n| `OPENAI_API_KEY` | Provider-dependent | Credentials for the configured OpenAI-backed judge model. |\\n\\nWhen changing the evaluation rubric or prompt, bump `DEEPEVAL_RUBRIC_VERSION` before recalibrating a frozen anchor. This preserves the association between stored results and the rubric that produced them.\\n\\n## Evaluation behavior\\n\\nThe evaluator distinguishes between invalid evaluation input and infrastructure/provider failures:\\n\\n| Condition | Evaluator behavior |\\n|---|---|\\n| Question is missing | Return a skipped evaluation with `evaluator_execution_status=skipped`. |\\n| Answer is missing | Return a skipped evaluation with `evaluator_execution_status=skipped`. |\\n| HTTP request or service failure | Return an error for the Archon application to persist as failed. |\\n| Judge/provider failure | Return an error for the Archon application to persist as failed. |\\n| Valid question and answer | Run the configured DeepEval GEval evaluation. |\\n\\nThis distinction prevents incomplete traces from being confused with evaluator outages or model-provider errors.\\n\\n## DeepEval and metric configuration\\n\\nThe service depends on:\\n\\n```text\\ndeepeval&gt;=3.0.0,&lt;4.0.0\\n```\\n\\nThe evaluator uses DeepEval GEval metrics. The configured threshold is supplied through `DEEPEVAL_THRESHOLD`; if that variable is absent, the implementation uses DeepEval\u2019s default metric threshold.\\n\\nThe judge model is selected through `DEEPEVAL_LLM_MODEL`. The model provider\u2019s credentials must be available to the evaluator container. For an OpenAI-backed configuration, this normally includes `OPENAI_API_KEY`.\\n\\nEach result is associated with the configured `DEEPEVAL_RUBRIC_VERSION`. Treat this value as an immutable identifier for the rubric and prompt configuration used during evaluation.\\n\\n## Container image\\n\\nThe service is packaged by `services/deepeval-evaluator/Dockerfile`.\\n\\nBuild characteristics:\\n\\n- Base image: `python:3.11-slim`\\n- Working directory: `/app`\\n- Installs dependencies from `requirements.txt`\\n- Copies `app.py` into the image\\n- Exposes port `8000`\\n- Runs Uvicorn with the asyncio event loop\\n\\nThe container command is:\\n\\n```bash\\nuvicorn app:app --host 0.0.0.0 --port 8000 --loop asyncio\\n```\\n\\nThe application object is therefore expected to be available as `app` in `app.py`.\\n\\nThe image sets:\\n\\n```bash\\nPYTHONDONTWRITEBYTECODE=1\\nPYTHONUNBUFFERED=1\\nPIP_NO_CACHE_DIR=1\\n```\\n\\nThese settings prevent Python bytecode files, ensure unbuffered application output, and disable pip\u2019s cache during installation.\\n\\n## Local and Compose deployment\\n\\nThe documented deployment uses the `deepeval` Docker Compose profile:\\n\\n```bash\\ndocker compose --profile deepeval up -d deepeval-evaluator\\n```\\n\\nWithin a Compose network, the Archon application can address the service using:\\n\\n```text\\nhttp://deepeval-evaluator:8000/evaluate\\n```\\n\\nA typical setup provides:\\n\\n```bash\\nARCHON_DEEPEVAL_EVALUATOR_URL=http://deepeval-evaluator:8000/evaluate\\nOPENAI_API_KEY=...\\n```\\n\\nAdd `DEEPEVAL_EVALUATOR_TOKEN` to the evaluator container and `ARCHON_DEEPEVAL_EVALUATOR_TOKEN` to the Archon application when bearer-token authentication is enabled.\\n\\n## Operational guidance\\n\\n- Use `GET /health` to verify readiness and inspect the active model, rubric version, and metric schema version.\\n- Do not expose credentials through health responses or logs.\\n- Treat `DEEPEVAL_RUBRIC_VERSION` as a release-level configuration value, not a dynamically changing label.\\n- Record the evaluator\u2019s skipped status separately from failed status.\\n- Investigate provider and HTTP failures independently from incomplete trace input.\\n- Keep the evaluator\u2019s DeepEval version within the declared `3.x` range.\\n- Ensure the judge provider credentials are available inside the evaluator container, not only in the Archon application container.\\n\\n## Module layout\\n\\n```text\\nservices/deepeval-evaluator/\\n\u251c\u2500\u2500 Dockerfile\\n\u251c\u2500\u2500 README.md\\n\u251c\u2500\u2500 requirements.txt\\n\u2514\u2500\u2500 app.py\\n```\\n\\n- `app.py` contains the FastAPI application and evaluation endpoint implementation.\\n- `requirements.txt` pins the web-server dependencies and constrains the DeepEval major version.\\n- `Dockerfile` defines the production container.\\n- `README.md` documents deployment and environment configuration.\",\"other-deploy\":\"# Other \u2014 deploy\\n\\n# Other \u2014 Deploy\\n\\nThe `deploy` module contains the production-oriented container and server provisioning configuration for Archon. It does not contain application runtime code or internal function calls. Instead, it defines how the application image is obtained, configured, extended, persisted, and optionally deployed with supporting services.\\n\\nThe module supports two deployment styles:\\n\\n- **Pre-built image deployment** using `ghcr.io/coleam00/archon:latest`\\n- **Cloud-init VPS provisioning** for automatically preparing a server\\n- **User-extensible image builds** based on the published Archon image\\n- **Optional evaluator services** for DeepEval and Ragas\\n\\n## Deployment architecture\\n\\n```mermaid\\ngraph TD\\n    Registry[GHCR Archon image] --&gt; App[app container]\\n    Compose[docker-compose.yml] --&gt; App\\n    Env[.env] --&gt; App\\n    Data[archon_data volume] --&gt; App\\n    Home[archon_user_home volume] --&gt; App\\n    Compose --&gt; DeepEval[Optional DeepEval evaluator]\\n    Compose --&gt; Ragas[Optional Ragas evaluator]\\n```\\n\\nThe `app` service is the central deployment unit. It receives configuration from `.env`, exposes the configured application port, and stores persistent data in Docker-managed volumes. Evaluator services are opt-in through Compose profiles.\\n\\n## Files\\n\\n| File | Purpose |\\n| --- | --- |\\n| `docker-compose.yml` | Main Compose definition for the pre-built Archon image |\\n| `docker-compose.override.example.yml` | Example override that adds a local build using `Dockerfile.user` |\\n| `Dockerfile.user.example` | Template for adding system, Python, npm, CLI, or binary dependencies |\\n| `cloud-init.yml` | Automated VPS setup script for cloud-init-compatible providers |\\n\\nThe `.example` files are templates. Copy them to the corresponding non-example names before customizing:\\n\\n```bash\\ncp deploy/Dockerfile.user.example deploy/Dockerfile.user\\ncp deploy/docker-compose.override.example.yml deploy/docker-compose.override.yml\\n```\\n\\nThe examples explicitly instruct users not to modify them directly. The customized files are intended to remain local and gitignored.\\n\\n## `docker-compose.yml`\\n\\nThe main Compose file is designed for end users who want to run the published Archon image without a local application build.\\n\\n### `app` service\\n\\nThe `app` service uses:\\n\\n```yaml\\nimage: ghcr.io/coleam00/archon:latest\\n```\\n\\nIt has the following behavior:\\n\\n- Restarts unless explicitly stopped\\n- Loads variables from `.env`\\n- Sets `ARCHON_DOCKER=true`\\n- Exposes the application on `${PORT:-3000}`\\n- Runs a health check against `/api/health`\\n- Persists Archon data and the application user home directory\\n\\nStart the default deployment with:\\n\\n```bash\\ndocker compose up -d\\n```\\n\\nThe service port is configurable:\\n\\n```dotenv\\nPORT=8080\\n```\\n\\nThis maps host port `8080` to container port `8080`. If `PORT` is not set, both ports default to `3000`.\\n\\n### Environment configuration\\n\\nThe service uses both:\\n\\n```yaml\\nenv_file: .env\\n```\\n\\nand Compose interpolation expressions such as:\\n\\n```yaml\\nARCHON_RAGAS_EVALUATOR_URL: \\\"${ARCHON_RAGAS_EVALUATOR_URL:-}\\\"\\n```\\n\\nThis means `.env` provides application configuration, while the explicit `environment` entries provide defaults and deployment-specific evaluator settings.\\n\\nEvaluator-related variables include:\\n\\n- `ARCHON_RAGAS_EVALUATOR_URL`\\n- `ARCHON_RAGAS_EVALUATOR_TIMEOUT_MS`\\n- `ARCHON_RAGAS_EVALUATOR_TOKEN`\\n- `ARCHON_DEEPEVAL_EVALUATOR_URL`\\n- `ARCHON_DEEPEVAL_EVALUATOR_TIMEOUT_MS`\\n- `ARCHON_DEEPEVAL_EVALUATOR_TOKEN`\\n- `ARCHON_PROMPTFOO_EVALUATOR_URL`\\n- `ARCHON_PROMPTFOO_EVALUATOR_TIMEOUT_MS`\\n- `ARCHON_PROMPTFOO_EVALUATOR_TOKEN`\\n- `ARCHON_PROMPTFOO_CLI_ENABLED`\\n- `ARCHON_PROMPTFOO_COMMAND`\\n\\nThe evaluator URLs must point to reachable evaluator endpoints. When an evaluator is running as another Compose service, use the service name and container port rather than the host-published port.\\n\\n### Persistent volumes\\n\\nThe application declares two named volumes:\\n\\n```yaml\\nvolumes:\\n  - ${ARCHON_DATA:-archon_data}:/.archon\\n  - ${ARCHON_USER_HOME:-archon_user_home}:/home/appuser\\n```\\n\\n`ARCHON_DATA` controls the volume mounted at `/.archon`. This is the primary Archon data location.\\n\\n`ARCHON_USER_HOME` controls the volume mounted at `/home/appuser`. It preserves files created by the application user, including user-level tools or configuration.\\n\\nCustom volume names can be set in `.env`:\\n\\n```dotenv\\nARCHON_DATA=my_archon_data\\nARCHON_USER_HOME=my_archon_home\\n```\\n\\n### Health check\\n\\nThe container health check executes:\\n\\n```bash\\ncurl -f http://localhost:${PORT:-3000}/api/health\\n```\\n\\nIts timing parameters are:\\n\\n- Interval: 30 seconds\\n- Timeout: 10 seconds\\n- Retries: 3\\n- Start period: 15 seconds\\n\\nThis verifies application availability from inside the container. It does not verify external DNS, TLS, reverse proxy configuration, or database connectivity unless those are reflected by the application health endpoint.\\n\\n## Optional PostgreSQL service\\n\\nThe Compose file includes a commented PostgreSQL service template using:\\n\\n```yaml\\nimage: postgres:17-alpine\\n```\\n\\nTo use it, uncomment the `postgres` service and the `postgres_data` volume declaration. The template creates:\\n\\n- Database: `remote_coding_agent`\\n- User: `postgres`\\n- Password: `${POSTGRES_PASSWORD:-postgres}`\\n- Persistent storage at `/var/lib/postgresql/data`\\n\\nThe application can then use an in-network connection string such as:\\n\\n```dotenv\\nDATABASE_URL=postgresql://postgres:postgres@postgres:5432/remote_coding_agent\\n```\\n\\nThe hostname `postgres` resolves to the Compose service on the default Compose network.\\n\\nThe default password is suitable only for controlled local or private deployments. Set `POSTGRES_PASSWORD` to a strong secret for server deployments and keep `.env` out of version control.\\n\\n## Optional evaluator services\\n\\nTwo evaluator services are included as opt-in Compose services.\\n\\n### DeepEval\\n\\nThe `deepeval-evaluator` service:\\n\\n- Builds from `../services/deepeval-evaluator`\\n- Uses the `deepeval` profile\\n- Listens on container port `8000`\\n- Publishes localhost port `${DEEPEVAL_EVALUATOR_PORT:-8020}`\\n- Checks `/health`\\n\\nStart it with:\\n\\n```bash\\ndocker compose --profile deepeval up -d\\n```\\n\\nThe service accepts:\\n\\n- `DEEPEVAL_EVALUATOR_TOKEN`\\n- `DEEPEVAL_LLM_MODEL`\\n- `DEEPEVAL_THRESHOLD`\\n\\nThe default model is `gpt-4o-mini`.\\n\\n### Ragas\\n\\nThe `ragas-evaluator` service:\\n\\n- Builds from `../services/ragas-evaluator`\\n- Uses the `ragas` profile\\n- Listens on container port `8000`\\n- Publishes localhost port `${RAGAS_EVALUATOR_PORT:-8010}`\\n- Checks `/health`\\n\\nStart it with:\\n\\n```bash\\ndocker compose --profile ragas up -d\\n```\\n\\nThe service accepts:\\n\\n- `RAGAS_LLM_MODEL`\\n- `RAGAS_EMBEDDING_MODEL`\\n- `RAGAS_EVALUATOR_TOKEN`\\n- `RAGAS_REQUEST_TIMEOUT_SECONDS`\\n- `RAGAS_MAX_RETRIES`\\n- `RAGAS_LLM_TEMPERATURE`\\n- `RAGAS_METRICS`\\n\\nThe default metrics are:\\n\\n```text\\nfaithfulness,answer_relevancy,context_precision,context_recall\\n```\\n\\nThe evaluator build paths are relative to the directory containing the Compose file. They require the corresponding service source directories to be present in the deployment checkout.\\n\\n## User-extensible image builds\\n\\n`Dockerfile.user.example` provides a supported extension point for adding dependencies without modifying the published Archon image.\\n\\nThe template starts from:\\n\\n```dockerfile\\nFROM ghcr.io/coleam00/archon:latest\\n```\\n\\nIt switches to `root` while installing dependencies, then returns to:\\n\\n```dockerfile\\nUSER appuser\\n```\\n\\nThis preserves the normal non-root runtime behavior.\\n\\nSupported customization patterns include:\\n\\n### System packages\\n\\n```dockerfile\\nRUN apt-get update &amp;&amp; apt-get install -y --no-install-recommends \\\\\\n    ripgrep \\\\\\n    fd-find \\\\\\n    jq \\\\\\n &amp;&amp; rm -rf /var/lib/apt/lists/*\\n```\\n\\nThe package list should be kept minimal, and apt metadata should be removed in the same layer to reduce image size.\\n\\n### GitHub CLI extensions\\n\\n```dockerfile\\nRUN gh extension install github/gh-copilot\\n```\\n\\n### Global npm packages\\n\\n```dockerfile\\nRUN npm install -g tsx prettier\\n```\\n\\n### Custom binaries\\n\\n```dockerfile\\nCOPY --chown=appuser:appuser ./my-tool /usr/local/bin/my-tool\\n```\\n\\nThe copied file must be executable and available on the application user's `PATH`.\\n\\n### Python packages\\n\\n```dockerfile\\nRUN pip install --no-cache-dir httpie\\n```\\n\\nThe `Dockerfile.user` template does not replace the Archon application image. It layers local additions on top of the published image.\\n\\n## Compose override for custom builds\\n\\nThe base Compose file uses `image:` and therefore pulls the published image. `docker-compose.override.example.yml` adds a build definition:\\n\\n```yaml\\nservices:\\n  app:\\n    build:\\n      context: .\\n      dockerfile: Dockerfile.user\\n```\\n\\nAfter copying the override and user Dockerfile, Compose automatically merges the override with `docker-compose.yml`:\\n\\n```bash\\ndocker compose up -d --build\\n```\\n\\nThe resulting application image is built from the local `Dockerfile.user` while retaining the base service configuration, including ports, volumes, environment, and health checks.\\n\\nThe build context is the deployment directory. Files copied by `Dockerfile.user` must therefore be available within that context.\\n\\n## Cloud-init provisioning\\n\\n`cloud-init.yml` automates initial setup on Ubuntu 22.04+, Debian 12+, and other cloud-init-compatible systems.\\n\\nIt is intended to be pasted into a VPS provider's User Data field during server creation.\\n\\n### Provisioning steps\\n\\nThe script performs the following operations:\\n\\n1. Updates and upgrades system packages\\n2. Installs `curl`, `git`, and `ufw`\\n3. Creates a 2 GB swap file if `/swapfile` does not already exist\\n4. Installs Docker using the Docker convenience script\\n5. Adds the `archon` user to the Docker group\\n6. Copies SSH keys from the default cloud user or root to `archon`\\n7. Opens SSH, HTTP, HTTPS, and HTTP/3 QUIC ports\\n8. Enables UFW\\n9. Clones Archon into `/opt/archon`\\n10. Copies `.env.example` and `Caddyfile.example`\\n11. Changes ownership of `/opt/archon` to `archon`\\n12. Pre-pulls PostgreSQL and Caddy images\\n13. Runs `docker compose build` as `archon`\\n14. Writes `/opt/archon/SETUP_COMPLETE`\\n\\nThe swap file is particularly important for small VPS instances because image builds and dependency installation can exceed available RAM.\\n\\n### Created `archon` user\\n\\nThe provisioning file creates a dedicated service user:\\n\\n```yaml\\n- name: archon\\n  gecos: Archon Service User\\n  shell: /bin/bash\\n  lock_passwd: true\\n```\\n\\nThe user receives Docker group access but no sudo access. Administrative operations such as package upgrades and reboots must be performed through the provider's default cloud user or root.\\n\\nSSH keys are copied from the UID 1000 user when available, with a fallback to `/root/.ssh/authorized_keys`.\\n\\n### Firewall rules\\n\\nThe following ports are opened:\\n\\n| Port | Protocol | Purpose |\\n| --- | --- | --- |\\n| 22 | TCP | SSH |\\n| 80 | TCP | HTTP and certificate challenges |\\n| 443 | TCP | HTTPS |\\n| 443 | UDP | HTTP/3 QUIC |\\n\\nThe `443/udp` rule is required for Caddy's HTTP/3 support.\\n\\n### Initial configuration\\n\\nCloud-init creates:\\n\\n```text\\n/opt/archon/.env\\n/opt/archon/Caddyfile\\n```\\n\\nBefore starting the application, edit `.env` and configure at least:\\n\\n- An AI credential such as `CLAUDE_CODE_OAUTH_TOKEN` or `CLAUDE_API_KEY`\\n- `DOMAIN`\\n- `DATABASE_URL`\\n\\nThe generated completion message suggests:\\n\\n```bash\\ncd /opt/archon\\ndocker compose --profile with-db --profile cloud up -d\\n```\\n\\nThe supplied `deploy/docker-compose.yml` defines the application and evaluator profiles shown above; database and reverse-proxy services are represented by commented or external configuration in this file. If using the cloud-init instructions as written, verify that the checked-out Compose configuration includes the expected `with-db` and `cloud` service definitions before starting those profiles.\\n\\nThe `Caddyfile` is prepared by cloud-init, but the provided Compose file does not define a Caddy service. Caddy must therefore be supplied by the deployment configuration that consumes the `Caddyfile`, or added as a separate service.\\n\\n### Completion marker\\n\\nSuccessful setup writes a human-readable marker file:\\n\\n```text\\n/opt/archon/SETUP_COMPLETE\\n```\\n\\nThis file contains the login instructions, required environment settings, startup command, log command, health endpoint, and deployment documentation URL.\\n\\n## Operational commands\\n\\nFrom the deployment directory:\\n\\n```bash\\n# Start the default app\\ndocker compose up -d\\n\\n# View service logs\\ndocker compose logs -f\\n\\n# Check running containers\\ndocker compose ps\\n\\n# Recreate containers after configuration changes\\ndocker compose up -d\\n\\n# Stop services\\ndocker compose down\\n\\n# Start DeepEval\\ndocker compose --profile deepeval up -d\\n\\n# Start Ragas\\ndocker compose --profile ragas up -d\\n\\n# Build a user-customized image\\ndocker compose up -d --build\\n```\\n\\nFor a cloud-init deployment:\\n\\n```bash\\nssh archon@your-server-ip\\ncd /opt/archon\\nnano .env\\ndocker compose up -d\\ncurl http://localhost:${PORT:-3000}/api/health\\n```\\n\\n## Relationship to the rest of the codebase\\n\\nThis module is an infrastructure boundary rather than an application module:\\n\\n- `docker-compose.yml` runs the published Archon application image.\\n- `services/deepeval-evaluator` and `services/ragas-evaluator` provide optional evaluator implementations consumed through configured URLs.\\n- Repository-level `.env.example` and `Caddyfile.example` provide the configuration templates used by `cloud-init.yml`.\\n- The application itself consumes the environment variables and mounted paths defined here.\\n- No deploy file imports or calls application functions directly; integration occurs through container environment variables, network service names, ports, volumes, and HTTP health endpoints.\",\"other-design-md\":\"# Other \u2014 DESIGN.md\\n\\n# Other \u2014 DESIGN.md\\n\\n## Purpose\\n\\n`DESIGN.md` defines a Vercel-inspired design system for the project. It is a visual and implementation reference rather than executable code. The document specifies:\\n\\n- Visual direction and design principles\\n- Color tokens and semantic roles\\n- Typography hierarchy\\n- Button, card, form, navigation, and workflow styling\\n- Spacing, layout, radius, and elevation rules\\n- Responsive behavior and breakpoint expectations\\n- Guidance for generating or implementing new components\\n\\nThe system is intentionally restrained: a primarily white canvas, near-black text, compressed Geist typography, subtle shadow-based borders, and functional use of accent colors.\\n\\n## Module Characteristics\\n\\nThis module has no executable API surface:\\n\\n- No functions or classes are defined.\\n- No internal or external calls are made.\\n- No incoming dependencies are declared.\\n- No execution flows are present.\\n\\nOther modules should treat `DESIGN.md` as a source of design constraints and token values when implementing UI components.\\n\\n## Design Foundation\\n\\nThe design system is based on four principles:\\n\\n1. **Minimal visual noise**  \\n   Use `#ffffff` surfaces, `#171717` primary text, generous whitespace, and restrained decoration.\\n\\n2. **Compressed typography**  \\n   Geist Sans headings use aggressive negative letter-spacing to create a dense, engineered appearance.\\n\\n3. **Shadow-based structure**  \\n   Use zero-offset box shadows as borders instead of traditional CSS borders. This keeps the border in the rendering layer without affecting the box model.\\n\\n4. **Functional color**  \\n   Accent colors communicate workflow state rather than serving as general decoration.\\n\\nThe overall visual contrast is intentionally soft. Primary text uses `#171717` instead of pure black, while cards and controls use low-opacity shadows rather than heavy outlines or elevation.\\n\\n## Color Tokens\\n\\n### Core Colors\\n\\n| Role | Value | Usage |\\n| --- | --- | --- |\\n| Vercel Black | `#171717` | Headings, primary text, dark surfaces, navigation text |\\n| Pure White | `#ffffff` | Page and card backgrounds, text on dark surfaces |\\n| True Black | `#000000` | Specific console and code contexts |\\n\\n### Workflow Colors\\n\\nWorkflow colors are reserved for the Develop \u2192 Preview \u2192 Ship pipeline.\\n\\n| Token | Value | Usage |\\n| --- | --- | --- |\\n| `--develop-text` | `#0a72ef` | Develop stage |\\n| `--preview-text` | `#de1d8d` | Preview stage |\\n| `--ship-text` | `#ff5b4f` | Ship stage |\\n\\nThese colors should not be applied decoratively to unrelated interface elements.\\n\\n### Neutral Scale\\n\\n| Role | Value | Usage |\\n| --- | --- | --- |\\n| Gray 900 | `#171717` | Primary text and headings |\\n| Gray 600 | `#4d4d4d` | Descriptions and secondary text |\\n| Gray 500 | `#666666` | Muted text and tertiary links |\\n| Gray 400 | `#808080` | Placeholders and disabled states |\\n| Gray 100 | `#ebebeb` | Dividers, image outlines, light rings |\\n| Gray 50 | `#fafafa` | Subtle surface tint and inner shadow highlight |\\n\\n### Interactive and Console Colors\\n\\n- Link blue: `#0072f5`\\n- Focus color, `--ds-focus-color`: `hsla(212, 100%, 48%, 1)`\\n- Tailwind ring color, `--tw-ring-color`: `rgba(147, 197, 253, 0.5)`\\n- Console blue, `--geist-console-text-color-blue`: `#0070f3`\\n- Console purple, `--geist-console-text-color-purple`: `#7928ca`\\n- Console pink, `--geist-console-text-color-pink`: `#eb367f`\\n\\n### Surface and Badge Colors\\n\\n- Overlay backdrop, `--ds-overlay-backdrop-color`: `hsla(0, 0%, 98%, 1)`\\n- Selection text, `--geist-selection-text-color`: `hsla(0, 0%, 95%, 1)`\\n- Badge background: `#ebf5ff`\\n- Badge text: `#0068d6`\\n\\n## Typography\\n\\n### Font Families\\n\\nUse Geist Sans for general interface text:\\n\\n```css\\nfont-family: Geist, Arial, \\\"Apple Color Emoji\\\", \\\"Segoe UI Emoji\\\",\\n  \\\"Segoe UI Symbol\\\";\\n```\\n\\nUse Geist Mono for code and technical labels:\\n\\n```css\\nfont-family: \\\"Geist Mono\\\", ui-monospace, SFMono-Regular, \\\"Roboto Mono\\\",\\n  Menlo, Monaco, \\\"Liberation Mono\\\", \\\"DejaVu Sans Mono\\\", \\\"Courier New\\\";\\n```\\n\\nGeist text enables the OpenType `liga` feature globally. Use `tnum` for captions or metrics that require tabular numbers.\\n\\n### Weight Roles\\n\\nThe system primarily uses three weights:\\n\\n- `400`: body and reading text\\n- `500`: UI controls, navigation, and interactive labels\\n- `600`: headings and emphasized content\\n- `700`: reserved for the 7px micro-badge style only\\n\\nAvoid introducing additional weights for ordinary content. Hierarchy should come primarily from size, line height, and letter-spacing.\\n\\n### Type Scale\\n\\n| Role | Family | Size | Weight | Line height | Letter spacing |\\n| --- | --- | ---: | ---: | ---: | ---: |\\n| Display Hero | Geist | `48px` | `600` | `1.00\u20131.17` | `-2.4px` to `-2.88px` |\\n| Section Heading | Geist | `40px` | `600` | `1.20` | `-2.4px` |\\n| Sub-heading Large | Geist | `32px` | `600` | `1.25` | `-1.28px` |\\n| Sub-heading | Geist | `32px` | `400` | `1.50` | `-1.28px` |\\n| Card Title | Geist | `24px` | `600` | `1.33` | `-0.96px` |\\n| Card Title Light | Geist | `24px` | `500` | `1.33` | `-0.96px` |\\n| Body Large | Geist | `20px` | `400` | `1.80` | Normal |\\n| Body | Geist | `18px` | `400` | `1.56` | Normal |\\n| Body Small | Geist | `16px` | `400` | `1.50` | Normal |\\n| Body Medium | Geist | `16px` | `500` | `1.50` | Normal |\\n| Body Semibold | Geist | `16px` | `600` | `1.50` | `-0.32px` |\\n| Button / Link | Geist | `14px` | `500` | `1.43` | Normal |\\n| Button Small | Geist | `14px` | `400` | `1.00` | Normal |\\n| Caption | Geist | `12px` | `400\u2013500` | `1.33` | Normal |\\n| Mono Body | Geist Mono | `16px` | `400` | `1.50` | Normal |\\n| Mono Caption | Geist Mono | `13px` | `500` | `1.54` | Normal |\\n| Mono Small | Geist Mono | `12px` | `500` | `1.00` | Normal |\\n| Micro Badge | Geist | `7px` | `700` | `1.00` | Normal |\\n\\n`Mono Small` labels are uppercase and intended for compact technical terminology. `Mono Body` is the default style for code blocks.\\n\\n## Borders, Shadows, and Elevation\\n\\nTraditional borders are generally replaced with box shadows.\\n\\n### Standard Shadow Tokens\\n\\n```css\\n/* Signature shadow-border */\\nbox-shadow: rgba(0, 0, 0, 0.08) 0px 0px 0px 1px;\\n\\n/* Light ring */\\nbox-shadow: rgb(235, 235, 235) 0px 0px 0px 1px;\\n\\n/* Subtle elevation */\\nbox-shadow: rgba(0, 0, 0, 0.04) 0px 2px 2px;\\n```\\n\\n### Card Stack\\n\\nFeatured cards use a layered shadow declaration:\\n\\n```css\\nbox-shadow:\\n  rgba(0, 0, 0, 0.08) 0px 0px 0px 1px,\\n  rgba(0, 0, 0, 0.04) 0px 2px 2px,\\n  rgba(0, 0, 0, 0.04) 0px 8px 8px -8px,\\n  #fafafa 0px 0px 0px 1px;\\n```\\n\\nEach layer has a separate purpose:\\n\\n1. The first layer creates the border-like ring.\\n2. The second adds minimal nearby elevation.\\n3. The third supplies softer ambient depth.\\n4. The `#fafafa` layer provides the subtle inner highlight.\\n\\n### Elevation Levels\\n\\n| Level | Treatment | Typical usage |\\n| --- | --- | --- |\\n| Flat | No shadow | Page background and text blocks |\\n| Ring | `rgba(0,0,0,0.08) 0px 0px 0px 1px` | Most bordered controls |\\n| Light Ring | `rgb(235,235,235) 0px 0px 0px 1px` | Tabs and images |\\n| Subtle Card | Ring plus `rgba(0,0,0,0.04) 0px 2px 2px` | Standard cards |\\n| Full Card | Complete card stack | Featured panels |\\n| Focus | `2px solid hsla(212, 100%, 48%, 1)` outline | Keyboard focus |\\n\\nInteractive elements must retain a visible focus treatment. The focus outline is supplemented by `var(--ds-focus-ring)` where that token is available.\\n\\n## Component Patterns\\n\\n### Buttons\\n\\n#### Shadow-Bordered White Button\\n\\n- Background: `#ffffff`\\n- Text: `#171717`\\n- Padding: `0px 6px`\\n- Radius: `6px`\\n- Ring: `rgb(235, 235, 235) 0px 0px 0px 1px`\\n- Hover background: `var(--ds-gray-1000)`\\n- Focus: `2px solid var(--ds-focus-color)` outline and focus-ring shadow\\n\\nThis is the standard secondary or ghost-style button.\\n\\n#### Dark CTA Button\\n\\nThe primary CTA pattern uses:\\n\\n- Background: `#171717`\\n- Text: `#ffffff`\\n- Padding: `8px 16px`\\n- Radius: `6px`\\n\\nUse this pattern for actions such as \u201cStart Deploying\u201d or \u201cGet Started.\u201d Primary action buttons should not use a full pill radius.\\n\\n#### Pill Badge\\n\\n- Background: `#ebf5ff`\\n- Text: `#0068d6`\\n- Padding: `0px 10px`\\n- Radius: `9999px`\\n- Font: Geist, `12px`, weight `500`\\n\\nPills are intended for statuses, tags, and feature labels.\\n\\n### Cards and Containers\\n\\nCards use:\\n\\n- White background\\n- `8px` radius for standard cards\\n- `12px` radius for featured or image cards\\n- Shadow-based borders rather than CSS `border`\\n- The full card shadow stack for highlighted panels\\n\\nProduct screenshots and image cards may use a light `1px solid #ebebeb` treatment, with `12px 12px 0px 0px` top rounding where appropriate. Hover states should intensify the shadow subtly rather than introduce strong color or elevation changes.\\n\\n### Inputs and Forms\\n\\nForm controls follow the same ring and focus conventions:\\n\\n- Use shadow-based borders.\\n- Use `2px solid var(--ds-focus-color)` for focus outlines.\\n- Use `var(--ds-gray-200)` as the radio focus background where applicable.\\n- Use `1px 0 0 0 var(--ds-gray-alpha-600)` for the specified focus shadow.\\n\\nFocus indicators must remain visible against the white background.\\n\\n### Navigation\\n\\nThe navigation pattern is a clean, sticky horizontal header:\\n\\n- White background\\n- Geist `14px`, weight `500` for links\\n- `#171717` link text\\n- Weight `600` or an underline for active items\\n- Right-aligned dark CTA controls\\n- Shadow-border separation from page content\\n- Hamburger-menu collapse on mobile\\n- Product dropdowns for multi-level navigation\\n\\nThe documented Vercel logotype dimensions are `262px \u00d7 52px`.\\n\\n### Workflow Pipeline\\n\\nThe workflow pipeline communicates the three stages of the product lifecycle:\\n\\n1. **Develop** \u2014 `--develop-text` (`#0a72ef`)\\n2. **Preview** \u2014 `--preview-text` (`#de1d8d`)\\n3. **Ship** \u2014 `--ship-text` (`#ff5b4f`)\\n\\nEach stage should include:\\n\\n- A Geist Mono uppercase technical label, typically `14px`\\n- A Geist title, typically `24px`, weight `600`\\n- A description, typically `16px`, weight `400`, colored `#4d4d4d`\\n- A connector line or arrow to the next stage\\n\\n### Trust Bar and Logo Grid\\n\\nTrust sections display company logos such as Perplexity, ChatGPT, and Cursor in grayscale. They may use:\\n\\n- A horizontal scroll layout on narrow screens\\n- A grid on larger screens\\n- Subtle `#ebebeb` separation\\n- No bright logo colors competing with the surrounding content\\n\\n### Metric Cards\\n\\nMetric cards emphasize a large value, such as \u201c10x faster\u201d:\\n\\n- Metric: Geist, `48px`, weight `600`\\n- Supporting description: gray body text\\n- Container: shadow-bordered card\\n- Use whitespace and typography rather than decorative color for emphasis\\n\\n## Layout and Spacing\\n\\n### Spacing Scale\\n\\nThe base unit is `8px`, with the documented scale:\\n\\n```text\\n1px, 2px, 3px, 4px, 5px, 6px, 8px,\\n10px, 12px, 14px, 16px, 32px, 36px, 40px\\n```\\n\\nThe primary scale intentionally jumps from `16px` to `32px`; `20px` and `24px` are not part of the primary spacing rhythm.\\n\\n### Containers and Grids\\n\\n- Maximum content width: approximately `1200px`\\n- Hero content: centered, single-column, and generously padded\\n- Feature content: two- or three-column grids\\n- Full-width section dividers: `border-bottom: 1px solid #171717`\\n- Code and dashboard previews: contained or full-width while preserving their border treatment\\n\\n### Whitespace\\n\\nSections should have substantial vertical separation, commonly `80px\u2013120px` or more on desktop. The system uses whitespace instead of alternating background colors to create section rhythm.\\n\\nThe intended contrast is:\\n\\n- Dense, tightly tracked headline text\\n- Large, open space around the headline and section content\\n\\n## Radius Scale\\n\\n| Name | Radius | Usage |\\n| --- | ---: | --- |\\n| Micro | `2px` | Inline code and small spans |\\n| Subtle | `4px` | Small containers |\\n| Standard | `6px` | Buttons and functional controls |\\n| Comfortable | `8px` | Cards and list items |\\n| Image | `12px` | Featured cards and image containers |\\n| Large | `64px` | Tab navigation |\\n| XL | `100px` | Large navigation links |\\n| Full Pill | `9999px` | Badges, tags, and status indicators |\\n| Circle | `50%` | Menu toggles and avatars |\\n\\n## Responsive Behavior\\n\\n### Breakpoints\\n\\n| Range | Behavior |\\n| --- | --- |\\n| `&lt;400px` | Tight single-column layout with minimal padding |\\n| `400\u2013600px` | Standard mobile stacked layout |\\n| `600\u2013768px` | Two-column grids begin where space permits |\\n| `768\u20131024px` | Full card grids and expanded padding |\\n| `1024\u20131200px` | Standard desktop layout |\\n| `1200\u20131400px` | Maximum-width desktop layout |\\n| `&gt;1400px` | Centered layout with generous outer margins |\\n\\n### Component Changes\\n\\nResponsive implementations should follow these transitions:\\n\\n- Hero typography scales down from `48px` while preserving proportional negative tracking.\\n- Horizontal navigation becomes a hamburger menu.\\n- Three-column feature grids collapse to two columns and then one.\\n- Code screenshots preserve their aspect ratio and may scroll horizontally.\\n- Trust logos change from a grid to horizontal scrolling on narrow screens.\\n- Footer columns stack vertically.\\n- Section spacing decreases from `80px+` to approximately `48px` on mobile.\\n- Hero gradients simplify and become less prominent on mobile.\\n\\nTouch targets should receive comfortable vertical padding, generally `8px\u201316px` for buttons. The mobile menu toggle uses a circular `50%` radius.\\n\\n## Implementation Guidance\\n\\nWhen adding a component based on this module:\\n\\n1. Start with a white surface and `#171717` text.\\n2. Choose typography by semantic role rather than styling each element ad hoc.\\n3. Apply negative letter-spacing only where specified; do not add positive tracking to Geist Sans.\\n4. Use weights `400`, `500`, and `600` according to content role.\\n5. Prefer a shadow ring over a traditional border.\\n6. Use the complete card shadow stack for featured surfaces, including the `#fafafa` inner ring.\\n7. Reserve `--develop-text`, `--preview-text`, and `--ship-text` for workflow stages.\\n8. Add the blue focus outline to every keyboard-interactive control.\\n9. Use `9999px` only for badges, tags, and status pills, not primary action buttons.\\n10. Validate the layout at the documented breakpoints, especially grid collapse, navigation changes, and screenshot overflow.\\n\\n## Agent Prompt Reference\\n\\nThe module includes reusable specifications for common generated components.\\n\\n### Hero\\n\\n- White background\\n- Headline: Geist, `48px`, weight `600`, line-height `1.00`, letter-spacing `-2.4px`, `#171717`\\n- Subtitle: Geist, `20px`, weight `400`, line-height `1.80`, `#4d4d4d`\\n- Dark CTA: `#171717`, `6px` radius, `8px 16px` padding\\n- Ghost CTA: white with the `rgba(0,0,0,0.08) 0px 0px 0px 1px` shadow ring\\n\\n### Card\\n\\n- White background\\n- No traditional CSS border\\n- Full card shadow stack\\n- `8px` radius\\n- Title: `24px`, weight `600`, letter-spacing `-0.96px`\\n- Body: `16px`, weight `400`, `#4d4d4d`\\n\\n### Badge\\n\\n- Background: `#ebf5ff`\\n- Text: `#0068d6`\\n- Radius: `9999px`\\n- Padding: `0px 10px`\\n- Geist `12px`, weight `500`\\n\\n### Navigation\\n\\n- Sticky white header\\n- Geist links at `14px`, weight `500`\\n- `#171717` link text\\n- Dark CTA on the right\\n- Shadow-border separation\\n\\n### Workflow Section\\n\\n- Three stages: Develop, Preview, Ship\\n- Geist Mono uppercase labels\\n- Stage colors: `#0a72ef`, `#de1d8d`, and `#ff5b4f`\\n- Stage titles: Geist `24px`, weight `600`\\n- Descriptions: Geist `16px`, weight `400`, `#4d4d4d`\\n\\n## Anti-Patterns\\n\\nAvoid the following implementations:\\n\\n- Positive letter-spacing on Geist Sans\\n- Weight `700` for normal body or UI text\\n- Traditional borders on standard cards when a shadow ring is appropriate\\n- Warm UI colors such as oranges, yellows, or greens\\n- Decorative use of workflow accent colors\\n- Heavy shadows with opacity greater than approximately `0.1`\\n- Increased tracking on body text\\n- Full-pill primary action buttons\\n- Omitting the `#fafafa` inner ring from featured card shadows\\n- Replacing `#171717` with `#000000` for ordinary text or headings\",\"other-docker-compose-override-example-yml\":\"# Other \u2014 docker-compose.override.example.yml\\n\\n# `docker-compose.override.example.yml`\\n\\n## Purpose\\n\\n`docker-compose.override.example.yml` is a template for local development and user-extended Docker builds. It provides a minimal Docker Compose override that changes the application image build from the default `Dockerfile` to `Dockerfile.user`.\\n\\nThe file is intentionally an example and should not be edited directly. Developers should copy it to:\\n\\n```text\\ndocker-compose.override.yml\\n```\\n\\nThe destination file is gitignored, allowing local Docker customizations without changing repository-tracked configuration.\\n\\n## How Docker Compose Uses It\\n\\nDocker Compose automatically loads `docker-compose.override.yml` alongside `docker-compose.yml` when both files are present. No additional `-f` flags are required:\\n\\n```bash\\ncp docker-compose.override.example.yml docker-compose.override.yml\\ndocker compose up -d\\n```\\n\\nThe override is merged into the base Compose configuration. It modifies only the `app` service\u2019s build configuration; all other service settings remain inherited from `docker-compose.yml`.\\n\\n## Configuration\\n\\nThe file defines the following override:\\n\\n```yaml\\nservices:\\n  app:\\n    build:\\n      context: .\\n      dockerfile: Dockerfile.user\\n```\\n\\n### `services.app.build.context`\\n\\nThe build context is the repository root:\\n\\n```yaml\\ncontext: .\\n```\\n\\nThis makes repository files available to the Docker build and matches the base Compose configuration.\\n\\n### `services.app.build.dockerfile`\\n\\nThe override selects:\\n\\n```yaml\\ndockerfile: Dockerfile.user\\n```\\n\\nThe base `docker-compose.yml` uses the default `Dockerfile`. This override changes the build to `Dockerfile.user`, which is intended for custom or user-extended application images.\\n\\nAny customizations required by a local developer should generally be implemented in `Dockerfile.user` or in the ignored `docker-compose.override.yml`, rather than by modifying this example file.\\n\\n## User Home Persistence\\n\\nThe application\u2019s `/home/appuser` directory is already persisted by the base Compose configuration through the `archon_user_home` named volume. This includes user-specific state such as:\\n\\n- Claude, Codex, and Pi configuration\\n- Git configuration\\n- Shell history\\n\\nNo additional volume configuration is needed in the override file.\\n\\nTo use a host directory instead of the named volume, set `ARCHON_USER_HOME` in `.env`:\\n\\n```dotenv\\nARCHON_USER_HOME=/your/host/path\\n```\\n\\nThe selected host path must be writable by UID `1001`, which is the expected user ID for the application user inside the container.\\n\\nThis environment-variable configuration does not require editing `docker-compose.override.yml`.\\n\\n## Relationship to Other Files\\n\\n| File | Role |\\n|---|---|\\n| `docker-compose.yml` | Defines the base services and default `app` build using `Dockerfile`. |\\n| `docker-compose.override.example.yml` | Tracked template that switches the `app` build to `Dockerfile.user`. |\\n| `docker-compose.override.yml` | Local, gitignored copy of the example used automatically by Docker Compose. |\\n| `Dockerfile` | Default application image build used without the override. |\\n| `Dockerfile.user` | Custom application image build selected by this override. |\\n| `.env` | Optional local environment configuration, including `ARCHON_USER_HOME`. |\\n| `archon_user_home` | Named volume defined by the base Compose configuration for `/home/appuser` persistence. |\\n\\n## Typical Workflow\\n\\n1. Copy the example file:\\n\\n   ```bash\\n   cp docker-compose.override.example.yml docker-compose.override.yml\\n   ```\\n\\n2. Ensure `Dockerfile.user` exists and contains the desired user-specific build steps.\\n\\n3. Optionally configure a host-backed home directory in `.env`:\\n\\n   ```dotenv\\n   ARCHON_USER_HOME=/your/host/path\\n   ```\\n\\n4. Start the application:\\n\\n   ```bash\\n   docker compose up -d\\n   ```\\n\\n5. Rebuild after changing `Dockerfile.user` or related build inputs:\\n\\n   ```bash\\n   docker compose up -d --build\\n   ```\\n\\n## Scope and Runtime Behavior\\n\\nThis module contains declarative Docker Compose configuration only. It has:\\n\\n- No functions or classes\\n- No internal or outgoing code calls\\n- No independent execution flow\\n\\nIts effect occurs when Docker Compose reads and merges it with `docker-compose.yml`. The resulting configuration builds the `app` service from `Dockerfile.user` while retaining the base file\u2019s services, volumes, networking, and other settings.\",\"other-docker-compose-yml\":\"# Other \u2014 docker-compose.yml\\n\\n# Other \u2014 `docker-compose.yml`\\n\\n`docker-compose.yml` defines the Docker Compose deployment for Archon. It provides the main application, optional PostgreSQL storage, HTTPS termination, form-based authentication, and optional DeepEval and Ragas evaluator services.\\n\\nThe `app` service runs by default. Other services are enabled with Compose profiles.\\n\\n## Service topology\\n\\n```mermaid\\ngraph TD\\n    User[Client] --&gt;|HTTP :3000 or HTTPS :443| App[app]\\n    User --&gt;|HTTPS :443| Caddy[caddy]\\n    Caddy --&gt; App\\n    Caddy --&gt; Auth[auth-service]\\n    App --&gt; Postgres[postgres]\\n    App --&gt; DeepEval[deepeval-evaluator]\\n    App --&gt; Ragas[ragas-evaluator]\\n```\\n\\nAll services use the `archon-network` bridge network. Services can communicate using their Compose service names, such as `postgres`, `deepeval-evaluator`, and `ragas-evaluator`.\\n\\n## Starting the stack\\n\\n### Application with SQLite\\n\\nThe default deployment starts only the application:\\n\\n```bash\\ndocker compose up -d\\n```\\n\\nSQLite is used when `DATABASE_URL` is not configured for PostgreSQL. Archon data is stored in the `/.archon` directory inside the container and persisted through the `archon_data` volume or the host path configured by `ARCHON_DATA`.\\n\\n### Application with PostgreSQL\\n\\nStart the application and local PostgreSQL container with the `with-db` profile:\\n\\n```bash\\ndocker compose --profile with-db up -d\\n```\\n\\nSet the application database URL in `.env`:\\n\\n```dotenv\\nDATABASE_URL=postgresql://postgres:postgres@postgres:5432/remote_coding_agent\\n```\\n\\nThe hostname is `postgres`, which resolves to the PostgreSQL service on `archon-network`.\\n\\nPostgreSQL can also be external to Compose. In that case, configure `DATABASE_URL` with the external connection string and omit the `with-db` profile.\\n\\n### Application with HTTPS\\n\\nStart Caddy with the `cloud` profile:\\n\\n```bash\\ndocker compose --profile cloud up -d\\n```\\n\\nBefore starting the service:\\n\\n1. Set `DOMAIN` in `.env`.\\n2. Point the domain's DNS A record to the Docker host.\\n3. Ensure ports 80 and 443 are reachable from the internet.\\n\\nCaddy reads its configuration from `./Caddyfile` and manages certificates through Let's Encrypt.\\n\\n### Application with authentication\\n\\nThe authentication service is enabled separately with the `auth` profile. It is normally used together with Caddy:\\n\\n```bash\\ndocker compose --profile cloud --profile auth up -d\\n```\\n\\nThe service requires authentication settings in `.env`, including:\\n\\n- `AUTH_USERNAME`\\n- `AUTH_PASSWORD_HASH`\\n- `COOKIE_SECRET`\\n\\nThe authentication service is available to other containers on the Compose network, but its port is not published to the host. Caddy's `forward_auth` configuration is responsible for connecting it to the external login flow.\\n\\n### Evaluator services\\n\\nEnable the optional evaluator services with their respective profiles:\\n\\n```bash\\ndocker compose --profile deepeval up -d\\ndocker compose --profile ragas up -d\\n```\\n\\nMultiple profiles can be enabled together:\\n\\n```bash\\ndocker compose --profile with-db --profile cloud up -d\\ndocker compose --profile cloud --profile auth --profile deepeval --profile ragas up -d\\n```\\n\\n## Services\\n\\n### `app`\\n\\nThe `app` service is the primary Archon container and is always enabled.\\n\\n```yaml\\napp:\\n  build: .\\n  image: archon\\n```\\n\\nThe image is built from the repository root and tagged locally as `archon`. Environment variables are loaded from `.env`, with Compose-level defaults for Docker and evaluator integration.\\n\\n#### Published port\\n\\nThe application port is published using the `PORT` variable:\\n\\n```yaml\\n- \\\"${PORT:-3000}:${PORT:-3000}\\\"\\n```\\n\\nIf `PORT` is not set, the application is available at:\\n\\n```text\\nhttp://localhost:3000\\n```\\n\\nThe same port is used on the host and inside the container.\\n\\n#### Container environment\\n\\nThe Compose file always sets:\\n\\n```dotenv\\nARCHON_DOCKER=true\\n```\\n\\nEvaluator-related variables are passed explicitly to the application:\\n\\n- `ARCHON_RAGAS_EVALUATOR_URL`\\n- `ARCHON_RAGAS_EVALUATOR_TIMEOUT_MS`\\n- `ARCHON_RAGAS_EVALUATOR_TOKEN`\\n- `ARCHON_DEEPEVAL_EVALUATOR_URL`\\n- `ARCHON_DEEPEVAL_EVALUATOR_TIMEOUT_MS`\\n- `ARCHON_DEEPEVAL_EVALUATOR_TOKEN`\\n- `ARCHON_PROMPTFOO_EVALUATOR_URL`\\n- `ARCHON_PROMPTFOO_EVALUATOR_TIMEOUT_MS`\\n- `ARCHON_PROMPTFOO_EVALUATOR_TOKEN`\\n- `ARCHON_PROMPTFOO_CLI_ENABLED`\\n- `ARCHON_PROMPTFOO_COMMAND`\\n\\nThe evaluator services are not automatically wired to these URLs. When running an evaluator container, configure the corresponding application URL in `.env`, using the service name and internal port. For example, the Ragas service listens internally on port `8000`, so the application can use an internal URL based on `ragas-evaluator:8000`.\\n\\n#### Persistent storage\\n\\nThe application mounts two persistent locations:\\n\\n```yaml\\n- ${ARCHON_DATA:-archon_data}:/.archon\\n- ${ARCHON_USER_HOME:-archon_user_home}:/home/appuser\\n```\\n\\n`ARCHON_DATA` controls Archon's application data:\\n\\n- If set to an absolute host path, that path is bind-mounted.\\n- Otherwise, Docker uses the named volume `archon_data`.\\n\\n`ARCHON_USER_HOME` controls `/home/appuser`, preserving user-specific state such as:\\n\\n- Claude Code skills, commands, agents, and hooks\\n- Codex and Pi authentication state\\n- `~/.gitconfig`\\n- Shell history\\n\\nBy default, this state is stored in the Docker-managed `archon_user_home` volume.\\n\\n#### Health and runtime behavior\\n\\nThe application health check requests:\\n\\n```text\\nGET http://localhost:${PORT:-3000}/api/health\\n```\\n\\nIts health check configuration is:\\n\\n- Interval: 30 seconds\\n- Timeout: 10 seconds\\n- Retries: 3\\n- Start period: 15 seconds\\n\\nThe container uses `restart: unless-stopped`, Google DNS servers, and disables IPv6 through:\\n\\n```yaml\\nnet.ipv6.conf.all.disable_ipv6=1\\n```\\n\\n### `postgres`\\n\\n`postgres` provides optional local PostgreSQL and is enabled by the `with-db` profile.\\n\\n```yaml\\nimage: postgres:17-alpine\\nprofiles: [\\\"with-db\\\"]\\n```\\n\\nThe database is initialized with:\\n\\n```yaml\\n./migrations/000_combined.sql:/docker-entrypoint-initdb.d/000_combined.sql:ro\\n```\\n\\nAll migration files are also mounted read-only at:\\n\\n```text\\n/migrations\\n```\\n\\nThe database configuration is:\\n\\n- Database: `remote_coding_agent`\\n- User: `postgres`\\n- Password: `${POSTGRES_PASSWORD:-postgres}`\\n\\nPostgreSQL data is persisted in the `postgres_data` named volume at `/var/lib/postgresql/data`.\\n\\nThe database port is bound only to loopback on the Docker host:\\n\\n```yaml\\n127.0.0.1:${POSTGRES_PORT:-5432}:5432\\n```\\n\\nThis makes PostgreSQL available locally to host tools without exposing it on external interfaces.\\n\\nThe health check uses:\\n\\n```bash\\npg_isready -U postgres\\n```\\n\\nwith a five-second interval, five-second timeout, and five retries.\\n\\nThe service does not define an explicit `depends_on` relationship with `app`. The application must be configured with the correct `DATABASE_URL`, and database readiness is independently reported through the PostgreSQL health check.\\n\\n### `caddy`\\n\\n`caddy` provides optional public HTTP/HTTPS access and automatic TLS. It is enabled by the `cloud` profile.\\n\\n```yaml\\nimage: caddy:2-alpine\\nprofiles: [\\\"cloud\\\"]\\n```\\n\\nPublished ports:\\n\\n- `80:80` for HTTP\\n- `443:443` for HTTPS\\n- `443:443/udp` for HTTP/3 or QUIC\\n\\nThe service mounts:\\n\\n```yaml\\n./Caddyfile:/etc/caddy/Caddyfile:ro\\ncaddy_data:/data\\ncaddy_config:/config\\n```\\n\\nThe Caddy configuration is maintained in the repository's `Caddyfile`. Certificate data and Caddy configuration are persisted through `caddy_data` and `caddy_config`.\\n\\nCaddy waits for the application to become healthy:\\n\\n```yaml\\ndepends_on:\\n  app:\\n    condition: service_healthy\\n```\\n\\nCaddy and the application communicate over `archon-network`; the application does not need to publish a separate internal-only port for Caddy to reach it.\\n\\n### `auth-service`\\n\\n`auth-service` provides form-based login support for Caddy's `forward_auth` integration. It is enabled by the `auth` profile:\\n\\n```yaml\\nbuild: ./auth-service\\nprofiles: [\\\"auth\\\"]\\n```\\n\\nThe service reads authentication configuration from `.env` and sets its listening port from:\\n\\n```dotenv\\nAUTH_PORT=${AUTH_SERVICE_PORT:-9000}\\n```\\n\\nIts port is exposed only to the Docker network:\\n\\n```yaml\\nexpose:\\n  - \\\"${AUTH_SERVICE_PORT:-9000}\\\"\\n```\\n\\nIt is not published to the host. The Caddy configuration should reference the service by its Compose hostname and configured internal port.\\n\\nThe service requires the authentication credentials and cookie settings documented in the Compose comments and `docs/docker.md`.\\n\\n### `deepeval-evaluator`\\n\\n`deepeval-evaluator` is an optional evaluator service for general LLM-as-judge semantic metrics. It is enabled by the `deepeval` profile:\\n\\n```yaml\\nbuild: ./services/deepeval-evaluator\\nprofiles: [\\\"deepeval\\\"]\\n```\\n\\nThe service provides `POST /evaluate` and listens on port `8000` inside the container. It is also available on the Docker host through a loopback-only binding:\\n\\n```yaml\\n127.0.0.1:${DEEPEVAL_EVALUATOR_PORT:-8020}:8000\\n```\\n\\nIts configurable environment variables include:\\n\\n- `DEEPEVAL_EVALUATOR_TOKEN`\\n- `DEEPEVAL_LLM_MODEL`, default `gpt-4o-mini`\\n- `DEEPEVAL_RUBRIC_VERSION`, default `deepeval-v1`\\n- `DEEPEVAL_THRESHOLD`\\n\\nThe service expects `OPENAI_API_KEY` from `.env`.\\n\\nThe health check executes a Python request against:\\n\\n```text\\nhttp://localhost:8000/health\\n```\\n\\nIt has a 30-second interval, 10-second timeout, three retries, and a 30-second startup period.\\n\\n### `ragas-evaluator`\\n\\n`ragas-evaluator` provides workflow and RAG semantic metrics and is enabled by the `ragas` profile:\\n\\n```yaml\\nbuild: ./services/ragas-evaluator\\nprofiles: [\\\"ragas\\\"]\\n```\\n\\nIt provides `POST /evaluate` on internal port `8000`. Its host port is bound to loopback:\\n\\n```yaml\\n127.0.0.1:${RAGAS_EVALUATOR_PORT:-8010}:8000\\n```\\n\\nThe service reads `OPENAI_API_KEY` and supports these settings:\\n\\n- `RAGAS_LLM_MODEL`, default `gpt-4o-mini`\\n- `RAGAS_RUBRIC_VERSION`, default `ragas-v1`\\n- `RAGAS_EMBEDDING_MODEL`, default `text-embedding-3-small`\\n- `RAGAS_EVALUATOR_TOKEN`\\n- `RAGAS_REQUEST_TIMEOUT_SECONDS`, default `120`\\n- `RAGAS_MAX_RETRIES`, default `1`\\n- `RAGAS_LLM_TEMPERATURE`, default `0`\\n- `RAGAS_METRICS`, default:\\n  `faithfulness,answer_relevancy,context_precision,context_recall`\\n\\nIts health check requests:\\n\\n```text\\nhttp://localhost:8000/health\\n```\\n\\nThe health check uses the same 30-second interval, 10-second timeout, three retries, and 30-second startup period as the DeepEval evaluator.\\n\\n## Storage and networking\\n\\nThe Compose file declares five named volumes:\\n\\n| Volume | Purpose |\\n|---|---|\\n| `archon_data` | Archon application data when `ARCHON_DATA` is not set |\\n| `archon_user_home` | Persistent `/home/appuser` state |\\n| `postgres_data` | PostgreSQL database files |\\n| `caddy_data` | Caddy runtime and certificate data |\\n| `caddy_config` | Caddy configuration state |\\n\\nAll services attach to the `archon-network` bridge network. The network provides service-name DNS and isolates container-to-container traffic from unrelated Docker networks.\\n\\nHost exposure is intentionally limited for internal services:\\n\\n- The application port follows `PORT` and is externally published.\\n- PostgreSQL is bound to `127.0.0.1`.\\n- DeepEval is bound to `127.0.0.1`.\\n- Ragas is bound to `127.0.0.1`.\\n- The authentication service uses `expose` only and has no host binding.\\n- Caddy publishes ports 80 and 443 for public access.\\n\\n## Configuration precedence\\n\\nThe Compose file uses both `env_file: .env` and Compose variable interpolation.\\n\\nVariables such as `PORT`, `ARCHON_DATA`, `ARCHON_USER_HOME`, database ports, evaluator ports, and evaluator settings are resolved from the shell environment or `.env` when available. The `${VARIABLE:-default}` form supplies a fallback when a variable is unset or empty.\\n\\nFor example:\\n\\n```yaml\\n- ${ARCHON_DATA:-archon_data}:/.archon\\n```\\n\\nuses a host path when `ARCHON_DATA` is configured and otherwise selects the named volume `archon_data`.\\n\\nKeep secrets and deployment-specific values in `.env`; do not commit them to the Compose file. In particular, database passwords, evaluator tokens, API keys, authentication secrets, and domain configuration should be supplied through the deployment environment.\",\"other-docker-entrypoint-sh\":\"# Other \u2014 docker-entrypoint.sh\\n\\n# `docker-entrypoint.sh`\\n\\n`docker-entrypoint.sh` is the container startup script for Archon. It prepares persistent user state, seeds built-in workflows and commands, configures Git and Claude Code, then starts Archon using either the installed `archon` executable or the Bun TypeScript development path.\\n\\nThe script runs with:\\n\\n```bash\\nset -e\\n```\\n\\nAny failing command that is not explicitly handled terminates container startup.\\n\\n## Startup flow\\n\\n```mermaid\\nflowchart TD\\n    A[Container starts] --&gt; B[Create Archon directories]\\n    B --&gt; C[Seed e2e workflows and commands]\\n    C --&gt; D[Select privilege runner]\\n    D --&gt; E[Warn about ignored environment variables]\\n    E --&gt; F[Register Git safe directories]\\n    F --&gt; G[Configure GH_TOKEN credential helper]\\n    G --&gt; H[Select glibc Claude binary]\\n    H --&gt; I{archon executable exists?}\\n    I --&gt;|Yes| J[exec archon serve]\\n    I --&gt;|No| K[bun run setup-auth]\\n    K --&gt; L[exec bun run start]\\n```\\n\\n## Directory initialization\\n\\nThe script ensures that the following directories exist:\\n\\n```text\\n/home/appuser/.archon/workspaces\\n/home/appuser/.archon/worktrees\\n```\\n\\nThese directories are required by Claude subprocesses and Archon worktree handling. In particular, a missing working directory can cause a Claude subprocess to fail without producing a useful error.\\n\\nThis initialization is important for both:\\n\\n- Named volumes, which may inherit directories from the image only on first creation.\\n- Bind mounts, which replace the image directory contents and therefore do not inherit directories created during the image build.\\n\\n## Seeding built-in e2e resources\\n\\nThe image contains built-in end-to-end resources under:\\n\\n```text\\n/app/.archon/workflows/e2e/\\n/app/.archon/commands/e2e/\\n```\\n\\nAt runtime, the loader scans the home-level Archon directory instead:\\n\\n```text\\n/home/appuser/.archon/workflows/\\n/home/appuser/.archon/commands/\\n```\\n\\nThe script copies each resource tree into the corresponding home-level directory:\\n\\n```bash\\ncp -rn /app/.archon/workflows/e2e/. /home/appuser/.archon/workflows/e2e/\\ncp -rn /app/.archon/commands/e2e/. /home/appuser/.archon/commands/e2e/\\n```\\n\\nThe `-n` option prevents overwriting existing files. This allows users to customize resources in a persisted volume without having their changes replaced when the container restarts or the image is rebuilt.\\n\\nIf either source directory does not exist, that resource category is skipped.\\n\\n## Privilege handling\\n\\nThe script supports both root and non-root container execution.\\n\\n### Root execution\\n\\nWhen `id -u` returns `0`, the script:\\n\\n1. Recursively changes ownership of `/home/appuser` to `appuser:appuser`.\\n2. Sets:\\n\\n   ```bash\\n   RUNNER=\\\"gosu appuser\\\"\\n   ```\\n\\n3. Runs Git and the Archon process as `appuser`.\\n\\nThe ownership correction is required because `/home/appuser` may be a bind mount whose files are owned by host UIDs that do not correspond to UID `1001` inside the container. The home directory contains persistent state such as:\\n\\n- Claude, Codex, and Pi configuration\\n- `~/.gitconfig`\\n- Shell history\\n- Archon configuration and repositories\\n\\nIf ownership correction fails, startup stops with an error. This commonly indicates a read-only volume or incompatible mount options.\\n\\n### Non-root execution\\n\\nWhen the container is already running as a non-root user\u2014for example, through Docker\u2019s `--user` option or Kubernetes security settings\u2014the script does not attempt ownership changes:\\n\\n```bash\\nRUNNER=\\\"\\\"\\n```\\n\\nAll subsequent commands run directly as the current user. The selected user must have sufficient permissions to access `/home/appuser` and modify its Git configuration.\\n\\n## Environment variable diagnostics\\n\\nThe script emits warnings for variables that may be present in a shared `.env` file but do not control the container runtime.\\n\\n### `ARCHON_HOME`\\n\\nIf set, the script warns that the value is ignored:\\n\\n```text\\n[archon] ARCHON_HOME=... ignored in Docker (container home is fixed at /home/appuser/.archon)\\n```\\n\\nDocker uses `/home/appuser/.archon` as the runtime home-level Archon directory.\\n\\n### `ARCHON_DATA`\\n\\nIf set, the script warns that the value is a host-side Docker Compose substitution token and is not read by the container:\\n\\n```text\\n[archon] ARCHON_DATA=... is a host-side compose token; not read inside the container\\n```\\n\\nThese are warnings only and do not stop startup.\\n\\n## Git safe-directory registration\\n\\nThe script searches for Git repositories below:\\n\\n```text\\n/home/appuser/.archon\\n```\\n\\nIt finds `.git` directories, derives each repository path, and registers the path as a global Git `safe.directory` if it is not already present.\\n\\nThis handles Git\u2019s ownership validation introduced in Git 2.35.2 and associated with CVE-2022-24765. It is especially important for macOS VirtioFS bind mounts, where host ownership may not map to the container\u2019s `appuser` UID.\\n\\nThe script checks existing values before adding a new entry:\\n\\n```bash\\ngit config --global --get-all safe.directory\\n```\\n\\nThis prevents duplicate entries from accumulating across container restarts. The persisted `~/.gitconfig` is reused on subsequent boots, and worktrees may exist at arbitrary depths that cannot be registered during image construction.\\n\\nThe search uses:\\n\\n```bash\\nfind /home/appuser/.archon -name \\\".git\\\" -prune -print\\n```\\n\\nGit configuration is executed through `RUNNER`, so root-started containers write the configuration as `appuser`.\\n\\n## GitHub HTTPS authentication\\n\\nWhen `GH_TOKEN` is set, the script configures GitHub HTTPS authentication using a Git credential helper:\\n\\n```bash\\ngit config --global credential.\\\"https://github.com\\\".helper \\\\\\n  '!f() { echo \\\"username=x-access-token\\\"; echo \\\"password=${GH_TOKEN}\\\"; }; f'\\n```\\n\\nThe token is referenced through the helper\u2019s runtime environment rather than written directly into the Git configuration file. This allows HTTPS clone and fetch operations to authenticate without persisting the token value in `~/.gitconfig`.\\n\\nThe helper is configured only when `GH_TOKEN` is non-empty.\\n\\n## Claude Code binary selection\\n\\nThe container uses a Debian/glibc runtime. The Claude Agent SDK package can contain both musl and glibc binaries, and its resolver may select the musl variant first because of Bun\u2019s hoisted optional dependencies.\\n\\nTo avoid executing an incompatible binary, the script explicitly selects a glibc Claude binary unless the caller has already supplied `CLAUDE_BIN_PATH`.\\n\\nSupported architectures and paths are:\\n\\n| Architecture | Binary |\\n|---|---|\\n| `x86_64` | `/app/node_modules/@anthropic-ai/claude-agent-sdk-linux-x64/claude` |\\n| `aarch64` | `/app/node_modules/@anthropic-ai/claude-agent-sdk-linux-arm64/claude` |\\n\\nIf `CLAUDE_BIN_PATH` is already set, the script preserves it and performs no automatic selection.\\n\\nIf it is not set, startup fails when:\\n\\n- The CPU architecture is not `x86_64` or `aarch64`.\\n- The expected binary is missing.\\n- The expected binary is not executable.\\n\\nFor unsupported or changed SDK package layouts, operators can provide a compatible binary explicitly:\\n\\n```bash\\ndocker run -e CLAUDE_BIN_PATH=/path/to/glibc/claude ...\\n```\\n\\n## Server startup modes\\n\\nThe final startup behavior depends on whether the packaged Archon executable exists.\\n\\n### Binary mode\\n\\nIf this file is executable:\\n\\n```text\\n/usr/local/bin/archon\\n```\\n\\nthe script starts the production server:\\n\\n```bash\\nexec $RUNNER archon serve\\n```\\n\\n### Bun source mode\\n\\nIf the executable is absent, the script assumes a Bun source/development image:\\n\\n```bash\\n$RUNNER bun run setup-auth\\nexec $RUNNER bun run start\\n```\\n\\n`bun run setup-auth` runs before the server starts, allowing source-mode images to prepare authentication state.\\n\\n## PID 1 and signal handling\\n\\nBoth server paths use `exec` for the final process. As a result, `archon serve` or `bun run start` replaces the shell and becomes PID 1 in the container.\\n\\nThis ensures that Docker and orchestration platforms deliver signals such as `SIGTERM` directly to the server, allowing Archon to perform graceful shutdown.\\n\\nThe script does not process command-line arguments; it always selects one of the two startup modes described above.\",\"other-dockerfile-base\":\"# Other \u2014 Dockerfile.base\\n\\n# Dockerfile.base\\n\\n`Dockerfile.base` builds the Archon system-dependency image. It packages the operating-system tools, browser runtimes, coding-agent CLIs, GitNexus, and shared user directories required by Archon runtime containers.\\n\\nThe image is intended to change infrequently and be reused as a base image by higher-level Dockerfiles.\\n\\n```bash\\ndocker build -f Dockerfile.base -t archon-base:latest .\\n```\\n\\nThis module contains no application functions, classes, or internal call graph. Its behavior is defined entirely by the Docker build stages and image-layer configuration.\\n\\n## Image architecture\\n\\nThe Dockerfile uses a two-stage build:\\n\\n```mermaid\\nflowchart LR\\n    A[node:18-slim builder] --&gt; B[agent-browser native binary]\\n    A --&gt; C[gitnexus package and native assets]\\n    B --&gt; D[debian:12-slim runtime]\\n    C --&gt; D\\n    D --&gt; E[System tools and Chromium]\\n    D --&gt; F[appuser and coding CLIs]\\n    D --&gt; G[Playwright Chromium]\\n    D --&gt; H[Archon runtime directories]\\n```\\n\\n### Stage 1: `node-builder`\\n\\nThe `node-builder` stage is based on `node:18-slim` and prepares Node-related artifacts without retaining the complete builder image in the final image.\\n\\nIt installs:\\n\\n- `agent-browser@0.22.1`\\n- `gitnexus`\\n\\nThe stage produces two categories of artifacts:\\n\\n1. **`agent-browser` native executable**\\n\\n   After installing `agent-browser`, the Dockerfile searches the package directory for an executable matching `agent-browser-*`:\\n\\n   ```bash\\n   find /usr/local/lib/node_modules/agent-browser \\\\\\n     -name 'agent-browser-*' -type f -executable\\n   ```\\n\\n   The first matching file is copied to:\\n\\n   ```text\\n   /tmp/agent-browser-native\\n   ```\\n\\n   The build fails if no native binary is found.\\n\\n2. **GitNexus package and native dependencies**\\n\\n   `gitnexus` is installed with `--ignore-scripts` to prevent the `onnxruntime-node` installation script from attempting an external download during the npm installation phase.\\n\\n   The Dockerfile then explicitly runs:\\n\\n   ```bash\\n   node \\\"$(npm root -g)/gitnexus/node_modules/@ladybugdb/core/install.js\\\"\\n   ```\\n\\n   This manually completes the native binary setup required by `@ladybugdb/core`.\\n\\n### Stage 2: runtime image\\n\\nThe final image is based on:\\n\\n```dockerfile\\nFROM debian:12-slim\\n```\\n\\nOnly selected artifacts from `node-builder` are copied into the runtime image:\\n\\n- `/tmp/agent-browser-native`\\n- `/usr/local/bin/node`\\n- `/usr/local/lib/node_modules/gitnexus`\\n\\nThis keeps the final image independent of npm\u2019s builder installation while still providing the required native binaries and GitNexus package.\\n\\n## APT configuration and system packages\\n\\nThe image sets:\\n\\n```text\\nDEBIAN_FRONTEND=noninteractive\\n```\\n\\nThis prevents interactive prompts during package installation.\\n\\n### Tsinghua APT mirror\\n\\nThe build attempts to replace the default Debian mirror with the Tsinghua University TUNA mirror. It supports both Debian source formats:\\n\\n- `/etc/apt/sources.list.d/debian.sources`\\n- `/etc/apt/sources.list`\\n\\nIf neither source file exists, it creates a Bookworm source list containing:\\n\\n- `bookworm`\\n- `bookworm-updates`\\n- `bookworm-security`\\n- `main`\\n- `contrib`\\n- `non-free`\\n- `non-free-firmware`\\n\\nThe image also writes:\\n\\n```text\\nAcquire::Check-Valid-Until \\\"false\\\";\\n```\\n\\nto disable APT repository metadata expiration checks. This is intended to improve build reliability with mirrored repositories, but it reduces freshness validation for repository metadata.\\n\\n### Installed Debian packages\\n\\nThe runtime image installs the following packages:\\n\\n| Package | Purpose |\\n|---|---|\\n| `git` | Source-control operations |\\n| `bash` | Shell execution and user shell |\\n| `gosu` | User switching while preserving process behavior |\\n| `ca-certificates` | TLS certificate validation |\\n| `curl` | Downloading installers and external artifacts |\\n| `gnupg` | Cryptographic tooling |\\n| `chromium` | System browser used by `agent-browser` |\\n| `wget` | Download utility |\\n| `tar` | Archive extraction |\\n| `bzip2` | bzip2 archive support |\\n| `openssh-client` | SSH-based Git and remote access |\\n| `python3` | Python runtime |\\n| `python3-pip` | Python package installation |\\n\\nAPT package lists are removed after installation:\\n\\n```bash\\nrm -rf /var/lib/apt/lists/*\\n```\\n\\n## GitHub CLI\\n\\nGitHub CLI version `2.67.0` is downloaded directly from the GitHub release archive rather than installed through an APT repository.\\n\\nThe binary is installed at:\\n\\n```text\\n/usr/local/bin/gh\\n```\\n\\nThe build verifies the installation with:\\n\\n```bash\\ngh --version\\n```\\n\\nThis approach avoids APT GPG repository-signature setup for GitHub CLI.\\n\\n## `agent-browser`\\n\\nThe final image receives the native executable from the builder stage:\\n\\n```text\\n/usr/local/bin/agent-browser-native\\n```\\n\\nIt is exposed through the standard command name:\\n\\n```text\\n/usr/local/bin/agent-browser\\n```\\n\\nusing a symbolic link.\\n\\nThe image deliberately uses the Debian system Chromium installation instead of downloading Chrome for Testing:\\n\\n```dockerfile\\nENV AGENT_BROWSER_EXECUTABLE_PATH=/usr/bin/chromium\\n```\\n\\nThis avoids an additional browser download of approximately 400 MB and ensures that `agent-browser` uses the browser installed by APT.\\n\\n## Node.js and npm\\n\\nThe final image receives Node.js 18 from two sources:\\n\\n1. The Node runtime binary is copied from `node-builder`:\\n\\n   ```text\\n   /usr/local/bin/node\\n   ```\\n\\n2. NodeSource\u2019s Node.js 18 APT setup script is executed, followed by installation of the `nodejs` package.\\n\\nThe Dockerfile also creates an `npx` link:\\n\\n```text\\n/usr/local/bin/npx\\n```\\n\\npointing to the npm-provided `npx` executable.\\n\\nNode-related global packages are redirected into the non-root user\u2019s home directory:\\n\\n```dockerfile\\nENV NPM_CONFIG_PREFIX=/home/appuser/.npm-global\\nENV PATH=\\\"/home/appuser/.npm-global/bin:${PATH}\\\"\\n```\\n\\nAs a result, packages installed later with `npm install -g` are placed under:\\n\\n```text\\n/home/appuser/.npm-global\\n```\\n\\n## GitNexus\\n\\nGitNexus is copied from the builder stage into:\\n\\n```text\\n/usr/local/lib/node_modules/gitnexus\\n```\\n\\nThe Dockerfile reads the package\u2019s `bin` field dynamically and creates the command link:\\n\\n```text\\n/usr/local/bin/gitnexus\\n```\\n\\nThis avoids hard-coding the package\u2019s current executable entry path.\\n\\nGitNexus is then configured for the installed coding agent by running:\\n\\n```bash\\nsu appuser -c \\\"gitnexus setup\\\"\\n```\\n\\n`gitnexus setup` is responsible for detecting the available coding-agent installation and writing the associated hooks and MCP server configuration.\\n\\n## Non-root runtime user\\n\\nThe image creates:\\n\\n```text\\nappuser\\nUID: 1000\\nShell: /bin/bash\\n```\\n\\nThe user\u2019s home directory is:\\n\\n```text\\n/home/appuser\\n```\\n\\nThe following directories are created and owned by `appuser`:\\n\\n```text\\n/home/appuser/.claude/skills\\n/home/appuser/.baidu-cc/skills\\n/home/appuser/.codex\\n```\\n\\nRunning the coding tools as `appuser` is required because Claude Code rejects root execution when `--dangerously-skip-permissions` is used.\\n\\nDownstream containers should preserve `appuser` as the effective runtime user unless they have a specific reason to override it.\\n\\n## Baidu Ducc client\\n\\nThe Ducc client, used as the Baidu AI programming assistant, is installed using the remote installer:\\n\\n```text\\nhttp://baidu-cc-client.bj.bcebos.com/baidu-cc/install.sh\\n```\\n\\nThe installer is executed with:\\n\\n```bash\\nHOME=/home/appuser\\n```\\n\\nAlthough the installation command runs as root, its files are placed under `/home/appuser` and ownership is corrected afterward.\\n\\nThe installed Claude-compatible executable is resolved with `readlink -f` and exposed under both command names:\\n\\n```text\\n/usr/local/bin/ducc\\n/usr/local/bin/claude\\n```\\n\\nThe build validates the installation as `appuser`:\\n\\n```bash\\nsu appuser -c \\\"ducc --version\\\"\\n```\\n\\n## `icode` CLI\\n\\nThe internal `icode` CLI is installed as `appuser`:\\n\\n```bash\\nsu appuser -c \\\"cd /home/appuser &amp;&amp; curl -sSL .../install.sh | bash -s -- --dev --completion zsh --skills-dir .claude\\\"\\n```\\n\\nThe `--skills-dir .claude` option causes the CLI\u2019s skills to be installed relative to:\\n\\n```text\\n/home/appuser/.claude\\n```\\n\\nThis installation is intentionally performed as the non-root user so that generated skill files have the correct ownership and location.\\n\\n## `icafe-cli-new`\\n\\nThe Docker build expects the following file in the build context:\\n\\n```text\\nassets/icafe/icafe-cli-new\\n```\\n\\nIt is copied to:\\n\\n```text\\n/home/appuser/.icafe/bin/icafe-cli-new\\n```\\n\\nThe copy uses `--chown=appuser:appuser`, and the binary is marked executable. The image validates it with:\\n\\n```bash\\n/home/appuser/.icafe/bin/icafe-cli-new version\\n```\\n\\nThis CLI is used by the `commit-to-icode` workflow to create iCafe cards automatically.\\n\\nThe source binary is described by the Dockerfile as a statically linked `linux/amd64` executable, so this image is intended for AMD64 builds unless the asset and build process are adapted for another architecture.\\n\\n## Preloaded Ducc skills\\n\\nThe build context must also contain:\\n\\n```text\\nassets/ducc-skills/cnap\\nassets/ducc-skills/get-ugate-token\\nassets/ducc-skills/.versions/cnap.txt\\nassets/ducc-skills/.versions/get-ugate-token.txt\\n```\\n\\nThe skill directories are copied into:\\n\\n```text\\n/home/appuser/.claude/skills/cnap\\n/home/appuser/.claude/skills/get-ugate-token\\n```\\n\\nTheir version files are copied into:\\n\\n```text\\n/home/appuser/.baidu-cc/skills/cnap.txt\\n/home/appuser/.baidu-cc/skills/get-ugate-token.txt\\n```\\n\\nThese skills are embedded at image-build time and do not require a login or runtime download.\\n\\n## Chromium and Playwright\\n\\nThe image includes two browser-related configurations:\\n\\n1. **System Chromium**\\n\\n   Installed through Debian packages and used by `agent-browser`:\\n\\n   ```text\\n   /usr/bin/chromium\\n   ```\\n\\n2. **Playwright Chromium**\\n\\n   The package `@baidu/yf-web-mcp-test-platform-sandbox@1.0.0-beta.9` is installed globally using the internal npm registry:\\n\\n   ```text\\n   http://registry.npm.baidu-int.com\\n   ```\\n\\n   From the package directory, the build runs:\\n\\n   ```bash\\n   npx playwright install --with-deps chromium\\n   ```\\n\\nPlaywright browser binaries are stored in the `appuser` home directory:\\n\\n```dockerfile\\nENV PLAYWRIGHT_BROWSERS_PATH=/home/appuser/.cache/ms-playwright\\n```\\n\\nThe npm global installation directory is also placed under the same user\u2019s home:\\n\\n```text\\n/home/appuser/.npm-global\\n```\\n\\nBoth locations are changed to `appuser` ownership after installation.\\n\\nThe configured launch arguments are:\\n\\n```dockerfile\\nENV PLAYWRIGHT_LAUNCH_ARGS=\\\"--no-sandbox --disable-dev-shm-usage\\\"\\n```\\n\\nThese settings support browser execution inside containers, where sandboxing and shared-memory limits commonly require explicit configuration.\\n\\n## Archon runtime directories\\n\\nThe image creates the shared Archon directories:\\n\\n```text\\n/.archon/workspaces\\n/.archon/worktrees\\n```\\n\\nBoth are owned recursively by `appuser`.\\n\\nDownstream application code can use these directories for:\\n\\n- Workspace checkouts\\n- Git worktrees\\n- Per-task or per-agent working state\\n\\nThe Dockerfile does not create project-specific subdirectories; consumers are expected to create them at runtime.\\n\\n## Build-context requirements\\n\\nA successful build requires the following files to be present relative to the Docker build context:\\n\\n```text\\nassets/icafe/icafe-cli-new\\nassets/ducc-skills/cnap\\nassets/ducc-skills/get-ugate-token\\nassets/ducc-skills/.versions/cnap.txt\\nassets/ducc-skills/.versions/get-ugate-token.txt\\n```\\n\\nThe command must use the repository root, or another context containing the `assets` tree:\\n\\n```bash\\ndocker build -f Dockerfile.base -t archon-base:latest .\\n```\\n\\nUsing a narrower context that excludes `assets/` will cause the `COPY` instructions to fail.\\n\\n## Runtime interface\\n\\n`Dockerfile.base` does not define a `CMD` or `ENTRYPOINT`. It provides an environment and toolchain for a downstream image, which must define the actual Archon process to start.\\n\\nA downstream Dockerfile typically consumes it as:\\n\\n```dockerfile\\nFROM archon-base:latest\\n```\\n\\nThe downstream image or container configuration is responsible for:\\n\\n- Copying the application source\\n- Installing application-specific dependencies\\n- Selecting the working directory\\n- Setting the runtime user if necessary\\n- Defining `CMD` or `ENTRYPOINT`\\n- Mounting or initializing workspace data\\n\\n## Maintenance guidance\\n\\nRebuild this image when any of the following change:\\n\\n- Debian or Node.js versions\\n- System package requirements\\n- `agent-browser` version\\n- GitNexus version or native installation behavior\\n- GitHub CLI version\\n- Ducc or `icode` installer behavior\\n- `icafe-cli-new`\\n- Embedded Ducc skills\\n- Playwright sandbox package or browser requirements\\n- Archon workspace directory layout\\n\\nBecause the image contains several network-installed tools and installer scripts, version changes should be validated by checking at least:\\n\\n```bash\\nagent-browser --help\\ngitnexus --help\\ngh --version\\nducc --version\\nclaude --version\\n/home/appuser/.icafe/bin/icafe-cli-new version\\nnode --version\\nnpm --version\\nchromium --version\\n```\\n\\nThe build is designed to maximize layer reuse: the base image should be rebuilt only when its dependency or embedded-tool inputs change, while application-specific changes should remain in downstream images.\",\"other-dockerfile-ci\":\"# Other \u2014 Dockerfile.ci\\n\\n# Dockerfile.ci\\n\\n`Dockerfile.ci` is reserved for defining the container image used by continuous integration (CI) jobs.\\n\\n## Current State\\n\\nThe file is currently empty. It contains no Docker directives, build stages, environment configuration, package installation commands, entrypoints, or comments.\\n\\nAs a result:\\n\\n- It does not define a buildable Docker image on its own.\\n- It does not install project dependencies or CI tooling.\\n- It does not configure a runtime user, working directory, or command.\\n- It has no direct execution flow or code-level dependencies within the repository.\\n\\n## Intended Role\\n\\nA CI-specific Dockerfile commonly provides a reproducible environment for automated workflows, separate from a production image. Typical responsibilities include:\\n\\n- Selecting a base image with the required language runtime and operating system tools.\\n- Installing build, test, linting, formatting, and packaging dependencies.\\n- Copying dependency manifests and restoring dependencies efficiently.\\n- Configuring environment variables required by CI jobs.\\n- Providing a consistent working directory and non-interactive defaults.\\n- Defining a default command when the CI platform runs the image directly.\\n\\nBecause `Dockerfile.ci` does not currently implement these responsibilities, the CI system must either:\\n\\n1. Use another image definition elsewhere in the repository or CI configuration, or\\n2. Expect this file to be populated before building with a command such as:\\n\\n```sh\\ndocker build -f Dockerfile.ci .\\n```\\n\\n## Integration With the Codebase\\n\\nThere are no source-level imports, function calls, classes, or runtime execution paths associated with `Dockerfile.ci`.\\n\\nIts integration is external and configuration-driven: a CI workflow, build script, or developer command would need to explicitly reference `Dockerfile.ci` as the Docker build file. No such connection is represented by the current module contents.\\n\\n## Contributing\\n\\nWhen adding CI image configuration, keep the Dockerfile focused on repeatable automation rather than production runtime concerns.\\n\\nRecommended practices:\\n\\n- Pin or deliberately manage base image versions.\\n- Use a `.dockerignore` file to avoid sending unnecessary files in the build context.\\n- Copy dependency manifests before application source files to preserve Docker layer caching.\\n- Avoid embedding credentials, tokens, or private registry secrets in `ARG`, `ENV`, or copied files.\\n- Install only tools needed by CI.\\n- Prefer explicit, deterministic dependency installation commands.\\n- Run CI commands as a non-root user where supported by the tooling.\\n- Document any required build arguments, environment variables, or expected CI entrypoints directly in the Dockerfile or adjacent CI configuration.\\n\\nUntil Docker directives are added, `Dockerfile.ci` functions only as a placeholder for future CI container configuration.\",\"other-dockerfile-user-example\":\"# Other \u2014 Dockerfile.user.example\\n\\n# Other \u2014 `Dockerfile.user.example`\\n\\n## Purpose\\n\\n`Dockerfile.user.example` is a template for local, user-specific Docker image customizations in Archon development environments.\\n\\nIt is intended to be copied to `Dockerfile.user`, then extended with tools or packages required by an individual developer. The example file should remain unchanged so it can continue to document supported customization patterns and receive updates from the repository.\\n\\n`Dockerfile.user` is expected to be gitignored, keeping local tooling choices out of version control.\\n\\n## Role in the Docker workflow\\n\\nThe file extends the locally built `archon` development image:\\n\\n```dockerfile\\nFROM archon\\n```\\n\\nThe expected workflow is:\\n\\n1. Copy the template:\\n\\n   ```sh\\n   cp Dockerfile.user.example Dockerfile.user\\n   ```\\n\\n2. Add local customizations to `Dockerfile.user`.\\n\\n3. Build the base image:\\n\\n   ```sh\\n   docker compose build\\n   ```\\n\\n4. Start the stack:\\n\\n   ```sh\\n   docker compose up -d\\n   ```\\n\\nThe resulting user image is based on the local `archon` image rather than on an external registry image. Docker Compose is expected to incorporate the user Dockerfile through the local development configuration, including `docker-compose.override.yml`.\\n\\nThe template itself does not define application services, networking, volumes, or runtime commands. Those concerns remain in the main Docker and Compose configuration.\\n\\n## Build-stage user permissions\\n\\nThe Dockerfile deliberately changes users during the build:\\n\\n```dockerfile\\nFROM archon\\n\\nUSER root\\n```\\n\\nCustom installation commands should normally be placed after `USER root`, because system package managers and global package installation commonly require elevated privileges.\\n\\nAt the end of the file, privileges are dropped again:\\n\\n```dockerfile\\nUSER appuser\\n```\\n\\nThis ensures containers created from the resulting image run as `appuser` by default rather than as `root`. Custom commands should account for this final runtime user:\\n\\n- Files copied into the image should be readable and usable by `appuser`.\\n- Executables intended for runtime use should be installed in a location available on `appuser`\u2019s `PATH`.\\n- Build-time-only operations should be completed before the final `USER appuser` instruction.\\n\\n## Supported customization patterns\\n\\nThe file includes commented examples for common local extensions. Uncomment and adapt only the sections needed by the development environment.\\n\\n### Additional APT packages\\n\\n```dockerfile\\nRUN apt-get update &amp;&amp; apt-get install -y --no-install-recommends \\\\\\n    ripgrep \\\\\\n    fd-find \\\\\\n    jq \\\\\\n &amp;&amp; rm -rf /var/lib/apt/lists/*\\n```\\n\\nThis pattern:\\n\\n- Refreshes the APT package index.\\n- Installs packages without optional recommendations.\\n- Removes cached package lists to reduce image size.\\n\\nAdditional Debian/Ubuntu system packages should be installed while the active user is `root`.\\n\\n### GitHub CLI extensions\\n\\n```dockerfile\\nRUN gh extension install github/gh-copilot\\n```\\n\\nThis is suitable for installing extensions for the GitHub CLI already present in the base image. The extension must be installed during the image build, and any required authentication or configuration should be provided at runtime rather than embedded in the image.\\n\\n### Global npm packages\\n\\n```dockerfile\\nRUN npm install -g tsx prettier\\n```\\n\\nGlobal npm packages provide command-line tools throughout the development container. The base image must provide a working Node.js and npm installation.\\n\\nBecause this command runs as `root`, verify that the resulting global package binaries are available to `appuser` after the final user switch.\\n\\n### Custom binaries\\n\\n```dockerfile\\nCOPY --chown=appuser:appuser ./my-tool /usr/local/bin/my-tool\\n```\\n\\nThis copies a local build-context file into a standard executable directory and assigns ownership to `appuser`.\\n\\nThe source path is resolved relative to the Docker build context. The binary must therefore be present in that context and not excluded by `.dockerignore`. If the file is not executable before copying, add an appropriate build step or prepare its permissions locally.\\n\\n### Python packages\\n\\n```dockerfile\\nRUN pip install --no-cache-dir httpie\\n```\\n\\nThis installs Python packages without retaining pip\u2019s download cache. Confirm that the base image\u2019s Python environment and `pip` configuration are appropriate for global installation. Packages installed during the root build must remain usable by `appuser`.\\n\\n## Extension guidelines\\n\\nWhen customizing `Dockerfile.user`:\\n\\n- Keep `FROM archon` unless the local Docker workflow is intentionally being redesigned.\\n- Leave `Dockerfile.user.example` unchanged.\\n- Group related installation commands into readable sections.\\n- Combine package installation and cache cleanup in the same layer where practical.\\n- Avoid placing credentials, tokens, SSH keys, or other secrets in the Dockerfile.\\n- Prefer reproducible package versions when a tool version affects development behavior.\\n- Ensure files and installed tools are accessible to `appuser`.\\n- Rebuild the image after changing the Dockerfile:\\n\\n  ```sh\\n  docker compose build\\n  ```\\n\\n- Restart the stack after rebuilding if necessary:\\n\\n  ```sh\\n  docker compose up -d\\n  ```\\n\\n## Relationship to the codebase\\n\\n`Dockerfile.user.example` is an infrastructure customization point rather than an application module:\\n\\n- It has no functions, classes, or runtime call graph.\\n- It makes no direct calls to application code.\\n- Its only dependency is the locally available `archon` base image.\\n- Its output is consumed indirectly by the Docker Compose development environment.\\n- The main project Dockerfile defines the base development environment; this file adds developer-specific tools on top of it.\\n\\nThe separation between the committed example and the local `Dockerfile.user` allows the repository to provide recommended patterns without forcing every developer to use the same tools or modifying shared image configuration.\",\"other-dockerfile\":\"# Other \u2014 Dockerfile\\n\\n# Dockerfile\\n\\nBuilds the Archon runtime image from prebuilt artifacts produced by `scripts/build.sh`. The image does not compile the application, install Bun, or build frontend assets. Instead, it copies the packaged application binary, bundled frontend, Claude Code binary, default Archon configuration, and migration scripts into a base image that supplies the operating-system dependencies and runtime utilities.\\n\\n```sh\\ndocker build -t archon:latest .\\n```\\n\\nA different base image can be selected at build time:\\n\\n```sh\\ndocker build \\\\\\n  --build-arg BASE_IMAGE=registry/archon-base:1.0 \\\\\\n  -t archon:latest .\\n```\\n\\n## Build Prerequisites\\n\\nThe Docker build context must contain an `output/` directory generated by `scripts/build.sh`. The Dockerfile expects these artifacts:\\n\\n| Artifact | Destination in image | Purpose |\\n|---|---|---|\\n| `output/archon-linux-x64` | `/usr/local/bin/archon` | Main Archon executable. It includes the Bun runtime. |\\n| `output/claude-linux-x64` | `/usr/local/bin/claude` | Claude Code executable extracted during the application build. |\\n| `output/web-dist/` | `/app/web-dist/` | Prebuilt frontend static assets. |\\n| `output/.archon/` | `/app/.archon/` | Default commands and workflows packaged with Archon. |\\n| `output/migrations/` | `/app/migrations/` | Database migration scripts. |\\n| `output/gitnexus-init.sh` | `/usr/local/bin/gitnexus-init.sh` | Initializes gitnexus MCP configuration for the runtime user. |\\n| `output/docker-entrypoint.sh` | `/usr/local/bin/docker-entrypoint.sh` | Container startup script. |\\n\\nBecause the image only copies existing outputs, `docker build` will fail if any required artifact is missing.\\n\\n## Image Architecture\\n\\n```mermaid\\nflowchart TD\\n    A[scripts/build.sh] --&gt; B[output/ artifacts]\\n    B --&gt; C[Dockerfile]\\n    D[BASE_IMAGE] --&gt; C\\n    C --&gt; E[Archon image]\\n    E --&gt; F[docker-entrypoint.sh]\\n    F --&gt; G[appuser]\\n    G --&gt; H[archon service on port 3000]\\n```\\n\\nThe `BASE_IMAGE` is responsible for foundational dependencies, including the `appuser` account, `gosu`, Git, and gitnexus plus its hooks. This Dockerfile layers Archon-specific binaries, configuration, permissions, and startup behavior on top of it.\\n\\n## Base Image Selection\\n\\n```dockerfile\\nARG BASE_IMAGE=iregistry.baidu-int.com/tianniu/doarchon_base:1778758446578\\nFROM ${BASE_IMAGE}\\n```\\n\\n`BASE_IMAGE` has a default internal registry image but can be overridden with `--build-arg`.\\n\\nThe selected base image must provide:\\n\\n- The `appuser` user and group.\\n- `gosu`, used to run Git configuration as `appuser`.\\n- `su`, used to execute `gitnexus-init.sh` as `appuser`.\\n- Git.\\n- gitnexus and its installed hooks.\\n- A writable `/home/appuser` home directory, including support for `.claude.json`.\\n\\n## OCI Metadata\\n\\nThe image defines standard Open Container Initiative labels:\\n\\n```dockerfile\\nLABEL org.opencontainers.image.source=\\\"https://github.com/coleam00/Archon\\\"\\nLABEL org.opencontainers.image.description=\\\"Control AI coding assistants remotely from Telegram, Slack, Discord, and GitHub\\\"\\nLABEL org.opencontainers.image.licenses=\\\"MIT\\\"\\n```\\n\\nThese labels identify the source repository, describe the image\u2019s role, and declare the MIT license.\\n\\n## Application Files\\n\\nThe working directory is set to `/app`:\\n\\n```dockerfile\\nWORKDIR /app\\n```\\n\\n### Archon executable\\n\\n```dockerfile\\nCOPY output/archon-linux-x64 /usr/local/bin/archon\\nRUN chmod +x /usr/local/bin/archon\\n```\\n\\nThe main executable is installed on `PATH` as `archon`. It includes the Bun runtime, so the container does not need a separate Bun installation.\\n\\n### Claude Code executable\\n\\n```dockerfile\\nCOPY output/claude-linux-x64 /usr/local/bin/claude\\nRUN chmod +x /usr/local/bin/claude\\n```\\n\\nThe Claude Code binary is made available as `claude`. Its location is explicitly exported through `CLAUDE_BIN_PATH`, allowing the startup path to bypass any Node.js or `node_modules`-based binary resolution.\\n\\n### Frontend distribution\\n\\n```dockerfile\\nCOPY output/web-dist/ /app/web-dist/\\nENV ARCHON_WEB_DIST=/app/web-dist\\n```\\n\\n`ARCHON_WEB_DIST` tells the Archon `serve` command to use the frontend assets baked into the image. This avoids downloading web assets from GitHub when the container starts.\\n\\n### Defaults and migrations\\n\\n```dockerfile\\nCOPY output/.archon/   ./.archon/\\nCOPY output/migrations/ ./migrations/\\n```\\n\\nThe image ships with default command and workflow definitions under `/app/.archon/` and database migrations under `/app/migrations/`.\\n\\nThese directories are application resources rather than user workspace state. Runtime state is handled separately through `/.archon`.\\n\\n## Runtime Environment\\n\\nThe Dockerfile defines two variables consumed by the application startup path:\\n\\n```dockerfile\\nENV ARCHON_WEB_DIST=/app/web-dist\\nENV CLAUDE_BIN_PATH=/usr/local/bin/claude\\n```\\n\\n| Variable | Value | Effect |\\n|---|---|---|\\n| `ARCHON_WEB_DIST` | `/app/web-dist` | Uses image-local frontend assets instead of downloading them. |\\n| `CLAUDE_BIN_PATH` | `/usr/local/bin/claude` | Directs the entrypoint or application to the packaged Claude executable. |\\n\\nWhen changing file locations, update the corresponding environment variable. Copying a binary to a new location without changing `CLAUDE_BIN_PATH`, for example, will leave startup logic pointing at the old path.\\n\\n## Permissions and Non-Root Execution\\n\\nThe image is built as root so it can install files and configure directories, but its service is intended to run as `appuser`.\\n\\n```dockerfile\\nRUN chown -R appuser:appuser /app\\n```\\n\\nThis makes the packaged application resources readable and manageable by the unprivileged runtime user.\\n\\n### Persistent `/.archon` directory\\n\\n```dockerfile\\nRUN mkdir -p /.archon &amp;&amp; chown appuser:appuser /.archon\\n```\\n\\n`/.archon` is prepared as an application state location. The ownership is particularly important when deployments use a Docker named volume mounted at `/.archon`.\\n\\nWhen Docker first creates a named volume for a path that already exists in the image, it copies the image directory contents and metadata into the volume. Precreating the directory with `appuser` ownership ensures the mounted volume remains writable after privilege is dropped.\\n\\n## Git Safe Directory Configuration\\n\\nThe container configures Git safe-directory exceptions as `appuser`:\\n\\n```dockerfile\\nRUN gosu appuser git config --global --add safe.directory '/.archon/workspaces' \\\\\\n    &amp;&amp; gosu appuser git config --global --add safe.directory '/.archon/workspaces/*' \\\\\\n    &amp;&amp; gosu appuser git config --global --add safe.directory '/.archon/worktrees' \\\\\\n    &amp;&amp; gosu appuser git config --global --add safe.directory '/.archon/worktrees/*'\\n```\\n\\nThese settings address Git\u2019s ownership checks introduced to mitigate CVE-2022-24765. Archon workspaces and worktrees may be created or mounted with ownership patterns that Git would otherwise reject as potentially unsafe.\\n\\nBoth the parent paths and wildcard child paths are configured:\\n\\n- `/.archon/workspaces`\\n- `/.archon/workspaces/*`\\n- `/.archon/worktrees`\\n- `/.archon/worktrees/*`\\n\\nThe configuration is written into `appuser`\u2019s global Git configuration, not root\u2019s configuration. This matters because Git commands run after the entrypoint drops privileges.\\n\\n## gitnexus Initialization\\n\\n```dockerfile\\nCOPY output/gitnexus-init.sh /usr/local/bin/gitnexus-init.sh\\nRUN chown appuser:appuser /home/appuser/.claude.json 2&gt;/dev/null; \\\\\\n    su appuser -c \\\"gitnexus-init.sh\\\"\\n```\\n\\nThe base image supplies gitnexus and its hooks. This layer adds the Archon-specific MCP server configuration by running `gitnexus-init.sh` as `appuser`.\\n\\nThe preceding `chown` attempts to correct ownership of `/home/appuser/.claude.json` when the file exists. Errors are intentionally ignored with `2&gt;/dev/null`, allowing builds to succeed when the base image does not yet contain that file.\\n\\nRunning the initialization script as `appuser` ensures that user-scoped Claude configuration is created with the same ownership and home-directory context used at runtime.\\n\\n## Entrypoint\\n\\n```dockerfile\\nCOPY output/docker-entrypoint.sh /usr/local/bin/\\nRUN sed -i 's/\\\\r$//' /usr/local/bin/docker-entrypoint.sh \\\\\\n    &amp;&amp; chmod +x /usr/local/bin/docker-entrypoint.sh\\n\\nENTRYPOINT [\\\"docker-entrypoint.sh\\\"]\\n```\\n\\n`docker-entrypoint.sh` is the container\u2019s startup boundary. It is responsible for lowering privileges to `appuser` and starting the Archon service.\\n\\nBefore it is marked executable, the Dockerfile removes carriage-return characters:\\n\\n```dockerfile\\nsed -i 's/\\\\r$//' /usr/local/bin/docker-entrypoint.sh\\n```\\n\\nThis prevents shell execution failures when the generated script has Windows-style CRLF line endings.\\n\\nThe entrypoint is referenced by filename rather than absolute path:\\n\\n```dockerfile\\nENTRYPOINT [\\\"docker-entrypoint.sh\\\"]\\n```\\n\\nThis depends on `/usr/local/bin` being on `PATH`, which is conventionally true for the base image environment.\\n\\n## Network Port\\n\\n```dockerfile\\nEXPOSE 3000\\n```\\n\\nThe image declares TCP port `3000` as the expected application port. `EXPOSE` is metadata only; it does not publish the port automatically.\\n\\nTo make the service reachable from the host:\\n\\n```sh\\ndocker run --rm -p 3000:3000 archon:latest\\n```\\n\\nFor persistent Archon runtime data, mount a named volume at `/.archon`:\\n\\n```sh\\ndocker run --rm \\\\\\n  -p 3000:3000 \\\\\\n  -v archon-data:/.archon \\\\\\n  archon:latest\\n```\\n\\n## Layer Order and Build Behavior\\n\\nThe Dockerfile places binary and static-content copies before configuration and entrypoint setup. Any change in `output/` artifacts invalidates the relevant Docker build cache layers.\\n\\nThe image intentionally does not include:\\n\\n- Source code compilation.\\n- Dependency installation.\\n- Bun installation.\\n- Frontend builds.\\n- Claude Code installation from npm or `node_modules`.\\n- Frontend downloads at container startup.\\n\\nThose activities belong to the build pipeline, particularly `scripts/build.sh`. Keeping them outside the Docker build makes the resulting image a deployment artifact assembled from known prebuilt outputs.\\n\\n## Contribution Notes\\n\\nWhen modifying this Dockerfile:\\n\\n1. Keep artifact names synchronized with `scripts/build.sh`.\\n2. Update both `COPY` instructions and environment variables if artifact locations change.\\n3. Preserve `appuser` ownership for `/app` and `/.archon`; runtime workflows depend on non-root write access.\\n4. Retain the Git safe-directory configuration if workspace paths remain under `/.archon`.\\n5. Ensure changes remain compatible with the base-image contract, especially availability of `appuser`, `gosu`, `su`, Git, and gitnexus.\\n6. If modifying `docker-entrypoint.sh`, maintain Unix line endings or keep the CRLF-normalization step.\\n7. Test image startup with a fresh named volume to verify that `appuser` can write to `/.archon`.\",\"other-e2e-dev\":\"# Other \u2014 e2e-dev\\n\\n# Other \u2014 e2e-dev\\n\\n`docker/e2e-dev` defines the development and end-to-end testing container used by the web development environment. It provides a cached system-dependency layer, a small application layer, browser and test tooling, code-server support, and scripts for starting the Comate remote server and persisting Claude workspace data.\\n\\nThe module contains:\\n\\n- `Dockerfile.base` \u2014 infrequently changing operating-system and toolchain layer.\\n- `Dockerfile` \u2014 lightweight application image based on `Dockerfile.base`.\\n- `init-claude-workspace.sh` \u2014 initializes the persistent Claude configuration symlink.\\n- `start_comate_server.sh` \u2014 downloads, installs, and starts a commit-specific Comate remote server.\\n\\nThere are no internal function calls or detected execution flows in the module. Its integration is primarily through Docker image construction and commands invoked by the external web client or container runtime.\\n\\n## Architecture\\n\\n```mermaid\\nflowchart TD\\n    Base[Dockerfile.base] --&gt; App[Dockerfile]\\n    App --&gt; Image[e2e-dev image]\\n    Image --&gt; Workspace[Developer container]\\n    Workspace --&gt; Init[init-claude-workspace.sh]\\n    Workspace --&gt; Comate[start_comate_server.sh]\\n    Comate --&gt; Server[Comate remote server]\\n```\\n\\n## Image construction\\n\\n### `Dockerfile.base`\\n\\n`Dockerfile.base` is the cacheable foundation image. It is based on the internal Ubuntu Noble AMD64 image:\\n\\n```dockerfile\\nFROM --platform=linux/amd64 iregistry.baidu-int.com/baidu-base/ubuntu:noble\\n```\\n\\nBuild this layer only when system dependencies or tool versions change:\\n\\n```bash\\ndocker build -f Dockerfile.base -t e2e-dev-base:latest .\\n```\\n\\nThe resulting image contains:\\n\\n- Ubuntu 24.04 system libraries and utilities.\\n- Git from `git-core/ppa`.\\n- GCC 12 and G++ 12.\\n- CMake, Make, Google Test, and Google Mock development files.\\n- Python 3.12, development headers, and pip.\\n- Maven 3.8.6.\\n- Node.js 24.4.1.\\n- JDK 17.0.2.\\n- Go 1.24.0.\\n- Bun 1.3.13.\\n- `jq`, `rg`, and `icafe-cli-new`.\\n- `kubectl`.\\n- `code-server` 3.12.0.\\n- `baidu-cc` and `icode` clients.\\n- `@comate/zulu`.\\n- `gitnexus` and its native `@ladybugdb/core` dependency.\\n- Chromium installed for Playwright.\\n- Python testing, web, graph, templating, HTTP, and configuration packages.\\n\\nThe base image also creates the `developer` user with UID and GID `1000`. Existing Ubuntu users or groups named `ubuntu` and `work` are removed first to avoid UID/GID conflicts.\\n\\n### Dependency configuration\\n\\nThe image configures internal package registries:\\n\\n```dockerfile\\nENV NPM_CONFIG_REGISTRY=http://registry.npm.baidu-int.com\\n```\\n\\nPython and Maven configuration files are copied into the developer home directory:\\n\\n```dockerfile\\nCOPY --chown=developer:developer .pip /home/developer/.pip\\nCOPY --chown=developer:developer .m2  /home/developer/.m2\\n```\\n\\nThe base image sets:\\n\\n- `PIP_BREAK_SYSTEM_PACKAGES=1` to allow system-level pip installation in the container.\\n- `JAVA_HOME=/opt/jdk-17.0.2`.\\n- `CODE_SERVER_DIR=/code-server`.\\n- `PKG_CONFIG_PATH` for system package discovery.\\n- `HF_HOME=/home/developer/.cache/huggingface` for the GitNexus embedding model cache.\\n- `PLAYWRIGHT_BROWSERS_PATH=/opt/playwright-browsers`.\\n- `PLAYWRIGHT_LAUNCH_ARGS=\\\"--no-sandbox --disable-dev-shm-usage\\\"`.\\n\\nThe Go installation path, Maven, JDK, code-server, and the Baidu client are added to `PATH`.\\n\\n### Bun installation fallback\\n\\nBun is installed at version `1.3.13`. The build first attempts the official installer. If `/usr/local/bin/bun` is not created, it downloads a package from the internal npm registry.\\n\\nThe fallback selects between:\\n\\n- `bun-linux-x64` when the CPU supports AVX2.\\n- `bun-linux-x64-baseline` otherwise.\\n\\nThe build verifies the resulting binary with:\\n\\n```bash\\n/usr/local/bin/bun --version\\n```\\n\\n### Playwright and Chromium\\n\\nPlaywright is installed both as a Python package and through globally installed npm packages. Chromium is installed into a shared location:\\n\\n```text\\n/opt/playwright-browsers\\n```\\n\\nThe directory is owned by `developer`, allowing the non-root runtime process to reuse browsers installed during the image build.\\n\\n### GitNexus\\n\\n`gitnexus` is installed globally with lifecycle scripts disabled:\\n\\n```bash\\nnpm install -g gitnexus --ignore-scripts\\n```\\n\\nThe native LadybugDB installation script is then run explicitly:\\n\\n```bash\\nnode \\\"$(npm root -g)/gitnexus/node_modules/@ladybugdb/core/install.js\\\"\\n```\\n\\nThe build also attempts to pre-download the `Snowflake/snowflake-arctic-embed-xs` embedding model using `hf-mirror.com`. The model is stored under `HF_HOME`. If the network is unavailable, the warm-up step logs a message and continues:\\n\\n```text\\n[warmup] skipped (network unavailable)\\n```\\n\\n### Non-root runtime\\n\\nThe base image creates and configures:\\n\\n```text\\ndeveloper:developer\\nUID: 1000\\nGID: 1000\\n```\\n\\nThe user receives passwordless sudo access and is used for Baidu client installation and embedding warm-up. The final application image explicitly switches back to this user:\\n\\n```dockerfile\\nUSER developer\\nWORKDIR /home/developer\\n```\\n\\nDo not remove or bypass this logic. The container is intended to support Claude Code\u2019s `--dangerously-skip-permissions` mode while avoiding normal root execution.\\n\\n## Application image\\n\\n### `Dockerfile`\\n\\n`Dockerfile` is the frequently rebuilt layer. It accepts a configurable base image:\\n\\n```dockerfile\\nARG BASE_IMAGE=iregistry.baidu-int.com/sqc-ee/e2e-dev:base-1785412114670\\nFROM ${BASE_IMAGE}\\n```\\n\\nTypical builds are:\\n\\n```bash\\ndocker build -t e2e-dev:latest .\\n```\\n\\nor:\\n\\n```bash\\ndocker build \\\\\\n  --build-arg BASE_IMAGE=registry/e2e-dev-base:1.0 \\\\\\n  -t e2e-dev:latest .\\n```\\n\\nThe file intentionally contains no application source copy or dependency installation. It is an extension point for custom images based on the prepared environment. Custom dependencies and files can be added before the final user configuration, for example:\\n\\n```dockerfile\\nRUN pip3 install \\nRUN npm install -g \\nCOPY  /path/in/image\\n```\\n\\nThe image ends with the non-root developer configuration:\\n\\n```dockerfile\\nUSER developer\\nWORKDIR /home/developer\\n```\\n\\n### Runtime helper scripts\\n\\nThe base image copies the following scripts into the image:\\n\\n```text\\n/bin/start_comate_server.sh\\n/usr/local/bin/init-claude-workspace.sh\\n```\\n\\nBoth scripts are available to the external web client or container startup configuration.\\n\\n## `init-claude-workspace.sh`\\n\\n`init-claude-workspace.sh` makes Claude configuration persistent by linking:\\n\\n```text\\n/home/developer/.claude -&gt; /workspace/.claude\\n```\\n\\n`/workspace/.claude` is expected to be backed by a persistent volume or PVC.\\n\\nThe script is idempotent and should be the first command in the web client\u2019s startup command, before any `ducc skill install` operation:\\n\\n```bash\\n/usr/local/bin/init-claude-workspace.sh\\n```\\n\\n### Initialization cases\\n\\nThe script handles three states:\\n\\n1. **Correct symlink already exists**\\n\\n   If `/home/developer/.claude` is already a symlink to `/workspace/.claude`, the script exits without changes.\\n\\n2. **A real directory exists**\\n\\n   The existing contents are copied into the persistent directory with:\\n\\n   ```bash\\n   cp -an \\\"$CLAUDE_HOME/.\\\" \\\"$CLAUDE_PVC/\\\"\\n   ```\\n\\n   `cp -an` preserves existing PVC files and does not overwrite them. The original directory is then removed and replaced with the symlink.\\n\\n3. **No existing path exists**\\n\\n   The persistent target is created and the symlink is established.\\n\\nThe script deliberately does not use `mv`. Moving the directory could detach a directory currently being written by another process and cause installed skills to disappear.\\n\\nThe symlink operation uses:\\n\\n```bash\\nln -sfn \\\"$CLAUDE_PVC\\\" \\\"$CLAUDE_HOME\\\"\\n```\\n\\nThe `-n` option prevents creation of an unintended nested symlink when the destination already exists as a directory.\\n\\n## `start_comate_server.sh`\\n\\n`start_comate_server.sh` installs and starts a commit-specific Comate remote server for the web client.\\n\\n### Command-line interface\\n\\nRequired options:\\n\\n```text\\n--commit COMMIT\\n--port PORT\\n```\\n\\nOptional options:\\n\\n```text\\n--quality QUALITY\\n--default-folder DIRECTORY\\n```\\n\\n`--quality` defaults to `stable`.\\n\\nHelp is available with:\\n\\n```bash\\n/bin/start_comate_server.sh --help\\n```\\n\\nExample:\\n\\n```bash\\n/bin/start_comate_server.sh \\\\\\n  --commit  \\\\\\n  --port 8080 \\\\\\n  --quality stable \\\\\\n  --default-folder /workspace\\n```\\n\\nUnknown options are reported and skipped. Missing `--commit` or `--port` causes the script to print usage information and exit with status `1`.\\n\\n### Installation paths\\n\\nThe server is stored per commit under the developer home directory:\\n\\n```text\\n$HOME/.comate/remote//\\n```\\n\\nImportant paths include:\\n\\n```text\\n$HOME/.comate/remote//server\\n$HOME/.comate/remote//server/bin/comate-server\\n$HOME/.comate/remote//..log\\n$HOME/.comate/remote//..lock\\n$HOME/.comate/remote/patchelf\\n```\\n\\nThis allows multiple server versions to coexist while avoiding repeated downloads of an already installed commit.\\n\\n### Platform and architecture detection\\n\\nThe script determines:\\n\\n- Platform from `uname -s`.\\n- Architecture from `uname -m`.\\n- Distribution ID from `/etc/os-release` or `/usr/lib/os-release`.\\n\\nSupported platform mappings include:\\n\\n| Host value | Server platform |\\n|---|---|\\n| `Linux` | `linux` |\\n| `FreeBSD` | `freebsd` |\\n| `DragonFly` | `dragonfly` |\\n\\nSupported architecture mappings include:\\n\\n| Machine value | Server architecture |\\n|---|---|\\n| `x86_64`, `amd64` | `x64` |\\n| `armv7l`, `armv8l` | `armhf` |\\n| `arm64`, `aarch64` | `arm64` |\\n\\nUnsupported platforms or architectures produce an installation result with exit code `1`.\\n\\nFor Alpine, the detected platform is changed to `alpine` for server artifact selection.\\n\\n### Server download URL\\n\\nThe server archive is selected using the requested quality, commit, platform, and architecture:\\n\\n```text\\nhttp://comate-ide.bj.bcebos.com/download///comate-reh-web--.tar.gz\\n```\\n\\nThe script downloads with `wget` when available and falls back to `curl`. Both paths use retries and a connection timeout.\\n\\nAfter downloading, `download_and_install_server()`:\\n\\n1. Changes to the commit\u2019s server directory.\\n2. Downloads `vscode-server.tar.gz`.\\n3. Extracts it with `--strip-components 1`.\\n4. Verifies that `server/bin/comate-server` exists.\\n5. Removes the archive.\\n\\nA failed download or invalid archive causes installation failure.\\n\\n### Concurrent installation protection\\n\\nWhen `flock` is available, installation is protected with the commit lock file:\\n\\n```text\\n$HOME/.comate/remote//..lock\\n```\\n\\nIf another process is installing the same commit, the script waits for the lock before checking and installing the server. This prevents duplicate extraction and partially installed server directories.\\n\\nIf `flock` is unavailable, the script performs installation without locking.\\n\\n### Old-version cleanup\\n\\n`cleanup_old_server_versions()` scans `$HOME/.comate/remote` and removes old version directories unless one of the following applies:\\n\\n- The directory is the currently requested commit.\\n- The directory was modified within the last 24 hours.\\n- A process appears to be running the version\u2019s `comate-server` script.\\n\\nThe 24-hour grace period reduces the chance of deleting a version that is still being installed or used by another startup process.\\n\\nCleanup failures during individual removals are ignored.\\n\\n### Extension service configuration\\n\\nBefore starting the server, the script configures the internal Open VSX endpoints:\\n\\n```text\\nVSCODE_EXTENSIONS_SERVICE_URL\\nVSCODE_EXTENSIONS_ITEM_URL\\nVSCODE_EXTENSIONS_RESOURCE_URL_TEMPLATE\\n```\\n\\nThese point to:\\n\\n```text\\nhttps://open-vsx.now.baidu-int.com/vscode/gallery\\nhttps://open-vsx.now.baidu-int.com/vscode/item\\nhttps://open-vsx.now.baidu-int.com/vscode/gallery/{publisher}/{name}/latest\\n```\\n\\n### `patchelf` compatibility handling\\n\\nThe script automatically enables compatibility patching for:\\n\\n- CentOS versions `&lt;= 8`.\\n- Ubuntu versions `&lt; 20`.\\n\\nThe behavior can be overridden by setting `APPLY_PATCHELF` in the environment.\\n\\nWhen enabled, the script configures:\\n\\n- `VSCODE_SERVER_CUSTOM_GLIBC_PATH`\\n- `VSCODE_SERVER_CUSTOM_GLIBC_LINKER`\\n- `VSCODE_SERVER_PATCHELF_PATH`\\n\\nFor Linux x64 and arm64, `ensure_patchelf()` downloads the appropriate binary to:\\n\\n```text\\n$HOME/.comate/remote/patchelf\\n```\\n\\nThe script uses architecture-specific linker paths for arm64 and x64. If the download is not applicable or fails, it falls back to:\\n\\n```text\\n/opt/compiler/gcc-4.8.2/bin/patchelf\\n```\\n\\nExisting environment values take precedence over automatically selected values.\\n\\n### Server startup\\n\\nThe installed server is launched with:\\n\\n```bash\\n\\\"$SERVER_SCRIPT\\\" \\\\\\n  --start-server \\\\\\n  --host=0.0.0.0 \\\\\\n  --port=\\\"$SERVER_PORT\\\" \\\\\\n  --default-folder=\\\"$DEFAULT_FOLDER\\\" \\\\\\n  --without-connection-token \\\\\\n  --telemetry-level off \\\\\\n  --accept-server-license-terms\\n```\\n\\nOutput is redirected to the commit-specific log file. The script waits for the log file to appear, then polls for:\\n\\n```text\\nExtension host agent listening on ...\\n```\\n\\nThe address following that message is stored in `LISTENING_ON`.\\n\\nThe script polls for:\\n\\n- Up to 5 seconds for the log file.\\n- Up to 20 seconds for the listening address.\\n\\nIf the server does not report a listening address, the script exits with status `1`.\\n\\n## Installation result protocol\\n\\n`print_install_results_and_exit()` prints a machine-readable result block used by the web client:\\n\\n```text\\nexitCode====\\nlisteningOn==\n==\\nconnectionToken==\\nlogFile====\\nosReleaseId====\\narch====\\nplatform====\\ntmpDir====\\n```\\n\\nThe connection token is intentionally empty because this script starts the web server with:\\n\\n```text\\n--without-connection-token\\n```\\n\\nConsumers should parse the delimited fields rather than relying on human-readable diagnostic messages.\\n\\n## Build-time verification\\n\\nThe base image performs a final installation check for the primary toolchain:\\n\\n```bash\\njava -version\\ngo version\\ng++ --version\\ncmake --version\\ngcovr --version\\ngitnexus --version\\nbun --version\\n```\\n\\nIt also verifies that Google Test libraries and headers exist:\\n\\n```text\\n/usr/lib/x86_64-linux-gnu/libgtest*\\n/usr/include/gtest/gtest.h\\n```\\n\\nA failure in these checks fails the base-image build.\\n\\n## Contribution and maintenance guidance\\n\\n- Modify `Dockerfile.base` only when system dependencies or tool versions change; doing so invalidates the expensive dependency layer.\\n- Keep frequently changing application-specific additions in `Dockerfile`.\\n- Preserve the `developer` user and final `USER developer` configuration.\\n- Keep `/workspace/.claude` as the persistent target for Claude state.\\n- Invoke `init-claude-workspace.sh` before skill installation.\\n- Preserve the structured output emitted by `print_install_results_and_exit()`.\\n- When changing Comate server startup behavior, verify both the download path and the `Extension host agent listening on ...` readiness check.\\n- Test both cached-server and first-install paths.\\n- Test concurrent startup for the same commit when `flock` is available.\\n- Avoid removing the Playwright browser ownership step; browser binaries are installed as root but must be usable by `developer`.\\n\\n## Relationship to the rest of the codebase\\n\\nThis module is self-contained infrastructure rather than application logic:\\n\\n- Docker build configuration supplies the runtime environment used by e2e and development workflows.\\n- `init-claude-workspace.sh` coordinates with the external web client\u2019s startup command and persistent workspace volume.\\n- `start_comate_server.sh` coordinates with the Comate web client through its command-line arguments, server artifact repository, log readiness message, and structured installation output.\\n- The installed tools support other repository workflows, including Python and Playwright tests, JavaScript/TypeScript execution with Bun, Java and Maven builds, Go builds, GitNexus analysis, browser automation, and Kubernetes access.\\n\\nNo module-local callers, callees, or programmatic call graph edges are defined; integration occurs through image contents, filesystem paths, environment variables, and shell-command protocols.\",\"other-eslint-config-mjs\":\"# Other \u2014 eslint.config.mjs\\n\\n# Other \u2014 `eslint.config.mjs`\\n\\n## Purpose\\n\\n`eslint.config.mjs` is the repository-wide ESLint flat configuration. It defines:\\n\\n- Files and directories ESLint must ignore.\\n- The JavaScript and TypeScript baseline rule sets.\\n- Prettier compatibility.\\n- Type-aware TypeScript linting for source, end-to-end, configuration, and script files.\\n- Repository-specific coding conventions and safety rules.\\n\\nThe module exports a single configuration created with `tseslint.config(...)`. It contains configuration only; it has no internal functions, classes, or runtime execution flow beyond constructing the exported ESLint configuration.\\n\\n## Configuration flow\\n\\n```mermaid\\nflowchart LR\\n  A[eslint.config.mjs] --&gt; B[Global ignores]\\n  B --&gt; C[ESLint recommended]\\n  C --&gt; D[TypeScript recommended, strict, stylistic]\\n  D --&gt; E[Prettier compatibility]\\n  E --&gt; F[Project-specific TypeScript settings]\\n  F --&gt; G[ESLint flat configuration]\\n```\\n\\nConfiguration entries are supplied in order. Later entries can refine or override earlier settings for matching files.\\n\\n## Export and composition\\n\\nThe module imports three configuration sources:\\n\\n- `eslint` from `@eslint/js`\\n- `tseslint` from `typescript-eslint`\\n- `prettierConfig` from `eslint-config-prettier`\\n\\nThe default export calls:\\n\\n```js\\ntseslint.config(...)\\n```\\n\\nThis helper composes the flat-config entries and supports the TypeScript ESLint configuration format.\\n\\nThe configuration layers are:\\n\\n1. Global ignores.\\n2. `eslint.configs.recommended`.\\n3. TypeScript ESLint recommended type-checked rules.\\n4. TypeScript ESLint strict type-checked rules.\\n5. TypeScript ESLint stylistic type-checked rules.\\n6. `prettierConfig`.\\n7. Project-specific TypeScript settings and rules.\\n\\nBecause `prettierConfig` appears before the project-specific block, repository rules defined later remain active if they overlap with rules disabled by Prettier integration.\\n\\n## Global ignores\\n\\nThe first configuration object defines an `ignores` array without a `files` selector. These patterns are global and exclude matching paths from the remaining configuration.\\n\\n### Dependency, build, and generated output\\n\\nThe following paths are excluded:\\n\\n- `node_modules/**`\\n- `packages/*/node_modules/**`\\n- `dist/**`\\n- `packages/*/dist/**`\\n- `coverage/**`\\n- `**/test-results/**`\\n- `output/**`\\n- `workspace/**`\\n- `worktrees/**`\\n- `.claude/worktrees/**`\\n\\nGenerated source and declaration files are also ignored:\\n\\n- `**/*.generated.ts`\\n- `**/*.generated.d.ts`\\n- `*.d.ts`\\n\\n### Repository tooling and workspace content\\n\\nThe configuration excludes content that is not part of the application TypeScript projects, including:\\n\\n- `~/**`\\n- `.agents/examples/**`\\n- `.agents/skills/**`\\n- `.codex/**`\\n- `.Codex/**`\\n- `.gitnexus/**`\\n- `.archon/**`\\n- `.claude/skills/**`\\n- `packages/docs-web/**`\\n\\nThese paths contain agent, workflow, documentation, or user-generated content rather than source code covered by the repository\u2019s TypeScript projects.\\n\\n### Tests and test helpers\\n\\nTest files and test helper directories are excluded:\\n\\n- `**/*.test.ts`\\n- `**/src/test/**`\\n\\nThe `**/test-results/**` pattern separately excludes generated test artifacts.\\n\\n### JavaScript and configuration files\\n\\nJavaScript and MJS files are not linted by this configuration:\\n\\n- `**/*.js`\\n- `*.mjs`\\n\\nSpecific web configuration and generated UI files are also excluded:\\n\\n- `packages/web/vite.config.ts`\\n- `packages/web/postcss.config.mjs`\\n- `packages/web/components.json`\\n- `packages/web/src/components/ui/**`\\n- `packages/web/src/lib/utils.ts`\\n\\nThe comments in the configuration identify these as files that either do not require type-checked linting or are generated by external tooling such as shadcn/ui.\\n\\n## Baseline rule sets\\n\\n### ESLint recommended rules\\n\\n`eslint.configs.recommended` enables ESLint\u2019s standard recommended rules for detecting common JavaScript errors and problematic patterns.\\n\\n### TypeScript recommended type-checked rules\\n\\nThe following TypeScript ESLint presets are included:\\n\\n```js\\n...tseslint.configs.recommendedTypeChecked,\\n...tseslint.configs.strictTypeChecked,\\n...tseslint.configs.stylisticTypeChecked,\\n```\\n\\nTogether they provide:\\n\\n- Type-aware correctness checks.\\n- Stricter TypeScript safety rules.\\n- TypeScript-specific style conventions.\\n\\nThese presets require TypeScript project information, which is supplied in the project-specific configuration through `projectService: true`.\\n\\n### Prettier integration\\n\\n`prettierConfig` disables ESLint rules that conflict with Prettier formatting. Formatting is therefore delegated to Prettier where appropriate, while explicit repository rules such as quote and semicolon requirements remain enforced in the later project-specific block.\\n\\n## Project-specific file scope\\n\\nThe project-specific settings apply to these files:\\n\\n```text\\npackages/*/src/**/*.{ts,tsx}\\npackages/web/e2e/**/*.{ts,tsx}\\npackages/web/playwright.config.ts\\nscripts/**/*.ts\\n```\\n\\nThis scope covers:\\n\\n- TypeScript and TSX source files in package source directories.\\n- Web end-to-end tests under `packages/web/e2e`.\\n- The Playwright configuration.\\n- Repository TypeScript scripts.\\n\\nSome files in this scope are excluded earlier by the global ignore list. For example, `packages/web/playwright.config.ts` is included by the project-specific selector, while `packages/web/vite.config.ts` is explicitly ignored globally.\\n\\n## TypeScript project service\\n\\nThe project-specific block enables type-aware linting with:\\n\\n```js\\nlanguageOptions: {\\n  parserOptions: {\\n    projectService: true,\\n    tsconfigRootDir: import.meta.dirname,\\n  },\\n},\\n```\\n\\n### `projectService`\\n\\n`projectService: true` allows TypeScript ESLint to obtain type information from the applicable TypeScript project configuration. This is required by the type-checked preset rules.\\n\\n### `tsconfigRootDir`\\n\\n`tsconfigRootDir: import.meta.dirname` anchors TypeScript project discovery at the directory containing `eslint.config.mjs`. This makes project resolution independent of the process\u2019s current working directory and supports the repository\u2019s package-based layout.\\n\\n## Enforced repository rules\\n\\nThe project-specific rules marked as errors must pass for matching files.\\n\\n### Function return types\\n\\n```js\\n'@typescript-eslint/explicit-function-return-type': 'error'\\n```\\n\\nFunctions must declare their return types explicitly. This makes public and nontrivial function contracts visible at the declaration site.\\n\\n### Explicit `any`\\n\\n```js\\n'@typescript-eslint/no-explicit-any': 'error'\\n```\\n\\nExplicit uses of `any` are rejected. Code interacting with loosely typed external systems should use a more specific type, an appropriate boundary type, or another deliberate alternative.\\n\\n### Unused variables\\n\\n```js\\n'@typescript-eslint/no-unused-vars': [\\n  'error',\\n  {\\n    argsIgnorePattern: '^_',\\n    varsIgnorePattern: '^_',\\n    caughtErrorsIgnorePattern: '^_',\\n  },\\n]\\n```\\n\\nUnused variables are errors. Parameters, variables, and caught errors whose names begin with `_` are intentionally permitted, providing an established convention for unused values.\\n\\nExamples of accepted intentional names include:\\n\\n```ts\\nfunction handler(_request: Request): void {\\n  // ...\\n}\\n\\ntry {\\n  // ...\\n} catch (_error) {\\n  // ...\\n}\\n```\\n\\n### Quotes and semicolons\\n\\n```js\\nquotes: ['error', 'single', { avoidEscape: true }],\\nsemi: ['error', 'always'],\\n```\\n\\nMatching files must use:\\n\\n- Single quotes by default.\\n- Double quotes only when required to avoid escaping.\\n- Semicolons at statement boundaries.\\n\\n### Naming conventions\\n\\n`@typescript-eslint/naming-convention` enforces the following naming patterns:\\n\\n| Selector | Allowed format |\\n|---|---|\\n| `interface` | PascalCase, optionally prefixed with `I` |\\n| `typeAlias` | PascalCase |\\n| `function` | camelCase or PascalCase |\\n| `variable` | camelCase or UPPER_CASE |\\n\\nThe interface rule uses the custom expression `^I?[A-Z]`, so interface names must begin with an uppercase character and may optionally begin with `I`. This permits both styles such as `UserProfile` and `IUserProfile`.\\n\\n### Non-null assertions\\n\\n```js\\n'@typescript-eslint/no-non-null-assertion': 'error'\\n```\\n\\nThe non-null assertion operator (`!`) is prohibited. Code must establish or model nullability explicitly instead of suppressing TypeScript\u2019s checks.\\n\\n## Deliberately disabled rules\\n\\nSeveral rules from the TypeScript ESLint presets are disabled to accommodate repository patterns and external integrations.\\n\\n### Template and expression rules\\n\\nThe following are disabled:\\n\\n```js\\n'@typescript-eslint/restrict-template-expressions': 'off',\\n'@typescript-eslint/restrict-plus-operands': 'off',\\n```\\n\\nThis permits:\\n\\n- Numbers and booleans in template literals.\\n- Mixed operands in `+` expressions, including intentional string concatenation.\\n\\n### Defensive coding patterns\\n\\n```js\\n'@typescript-eslint/no-unnecessary-condition': 'off',\\n'@typescript-eslint/prefer-nullish-coalescing': 'off',\\n```\\n\\nThe configuration allows defensive checks that TypeScript may consider unnecessary. It also permits `||` where truthiness semantics are intentional, particularly for environment variables where an empty string should be treated as missing.\\n\\n### External SDK interoperability\\n\\nThese rules are disabled:\\n\\n```js\\n'@typescript-eslint/no-unsafe-assignment': 'off',\\n'@typescript-eslint/no-unsafe-member-access': 'off',\\n'@typescript-eslint/no-unsafe-argument': 'off',\\n'@typescript-eslint/no-misused-promises': 'off',\\n'@typescript-eslint/no-floating-promises': 'off',\\n```\\n\\nThis accommodates SDKs and integration libraries with incomplete or `any`-based type definitions. Promise-related restrictions are also relaxed for event-handler APIs whose callback contracts do not align cleanly with TypeScript\u2019s promise analysis.\\n\\n### Style and migration preferences\\n\\nThe following are disabled:\\n\\n```js\\n'@typescript-eslint/use-unknown-in-catch-callback-variable': 'off',\\n'@typescript-eslint/no-deprecated': 'off',\\n'@typescript-eslint/require-await': 'off',\\n'@typescript-eslint/consistent-generic-constructors': 'off',\\n```\\n\\nThis allows:\\n\\n- The existing catch-variable typing convention.\\n- Deprecated APIs during migration periods.\\n- Empty or interface-compliance async functions.\\n- Either supported generic constructor style.\\n\\n## Relationship to the rest of the codebase\\n\\nThis module is consumed by ESLint as the repository\u2019s flat configuration entry point. It does not import application modules or invoke project code.\\n\\nIts file selectors and ignores reflect the repository structure:\\n\\n- `packages/*/src` contains package implementation code.\\n- `packages/web/e2e` contains browser end-to-end code.\\n- `packages/web` contains Playwright and other tooling configuration.\\n- `scripts` contains repository automation.\\n- Generated, vendored, documentation, agent, and workspace directories are intentionally outside the linting scope.\\n\\nThe TypeScript project service connects linting to the repository\u2019s TypeScript project definitions, allowing type-aware rules to inspect the same project structure used by the compiler.\\n\\n## Maintenance guidance\\n\\nWhen changing this file:\\n\\n1. Add new source roots to the project-specific `files` list if they should receive type-aware linting.\\n2. Add generated or external-tool output to `ignores` rather than weakening rules globally.\\n3. Keep global exclusions in the first configuration object so they apply consistently.\\n4. Consider configuration order when changing a rule: later entries can override earlier presets.\\n5. Preserve the distinction between enforced rules and intentionally disabled rules.\\n6. Avoid disabling type-aware rules solely to handle a single file; exclude or scope that file when the exception is structural.\\n7. Update comments when repository tooling or generated-file locations change.\",\"other-git\":\"# Other \u2014 git\\n\\n# `@archon/git` \u2014 Git Utilities\\n\\n`@archon/git` provides the process, filesystem, repository, branch, and worktree operations used throughout Archon. It wraps Git commands through `execFileAsync`, exposes branded path and branch types, and applies consistent error handling for expected repository states versus operational failures.\\n\\nThe package entry point is `packages/git/src/index.ts`.\\n\\n## Responsibilities\\n\\nThe module supports:\\n\\n- Git repository discovery and remote inspection\\n- Repository cloning and synchronization\\n- Default branch detection and branch checkout\\n- Worktree path resolution, discovery, validation, and removal\\n- Detection and committing of working-tree changes\\n- Merge, patch-equivalence, ancestry, and commit-date checks\\n- Process-local serialization of Git operations with `KeyedMutex`\\n- Testable wrappers around `child_process.execFile` and `fs.mkdir`\\n\\nMost Git commands use argument arrays rather than shell command strings. This avoids shell interpolation and makes paths containing spaces safe.\\n\\n```ts\\nimport {\\n  checkout,\\n  getDefaultBranch,\\n  listWorktrees,\\n  syncWorkspace,\\n  toRepoPath,\\n} from '@archon/git';\\n\\nconst repoPath = toRepoPath('/workspace/my-repo');\\nconst branch = await getDefaultBranch(repoPath);\\n\\nawait checkout(repoPath, branch);\\nconst worktrees = await listWorktrees(repoPath);\\n```\\n\\n## Package architecture\\n\\n```mermaid\\nflowchart LR\\n  index[index.ts] --&gt; types[types.ts]\\n  index --&gt; exec[exec.ts]\\n  index --&gt; branch[branch.ts]\\n  index --&gt; worktree[worktree.ts]\\n  index --&gt; repo[repo.ts]\\n  index --&gt; mutex[keyed-mutex.ts]\\n  branch --&gt; exec\\n  worktree --&gt; exec\\n  repo --&gt; branch\\n  repo --&gt; exec\\n  worktree --&gt; paths[\\\"@archon/paths\\\"]\\n```\\n\\nThe three operational modules have distinct roles:\\n\\n| Module | Purpose |\\n|---|---|\\n| `exec.ts` | Testable wrappers for child processes and directory creation |\\n| `branch.ts` | Branch inspection and working-tree operations |\\n| `worktree.ts` | Git worktree layout, discovery, ownership, and removal |\\n| `repo.ts` | Repository discovery, cloning, remote synchronization, and Git safety configuration |\\n| `types.ts` | Branded string types and structured result types |\\n| `keyed-mutex.ts` | Per-key async serialization |\\n\\nAll public APIs are re-exported from `src/index.ts`.\\n\\n---\\n\\n## Branded types and result contracts\\n\\n### `RepoPath`, `BranchName`, and `WorktreePath`\\n\\nThe module uses branded string types to prevent accidentally passing a branch name where a repository path is expected:\\n\\n```ts\\nexport type RepoPath = string &amp; { readonly [REPO_PATH_BRAND]: true };\\nexport type BranchName = string &amp; { readonly [BRANCH_NAME_BRAND]: true };\\nexport type WorktreePath = string &amp; { readonly [WORKTREE_PATH_BRAND]: true };\\n```\\n\\nConvert external strings with:\\n\\n- `toRepoPath(path)`\\n- `toBranchName(name)`\\n- `toWorktreePath(path)`\\n\\nEach converter rejects an empty string. The branding is compile-time only; the runtime value remains the original string.\\n\\n```ts\\nconst repo = toRepoPath('/workspace/repo');\\nconst branch = toBranchName('feature/auth');\\nconst worktree = toWorktreePath('/workspace/worktrees/feature-auth');\\n```\\n\\n### `GitResult`\\n\\nOperations intended for package boundaries return a discriminated result instead of throwing:\\n\\n```ts\\ntype GitResult =\\n  | { ok: true; value: T }\\n  | { ok: false; error: GitError };\\n```\\n\\n`GitError` codes are:\\n\\n- `not_a_repo`\\n- `permission_denied`\\n- `branch_not_found`\\n- `no_space`\\n- `unknown`\\n\\n`cloneRepository` and `syncRepository` use this contract. Most lower-level inspection and worktree functions throw for unexpected failures.\\n\\n### `WorkspaceSyncResult`\\n\\n`syncWorkspace` returns:\\n\\n```ts\\ninterface WorkspaceSyncResult {\\n  branch: BranchName;\\n  synced: boolean;\\n  previousHead: string;\\n  newHead: string;\\n  updated: boolean;\\n}\\n```\\n\\n`previousHead` and `newHead` are short, eight-character commit IDs when available. HEAD lookup failures are non-fatal and result in an empty string.\\n\\n---\\n\\n## Command execution\\n\\n### `execFileAsync`\\n\\n`execFileAsync(cmd, args, options?)` wraps Node's `child_process.execFile` and normalizes `stdout` and `stderr` to strings.\\n\\nSupported options include:\\n\\n- `timeout`\\n- `cwd`\\n- `maxBuffer`\\n- `env`\\n\\nGit functions generally use one of two styles:\\n\\n```ts\\nawait execFileAsync('git', ['-C', repoPath, 'status', '--porcelain']);\\n```\\n\\nor:\\n\\n```ts\\nawait execFileAsync('git', ['fetch', 'origin'], {\\n  cwd: repoPath,\\n  timeout: 60000,\\n});\\n```\\n\\nThe wrapper exists primarily to make Git operations mockable in tests. Do not replace it with shell-based execution unless there is a specific requirement.\\n\\n### `mkdirAsync`\\n\\n`mkdirAsync(path, options?)` wraps `fs.promises.mkdir` and is provided for the same testability reason.\\n\\n---\\n\\n## Repository operations\\n\\n### `findRepoRoot(startPath)`\\n\\nRuns `git rev-parse --show-toplevel` and returns the containing repository as a `RepoPath`.\\n\\n- Returns `null` when `startPath` is not inside a Git repository.\\n- Throws for unexpected failures such as permission errors.\\n- Converts the returned path with `toRepoPath`.\\n\\nThis is used by the CLI to resolve the repository associated with the user's current location.\\n\\n### `getRemoteUrl(repoPath)`\\n\\nReturns the URL configured for the `origin` remote.\\n\\n- Returns `null` when `origin` is absent or has no URL.\\n- Throws for unexpected Git failures.\\n\\n### `cloneRepository(url, targetPath, options?)`\\n\\nClones a repository and returns `GitResult`.\\n\\n```ts\\nconst result = await cloneRepository(\\n  'https://github.com/owner/repo.git',\\n  toRepoPath('/workspace/repo'),\\n  { token }\\n);\\n\\nif (!result.ok) {\\n  // Handle result.error.code\\n}\\n```\\n\\nBehavior:\\n\\n- Uses `git clone  `.\\n- Has a 120-second timeout.\\n- If `options.token` is supplied, inserts it into the URL as the username for authenticated HTTPS cloning.\\n- Sanitizes the token in error messages before returning or logging failures.\\n- Classifies common failures as `not_a_repo`, `permission_denied`, or `no_space`.\\n- Returns `unknown` for all other failures.\\n\\n### `syncRepository(repoPath, branch)`\\n\\nSynchronizes a repository using:\\n\\n1. `git fetch origin`\\n2. `git reset --hard origin/`\\n\\nThe reset only runs after a successful fetch.\\n\\nIt uses `cwd: repoPath` rather than Git's `-C` option and returns `GitResult`:\\n\\n- Fetch errors can produce `not_a_repo`, `permission_denied`, `no_space`, or `unknown`.\\n- Reset errors referring to an unknown revision produce `branch_not_found`.\\n- Other reset failures produce `unknown`.\\n\\nThis operation is destructive because `reset --hard` discards local changes.\\n\\n### `addSafeDirectory(path)`\\n\\nRuns:\\n\\n```text\\ngit config --global --add safe.directory \\n```\\n\\nPaths are passed as an argument, so spaces and other shell-significant characters are not interpreted by a shell. The function throws if Git cannot update the global configuration.\\n\\n---\\n\\n## Workspace synchronization\\n\\n### `syncWorkspace(workspacePath, baseBranch?, options?)`\\n\\n`syncWorkspace` is the higher-level synchronization flow for an Archon workspace:\\n\\n1. Resolve the branch:\\n   - Use the supplied `baseBranch`, or\\n   - Call `getDefaultBranch(workspacePath)`.\\n2. Fetch the selected branch from `origin`.\\n3. Unless `resetAfterFetch` is `false`, record the current HEAD.\\n4. Hard-reset to `origin/`.\\n5. Record the new HEAD and report whether it changed.\\n\\n```ts\\nawait syncWorkspace(repoPath, undefined, {\\n  resetAfterFetch: false,\\n});\\n```\\n\\n`resetAfterFetch` defaults to `true`.\\n\\n### Safety considerations\\n\\nHard reset is appropriate for Archon-managed clones, but destructive for a user-owned local checkout. Callers must select the mode based on repository ownership:\\n\\n- Archon-managed workspace: default reset behavior is appropriate.\\n- Locally registered repository: use `{ resetAfterFetch: false }` unless discarding changes is explicitly intended.\\n\\nWhen a configured `baseBranch` cannot be found on the remote, the function throws an actionable error directing the caller to update or remove `worktree.baseBranch` in `.archon/config.yaml`. An auto-detected branch failure receives the normal fetch error because there is no configured setting to correct.\\n\\n---\\n\\n## Default branch and branch operations\\n\\n### `getDefaultBranch(repoPath)`\\n\\nDefault branch detection follows this chain:\\n\\n```mermaid\\nflowchart TD\\n  start[getDefaultBranch] --&gt; symbolic[\\\"git symbolic-ref origin/HEAD\\\"]\\n  symbolic --&gt;|success| result[Return branch name]\\n  symbolic --&gt;|expected ref error| verify[\\\"git rev-parse --verify origin/main\\\"]\\n  symbolic --&gt;|unexpected error| throw1[Throw]\\n  verify --&gt;|success| main[Return main]\\n  verify --&gt;|missing origin/main| config[Throw with config.yaml hint]\\n  verify --&gt;|unexpected error| throw2[Throw]\\n```\\n\\nThe function first runs:\\n\\n```text\\ngit -C  symbolic-ref refs/remotes/origin/HEAD --short\\n```\\n\\nFor output such as `origin/develop`, it returns `develop`.\\n\\nIf the symbolic reference is unavailable because the remote HEAD is not configured, it verifies `origin/main` and returns `main` when present. If neither source is available, it throws and advises setting:\\n\\n```yaml\\nworktree:\\n  baseBranch: \\n```\\n\\nOnly recognized \u201creference not found\u201d conditions trigger fallback. Permission errors, repository corruption, and similar unexpected failures are propagated.\\n\\n### `checkout(repoPath, branchName)`\\n\\nAttempts to check out an existing branch:\\n\\n```text\\ngit -C  checkout \\n```\\n\\nIf Git reports that the branch or pathspec does not exist, it creates and checks out the branch:\\n\\n```text\\ngit -C  checkout -b \\n```\\n\\nUnexpected errors are thrown.\\n\\n### `hasUncommittedChanges(workingPath)`\\n\\nRuns `git status --porcelain` and returns whether the output contains non-whitespace content.\\n\\nThe function is deliberately fail-safe:\\n\\n- Missing path (`ENOENT` or \u201cNo such file or directory\u201d): returns `false`.\\n- Any other error: logs the failure and returns `true`.\\n\\nReturning `true` on unexpected failures prevents cleanup code from deleting potentially modified or inaccessible data.\\n\\n### `commitAllChanges(workingPath, message)`\\n\\nCommits all changes only when `hasUncommittedChanges` reports a dirty working tree:\\n\\n1. `git add -A`\\n2. `git commit -m `\\n\\nReturns:\\n\\n- `true` if a commit is created.\\n- `false` if there is nothing to commit.\\n\\nA commit failure whose combined `stdout`/`stderr` contains \u201cnothing to commit\u201d is treated as a no-op. This handles cases where line-ending normalization makes `git status` appear dirty before `git add -A`.\\n\\nOther failures are thrown.\\n\\n### `isBranchMerged(repoPath, branchName, mainBranch)`\\n\\nRuns:\\n\\n```text\\ngit branch --merged \\n```\\n\\nThe output is parsed line by line, trimming whitespace and the current-branch marker (`*`). Returns whether `branchName` is listed.\\n\\nExpected missing-repository or missing-reference errors return `false`. Unexpected errors are thrown.\\n\\n### `isPatchEquivalent(repoPath, branchName, baseBranch)`\\n\\nUses:\\n\\n```text\\ngit cherry  \\n```\\n\\nGit reports each branch commit with:\\n\\n- `- `: an equivalent patch already exists in the base branch, such as after a squash merge or cherry-pick.\\n- `+ `: the patch is not present in the base branch.\\n\\nThe function returns `true` when every reported commit starts with `-`, including when there are no commits to compare. Expected missing-repository or missing-reference errors return `false`; unexpected failures throw.\\n\\n### `isAncestorOf(workingPath, ancestorRef)`\\n\\nRuns:\\n\\n```text\\ngit merge-base --is-ancestor  HEAD\\n```\\n\\nReturns:\\n\\n- `true` when the command succeeds.\\n- `false` when Git exits with code `1`, meaning the ref is not an ancestor.\\n- `false` for expected missing-path, missing-repository, or missing-reference errors.\\n- Throws for unexpected failures.\\n\\nIsolation code uses this check to detect whether a worktree is based on the expected branch.\\n\\n### `getLastCommitDate(workingPath)`\\n\\nRuns:\\n\\n```text\\ngit log -1 --format=%ci\\n```\\n\\nReturns a `Date`, or `null` when:\\n\\n- The repository has no commits.\\n- The path does not exist.\\n- The path is not a Git repository.\\n- Git produces empty or invalid date output.\\n\\nUnexpected errors are thrown. Invalid date strings are logged as warnings.\\n\\n---\\n\\n## Worktree operations\\n\\n### Worktree layouts\\n\\n`getWorktreeBase(repoPath, codebaseName?, override?)` resolves the directory under which branch-specific worktrees are created.\\n\\nThere are two layouts:\\n\\n| Layout | Base path |\\n|---|---|\\n| `repo-local` | `/` |\\n| `workspace-scoped` | `~/.archon/workspaces///worktrees` |\\n\\nThe default is always `workspace-scoped`. A `repoLocal` override takes precedence.\\n\\n```ts\\nconst { base, layout } = getWorktreeBase(\\n  repoPath,\\n  'acme/widget',\\n  { repoLocal: '.worktrees' }\\n);\\n// base: /.worktrees\\n// layout: \\\"repo-local\\\"\\n```\\n\\nFor the workspace-scoped layout, owner/repository resolution uses this precedence:\\n\\n1. A valid `codebaseName` in `owner/repo` format.\\n2. `owner/repo` segments detected under `getArchonWorkspacesPath()`.\\n3. The final two path segments from `repoPath`, via `extractOwnerRepo`.\\n\\n`getProjectWorktreesPath` and `getArchonWorkspacesPath` come from `@archon/paths`.\\n\\n### `extractOwnerRepo(repoPath)`\\n\\nExtracts the final two non-empty path segments as `{ owner, repo }`. Both `/` and `\\\\` separators are supported.\\n\\n```ts\\nextractOwnerRepo(toRepoPath('/home/user/acme/widget'));\\n// { owner: 'acme', repo: 'widget' }\\n```\\n\\nThrows when fewer than two path segments are available.\\n\\n### `isProjectScopedWorktreeBase(repoPath, codebaseName?)`\\n\\nDeprecated compatibility helper. It returns whether `getWorktreeBase(...).layout` is `workspace-scoped`.\\n\\nNew code should inspect the `layout` returned by `getWorktreeBase`, especially when using a `repoLocal` override:\\n\\n```ts\\nconst isWorkspaceScoped =\\n  getWorktreeBase(repoPath, codebaseName, override).layout === 'workspace-scoped';\\n```\\n\\n### `worktreeExists(worktreePath)`\\n\\nChecks for:\\n\\n1. The worktree path.\\n2. A `.git` entry inside it.\\n\\nA `.git` entry may be a file or directory; this function does not validate its contents.\\n\\n- Returns `false` when the path does not exist.\\n- Returns `false` and logs a corruption warning when the directory exists but `.git` is missing.\\n- Throws for permission and other unexpected filesystem errors.\\n\\n### `listWorktrees(repoPath)`\\n\\nRuns:\\n\\n```text\\ngit worktree list --porcelain\\n```\\n\\nand parses `worktree` and `branch` records into `WorktreeInfo` objects:\\n\\n```ts\\ninterface WorktreeInfo {\\n  path: WorktreePath;\\n  branch: BranchName;\\n}\\n```\\n\\nBranch values have the `refs/heads/` prefix removed.\\n\\nExpected \u201cnot a git repository\u201d and missing-path errors return an empty array. Unexpected failures, including a missing Git executable or permission errors, throw.\\n\\n### `findWorktreeByBranch(repoPath, branchPattern)`\\n\\nBuilds on `listWorktrees`.\\n\\nMatching order:\\n\\n1. Exact branch match.\\n2. Slash-to-dash slugified match.\\n\\nFor example, `feature/auth` can match a worktree whose branch is `feature-auth`. Returns the matching `WorktreePath`, or `null`.\\n\\n### `isWorktreePath(path)`\\n\\nDistinguishes a linked worktree from a main checkout by inspecting `/.git`:\\n\\n- A `.git` file beginning with `gitdir:` means the path is a worktree.\\n- A `.git` directory means it is a main checkout.\\n- Missing `.git` or a missing path returns `false`.\\n- Unexpected filesystem errors throw.\\n\\n### `getCanonicalRepoPath(path)`\\n\\nReturns the canonical repository path for a path:\\n\\n- For a normal checkout, returns the input path as `RepoPath`.\\n- For a linked worktree, parses its `.git` pointer and extracts the parent repository.\\n- Throws when the `.git` pointer has an unexpected format.\\n\\nThis canonical path is important when serializing operations that affect shared Git metadata.\\n\\n### `verifyWorktreeOwnership(worktreePath, expectedRepo)`\\n\\nStrictly validates that a worktree belongs to the expected repository by reading its `.git` pointer.\\n\\nA successful return means the worktree can be safely adopted. It throws for:\\n\\n- A full checkout at the path (`.git` is a directory).\\n- Missing or unreadable `.git`.\\n- Malformed or submodule-style Git pointers.\\n- A worktree registered to another clone.\\n\\nPaths are normalized with `resolve()` before comparison. The original filesystem error code is preserved on wrapped errors, and the original error is available through `cause`.\\n\\nThis guard is used by isolation resolution to prevent cross-checkout adoption bugs.\\n\\n### `removeWorktree(repoPath, worktreePath)`\\n\\nRuns:\\n\\n```text\\ngit -C  worktree remove \\n```\\n\\nGit's own safety checks prevent removal when the worktree contains uncommitted changes. Errors are propagated to the caller.\\n\\n---\\n\\n## Concurrency with `KeyedMutex`\\n\\n`KeyedMutex` serializes asynchronous operations by string key:\\n\\n```ts\\nconst mutex = new KeyedMutex();\\n\\nawait mutex.run(canonicalRepoPath, async () =&gt; {\\n  // Git writes affecting this repository\\n});\\n```\\n\\nSemantics:\\n\\n- Operations with the same key run one at a time.\\n- Same-key operations execute in FIFO order.\\n- Operations with different keys can run concurrently.\\n- The lock is released when the callback resolves or rejects.\\n- Queued keys are removed after their queue drains.\\n- `size()` reports the number of currently tracked keys.\\n\\nThe mutex is process-local and does not coordinate separate Archon processes. It is intended for operations that contend on shared repository state, such as fetch, reset, worktree creation, and branch updates. The worktree provider uses `run` when destroying worktrees.\\n\\n---\\n\\n## Error-handling conventions\\n\\nThe module distinguishes expected environmental states from unexpected operational failures.\\n\\n### Expected conditions\\n\\nDepending on the API, expected conditions are represented as:\\n\\n- `null`: `findRepoRoot`, `getRemoteUrl`, `getLastCommitDate`\\n- `false`: `hasUncommittedChanges` for a missing path, branch relationship checks for missing refs\\n- `[]`: `listWorktrees` when the path is missing or not a repository\\n- `GitResult` with a typed error code: `cloneRepository`, `syncRepository`\\n- Fallback behavior: `getDefaultBranch`, `checkout`\\n\\n### Unexpected conditions\\n\\nPermission failures, repository corruption, lock failures, and similar conditions generally:\\n\\n1. Log through a lazily initialized `createLogger('git')`.\\n2. Throw an error with operation and path context.\\n\\nThe lazy logger initialization is intentional: tests can install mocks for `@archon/paths` before the logger is created.\\n\\nA notable exception is `hasUncommittedChanges`, which returns `true` on unexpected errors to fail safely during cleanup.\\n\\n---\\n\\n## Integration with the rest of Archon\\n\\nThe module is used by several higher-level subsystems:\\n\\n- The CLI calls `findRepoRoot` to locate the current repository.\\n- Isolation resolution uses:\\n  - `worktreeExists` to detect reusable worktrees.\\n  - `getCanonicalRepoPath` to normalize repository identity.\\n  - `verifyWorktreeOwnership` before adoption.\\n  - `isAncestorOf` for base-branch validation.\\n  - `toWorktreePath` and `toRepoPath` for type-safe boundaries.\\n- Worktree providers use:\\n  - `listWorktrees`, `getCanonicalRepoPath`, and `worktreeExists` for lookup.\\n  - `KeyedMutex.run` for serialized destruction.\\n  - `execFileAsync` for provider-specific Git operations.\\n- Workflow and isolation commands use `getDefaultBranch`.\\n- Runtime validation and workflow execution use `execFileAsync` for external command checks.\\n- Path resolution and logging are supplied by `@archon/paths`.\\n\\nBecause multiple consumers can operate on the same canonical repository, callers performing Git writes should use a consistent mutex key\u2014normally the canonical repository path returned by `getCanonicalRepoPath`.\\n\\n---\\n\\n## Testing and contribution guidance\\n\\nTests use Bun and mock `execFileAsync` to assert command arguments, timeouts, and error classification. Run the package checks with:\\n\\n```sh\\nbun test packages/git/src/\\nbun x tsc --noEmit -p packages/git/tsconfig.json\\n```\\n\\nWhen adding a Git operation:\\n\\n- Use `execFileAsync`, not shell execution.\\n- Pass paths and user-provided values as argument-array entries.\\n- Classify only well-understood expected errors.\\n- Preserve unexpected failures rather than silently converting them to success.\\n- Consider whether the operation mutates shared repository state and should be called under `KeyedMutex`.\\n- Use branded types at public boundaries.\\n- Add tests for both `stderr` and `Error.message` when Git may report the same condition in either location.\\n- Treat operations involving `reset --hard`, worktree removal, or cleanup as destructive and document their safety assumptions.\",\"other-knowledge\":\"# Other \u2014 knowledge\\n\\n# Other \u2014 Knowledge Module\\n\\nThis module contains operational knowledge and knowledge-graph maintenance artifacts rather than executable application code:\\n\\n- `docs/knowledge/baidu-pipeline-docker-build.md` documents the Baidu CI pipeline contract for building Docker images.\\n- `docs/knowledge/kg-self-seal.json` records a knowledge-graph integrity remediation run for the `baidu/acg2b-ep/ai-ku` service.\\n\\nThere are no detected internal calls, incoming calls, outgoing calls, or execution flows for this module. Its connection to the rest of the repository is informational and operational: it defines deployment conventions and captures metadata derived from application APIs and Pydantic models.\\n\\n## Baidu Pipeline Docker Build Contract\\n\\n`baidu-pipeline-docker-build.md` defines the required artifact flow for Docker images built in the Baidu pipeline.\\n\\nThe central rule is:\\n\\n&gt; Pipeline Dockerfiles must copy build inputs from `output/`, not directly from application source directories.\\n\\nA local-only Dockerfile may copy directly from source paths such as `src/` or `pyproject.toml`, but a Dockerfile used in the pipeline must consume the prepared delivery artifact.\\n\\n```mermaid\\nflowchart LR\\n    A[Application sourceapps/api/] --&gt; B[build_apiserver.sh]\\n    B --&gt; C[output/ artifact]\\n    C --&gt; D[Pipeline Package stage]\\n    D --&gt; E[Dockerfile COPY output/...]\\n    E --&gt; F[Docker image]\\n    F --&gt; G[Deploy stage]\\n```\\n\\n### Why `output/` Is Required\\n\\nThe pipeline is divided into separate Build, Package, and Deploy stages. `output/` is the handoff boundary between Build and Package:\\n\\n1. The Build stage runs a script such as `build_apiserver.sh`.\\n2. The script collects all image-required files into `output/`.\\n3. The Package stage builds the image using the repository root as its Docker build context.\\n4. The pipeline Dockerfile copies only `output/...` files into the image.\\n5. The Deploy stage deploys the resulting image.\\n\\nThis convention provides:\\n\\n- **Stage isolation**: later stages consume the prepared artifact rather than relying on arbitrary workspace source paths.\\n- **Explicit delivery contents**: the build script defines exactly which files are shipped.\\n- **Reproducibility**: the Docker image is based on the build output, not on untracked files available during image construction.\\n- **Separation of responsibilities**: build scripts prepare artifacts; Dockerfiles package artifacts.\\n\\n## Build Artifact Preparation\\n\\nThe documented build-script pattern is represented by `build_apiserver.sh`, which packages the API service from `apps/api`.\\n\\n### Expected Build-Script Behavior\\n\\nThe script:\\n\\n1. Sets the application root with `API_DIR=\\\"apps/api\\\"`.\\n2. Removes prior artifacts with `rm -rf output`.\\n3. Creates the output directory, including `output/logs`.\\n4. Copies application source, packaging metadata, configuration, and database migrations into `output/`.\\n5. Lists the resulting contents as a basic verification step.\\n\\nThe documented copy operations are:\\n\\n```bash\\ncp -r \\\"$API_DIR/src\\\" output/\\ncp \\\"$API_DIR/pyproject.toml\\\" output/\\ncp \\\"$API_DIR/README.md\\\" output/\\ncp \\\"$API_DIR/alembic.ini\\\" output/\\ncp \\\"$API_DIR/.env.example\\\" output/\\ncp \\\"$API_DIR/Makefile\\\" output/\\ncp -r \\\"$API_DIR/alembic\\\" output/\\n```\\n\\nThe resulting delivery structure is:\\n\\n```text\\noutput/\\n\u251c\u2500\u2500 src/\\n\u251c\u2500\u2500 pyproject.toml\\n\u251c\u2500\u2500 README.md\\n\u251c\u2500\u2500 alembic.ini\\n\u251c\u2500\u2500 .env.example\\n\u251c\u2500\u2500 Makefile\\n\u2514\u2500\u2500 alembic/\\n```\\n\\n### Maintaining the Build Script\\n\\nWhen an application gains a runtime dependency on a repository file, contributors must determine whether that file is required inside the production image.\\n\\nIf it is required:\\n\\n1. Add a copy step to `build_apiserver.sh` so it enters `output/`.\\n2. Add or update the matching `COPY output/...` instruction in the pipeline Dockerfile.\\n3. Verify that the image can be built using only the prepared artifact.\\n\\nDo not add a direct `COPY apps/api/...` instruction to a pipeline Dockerfile as a shortcut. Doing so bypasses the stage-delivery contract.\\n\\n## Pipeline Dockerfile Pattern\\n\\nThe documented production Dockerfile is `apps/api/Dockerfile`. It uses:\\n\\n```dockerfile\\nFROM iregistry.baidu-int.com/tianniu/python:3.13-uv\\nWORKDIR /app\\n```\\n\\nThe base image is documented as already containing `gcc`, `curl`, `default-libmysqlclient-dev`, `libmariadb3`, and `uv`.\\n\\n### Dependency Layer\\n\\nThe Dockerfile first copies dependency metadata:\\n\\n```dockerfile\\nCOPY output/pyproject.toml output/README.md ./\\n```\\n\\nIt then configures Python and `uv`:\\n\\n```dockerfile\\nENV PYTHONUNBUFFERED=1\\nENV PYTHONDONTWRITEBYTECODE=1\\nENV UV_INDEX_URL=https://pip.baidu-int.com/simple/\\nENV PATH=\\\"/app/.venv/bin:$PATH\\\"\\n```\\n\\nDependencies are installed into a local virtual environment:\\n\\n```dockerfile\\nRUN uv venv --python 3.13 .venv \\\\\\n    &amp;&amp; uv pip install --no-cache-dir -e .\\n```\\n\\nCopying `pyproject.toml` and `README.md` before application source preserves Docker layer caching: dependency installation can be reused when source-only changes occur.\\n\\n### Application Layer\\n\\nApplication code and migration files are copied exclusively from the prepared artifact:\\n\\n```dockerfile\\nCOPY output/src ./src\\nCOPY output/alembic.ini ./alembic.ini\\nCOPY output/alembic ./alembic\\n```\\n\\nThe image creates a logs directory:\\n\\n```dockerfile\\nRUN mkdir -p logs\\n```\\n\\nIt exposes operational behavior through:\\n\\n- a `HEALTHCHECK` that queries `/health` on `${main:-8000}`;\\n- a `CMD` that runs `alembic upgrade head` before starting `uvicorn`.\\n\\n```dockerfile\\nCMD [\\\"sh\\\", \\\"-c\\\", \\\"alembic upgrade head &amp;&amp; uvicorn src.app.main:app --host 0.0.0.0 --port ${main:-8000}\\\"]\\n```\\n\\n### Build Context Requirement\\n\\n`COPY output/...` paths are evaluated relative to the Docker build context. The documented command assumes the repository root is the build context:\\n\\n```bash\\ndocker build -t efficiency-dashboard:prod .\\n```\\n\\nRunning `docker build` from a subdirectory or supplying a different context can make `output/` unavailable even if the artifact exists elsewhere.\\n\\n## Local Dockerfiles\\n\\nThe `output/` rule applies specifically to Dockerfiles used in the Baidu pipeline.\\n\\nFor local development or debugging, a simpler Dockerfile may copy source files directly:\\n\\n```dockerfile\\nFROM python:3.13\\nCOPY src/ ./src\\nCOPY pyproject.toml .\\nRUN pip install -e .\\nCMD [\\\"uvicorn\\\", \\\"src.app.main:app\\\"]\\n```\\n\\nKeep local and pipeline Dockerfiles clearly differentiated. A local Dockerfile is allowed to optimize developer iteration; the pipeline Dockerfile must preserve the artifact boundary.\\n\\n## Knowledge-Graph Integrity Record\\n\\n`kg-self-seal.json` records the results of an integrity remediation operation for product `prod_p442je`, associated with the `baidu/acg2b-ep/ai-ku` service.\\n\\nIt is a structured record of graph updates and validation results, not a runtime service configuration file.\\n\\n### Recorded Service Metadata\\n\\nThe record fills the `description` field for the `Service` node:\\n\\n```text\\nbaidu/acg2b-ep/ai-ku\\n```\\n\\nThe stored description characterizes AI-Ku as a knowledge-management platform with graph, document/RAG, OpenKB, chat, authentication, evaluation, inspection, sandbox, Claude package, and workflow-memory capabilities. It also records dependencies on Neo4j, Qdrant, and the OpenAI API.\\n\\n### API Schema Associations\\n\\nThe remediation data associates API nodes with request and response Pydantic models found in the codebase. Examples include:\\n\\n| API | Request model evidence |\\n|---|---|\\n| `POST /products` | `ProductCreateRequest` |\\n| `PUT /products/{product_id}` | `ProductUpdateRequest` |\\n| `POST /products/{product_id}/entities` | `EntityListRequest` |\\n| `POST /products/{product_id}/entities/search` | `EntitySearchRequest` |\\n| `POST /products/{product_id}/entities/impact` | `ImpactRequest` |\\n| `POST /api-keys` | `ApiKeyCreateRequest` |\\n| `POST /upload/text` | `TextUploadRequest` |\\n| `POST /search` | `SearchRequest` |\\n| `POST /rag` | `RAGRequest` |\\n| `POST /conversations` | `CreateConversationRequest` |\\n| `POST /runs` | `SysEvalRunRequest` |\\n| `POST /graph-inspection/run` | `GraphInspectionRunRequest` |\\n| `POST /query` | `QueryRequest` |\\n| `POST /claude-package/deploy` | `ClaudePackageDeployRequest` |\\n| `POST /ingest` | `WorkflowRunIngestInput` |\\n| `POST /prefetch` | `WorkflowMemoryPrefetchRequest` |\\n\\nExplicit response-model associations include:\\n\\n| API | Response model |\\n|---|---|\\n| `POST /conversations` | `ConversationResponse` |\\n| `GET /conversations` | `ConversationListResponse` |\\n| `GET /conversations/{conversation_id}` | `ConversationResponse` |\\n| `GET /conversations/{conversation_id}/messages` | `MessageListResponse` |\\n| `POST /conversations/{conversation_id}/clear` | `ClearContextResponse` |\\n| `POST /claude-package/deploy` | `ClaudePackageDeployResponse` |\\n\\nThe evidence paths identify the authoritative model definitions, including:\\n\\n- `ai_ku/graph_store/api_models.py`\\n- `ai_ku/auth/models.py`\\n- `ai_ku/doc_store/api.py`\\n- `ai_ku/chat/api_models.py`\\n- `ai_ku/common/api.py`\\n- `ai_ku/eval/blackbox/api_models.py`\\n- `ai_ku/graph_store/inspection/models.py`\\n- `ai_ku/openkb/api.py`\\n- `ai_ku/sandbox/api_models.py`\\n- `ai_ku/workflow_ingest/service.py`\\n- `ai_ku/workflow_ingest/memory_models.py`\\n\\n### Graph Relationship Repairs\\n\\nThe record adds `HANDLES` relationships from `Service:baidu/acg2b-ep/ai-ku` to three API nodes that were previously isolated:\\n\\n- `GET /products/{product_id}/integrity/tasks`\\n- `GET /products/{product_id}/integrity/tasks/{task_id}`\\n- `POST /graph-inspection/run`\\n\\nThese relationships ensure the graph can identify the owning service for the API nodes.\\n\\n### Validation Results\\n\\nThe recorded validation improved graph consistency from invalid to valid:\\n\\n| Metric | Before | After |\\n|---|---:|---:|\\n| Validation errors | 3 | 0 |\\n| API nodes | 81 | 81 |\\n| `HANDLES` relationships | 86 | 89 |\\n| Service nodes missing descriptions | 1 | 0 |\\n\\nThe remaining schema gaps are intentional or evidence-limited:\\n\\n- GET and DELETE endpoints without explicit request bodies do not receive request schemas.\\n- Many response schemas remain absent because their handlers return plain dictionaries rather than declaring an explicit Pydantic `response_model`.\\n- `covered_by_testcase` relationships were not created because that relationship type was outside the permitted whitelist; only `HANDLES` and `BELONGS_TO` were allowed.\\n\\n## Contribution Guidance\\n\\nWhen changing pipeline packaging:\\n\\n- Update both the build script and pipeline Dockerfile.\\n- Treat `output/` as the complete, explicit image input.\\n- Build from the repository-root context when validating `COPY output/...` paths.\\n- Keep dependency definitions copied before source code to retain Docker cache efficiency.\\n\\nWhen changing APIs or Pydantic models:\\n\\n- Update the implementation model in its owning module, such as `ai_ku/graph_store/api_models.py` or `ai_ku/chat/api_models.py`.\\n- Ensure knowledge-graph API metadata remains aligned with the actual request and response models.\\n- Add explicit response models where appropriate if response-schema completeness is important for graph documentation and validation.\\n- Preserve `HANDLES` ownership relationships for newly introduced API nodes so they are not orphaned in graph validation.\",\"other-makefile\":\"# Other \u2014 Makefile\\n\\n# Other \u2014 Makefile\\n\\nThe repository Makefile provides a single command interface for:\\n\\n- Running Bun-based source checks and development tasks\\n- Building and publishing CI, base, application, and end-to-end development Docker images\\n- Running an emergency PostgreSQL migration\\n- Coordinating multi-step Docker build and push workflows\\n\\nThe Makefile does not contain application logic. It orchestrates shell commands, Docker builds, registry pushes, and repository scripts.\\n\\n## Image naming and tagging\\n\\nThe Makefile defines four private registry locations:\\n\\n```make\\nREGISTRY_CI       := iregistry.baidu-int.com/tianniu/doarchon_ci\\nREGISTRY_BASE     := iregistry.baidu-int.com/tianniu/doarchon_base\\nREGISTRY_APP      := iregistry.baidu-int.com/tianniu/doarchon\\nREGISTRY_E2E_DEV  := iregistry.baidu-int.com/sqc-ee/e2e-dev\\n```\\n\\nA millisecond Unix timestamp is generated when Make evaluates the file:\\n\\n```make\\nTIMESTAMP := $(shell python3 -c \\\"import time; print(int(time.time() * 1000))\\\")\\n```\\n\\nThe CI, base, and application image tags use that timestamp:\\n\\n```text\\ndoarchon_ci:\\ndoarchon_base:\\ndoarchon:\\n```\\n\\nThe `e2e-dev` images use different tag conventions:\\n\\n```text\\ne2e-dev:base-\\ne2e-dev:latest\\n```\\n\\nConsequently, a single Make invocation uses the same timestamp for all timestamped images. Separate invocations generate new tags.\\n\\n## Target overview\\n\\n```mermaid\\nflowchart TD\\n    test[test] --&gt; bunTest[bun run test]\\n    lint[lint] --&gt; bunLint[bun run lint]\\n    build[build] --&gt; bunBuild[bun run build]\\n    buildBase[build-base] --&gt; dockerBase[Dockerfile.base]\\n    buildApp[build-app] --&gt; script[scripts/build.sh]\\n    buildApp --&gt; dockerApp[Dockerfile]\\n    buildImage[build-image] --&gt; buildBase\\n    buildImage --&gt; buildApp\\n    push[push] --&gt; pushBase[push-base]\\n    push --&gt; pushApp[push-app]\\n    pushBase --&gt; buildBase\\n    pushApp --&gt; buildApp\\n```\\n\\n## Source and development targets\\n\\n### `test`\\n\\nRuns the repository test suite through Bun:\\n\\n```bash\\nmake test\\n```\\n\\nEquivalent command:\\n\\n```bash\\nbun run test\\n```\\n\\n### `lint`\\n\\nRuns the configured Bun lint task:\\n\\n```bash\\nmake lint\\n```\\n\\nEquivalent command:\\n\\n```bash\\nbun run lint\\n```\\n\\n### `build`\\n\\nBuilds the application source using the Bun build script:\\n\\n```bash\\nmake build\\n```\\n\\nEquivalent command:\\n\\n```bash\\nbun run build\\n```\\n\\nThis target is separate from `build-app`, which prepares and builds a Docker application image.\\n\\n### `dev`\\n\\nRuns the development server:\\n\\n```make\\ndev: deps\\n\\tbun run dev\\n```\\n\\nThe target depends on `deps`, but no `deps` target is defined in the provided Makefile. A compatible `deps` target must therefore be supplied elsewhere, or `make dev` will fail with an unknown-target error. The `dev` target is also not included in the Makefile\u2019s `.PHONY` declaration.\\n\\n## Database migration\\n\\n### `db-migrate`\\n\\nRuns the PostgreSQL migration script manually:\\n\\n```bash\\nmake db-migrate DATABASE_URL=postgres://user:pass@host:5432/dbname\\n```\\n\\nThe target first verifies that `DATABASE_URL` is set:\\n\\n```sh\\nif [ -z \\\"$(DATABASE_URL)\\\" ]; then\\n    echo \\\"Error: DATABASE_URL is required...\\\"\\n    exit 1\\nfi\\n```\\n\\nWhen the variable is present, it executes:\\n\\n```bash\\nDATABASE_URL=$(DATABASE_URL) bun run packages/core/src/db/migrate.ts\\n```\\n\\nThis target is intended for emergency or manual repairs. Production service startup is documented as running migrations automatically, so normal deployments should not require this command.\\n\\n`db-migrate` is not declared in `.PHONY`. If a file or directory named `db-migrate` exists in the repository root, Make may consider the target up to date instead of executing it.\\n\\n## CI image workflow\\n\\n### `ci-build`\\n\\nBuilds the CI image for the `linux/amd64` platform using `dockerfile.ci`:\\n\\n```bash\\nmake ci-build\\n```\\n\\nThe resulting image is tagged with the generated timestamp:\\n\\n```bash\\ndocker build \\\\\\n  --platform linux/amd64 \\\\\\n  -f dockerfile.ci \\\\\\n  -t iregistry.baidu-int.com/tianniu/doarchon_ci: \\\\\\n  .\\n```\\n\\n### `ci-push`\\n\\nDepends on `ci-build`, then pushes the timestamped CI image:\\n\\n```bash\\nmake ci-push\\n```\\n\\nIt prints the pushed image reference after a successful upload.\\n\\n### `ci`\\n\\nAlias for the complete CI image build-and-push workflow:\\n\\n```bash\\nmake ci\\n```\\n\\nIts dependency chain is:\\n\\n```text\\nci \u2192 ci-push \u2192 ci-build\\n```\\n\\n## Base image workflow\\n\\nThe base image contains system-level dependencies and is intended to be built less frequently than the application image.\\n\\n### `build-base`\\n\\nBuilds `Dockerfile.base` for `linux/amd64`, first tagging it locally as `archon-base:latest`:\\n\\n```bash\\nmake build-base\\n```\\n\\nThe target then applies the timestamped registry tag:\\n\\n```bash\\ndocker tag archon-base:latest \\\\\\n  iregistry.baidu-int.com/tianniu/doarchon_base:\\n```\\n\\nThe local `archon-base:latest` tag remains available after the build.\\n\\n### `push-base`\\n\\nDepends on `build-base` and pushes the timestamped base image:\\n\\n```bash\\nmake push-base\\n```\\n\\nDependency chain:\\n\\n```text\\npush-base \u2192 build-base\\n```\\n\\n## Application image workflow\\n\\n### `build-app`\\n\\nPrepares and builds the application image:\\n\\n```bash\\nmake build-app\\n```\\n\\nThe target performs the following steps in order:\\n\\n1. Runs the repository image-preparation script:\\n\\n   ```bash\\n   bash scripts/build.sh\\n   ```\\n\\n2. Builds the application image for `linux/amd64` using the repository\u2019s default `Dockerfile`:\\n\\n   ```bash\\n   docker build --platform linux/amd64 -t archon:latest .\\n   ```\\n\\n3. Tags the local image with the timestamped application registry reference:\\n\\n   ```bash\\n   docker tag archon:latest \\\\\\n     iregistry.baidu-int.com/tianniu/doarchon:\\n   ```\\n\\n### `push-app`\\n\\nDepends on `build-app` and pushes the timestamped application image:\\n\\n```bash\\nmake push-app\\n```\\n\\nDependency chain:\\n\\n```text\\npush-app \u2192 build-app\\n```\\n\\n## Combined Docker workflows\\n\\n### `build-image`\\n\\nBuilds both the base and application images:\\n\\n```bash\\nmake build-image\\n```\\n\\nIts dependencies are:\\n\\n```text\\nbuild-image \u2192 build-base\\nbuild-image \u2192 build-app\\n```\\n\\nThis target only builds and tags images. It does not push them.\\n\\n### `push`\\n\\nBuilds and pushes both the base and application images:\\n\\n```bash\\nmake push\\n```\\n\\nIts dependencies are:\\n\\n```text\\npush \u2192 push-base \u2192 build-base\\npush \u2192 push-app \u2192 build-app\\n```\\n\\nBecause `push-base` and `push-app` each depend on their corresponding build target, `make push` performs fresh builds before pushing.\\n\\n## `e2e-dev` image workflow\\n\\nThe `e2e-dev` targets build images from the `docker/e2e-dev` directory. They are intended for the CI environment and produce a base image followed by a final image.\\n\\n### `e2e-dev-build-base`\\n\\nBuilds the e2e development base image:\\n\\n```bash\\nmake e2e-dev-build-base\\n```\\n\\nBuild details:\\n\\n- Platform: `linux/amd64`\\n- Dockerfile: `docker/e2e-dev/Dockerfile.base`\\n- Build context: `docker/e2e-dev`\\n- Local tag: `e2e-dev-base:latest`\\n- Registry tag: `iregistry.baidu-int.com/sqc-ee/e2e-dev:base-`\\n\\n### `e2e-dev-push-base`\\n\\nDepends on `e2e-dev-build-base` and pushes the timestamped base image:\\n\\n```bash\\nmake e2e-dev-push-base\\n```\\n\\n### `e2e-dev-build-final`\\n\\nBuilds the final e2e development image:\\n\\n```bash\\nmake e2e-dev-build-final\\n```\\n\\nBuild details:\\n\\n- Platform: `linux/amd64`\\n- Dockerfile: `docker/e2e-dev/Dockerfile`\\n- Build context: `docker/e2e-dev`\\n- Registry tag: `iregistry.baidu-int.com/sqc-ee/e2e-dev:latest`\\n\\nUnlike the base image, the final image always uses the `latest` tag.\\n\\n### `e2e-dev-push-final`\\n\\nDepends on `e2e-dev-build-final` and pushes the final image:\\n\\n```bash\\nmake e2e-dev-push-final\\n```\\n\\n### `e2e-dev-push`\\n\\nBuilds and pushes both the e2e development base and final images:\\n\\n```bash\\nmake e2e-dev-push\\n```\\n\\nIts dependencies are:\\n\\n```text\\ne2e-dev-push \u2192 e2e-dev-push-base \u2192 e2e-dev-build-base\\ne2e-dev-push \u2192 e2e-dev-push-final \u2192 e2e-dev-build-final\\n```\\n\\nAfter both pushes complete, it prints the generated base image reference and the final `latest` reference.\\n\\n### `e2e-dev`\\n\\nAlias for `e2e-dev-push`:\\n\\n```bash\\nmake e2e-dev\\n```\\n\\n## Phony targets\\n\\nThe Makefile marks the operational targets as `.PHONY`, including:\\n\\n- Source tasks: `test`, `lint`, `build`\\n- CI image tasks: `ci-build`, `ci-push`, `ci`\\n- Base and application image tasks: `build-base`, `build-app`, `build-image`, `push-base`, `push-app`, `push`\\n- E2E image tasks: `e2e-dev-build-base`, `e2e-dev-push-base`, `e2e-dev-build-final`, `e2e-dev-push-final`, `e2e-dev-push`, `e2e-dev`\\n\\nThe `dev` and `db-migrate` targets are present but are not listed as phony. Contributors should consider adding them to `.PHONY` if they are intended to run unconditionally regardless of files in the repository root.\\n\\n## Registry and environment requirements\\n\\nThe Docker targets assume:\\n\\n- Docker is installed and available on `PATH`\\n- The Docker daemon can build `linux/amd64` images\\n- The current user is authenticated to the internal registries\\n- The registry names resolve from the build environment\\n- Python 3 is available to generate `TIMESTAMP`\\n- Bun is installed for source, development, and migration commands\\n- `bash` is available for `scripts/build.sh`\\n\\nThe Makefile does not perform registry login, configure buildx, or validate Docker connectivity before starting a build or push. Those steps must be handled by the developer environment or CI pipeline.\\n\\n## Typical usage\\n\\nRun source checks:\\n\\n```bash\\nmake test\\nmake lint\\nmake build\\n```\\n\\nBuild the application image without pushing:\\n\\n```bash\\nmake build-image\\n```\\n\\nBuild and publish the base and application images:\\n\\n```bash\\nmake push\\n```\\n\\nPublish the CI image:\\n\\n```bash\\nmake ci\\n```\\n\\nBuild and publish the e2e development images:\\n\\n```bash\\nmake e2e-dev\\n```\\n\\nRun a manual database migration:\\n\\n```bash\\nmake db-migrate DATABASE_URL=postgres://user:pass@host:5432/dbname\\n```\\n\\nStart local development, provided the `deps` target is available:\\n\\n```bash\\nmake dev\\n```\",\"other-migrations\":\"# Other \u2014 migrations\\n\\n# Other \u2014 Migrations\\n\\nThe `migrations/` module defines the PostgreSQL persistence schema for Remote Coding Agent. It contains:\\n\\n- Incremental SQL migrations named with numeric prefixes.\\n- `000_combined.sql`, an idempotent bootstrap schema for new databases and selected upgrade paths.\\n- Schema evolution for conversations, sessions, isolation environments, workflows, observability, evaluations, user/product access control, UI replay, and related operational records.\\n\\nThere is no application code in this module. Its contract is the database schema: table names, column types, foreign keys, indexes, defaults, uniqueness rules, and data-preserving upgrade behavior.\\n\\n## Database assumptions\\n\\nThe schema targets PostgreSQL and relies on PostgreSQL-specific features:\\n\\n- `UUID` identifiers with `gen_random_uuid()`\\n- `JSONB` document columns and JSON operators\\n- Partial indexes, such as `WHERE status = 'running'`\\n- Expression indexes, such as `COALESCE(node_id, '')`\\n- `TIMESTAMP WITH TIME ZONE`\\n- `ON DELETE CASCADE` and `ON DELETE SET NULL` foreign-key actions\\n- `CREATE ... IF NOT EXISTS` and `ALTER TABLE ... ADD COLUMN IF NOT EXISTS` for rerunnable bootstrap/upgrade statements\\n\\nThe database must provide `gen_random_uuid()`, typically through the `pgcrypto` extension.\\n\\n## Migration execution model\\n\\n`schema_migrations` records applied filenames:\\n\\n```sql\\nCREATE TABLE IF NOT EXISTS schema_migrations (\\n  filename   TEXT PRIMARY KEY,\\n  applied_at TIMESTAMP WITH TIME ZONE DEFAULT NOW()\\n);\\n```\\n\\nThe comment in `000_combined.sql` establishes the intended runner behavior: a migration filename already present in `schema_migrations` is skipped.\\n\\n### Fresh database bootstrap\\n\\nFor a fresh installation, `000_combined.sql` creates a substantial base schema, applies compatibility `ALTER TABLE` statements, removes obsolete schema objects, and inserts migration filenames for migrations that are already baked into the combined schema.\\n\\nThis avoids replaying early non-idempotent migrations such as `001_initial_schema.sql`, whose plain `CREATE TABLE` statements would fail if the tables already exist.\\n\\n### Existing database upgrades\\n\\nExisting installations should apply incremental migrations in the project\u2019s migration-runner order. Incremental files describe the historical transition and may contain:\\n\\n- non-idempotent DDL;\\n- one-time data backfills;\\n- deduplication deletes before unique indexes are added;\\n- prerequisite comments that must be honored before destructive changes.\\n\\nDo not treat `000_combined.sql` as a replacement for every incremental migration without first checking whether the desired migration is baked into it and marked in `schema_migrations`.\\n\\n## Schema domains\\n\\n```mermaid\\nerDiagram\\n    remote_agent_users ||--o{ remote_agent_codebases : owns\\n    remote_agent_codebases ||--o{ remote_agent_conversations : selected_by\\n    remote_agent_conversations ||--o{ remote_agent_sessions : contains\\n    remote_agent_conversations ||--o{ remote_agent_messages : contains\\n    remote_agent_conversations ||--o{ remote_agent_workflow_runs : starts\\n    remote_agent_workflow_runs ||--o{ remote_agent_workflow_events : emits\\n    remote_agent_workflow_runs ||--o{ remote_agent_traces : observed_by\\n    remote_agent_traces ||--o{ remote_agent_trace_spans : contains\\n    remote_agent_traces ||--o{ remote_agent_trace_events : contains\\n```\\n\\nThe migrations broadly divide into the following domains:\\n\\n| Domain | Primary tables | Purpose |\\n|---|---|---|\\n| Core agent state | `remote_agent_codebases`, `remote_agent_conversations`, `remote_agent_sessions`, `remote_agent_messages` | Repository configuration and user/assistant conversation history |\\n| Isolation | `remote_agent_isolation_environments` | Worktree/container/VM-style working environments tied to work items |\\n| Workflow execution | `remote_agent_workflow_runs`, `remote_agent_workflow_events` | Workflow lifecycle, resumability, step-level UI events |\\n| Runtime observability | `remote_agent_traces`, `remote_agent_trace_spans`, `remote_agent_trace_events`, `remote_agent_error_details` | Request traces, nested operations, event timelines, diagnostics |\\n| Knowledge observability | `remote_agent_knowledge_retrievals`, `remote_agent_knowledge_context_uses`, `remote_agent_knowledge_sync_jobs` | Body-free retrieval, context injection, and export synchronization metrics |\\n| Evaluation and evolution | `remote_agent_*_evaluations`, `remote_agent_evaluation_golden_samples`, `remote_agent_human_feedback`, `remote_agent_evolution_*` | Derived quality judgments, objective datasets, and supervised improvement candidates |\\n| Identity and access | `remote_agent_users`, `remote_agent_user_workflows`, `remote_agent_user_settings`, product-space tables | Per-user data ownership and product-space membership |\\n| Workflow definitions | `remote_agent_workflows`, `remote_agent_workflow_definition_versions`, `remote_agent_workflow_version_snapshots`, `remote_agent_workflow_models` | Shared workflow storage, immutable versions, execution snapshots, model catalog |\\n| Operations | `remote_agent_ugate_tokens`, UI replay tables, alert tables, sandbox tables | Tokens, quality/replay artifacts, alerting, and sandbox records |\\n\\n## Core agent state\\n\\n### `remote_agent_codebases`\\n\\nStores repository-level configuration:\\n\\n- Repository identity: `name`, `repository_url`, `default_cwd`\\n- Assistant selection: `ai_assistant_type`\\n- Command configuration: `commands JSONB`\\n- Environment safety control: `allow_env_keys BOOLEAN NOT NULL DEFAULT FALSE`\\n- Ownership and product-space association added by later migrations: `owner_user_id`, `product_id`\\n\\n`remote_agent_codebase_env_vars` is a child table with a unique `(codebase_id, key)` constraint. Its values are documented as inputs merged into `Options.env` on Claude SDK calls.\\n\\nBecause values are stored in plaintext `TEXT`, this table must be protected like other credentials/configuration storage. Migration `020_codebase_env_vars.sql` explicitly notes that it does not encrypt values.\\n\\n### `remote_agent_conversations`\\n\\nMaps an external platform conversation to agent state through:\\n\\n```sql\\nUNIQUE(platform_type, platform_conversation_id)\\n```\\n\\nImportant fields include:\\n\\n- `codebase_id`: selected repository; `ON DELETE SET NULL`\\n- `cwd`: active working directory\\n- `ai_assistant_type`\\n- `isolation_env_id`: the current `remote_agent_isolation_environments` record\\n- `title`, `hidden`, and `deleted_at`: UI presentation and soft deletion\\n- `last_activity_at`: activity/staleness tracking\\n- `owner_user_id`: per-user isolation\\n- `combo_id`: optional multi-codebase combo association, added by `023_codebase_combos.sql`\\n\\nThe isolation model intentionally evolved away from storing worktree paths directly on conversations. The final model uses `isolation_env_id` as the sole isolation reference.\\n\\n### `remote_agent_sessions`\\n\\nSessions represent assistant-session lifecycles within conversations.\\n\\nThe original active-session design was expanded into an audit chain:\\n\\n- `parent_session_id` links a replacement session to the preceding session.\\n- `transition_reason` records why a new session began.\\n- `ended_reason` records why an old session ended.\\n- `active`, `started_at`, and `ended_at` represent session lifecycle state.\\n\\nIndexes support finding an active session for a conversation and traversing historical chains in reverse chronological order.\\n\\n### `remote_agent_messages`\\n\\nStores persisted conversation messages in chronological order:\\n\\n```sql\\nCREATE INDEX idx_messages_conversation_id\\n  ON remote_agent_messages(conversation_id, created_at ASC);\\n```\\n\\nIt includes:\\n\\n- `role`\\n- `content`\\n- `metadata JSONB`\\n- `mode`, defaulting to `'normal'`\\n- `knowledge_conversation_id`\\n\\nMigration `037_messages_created_at_timestamptz.sql` converts `created_at` from timestamp-without-time-zone to `TIMESTAMP WITH TIME ZONE`, interpreting historical values in `Asia/Shanghai` to correct an observed UTC display shift.\\n\\n## Isolation environment lifecycle\\n\\n`remote_agent_isolation_environments` separates a work environment\u2019s lifecycle from a conversation\u2019s lifecycle.\\n\\nAn environment is identified by:\\n\\n- `codebase_id`\\n- `workflow_type`, such as `issue`, `pr`, `review`, `thread`, or `task`\\n- `workflow_id`\\n- `provider`, defaulting to `worktree`\\n- `working_path`\\n- `branch_name`\\n- `status`, typically `active` or `destroyed`\\n\\nThe active-only uniqueness rule is important:\\n\\n```sql\\nCREATE UNIQUE INDEX unique_active_workflow\\n  ON remote_agent_isolation_environments (codebase_id, workflow_type, workflow_id)\\n  WHERE status = 'active';\\n```\\n\\nThis permits a destroyed environment to remain in history while allowing a new active environment for the same work item.\\n\\n### Historical migration path\\n\\nThe isolation migrations should be read as one transition:\\n\\n1. `003_add_worktree.sql` added `worktree_path` to conversations.\\n2. `005_isolation_abstraction.sql` added provider-neutral `isolation_env_id` and `isolation_provider`, initially retaining the old path.\\n3. `006_isolation_environments.sql` introduced `remote_agent_isolation_environments`, renamed the old string `isolation_env_id` to `isolation_env_id_legacy` when necessary, and added the new UUID foreign key.\\n4. `007_drop_legacy_columns.sql` removed `worktree_path`, `isolation_env_id_legacy`, and `isolation_provider`.\\n\\nBefore applying `007_drop_legacy_columns.sql` independently, run its supplied verification query. The migration is destructive and assumes all legacy values have corresponding `isolation_env_id` values.\\n\\n## Workflow execution and history\\n\\n### `remote_agent_workflow_runs`\\n\\nA workflow run connects a workflow invocation to its conversation, codebase, owner, and execution state.\\n\\nKey execution fields:\\n\\n- `workflow_name`\\n- `conversation_id`\\n- `parent_conversation_id` for background-dispatched child workflows\\n- `codebase_id`\\n- `working_path` for branch/worktree-aware resume detection\\n- `current_step_index`\\n- `status`, defaulting to `'pending'`\\n- `user_message`\\n- `metadata JSONB`\\n- `started_at`, `original_started_at`, `completed_at`, and `last_activity_at`\\n- `current_iteration` and `loop_back_cursor` for iterative workflow state\\n\\n`018_fix_workflow_status_default.sql` is semantically significant: run creation starts as `pending`, after which the executor explicitly changes it to `running`. New writes should not assume that a newly inserted row is already running.\\n\\nHistorical-run governance fields support retaining failures without deleting audit records:\\n\\n- `run_quality_scope`, defaulting to `'current'`\\n- `failure_classification`\\n- `archived_at`\\n- `archived_reason`\\n\\nThe partial `last_activity_at` index applies only to rows whose status is `running`, supporting efficient stale-run detection.\\n\\nLater access-control migrations add:\\n\\n- `owner_user_id`\\n- `workflow_record_id`, referencing `remote_agent_workflows`\\n- `product_id`\\n\\n### `remote_agent_workflow_events`\\n\\nWorkflow events hold lean, UI-relevant facts such as step transitions, artifacts, errors, and parallel-agent status. Detailed assistant and tool payloads are intentionally kept out of this table; the migration comments direct verbose logs to JSONL files under:\\n\\n```text\\n{cwd}/.archon/logs/{runId}.jsonl\\n```\\n\\nEvents cascade-delete with their parent workflow run.\\n\\n## Runtime tracing and alerts\\n\\n### Trace hierarchy\\n\\nThe runtime observability model is append-oriented:\\n\\n- `remote_agent_traces`: one high-level request or workflow trace\\n- `remote_agent_trace_spans`: timed nested operations within a trace\\n- `remote_agent_trace_events`: factual timeline events associated with traces or spans\\n- `remote_agent_error_details`: extended error diagnostics\\n\\nA trace can reference a conversation, root message, session, codebase, and workflow run. Spans form a tree through `parent_span_id`. Events can reference the trace, a span, and contextual identifiers such as a workflow node, provider, model, tool, or skill.\\n\\nTrace payload columns are deliberately previews rather than full raw prompts or tool calls:\\n\\n- `input_preview`\\n- `output_preview`\\n- `metadata`\\n- span `attributes`\\n- event `data`\\n\\nThe migration comments require sensitive data to be redacted before persistence.\\n\\n### Trace schema compatibility\\n\\n`remote_agent_traces.schema_version` records the trace shape. `remote_agent_trace_schema_migrations` audits transformations between versions with:\\n\\n- `from_schema_version`\\n- `to_schema_version`\\n- `reason`\\n- `migrated_fields`\\n- `metadata`\\n\\nSeveral migrations repeat `ADD COLUMN IF NOT EXISTS` statements for trace tables. This is intentional compatibility backfill support for databases created while the tracing schema was incomplete.\\n\\n### Alerts\\n\\n`remote_agent_trace_alert_rules` defines configurable thresholds, windows, severity, cooldowns, and delivery targets.\\n\\n`remote_agent_trace_alerts` stores deduplicated alert state. `dedupe_key` is unique, so writers should update the existing alert\u2019s `last_seen_at` and `occurrence_count` rather than creating a duplicate.\\n\\n`026_runtime_trace_issue_id.sql` adds a stable `issue_id` and backfills existing alerts:\\n\\n1. Uses `dedupe_key` when it begins with `issue:`.\\n2. Otherwise assigns `issue:`.\\n\\nThis makes health issues cluster consistently across alerts and downstream intelligence.\\n\\n## Knowledge observability\\n\\nThe knowledge tables are intentionally body-free: they record metadata and measurements rather than retrieved document content or query text.\\n\\n### `remote_agent_knowledge_retrievals`\\n\\nTracks individual retrieval/tool calls. Its uniqueness constraint:\\n\\n```sql\\nUNIQUE (workflow_run_id, node_id, tool_call_id)\\n```\\n\\nmakes repeated writes for the same call detectable. Fields cover lifecycle status, latency, tool identity, result counts, cache behavior, query fingerprints, and gateway usage/cost.\\n\\n### `remote_agent_knowledge_context_uses`\\n\\nRecords how retrieved knowledge was injected into model context, including:\\n\\n- context kind and source\\n- injected character count\\n- total prompt character count\\n- estimated knowledge input tokens\\n\\nThe uniqueness key is scoped to one model attempt and contextual field:\\n\\n```sql\\nUNIQUE (\\n  workflow_run_id,\\n  model_attempt_id,\\n  context_kind,\\n  source_node_id,\\n  field_name\\n)\\n```\\n\\n### `remote_agent_knowledge_sync_jobs`\\n\\nTracks export/synchronization of workflow knowledge to an external service. It has both a globally unique `idempotency_key` and a per-run/export-version uniqueness constraint. Use these keys to make dispatch and reconciliation retry-safe.\\n\\n## Evaluations and supervised evolution\\n\\nThe evaluation migrations maintain derived judgments separately from factual trace records.\\n\\n### Evaluation tables\\n\\n- `remote_agent_workflow_evaluations`\\n- `remote_agent_node_evaluations`\\n- `remote_agent_skill_evaluations`\\n\\nEach references a workflow run and may reference trace/span data. They store evaluator identity, score, status, metrics, signals, and findings.\\n\\n`028_dedupe_workflow_evaluations.sql` removes historical duplicates, retaining the newest row per logical key, then creates unique expression/index constraints:\\n\\n- workflow: `(workflow_run_id, evaluator_type)`\\n- node: `(workflow_run_id, node_id, evaluator_type)`\\n- skill: `(workflow_run_id, COALESCE(node_id, ''), skill_name, evaluator_type)`\\n\\nAfter this migration, evaluation writers should use an upsert pattern compatible with these keys.\\n\\n### Objective and human data\\n\\n`030_evaluation_objective_datasets.sql` adds:\\n\\n- `remote_agent_evaluation_golden_samples`: expected answers, reference contexts, and expected tools\\n- `remote_agent_human_feedback`: ratings, labels, comments, and metadata tied to workflow runs/traces\\n\\nGolden samples use a uniqueness expression that treats nullable version/node/skill fields as empty strings. Writers must use the same normalization when identifying a logical sample.\\n\\n### Evolution records\\n\\n`remote_agent_evolution_candidates` stores proposed workflow, node, or skill changes. Candidates are recommendations only; they do not directly mutate definitions. Active candidate uniqueness prevents multiple simultaneous recommendations for the same `(workflow_run_id, scope, target_key)`.\\n\\n`remote_agent_evolution_experiments` records supervised evaluation of a candidate.\\n\\n## Identity, ownership, and product spaces\\n\\n### Users and personal ownership\\n\\n`remote_agent_users` stores UUAP-authenticated users. `001_user_isolation.sql` adds:\\n\\n```sql\\nrole TEXT NOT NULL DEFAULT 'user'\\nCHECK (role IN ('admin', 'user'))\\n```\\n\\nIt also adds nullable `owner_user_id` foreign keys to codebases, conversations, and workflow runs. `ON DELETE SET NULL` preserves records if a user row is removed, while `remote_agent_user_workflows` and `remote_agent_user_settings` use `ON DELETE CASCADE` because they are user-owned configuration.\\n\\n### Product spaces\\n\\n`002_product_spaces.sql` introduces:\\n\\n- `remote_agent_product_spaces`\\n- `remote_agent_product_members`\\n- `remote_agent_uic_groups`\\n\\nProduct membership roles are constrained to `admin`, `product_admin`, and `member`. UIC groups persist an email-group snapshot in `member_snapshot JSONB`.\\n\\n`042_personal_space.sql` adds `is_personal`, documented as supporting lazily created personal spaces.\\n\\n### Shared codebases, combos, and workflows\\n\\nLater migrations extend product-space support:\\n\\n- `035_space_codebases.sql` adds `product_id` to codebases and combos.\\n- `023_codebase_combos.sql` adds `remote_agent_combos` and `remote_agent_combo_codebases`, plus `remote_agent_conversations.combo_id`.\\n- `032_workflows_product_space.sql` creates `remote_agent_workflows` with `system` and `product` scopes.\\n- `043_workflow_project_source.sql` adds `codebase_id` and `source_type` to workflows.\\n\\n`remote_agent_workflows` uses check constraints to enforce its scope contract:\\n\\n- `scope = 'product'` requires `product_id`.\\n- `scope = 'system'` forbids `product_id`.\\n\\nPartial unique indexes keep system workflow names globally unique while product workflow names are unique only inside their product space.\\n\\n## Workflow versions and selectable models\\n\\n`remote_agent_workflow_version_snapshots` stores the exact workflow definition snapshot used by a workflow run. It has one snapshot per run through the unique `workflow_run_id` index.\\n\\n`remote_agent_workflow_definition_versions` stores immutable definition history for manual changes, evolution promotions, and rollbacks. The active workflow definition remains in its primary workflow storage; version rows provide history.\\n\\n`052_workflow_models.sql` defines `remote_agent_workflow_models`, the database-backed source for selectable workflow models. It seeds named model records with provider tags, multimodal capability, context window, cost multiplier, ordering, and enablement state:\\n\\n```sql\\nINSERT INTO remote_agent_workflow_models (...) VALUES (...)\\nON CONFLICT (model_id) DO NOTHING;\\n```\\n\\nThe conflict behavior preserves local changes and prevents seed updates from overwriting existing model rows. If model metadata needs to be updated for existing installations, a future migration must explicitly issue `UPDATE` statements.\\n\\n## Other operational schema\\n\\n| Migration | Tables / changes | Role |\\n|---|---|---|\\n| `022_ugate_tokens.sql` | `remote_agent_ugate_tokens` | Persistent per-user ugate tokens, synchronized to local UUAP configuration on startup |\\n| `024_ugate_token_icafe_space.sql` | `ic\",\"other-mock\":\"# Other \u2014 mock\\n\\n# Other \u2014 mock\\n\\n## Overview\\n\\nThe `docs/mock` module contains mock issue specifications used to describe product and engineering work. These files are JSON fixtures rather than executable application code. They do not define runtime functions, classes, components, or API calls.\\n\\nThe module currently documents two workflow-related changes:\\n\\n1. Adding a static `\u4ea7\u54c1\u7a7a\u95f4` label beside the `\u5168\u90e8\uff08\u7cfb\u7edf\u5185\u7f6e\uff09` product-space selector on the workflow page.\\n2. Replacing the `WorkflowInvoker` single-line text input with a multiline `` supporting `Shift+Enter` line breaks.\\n\\nBecause this module contains issue data only:\\n\\n- It has no internal function calls.\\n- It has no outgoing calls.\\n- It has no incoming calls.\\n- It has no detected execution flows.\\n- The referenced implementation lives elsewhere in the codebase, especially under `packages/web/src/components/sidebar/`.\\n\\n## Files\\n\\n### `\u5de5\u4f5c\u6d41\u4ea7\u54c1\u7a7a\u95f4\u6807\u7b7e-issue.json`\\n\\nDescribes the workflow-page filter-label change.\\n\\n### `\u5de5\u4f5c\u6d41\u5bf9\u8bdd\u6846\u652f\u6301\u6362\u884c-issue.json`\\n\\nDescribes the `WorkflowInvoker` multiline-input change and its associated test coverage.\\n\\nBoth files use the same top-level structure:\\n\\n```json\\n{\\n  \\\"issues\\\": [\\n    {\\n      \\\"id\\\": \\\"issue-1\\\",\\n      \\\"title\\\": \\\"...\\\",\\n      \\\"what_to_build\\\": \\\"...\\\",\\n      \\\"acceptance_criteria\\\": [],\\n      \\\"blocked_by\\\": [],\\n      \\\"type\\\": \\\"AFK\\\",\\n      \\\"done\\\": false,\\n      \\\"test_cases\\\": []\\n    }\\n  ]\\n}\\n```\\n\\n## Issue schema\\n\\nEach issue entry contains the following fields:\\n\\n| Field | Description |\\n| --- | --- |\\n| `id` | Identifier for the issue, currently `issue-1`. |\\n| `title` | Short description of the requested change. |\\n| `what_to_build` | Implementation-oriented requirements and target files. |\\n| `acceptance_criteria` | Behavioral and structural conditions required for completion. |\\n| `blocked_by` | IDs of issues that must be completed first. Both current issues have no blockers. |\\n| `type` | Work classification. Both issues use `AFK`. |\\n| `done` | Completion status. Both current issues are marked `false`. |\\n| `test_cases` | Manual, automated, review, regression, and pre-production verification steps. |\\n\\nEach test case includes:\\n\\n| Field | Description |\\n| --- | --- |\\n| `id` | Stable test identifier, such as `UI-SHIFT-ENTER-001`. |\\n| `title` | Human-readable test name. |\\n| `priority` | Test priority, primarily `P0` or `P1`. |\\n| `precondition` | Required setup before executing the test. |\\n| `steps` | Ordered execution instructions. |\\n| `expected_result` | Required outcome. |\\n| `type` | Test category, such as `unit`, `ui`, `scenario`, or `preprod_ui`. |\\n| `info` | Additional test context. |\\n| `feature_point` | Capability or behavior covered by the test. |\\n\\n## Issue: workflow product-space label\\n\\nThe `\u5de5\u4f5c\u6d41\u4ea7\u54c1\u7a7a\u95f4\u6807\u7b7e-issue.json` issue requests a static label immediately to the left of the `\u5168\u90e8\uff08\u7cfb\u7edf\u5185\u7f6e\uff09` dropdown in the workflow page\u2019s top filter area.\\n\\n### Required behavior\\n\\nThe implementation must:\\n\\n- Render the text `\u4ea7\u54c1\u7a7a\u95f4` directly before the `\u5168\u90e8\uff08\u7cfb\u7edf\u5185\u7f6e\uff09` dropdown.\\n- Reuse the visual styling of existing filter labels, including font size, color, and line height.\\n- Leave the dropdown\u2019s selection and switching behavior unchanged.\\n- Treat `\u4ea7\u54c1\u7a7a\u95f4` as display-only text with no click interaction.\\n\\nThe requested change is intentionally narrow. The code-review test `CR-SPACE-LABEL-001` specifically requires that the diff:\\n\\n- Be limited to the workflow-page filter-area component.\\n- Add a static text node.\\n- Place the node before the dropdown in DOM order.\\n- Reuse an existing `className` or inline style convention.\\n- Avoid changing the dropdown\u2019s `onChange`, `value`, or related behavior.\\n\\n### Verification coverage\\n\\nThe issue includes the following validation layers:\\n\\n- **Code review**: confirms placement, styling reuse, and zero dropdown-logic changes.\\n- **UI test**: verifies that a `\u4ea7\u54c1\u7a7a\u95f4` text node exists before the `\u5168\u90e8\uff08\u7cfb\u7edf\u5185\u7f6e\uff09` dropdown.\\n- **UI regression test**: verifies that selecting a different dropdown option still triggers `onChange` and leaves the label unchanged.\\n- **Pre-production UI acceptance**: confirms visual consistency and the absence of click behavior.\\n- **Pre-production regression**: confirms that product-space filtering continues to work.\\n\\n## Issue: multiline `WorkflowInvoker` input\\n\\nThe `\u5de5\u4f5c\u6d41\u5bf9\u8bdd\u6846\u652f\u6301\u6362\u884c-issue.json` issue targets:\\n\\n```text\\npackages/web/src/components/sidebar/WorkflowInvoker.tsx\\n```\\n\\nIt requests replacing the current:\\n\\n```tsx\\n\\n```\\n\\nwith a `` that supports multiline workflow messages.\\n\\nThe issue also requires a new test file:\\n\\n```text\\npackages/web/src/components/sidebar/WorkflowInvoker.test.tsx\\n```\\n\\n### Keyboard behavior\\n\\nThe requested keyboard behavior is based on the existing exported function:\\n\\n```text\\nshouldTriggerSend(key, shiftKey, isComposing)\\n```\\n\\n`WorkflowInvoker` should reuse this function rather than introducing duplicate inline keyboard logic.\\n\\nExpected behavior:\\n\\n| Key state | Result |\\n| --- | --- |\\n| `Enter`, no `Shift`, not composing | Send the message. Call `preventDefault()`. |\\n| `Shift+Enter`, not composing | Insert a newline. Do not send. |\\n| `Enter` while `isComposing=true` | Do not send; allow IME candidate confirmation. |\\n| `Shift+Enter` while composing | Do not send. |\\n| Any non-Enter key | Do not send. |\\n\\nThe existing unit tests for `shouldTriggerSend` are located at:\\n\\n```text\\npackages/web/src/components/chat/MessageInput.test.tsx\\n```\\n\\nThe issue treats these tests as reusable coverage for the shared keyboard rule, including:\\n\\n- Enter sends.\\n- Shift+Enter does not send.\\n- Enter during IME composition does not send.\\n- Shift+Enter during IME composition does not send.\\n- Non-Enter keys do not send.\\n\\n### Automatic height behavior\\n\\nThe textarea\u2019s `onChange` handler must resize the control based on `scrollHeight`:\\n\\n- Reset the height before measuring so the control can shrink after content is removed.\\n- Expand automatically as content grows.\\n- Cap the height at `200px`.\\n- Set vertical overflow to `auto` when content exceeds the cap.\\n- Disable manual resizing with:\\n\\n```css\\nresize: none;\\n```\\n\\nThe requested behavior can be represented conceptually as:\\n\\n```text\\nheight = min(scrollHeight, 200px)\\noverflowY = scrollHeight &gt; 200px ? auto : hidden\\n```\\n\\nThe exact implementation should follow the component\u2019s existing styling conventions.\\n\\n### Send and reset behavior\\n\\nAfter a successful send:\\n\\n- Call the existing workflow execution path through `handleRun`.\\n- Pass the complete message, including embedded newline characters, to `runWorkflow`.\\n- Clear the input with:\\n\\n```text\\nsetMessage('')\\n```\\n\\n- Reset the textarea height to `auto`.\\n\\nThe reset is required so that a previously expanded multiline textarea returns to its initial height after sending.\\n\\n### Message preservation\\n\\nNewline characters must remain intact throughout the input and send flow. For example:\\n\\n```text\\n\u7b2c\u4e00\u884c\\n\u7b2c\u4e8c\u884c\\n\u7b2c\u4e09\u884c\\n```\\n\\nmust be passed to `runWorkflow` with the intervening `\\\\n` characters preserved.\\n\\nA `Shift+Enter` at the cursor position must split the existing value without discarding the text after the cursor. The issue explicitly verifies this with:\\n\\n```text\\nhello world\\n```\\n\\nwhere the cursor is positioned after `hello`, producing:\\n\\n```text\\nhello\\n world\\n```\\n\\n## Test coverage for `WorkflowInvoker`\\n\\nThe requested `WorkflowInvoker.test.tsx` coverage includes:\\n\\n### Element rendering\\n\\nThe component must render:\\n\\n- A ``.\\n- No `input[type=\\\"text\\\"]`.\\n\\nThe test setup requires a selected workflow and a mocked `listWorkflows` response containing at least one workflow.\\n\\n### Automatic resizing\\n\\nThe UI tests simulate multiline input and inspect the textarea styles:\\n\\n- Height must not exceed `200px`.\\n- `overflowY` must become `auto` when content exceeds the height limit.\\n\\n### Enter and Shift+Enter\\n\\nThe tests verify that:\\n\\n- Enter invokes the workflow execution path once.\\n- `preventDefault()` is called for send behavior.\\n- Shift+Enter does not invoke `runWorkflow`.\\n- Shift+Enter preserves the newline in the textarea value.\\n\\n### Multiline end-to-end scenario\\n\\nThe scenario tests cover:\\n\\n1. Entering a first line.\\n2. Pressing `Shift+Enter`.\\n3. Entering a second line.\\n4. Pressing `Shift+Enter` again.\\n5. Entering a third line.\\n6. Pressing Enter to send.\\n7. Verifying that `runWorkflow` receives all three lines.\\n8. Verifying that the textarea is cleared afterward.\\n\\n### IME compatibility\\n\\nPre-production coverage validates Chinese input-method behavior:\\n\\n- Pressing Enter while an IME composition is active must not send the workflow message.\\n- After the candidate is committed, pressing Enter must send normally.\\n\\nThis protection is important because replacing `` with `` changes the browser\u2019s default Enter behavior and could otherwise cause accidental sends during candidate selection.\\n\\n## Relationship to the application code\\n\\nThe mock files describe changes to application components but do not import or invoke them.\\n\\nThe relevant code relationships are specified by the issue content:\\n\\n```text\\nWorkflowInvoker.tsx\\n  \u251c\u2500 uses shouldTriggerSend(...)\\n  \u251c\u2500 maintains message state\\n  \u251c\u2500 calls handleRun\\n  \u2514\u2500 sends messages through runWorkflow\\n\\nMessageInput.test.tsx\\n  \u2514\u2500 verifies shouldTriggerSend(...)\\n```\\n\\nThe product-space label issue similarly identifies a workflow-page filter component, but the mock does not specify its source path or component name. Contributors should locate the existing rendering site for the `\u5168\u90e8\uff08\u7cfb\u7edf\u5185\u7f6e\uff09` dropdown and reuse its established label styles.\\n\\n## Contribution guidance\\n\\nWhen implementing work described by these fixtures:\\n\\n1. Treat `what_to_build` as the implementation scope.\\n2. Preserve existing component behavior unless an acceptance criterion explicitly changes it.\\n3. Reuse existing styling and shared keyboard helpers rather than adding duplicate conventions.\\n4. Update or add tests at the paths named in the issue.\\n5. Validate both DOM structure and behavior; the acceptance criteria distinguish between rendering, keyboard interaction, and workflow execution.\\n6. Run the existing keyboard unit tests:\\n\\n   ```bash\\n   bun test packages/web/src/components/chat/MessageInput.test.tsx\\n   ```\\n\\n7. Include regression coverage for both single-line sending and multiline message delivery.\\n8. Keep the mock issue status synchronized by changing `done` only after the implementation and required verification are complete.\",\"other-package-json\":\"# Other \u2014 package.json\\n\\n# `package.json`\\n\\nThe repository root `package.json` defines the Archon monorepo, its Bun-based development workflow, shared tooling, dependency policy, and validation commands. It is a private package and is not intended to be published as an npm package.\\n\\n## Package metadata\\n\\n| Field | Value | Purpose |\\n|---|---|---|\\n| `name` | `archon` | Root project name |\\n| `version` | `0.3.10` | Repository version |\\n| `private` | `true` | Prevents accidental publication |\\n| `type` | `module` | Treats JavaScript files as ES modules |\\n| `engines.bun` | `^1.3.0` | Declares the supported Bun version |\\n| `workspaces` | `packages/*` | Includes every package directory under `packages/` |\\n\\nThe repository uses Bun workspaces. Workspace packages are addressed by their package names, such as `@archon/server`, `@archon/web`, and `@archon/docs-web`, through Bun\u2019s `--filter` option.\\n\\n## Workspace and execution model\\n\\nMost scripts execute commands through Bun:\\n\\n```sh\\nbun --filter  \\nbun --filter '*' \\n```\\n\\nThe wildcard form runs a matching script across workspace packages. For example:\\n\\n```sh\\nbun --filter '*' dev\\nbun --filter '*' build\\nbun --filter '*' --parallel test\\n```\\n\\nThe root manifest also exposes direct entry points for selected packages:\\n\\n```sh\\nbun --cwd packages/cli src/cli.ts\\nbun --filter @archon/server start\\nbun --filter @archon/web dev\\nbun --filter @archon/docs-web dev\\n```\\n\\nBecause the root package is marked `private`, it primarily acts as an orchestration layer. Runtime behavior is implemented by the packages in `packages/*`; this manifest coordinates their development, build, test, and quality workflows.\\n\\n## Development and application commands\\n\\n| Script | Description |\\n|---|---|\\n| `cli` | Runs the CLI entry point at `packages/cli/src/cli.ts`. |\\n| `dev` | Runs the `dev` script in all workspace packages. |\\n| `dev:server` | Starts development mode for `@archon/server`. |\\n| `start` | Starts `@archon/server`. |\\n| `build` | Runs the `build` script in all workspace packages. |\\n| `build:binaries` | Executes `scripts/build-binaries.sh` to build binaries. |\\n| `build:checksums` | Executes `scripts/checksums.sh` to generate checksums. |\\n| `dev:web` / `build:web` | Runs development or production build mode for `@archon/web`. |\\n| `dev:docs` / `build:docs` | Runs development or production build mode for `@archon/docs-web`. |\\n| `setup-auth` | Runs the `setup-auth` script defined by `@archon/server`. |\\n\\nThe shell-based binary and checksum commands require a shell environment capable of running the scripts in `scripts/`.\\n\\n## Generated and bundled artifacts\\n\\nThe repository maintains generated bundled defaults and workflow syntax documentation:\\n\\n| Script | Description |\\n|---|---|\\n| `generate:bundled` | Runs `scripts/generate-bundled-defaults.ts`. |\\n| `check:bundled` | Regenerates bundled defaults in check mode. |\\n| `gen:workflow-syntax` | Runs `scripts/gen-workflow-syntax-doc.ts`. |\\n| `check:bundled-skill` | Validates bundled skill content using `scripts/check-bundled-skill.ts --check`. |\\n\\n`check:bundled` and `check:bundled-skill` are included in the top-level `validate` workflow, so generated artifacts must be synchronized with their source definitions before validation passes.\\n\\n## Testing commands\\n\\n### General workspace tests\\n\\n| Script | Description |\\n|---|---|\\n| `test` | Runs every workspace package\u2019s `test` script in parallel. |\\n| `test:sequential` | Tests the listed packages one at a time and prints a warning when a package test fails. |\\n| `test:watch` | Runs the server package\u2019s watch-mode tests. |\\n| `test:affected` | Delegates affected-package selection to `scripts/select-affected.ts --run`. |\\n| `test:coverage` | Runs coverage collection through `scripts/run-coverage.ts`. |\\n| `coverage:report` | Generates or evaluates a coverage report through `scripts/coverage-gate.ts`. |\\n| `coverage:gate` | Enforces line, function, and diff coverage thresholds. |\\n\\nThe sequential test command explicitly targets:\\n\\n```text\\nadapters auth cli core git isolation paths providers server web workflows\\n```\\n\\nIt is useful when parallel test execution makes failures difficult to isolate. Its shell loop continues after an individual package failure and emits a warning rather than immediately terminating.\\n\\n### API, end-to-end, and scenario tests\\n\\n| Script | Description |\\n|---|---|\\n| `test:api` | Runs `@archon/server`\u2019s `test:api` script. |\\n| `test:api:routes` | Runs server API route tests. |\\n| `test:api:scenario` | Runs server API scenario tests. |\\n| `test:e2e` | Runs `@archon/web` end-to-end tests. |\\n| `test:e2e:record` | Runs the web package\u2019s end-to-end recording workflow. |\\n| `test:e2e:ui` | Runs the web package\u2019s UI test mode. |\\n| `test:e2e:scaffold` | Runs `scripts/ui-replay-scaffold.ts`. |\\n| `test:aiflow:scenario` | Executes AI-flow scenario cases through `scripts/run-aiflow-scenario-cases.sh --stage dev`. |\\n| `eval:ragas:stress` | Runs the RAGAS stress evaluation script. |\\n\\nThese commands keep package-specific test implementation in the owning workspace while providing convenient root-level entry points.\\n\\n## Type checking, linting, and formatting\\n\\n| Script | Description |\\n|---|---|\\n| `type-check` | Runs each workspace\u2019s `type-check` script and then type-checks the scripts project with `tsc --noEmit -p scripts/tsconfig.json`. |\\n| `lint` | Runs ESLint over the repository with an 8 GB Node heap limit and caching enabled. |\\n| `lint:fix` | Runs the same ESLint command with automatic fixes enabled. |\\n| `format` | Formats the repository with Prettier. |\\n| `format:check` | Checks formatting without modifying files. |\\n\\nThe explicit heap size in the ESLint commands is intended to support linting the full monorepo.\\n\\n## Validation and quality gates\\n\\nThe primary repository-wide validation command is:\\n\\n```sh\\nbun run validate\\n```\\n\\nIt runs the following checks in order:\\n\\n```text\\ncheck:bundled\\ncheck:bundled-skill\\ntype-check\\nlint --max-warnings 0\\nformat:check\\ntest\\n```\\n\\n`validate` therefore checks generated content, TypeScript correctness, lint cleanliness, formatting, and all workspace tests.\\n\\nSecurity and coverage are handled by a separate quality gate:\\n\\n```sh\\nbun run quality:gate\\n```\\n\\nThis invokes:\\n\\n```text\\nsecurity:secrets\\ntest:coverage\\ncoverage:gate\\n```\\n\\nThe configured coverage thresholds are:\\n\\n- Minimum line coverage: `90`\\n- Minimum function coverage: `90`\\n- Minimum changed-line/diff coverage: `80`\\n\\nAdditional security and reporting commands include:\\n\\n| Script | Description |\\n|---|---|\\n| `security:secrets` | Runs `scripts/security-secrets.sh`. |\\n| `security:audit` | Runs `bun audit` and fails for vulnerabilities at the `high` level or above. |\\n| `quality:report` | Generates a quality report through `scripts/quality-report.ts`. |\\n| `report` | Generates an Allure report and serves it on port `64965`. |\\n| `validate:api` | Alias for `test:api`. |\\n\\n## Dependency configuration\\n\\n### Development dependencies\\n\\nThe root development dependencies provide shared repository tooling:\\n\\n- **Bun and TypeScript support:** `@types/bun`, `bun-types`, `typescript`\\n- **Linting:** `eslint`, `@eslint/js`, `typescript-eslint`, `eslint-config-prettier`\\n- **Formatting:** `prettier`\\n- **Testing and reporting:** `allure-bun`, `allure-commandline`, `allure-js-commons`\\n- **Git hooks:** `husky`, `lint-staged`\\n- **Logging support:** `pino-pretty`\\n\\nThese dependencies support root-level scripts and may also be available to workspace packages through the Bun workspace installation.\\n\\n### Runtime dependencies\\n\\nThe root package declares the following dependencies:\\n\\n- `@anthropic-ai/claude-agent-sdk`\\n- `@codemirror/lang-yaml`\\n- `@uiw/codemirror-theme-vscode`\\n- `@uiw/react-codemirror`\\n- `web`\\n- `yaml`\\n\\nThe manifest does not define runtime entry points for the root package. These dependencies are available to the repository\u2019s workspace installation and are consumed by package code where imported.\\n\\n### Dependency overrides\\n\\nThe `overrides` section forces repository-wide versions for selected transitive dependencies:\\n\\n```json\\n{\\n  \\\"test-exclude\\\": \\\"^7.0.1\\\",\\n  \\\"axios\\\": \\\"^1.15.0\\\",\\n  \\\"follow-redirects\\\": \\\"^1.16.0\\\",\\n  \\\"path-to-regexp\\\": \\\"^8.4.2\\\",\\n  \\\"qs\\\": \\\"^6.15.1\\\",\\n  \\\"flatted\\\": \\\"^3.4.2\\\",\\n  \\\"@hono/node-server\\\": \\\"^1.19.13\\\"\\n}\\n```\\n\\nOverrides ensure that dependency resolution uses the specified versions even when workspace or transitive packages request different compatible ranges. Changes to this section can affect multiple packages and should be validated with testing and security audit commands.\\n\\n## Git hooks and installation lifecycle\\n\\nThe `prepare` lifecycle script runs:\\n\\n```sh\\nhusky\\n```\\n\\nThis initializes Husky hooks after dependency installation. Hook behavior is configured outside this manifest.\\n\\n## Allure reporting\\n\\nThe `report` command expects test results in `allure-results`:\\n\\n```sh\\nbunx allure generate allure-results --clean -o allure-report\\nopen http://localhost:64965\\nbunx --bun serve allure-report -p 64965\\n```\\n\\nIt generates the static report in `allure-report`, opens the report URL, and serves the generated files on port `64965`. The `open` command assumes a platform that provides the standard `open` utility.\\n\\n## Contribution guidance\\n\\nWhen adding or changing a root script:\\n\\n1. Prefer delegating package-specific behavior to a workspace script through `bun --filter`.\\n2. Keep repository-wide orchestration in the root manifest or `scripts/`.\\n3. Update `validate` when a new required consistency check is introduced.\\n4. Run at least `bun run type-check`, `bun run lint`, `bun run format:check`, and the relevant test command.\\n5. Run `bun run security:audit` when changing dependencies or overrides.\\n6. Preserve the Bun engine requirement and ES module configuration unless the workspace execution model is intentionally changed.\",\"other-parallel-study\":\"# Other \u2014 parallel-study\\n\\n# Other \u2014 `parallel-study`\\n\\n## Purpose\\n\\nThe `parallel-study` module contains structured implementation studies for independent feature areas. Each study is represented by an `issues.json` file containing a dependency-ordered set of proposed work items.\\n\\nThis module is planning and coordination data rather than executable application code:\\n\\n- It contains no functions, classes, or runtime entry points.\\n- It has no internal or outgoing call graph.\\n- No execution flows were detected.\\n- The referenced APIs and components belong to other parts of the codebase and are intended to be reused by future implementation work.\\n\\nThe studies focus on three areas:\\n\\n1. Adding pause and resume support to the sidebar workflow-run UI.\\n2. Adding editing support to combo definitions.\\n3. Validating workflow commands before a run starts.\\n\\n## Directory layout\\n\\n```text\\ndocs/parallel-study/\\n\u251c\u2500\u2500 sample-01-sidebar-pause/\\n\u2502   \u2514\u2500\u2500 issues.json\\n\u251c\u2500\u2500 sample-02-combo-edit/\\n\u2502   \u2514\u2500\u2500 issues.json\\n\u2514\u2500\u2500 sample-03-command-check/\\n    \u2514\u2500\u2500 issues.json\\n```\\n\\nEach `issues.json` file contains an array of issue objects with the following fields:\\n\\n| Field | Description |\\n|---|---|\\n| `id` | Stable issue identifier within the study |\\n| `title` | Human-readable issue title |\\n| `type` | Work classification; all current issues use `AFK` |\\n| `blocked_by` | Issue IDs that must be completed first |\\n| `what_to_build` | Implementation scope and reuse guidance |\\n| `acceptance` | Conditions that define completion |\\n\\nThe `blocked_by` field creates a linear or partial dependency graph. Work should not begin on a blocked issue until its prerequisites are complete.\\n\\n---\\n\\n## Study 1: Sidebar pause and resume\\n\\n**Location:** `sample-01-sidebar-pause/issues.json`\\n\\nThis study extends the sidebar workflow-run experience with the same pause/resume behavior already used by the Chat interface.\\n\\n### Existing components and APIs\\n\\nThe planned work references:\\n\\n- `SidebarComposer`\\n- `SidebarRunDetail`\\n- `useSidebarRun`\\n- `userPauseWorkflowRun(runId, targetNodeId)` in `api.ts`\\n- `MessageInput`\\n- `ChatInterface`\\n- `InputRequestForm`\\n- `loop_user_input`\\n- `pauseSignature`\\n- `shouldClearActing`\\n\\nThe Chat UI is the behavioral reference for the sidebar implementation. The study explicitly requires reusing the existing pause API and backend continuation mechanism rather than introducing a new endpoint or protocol.\\n\\n### Issue dependency flow\\n\\n```mermaid\\nflowchart LR\\n    I1[\\\"issue-1Pause button\\\"] --&gt; I2[\\\"issue-2Supplement and resume\\\"]\\n    I2 --&gt; I3[\\\"issue-3Overlay and refresh state\\\"]\\n```\\n\\n### Issue 1: Add a pause action\\n\\nThe first issue adds a pause button to the running state of `SidebarComposer` and/or `SidebarRunDetail`.\\n\\nExpected behavior:\\n\\n1. A workflow run in `running` state displays a pause control.\\n2. Clicking the control calls the existing `userPauseWorkflowRun(runId, targetNodeId)` API.\\n3. The run transitions to `paused`.\\n4. No backend API or pause mechanism is added.\\n\\nThe implementation should follow the pause interaction pattern used by `MessageInput` and `ChatInterface`, while adapting the presentation and state handling to the sidebar.\\n\\n### Issue 2: Collect supplemental information while paused\\n\\nOnce issue 1 is complete, the paused sidebar state should provide a text input for additional user information.\\n\\nThe intended behavior is:\\n\\n1. A paused run displays an input form.\\n2. The user enters supplemental text.\\n3. Submission uses the existing pause/resume path and carries the supplement.\\n4. The backend injects the value into `loop_user_input`.\\n5. The run resumes and returns to `running`.\\n\\n`InputRequestForm` and the existing clarify interaction are the UI patterns to reuse. The continuation mechanism is already supported by the backend; this issue is limited to connecting the sidebar UI to it.\\n\\n### Issue 3: Converge pause/resume visual state\\n\\nThe final issue addresses transient state handling in `useSidebarRun`.\\n\\nThe pause \u2192 supplement \u2192 resume sequence must correctly update:\\n\\n- Processing overlays.\\n- Acting or busy indicators.\\n- Run status refreshes.\\n- Cleanup of stale state after the run resumes.\\n\\nThe relevant implementation points are `pauseSignature` and `shouldClearActing`. These values should be adjusted so that the sidebar does not remain visually stuck in an acting state after a pause or resume operation.\\n\\n### Integration considerations\\n\\nContributors working on this study should preserve the following boundaries:\\n\\n- Use `userPauseWorkflowRun` instead of adding a new request function.\\n- Match the Chat pause behavior before introducing sidebar-specific behavior.\\n- Keep supplemental input compatible with `loop_user_input`.\\n- Treat `useSidebarRun` as the source of sidebar run-state coordination.\\n- Avoid changing the backend pause/resume implementation.\\n\\n---\\n\\n## Study 2: Combo editing\\n\\n**Location:** `sample-02-combo-edit/issues.json`\\n\\nThis study adds editing support to `SpaceComboSection`. A combo can currently be created using a form, and the planned work reuses that form structure for editing.\\n\\n### Existing components and APIs\\n\\nThe planned implementation references:\\n\\n- `SpaceComboSection.tsx`\\n- `updateCombo`\\n- `api.ts`\\n- `updateComboBodySchema`\\n- `PATCH /api/combos/{id}`\\n- `db.updateCombo`\\n\\n`updateCombo` is already imported but unused in the target component, making it the intended API for the new edit flow.\\n\\n### Issue 1: Add an edit entry point\\n\\nEach combo item in `SpaceComboSection.tsx` should expose an edit button.\\n\\nEntering edit mode should:\\n\\n- Replace or augment the item with the existing combo form structure.\\n- Pre-fill the current combo `name`.\\n- Pre-fill the current `description`.\\n- Mark the currently associated codebases as selected.\\n- Allow the user to modify the selected codebase checkboxes.\\n\\nThe edit form should share creation-form behavior and validation where practical rather than defining a separate form model.\\n\\n### Issue 2: Submit combo membership changes\\n\\nWhen the edit form is submitted, it should collect:\\n\\n- The combo name.\\n- The combo description.\\n- The selected `codebase_ids`.\\n\\nThe client should call:\\n\\n```ts\\nupdateCombo(id, {\\n  name,\\n  description,\\n  codebase_ids,\\n})\\n```\\n\\nThe existing backend path is:\\n\\n```text\\nPATCH /api/combos/{id}\\n    \u2514\u2500\u2500 db.updateCombo\\n```\\n\\nThe database update already supports replacing combo membership by deleting existing members and inserting the submitted members. The planned work therefore does not require backend or database changes.\\n\\nAfter a successful update, `SpaceComboSection` should refresh its list so that the displayed combo and codebase membership reflect the saved values.\\n\\n### Integration considerations\\n\\n- Reuse `updateCombo` from `api.ts`.\\n- Keep request validation aligned with `updateComboBodySchema`.\\n- Submit the complete selected `codebase_ids` collection, including both additions and removals.\\n- Refresh the combo list after a successful mutation.\\n- Do not duplicate the existing database membership-update logic in the frontend.\\n\\n---\\n\\n## Study 3: Pre-run command validation\\n\\n**Location:** `sample-03-command-check/issues.json`\\n\\nThis study moves command existence validation earlier in the workflow-run lifecycle. The goal is to fail before execution begins instead of allowing a run to reach a node that references a missing command.\\n\\n### Existing components and functions\\n\\nThe planned work references:\\n\\n- `executor.ts`\\n- `workflow-runs.ts`\\n- `validateWorkflowResources`\\n- `validator.ts`\\n- `loadCommandPrompt`\\n- `command_not_found`\\n- Levenshtein-based fuzzy suggestions\\n\\nThe validator already contains the required resource-checking logic. The change is to invoke it at the correct point in the run-start path.\\n\\n### Issue 1: Validate resources before execution\\n\\nThe workflow run entry points in `executor.ts` and `workflow-runs.ts` should perform a preflight validation before the first node executes.\\n\\nExpected behavior:\\n\\n1. A run request enters the workflow-start path.\\n2. `validateWorkflowResources` checks referenced resources, including commands.\\n3. If a command is missing, the run is rejected immediately.\\n4. The returned error identifies the missing command and includes a useful suggestion when applicable.\\n5. Workflows referencing valid commands continue to start normally.\\n\\nThis is a fail-fast change. It should prevent partial execution and avoid delaying an otherwise predictable error until a later node calls `loadCommandPrompt`.\\n\\n### Issue 2: Unify validation and runtime errors\\n\\nThe preflight error must use the same naming and suggestion format as the runtime `loadCommandPrompt` `command_not_found` error.\\n\\nBoth paths should provide:\\n\\n- The missing command name.\\n- Consistent error wording.\\n- A Levenshtein-based fuzzy suggestion where one is available.\\n- The same conceptual error category, so callers and users do not see different messages depending on when validation occurred.\\n\\nThe preferred implementation is to reuse existing formatting or suggestion logic rather than maintaining separate error-construction rules in `executor.ts`, `workflow-runs.ts`, and `loadCommandPrompt`.\\n\\n### Integration considerations\\n\\n- Invoke `validateWorkflowResources` before the first workflow node runs.\\n- Preserve normal startup for valid workflows.\\n- Do not replace runtime validation; preflight validation complements the runtime guard.\\n- Keep startup and runtime `command_not_found` output consistent.\\n- Preserve the existing fuzzy matching behavior and suggestion quality.\\n\\n---\\n\\n## Dependency and contribution model\\n\\nThe issue files define the intended implementation order:\\n\\n- Sidebar pause: issue 1 \u2192 issue 2 \u2192 issue 3.\\n- Combo editing: issue 1 \u2192 issue 2.\\n- Command validation: issue 1 \u2192 issue 2.\\n\\nThe studies are independent of one another. Changes in one sample should not require changes to the other samples unless shared application infrastructure is modified.\\n\\nBecause this module contains no executable code, contributors should update the relevant issue study when scope or dependencies change, while implementing the actual behavior in the referenced application modules. The issue acceptance criteria should be treated as the contract for those changes.\",\"other-paths\":\"# Other \u2014 paths\\n\\n# `@archon/paths`\\n\\n`@archon/paths` is a low-level shared package for Archon runtime infrastructure. It centralizes:\\n\\n- Archon home, workspace, worktree, project, artifact, log, and configuration paths\\n- Repository command and workflow discovery paths\\n- Startup environment isolation and Archon-owned `.env` loading\\n- Structured logging\\n- Build metadata\\n- Update checks\\n- Anonymous workflow telemetry\\n- Claude Code MCP configuration initialization\\n\\nThe package is intentionally near the bottom of the dependency graph so services, CLI entry points, workflow execution, providers, routes, and server code can depend on common infrastructure without introducing application-level dependency cycles.\\n\\n## Package entry points\\n\\nThe package exports the main API from `@archon/paths` and provides dedicated startup environment entry points:\\n\\n```ts\\nimport {\\n  getArchonHome,\\n  getProjectRoot,\\n  createLogger,\\n} from '@archon/paths';\\n```\\n\\n| Import | Purpose |\\n|---|---|\\n| `@archon/paths` | Main path, logging, telemetry, update, build metadata, and MCP APIs |\\n| `@archon/paths/strip-cwd-env` | Explicit `stripCwdEnv()` function |\\n| `@archon/paths/strip-cwd-env-boot` | Side-effect import that strips environment variables immediately |\\n| `@archon/paths/env-loader` | `loadArchonEnv()` for loading Archon-owned environment files |\\n\\n`strip-cwd-env-boot` must be imported before modules that read environment variables during initialization.\\n\\n```ts\\nimport '@archon/paths/strip-cwd-env-boot';\\nimport { loadArchonEnv } from '@archon/paths/env-loader';\\n\\nloadArchonEnv();\\n```\\n\\n## Storage layout\\n\\nThe default local root is `~/.archon`. In Docker, the root is `/.archon`.\\n\\n```text\\n/\\n\u251c\u2500\u2500 workspaces/\\n\u2502   \u2514\u2500\u2500 /\\n\u2502       \u2514\u2500\u2500 /\\n\u2502           \u251c\u2500\u2500 source/\\n\u2502           \u251c\u2500\u2500 worktrees/\\n\u2502           \u251c\u2500\u2500 artifacts/\\n\u2502           \u2502   \u2514\u2500\u2500 runs/\\n\u2502           \u2502       \u2514\u2500\u2500 /\\n\u2502           \u2514\u2500\u2500 logs/\\n\u2502               \u2514\u2500\u2500 .jsonl\\n\u251c\u2500\u2500 worktrees/                  # Legacy global worktrees\\n\u251c\u2500\u2500 commands/                   # User-wide commands\\n\u251c\u2500\u2500 workflows/                  # User-wide workflows\\n\u251c\u2500\u2500 scripts/                    # User-wide scripts\\n\u251c\u2500\u2500 config.yaml\\n\u251c\u2500\u2500 .env                        # User-wide Archon environment\\n\u251c\u2500\u2500 telemetry-id\\n\u251c\u2500\u2500 update-check.json\\n\u2514\u2500\u2500 web-dist/\\n    \u2514\u2500\u2500 /\\n```\\n\\nRepository-local Archon files live under the repository\u2019s `.archon` directory:\\n\\n```text\\n/.archon/\\n\u251c\u2500\u2500 commands/\\n\u251c\u2500\u2500 workflows/\\n\u251c\u2500\u2500 scripts/\\n\u2514\u2500\u2500 .env\\n```\\n\\nThe legacy home workflow path, `/.archon/workflows`, is retained only for migration detection and deprecation warnings. It is not a valid workflow source.\\n\\n## Archon home and environment-dependent paths\\n\\n### `isDocker()`\\n\\n`isDocker()` returns `true` when any of the following conditions is met:\\n\\n- `WORKSPACE_PATH === '/workspace'`\\n- `HOME === '/root'` and `WORKSPACE_PATH` is set\\n- `ARCHON_DOCKER === 'true'`\\n\\n### `getArchonHome()`\\n\\n`getArchonHome()` resolves the root for Archon-managed files:\\n\\n- Docker: `/.archon`\\n- Local with `ARCHON_HOME`: the value of `ARCHON_HOME`\\n- Local without an override: `~/.archon`\\n\\n`ARCHON_HOME` supports tilde expansion:\\n\\n```ts\\nprocess.env.ARCHON_HOME = '~/custom-archon';\\n\\ngetArchonHome();\\n// /custom-archon\\n```\\n\\nA literal `ARCHON_HOME=undefined` is rejected with an error. This generally indicates that an undefined value was accidentally converted to a string.\\n\\n### Root-level path helpers\\n\\nThese functions derive paths from `getArchonHome()`:\\n\\n| Function | Result |\\n|---|---|\\n| `getArchonWorkspacesPath()` | `/workspaces` |\\n| `getArchonWorktreesPath()` | `/worktrees` |\\n| `getArchonConfigPath()` | `/config.yaml` |\\n| `getHomeWorkflowsPath()` | `/workflows` |\\n| `getHomeCommandsPath()` | `/commands` |\\n| `getHomeScriptsPath()` | `/scripts` |\\n| `getArchonEnvPath()` | `/.env` |\\n| `getWebDistDir(version)` | `/web-dist/` |\\n\\n`expandTilde()` expands paths beginning with `~` and leaves other paths unchanged.\\n\\n### Creating workspace directories\\n\\n`ensureArchonWorkspacesPath()` creates the global workspaces directory using recursive `mkdir` and returns the resulting path. It is safe to call during fresh installation or repeatedly.\\n\\nPer-user workspace helpers provide an additional username segment:\\n\\n```ts\\ngetUserWorkspacesPath(username);\\nensureUserWorkspacesPath(username);\\n```\\n\\nThese resolve and create:\\n\\n```text\\n/workspaces/\\n```\\n\\n## Bundled application defaults\\n\\nThe application\u2019s bundled `.archon` directory is resolved independently from the user\u2019s Archon home.\\n\\n- `getAppArchonBasePath()` returns the repository-level `.archon` directory during local development.\\n- `getDefaultCommandsPath()` returns the bundled `commands/defaults` directory.\\n- `getDefaultWorkflowsPath()` returns the bundled `workflows/defaults` directory.\\n\\nWorkflow and command code uses these helpers when loading defaults. This keeps bundled content separate from user overrides and avoids paths tied to a particular package such as `packages/core` or `packages/paths`.\\n\\n`validateAppDefaultsPaths()` checks whether the bundled commands and workflows directories are accessible. It logs:\\n\\n- Individual warnings when a path is missing or inaccessible\\n- `app_defaults_verified` when both paths are available\\n- `app_defaults_not_available` when neither path is available\\n\\nMissing defaults are handled gracefully, which is important in Docker and other deployment environments where bundled files may not be present.\\n\\n`logArchonPaths()` logs the resolved home, workspace, worktree, and config paths using the `archon-paths` logger namespace.\\n\\n## Project-centric paths\\n\\nProjects are stored beneath:\\n\\n```text\\n/workspaces//\\n```\\n\\nThe project helpers are compositional:\\n\\n```ts\\nconst root = getProjectRoot(owner, repo);\\n\\ngetProjectSourcePath(owner, repo);     // root/source\\ngetProjectWorktreesPath(owner, repo);  // root/worktrees\\ngetProjectArtifactsPath(owner, repo);  // root/artifacts\\ngetProjectLogsPath(owner, repo);       // root/logs\\n```\\n\\nWorkflow-specific paths are derived from those directories:\\n\\n```ts\\ngetRunArtifactsPath(owner, repo, workflowRunId);\\n// root/artifacts/runs/\\n\\ngetRunLogPath(owner, repo, workflowRunId);\\n// root/logs/.jsonl\\n```\\n\\nThe workflow executor uses `getRunArtifactsPath()` when resolving project execution paths. Other providers use `getArchonWorkspacesPath()` when synchronizing workspaces.\\n\\n### `parseOwnerRepo()`\\n\\n`parseOwnerRepo(name)` converts an exact `owner/repo` string into:\\n\\n```ts\\n{ owner: string; repo: string }\\n```\\n\\nIt returns `null` unless the input has exactly two non-empty path segments. Each segment must match:\\n\\n```ts\\n/^[a-zA-Z0-9._-]+$/\\n```\\n\\nThis prevents nested paths, shell-like characters, and path traversal from being interpreted as project identifiers.\\n\\n```ts\\nparseOwnerRepo('acme/widget');\\n// { owner: 'acme', repo: 'widget' }\\n\\nparseOwnerRepo('acme/nested/widget');\\n// null\\n\\nparseOwnerRepo('../etc/passwd');\\n// null\\n```\\n\\nCallers should parse and validate a project identifier before passing owner and repository values into path construction.\\n\\n### `resolveProjectRootFromCwd()`\\n\\n`resolveProjectRootFromCwd(cwd)` identifies the project root for a path under the global workspace directory.\\n\\nFor example:\\n\\n```ts\\nresolveProjectRootFromCwd(\\n  '/workspaces/acme/widget/source'\\n);\\n// /workspaces/acme/widget\\n```\\n\\nThe function recognizes paths beneath any project subdirectory, including `source` and project worktrees. It returns `null` when:\\n\\n- The path is outside `/workspaces`\\n- Only an owner segment is present\\n- A complete `/` pair cannot be determined\\n\\nThis helper is based on the configured workspace root, so `ARCHON_HOME` overrides are respected.\\n\\n## Project structure and source links\\n\\n### `ensureProjectStructure()`\\n\\n`ensureProjectStructure(owner, repo)` creates all four project directories concurrently:\\n\\n```text\\nsource/\\nworktrees/\\nartifacts/\\nlogs/\\n```\\n\\nIt uses recursive directory creation and is idempotent:\\n\\n```ts\\nawait ensureProjectStructure('acme', 'widget');\\n```\\n\\nThe function does not clone source code or create a source link; it only establishes the directory structure.\\n\\n### `createProjectSourceSymlink()`\\n\\n`createProjectSourceSymlink(owner, repo, targetPath)` creates the project\u2019s `source` path as a symlink to a local directory.\\n\\nIts behavior depends on the existing source path:\\n\\n- Missing path: creates the symlink\\n- Existing symlink to the same normalized target: no-op\\n- Existing symlink to another target: throws\\n- Existing non-empty directory: assumes it is a real clone and leaves it unchanged\\n- Existing empty directory: removes it and creates the symlink\\n\\nThe link type is platform-specific:\\n\\n- Unix: `dir` symlink\\n- Windows: `junction`\\n\\nThis distinction allows `ensureProjectStructure()` to run before source setup without preventing a later source symlink from being created.\\n\\n## Command and workflow discovery paths\\n\\n### Repository-relative search paths\\n\\n`getCommandFolderSearchPaths(configuredFolder?)` returns command directories in priority order:\\n\\n```ts\\n[\\n  '.archon/commands',\\n  '.archon/commands/defaults',\\n  configuredFolder, // when supplied and not duplicated\\n]\\n```\\n\\nThe first matching command wins. The repository\u2019s custom commands always have priority over bundled defaults and configured additional paths.\\n\\nThe function avoids duplicate entries when `configuredFolder` is already one of the two standard paths.\\n\\n`getWorkflowFolderSearchPaths()` currently returns:\\n\\n```ts\\n['.archon/workflows']\\n```\\n\\nWorkflow discovery also consults the home-scoped and bundled workflow locations through `getHomeWorkflowsPath()` and `getDefaultWorkflowsPath()`.\\n\\n### Recursive Markdown discovery\\n\\n`findMarkdownFilesRecursive(rootPath, relativePath?, options?)` discovers `.md` files recursively and returns:\\n\\n```ts\\n{\\n  commandName: string;\\n  relativePath: string;\\n}[]\\n```\\n\\nBehavior:\\n\\n- `commandName` is the filename without the `.md` extension\\n- `relativePath` is relative to `rootPath`\\n- Hidden directories and files are skipped\\n- `node_modules` is skipped\\n- Missing roots return an empty array\\n- Other filesystem errors are rethrown\\n- Recursion is unlimited by default\\n\\nUse `maxDepth` to limit traversal. Depth counts directory boundaries from the root:\\n\\n```ts\\nawait findMarkdownFilesRecursive(commandsPath, '', { maxDepth: 1 });\\n```\\n\\nWith `maxDepth: 1`, files directly under the root and one directory below it are included, while deeper files are ignored.\\n\\n## Startup environment isolation\\n\\nArchon separates environment variables owned by the target repository from variables intended for Archon itself.\\n\\n### Why stripping is required\\n\\nBun automatically loads several `.env` files from the current working directory before application code runs:\\n\\n```text\\n.env\\n.env.local\\n.env.development\\n.env.production\\n```\\n\\nWhen Archon is launched inside a target repository, those variables become part of `process.env`. Loading Archon\u2019s own environment with `dotenv` does not remove keys that exist only in the target repository, so those values could leak into Archon and spawned Claude processes.\\n\\n`stripCwdEnv()` removes keys parsed from the four CWD files before Archon loads its own environment.\\n\\nIt also removes nested-session and debugger variables that can interfere with Claude Code subprocesses:\\n\\n- `CLAUDECODE`\\n- `CLAUDE_CODE_*` session markers\\n- `NODE_OPTIONS`\\n- `VSCODE_INSPECTOR_OPTIONS`\\n\\nAuthentication variables are intentionally preserved:\\n\\n- `CLAUDE_CODE_OAUTH_TOKEN`\\n- `CLAUDE_CODE_USE_BEDROCK`\\n- `CLAUDE_CODE_USE_VERTEX`\\n\\nShell-inherited variables that are not present in the CWD `.env` files remain untouched.\\n\\n### Boot order\\n\\nThe intended startup sequence is:\\n\\n```mermaid\\nflowchart LR\\n    A[CLI entry point] --&gt; B[strip-cwd-env-boot]\\n    B --&gt; C[stripCwdEnv]\\n    C --&gt; D[loadArchonEnv]\\n    D --&gt; E[Archon modules initialize]\\n    E --&gt; F[Claude/workflow subprocess]\\n```\\n\\n`strip-cwd-env-boot.ts` invokes `stripCwdEnv()` as an import-time side effect. It must be the first import in CLI entry points because modules such as `logger.ts` read environment variables while they initialize.\\n\\n`stripCwdEnv()` emits operator-facing stderr messages when it removes variables:\\n\\n```text\\n[archon] stripped N keys from  (.env, .env.local) ...\\n```\\n\\nIt emits a warning when a CWD environment file cannot be parsed for an unexpected reason. If `CLAUDECODE=1` is detected, it warns about running inside Claude Code unless `ARCHON_SUPPRESS_NESTED_CLAUDE_WARNING=1` is set.\\n\\n### Archon-owned environment loading\\n\\n`loadArchonEnv(cwd)` loads only Archon-owned environment files:\\n\\n1. `/.env`\\n2. `/.archon/.env`\\n\\nBoth loads use `override: true`, so the precedence is:\\n\\n```text\\nshell environment\\n    \u2193 overridden by\\n/.env\\n    \u2193 overridden by\\n/.archon/.env\\n```\\n\\nThe plain `/.env` is never loaded by `loadArchonEnv()`. The `.archon/` directory is the ownership boundary for repository-specific Archon configuration.\\n\\nThe loader:\\n\\n- Suppresses dotenv\u2019s default output with `quiet: true`\\n- Logs the number of loaded keys to stderr\\n- Logs nothing for missing or empty files\\n- Uses `~` in displayed paths when possible\\n- Treats malformed or unreadable files as fatal and exits with status `1`\\n\\nTypical entry-point usage:\\n\\n```ts\\nimport '@archon/paths/strip-cwd-env-boot';\\nimport { loadArchonEnv } from '@archon/paths/env-loader';\\n\\nloadArchonEnv(process.cwd());\\n```\\n\\n## Structured logging\\n\\n`logger.ts` provides Pino-based logging for the entire codebase.\\n\\n### `rootLogger`\\n\\n`rootLogger` is the shared Pino logger. Its initial level comes from `LOG_LEVEL`, defaulting to `info`.\\n\\nValid levels are:\\n\\n```text\\nfatal\\nerror\\nwarn\\ninfo\\ndebug\\ntrace\\n```\\n\\nInvalid `LOG_LEVEL` values produce a console warning and fall back to `info`.\\n\\nOutput format:\\n\\n- Pretty-printed output when stdout is a TTY and `NODE_ENV !== 'production'`\\n- Newline-delimited JSON otherwise\\n\\nPretty output is created as a destination stream rather than a worker transport to remain compatible with Bun compiled binaries.\\n\\n### `createLogger()`\\n\\n`createLogger(module)` creates a child logger with a `module` binding:\\n\\n```ts\\nconst log = createLogger('workflow.executor');\\n\\nlog.info({ workflowId }, 'workflow_started');\\nlog.error({ err }, 'workflow_failed');\\n```\\n\\nMany packages use this helper, including routes, database code, workflow execution, providers, sandbox utilities, orchestration, and server synchronization tasks.\\n\\n### Runtime log levels\\n\\n```ts\\nsetLogLevel('debug');\\nconst level = getLogLevel();\\n```\\n\\n`setLogLevel()` is case-insensitive and throws for invalid levels. The root logger\u2019s level changes immediately, but child loggers inherit the effective level when they are created. Startup code should set the level before modules create long-lived child loggers.\\n\\n## Build metadata\\n\\n`bundled-build.ts` exports constants written during binary compilation:\\n\\n```ts\\nBUNDLED_IS_BINARY\\nBUNDLED_VERSION\\nBUNDLED_GIT_COMMIT\\n```\\n\\nDevelopment values are:\\n\\n```ts\\nBUNDLED_IS_BINARY = false;\\nBUNDLED_VERSION = 'dev';\\nBUNDLED_GIT_COMMIT = 'unknown';\\n```\\n\\n`scripts/build-binaries.sh` rewrites the file before compiling a binary and restores it afterward. Keeping these values in `@archon/paths` allows any package to read build information without introducing a dependency cycle.\\n\\n## Update checks\\n\\n`update-check.ts` provides release-version comparison and cached GitHub release checks:\\n\\n- `isNewerVersion(current, latest)` compares numeric semantic version segments\\n- `parseLatestRelease(response)` validates and normalizes a GitHub release response, including optional `v` prefixes\\n- `checkForUpdate(currentVersion)` returns update information or `null` when the check fails\\n- `getCachedUpdateCheck()` reads cached update information and determines whether it represents a newer release\\n\\nUpdate results include:\\n\\n```ts\\ninterface UpdateCheckResult {\\n  updateAvailable: boolean;\\n  currentVersion: string;\\n  latestVersion: string;\\n  releaseUrl: string;\\n}\\n```\\n\\nResults are cached under:\\n\\n```text\\n/update-check.json\\n```\\n\\nA fresh cache avoids a network request. Network failures, non-success HTTP responses, and cache write failures do not prevent the caller from continuing; a fetched result can still be returned even if it cannot be cached.\\n\\n## Anonymous telemetry\\n\\n`telemetry.ts` sends the anonymous `workflow_invoked` event through PostHog.\\n\\n### Opt-out\\n\\nTelemetry is disabled when any of these conditions applies:\\n\\n```text\\nARCHON_TELEMETRY_DISABLED=1\\nDO_NOT_TRACK=1\\nPOSTHOG_API_KEY is empty or unavailable\\n```\\n\\nThe module includes a write-only default PostHog key. `POSTHOG_API_KEY` and `POSTHOG_HOST` can override the default configuration.\\n\\n### `captureWorkflowInvoked()`\\n\\n```ts\\ncaptureWorkflowInvoked({\\n  workflowName: 'example',\\n  workflowDescription: 'Optional description',\\n  platform: 'cli',\\n  archonVersion: '0.3.10',\\n});\\n```\\n\\nThe function is fire-and-forget and never throws. Descriptions are limited to 500 characters. Captured properties include the workflow name and optional platform, version, and description.\\n\\nNetwork and SDK failures are suppressed from users and logged at debug level. A custom fetch wrapper masks network and non-2xx failures so PostHog does not write noisy errors to stderr.\\n\\n### Anonymous installation ID\\n\\n`getOrCreateTelemetryId()` stores a stable UUID at:\\n\\n```text\\n/telemetry-id\\n```\\n\\nIf the file cannot be read or written, a session-only UUID is used. The persisted identifier contains no user identity.\\n\\n### Shutdown\\n\\n`shutdownTelemetry()` flushes queued events and closes the PostHog client. It is safe to call when telemetry was never initialized and should be called when a server receives a termination signal or a CLI command exits.\\n\\n## MCP initialization\\n\\n`initMcpServers()` ensures that Claude Code\u2019s user configuration contains the managed `ai-ku` MCP server.\\n\\nThe configuration file is:\\n\\n```text\\n~/.claude.json\\n```\\n\\nThe URL is selected in this order:\\n\\n1. `AI_KU_MCP_URL`\\n2. The built-in default URL\\n\\nThe function preserves unrelated Claude configuration and unrelated MCP servers. It replaces only the managed `ai-ku` entry and writes formatted JSON with a trailing newline.\\n\\nCalling it repeatedly is safe.\\n\\n## Contributing and integration guidelines\\n\\n### Use helpers instead of reconstructing paths\\n\\nPrefer:\\n\\n```ts\\nconst logPath = getRunLogPath(owner, repo, runId);\\n```\\n\\nover manually joining `getArchonHome()` and path segments. Centralized helpers preserve Docker behavior, `ARCHON_HOME` overrides, and layout changes.\\n\\n### Preserve startup ordering\\n\\nFor CLI entry points:\\n\\n1. Import `@archon/paths/strip-cwd-env-boot` first.\\n2. Load Archon-owned environment files with `loadArchonEnv()`.\\n3. Initialize modules that read environment variables.\\n4. Start services, workflow execution, or subprocesses.\\n\\nDo not import modules that initialize environment-sensitive state before the stripping side effect runs.\\n\\n### Keep user and bundled scopes distinct\\n\\n- Repository custom commands: `/.archon/commands`\\n- Home commands: `/commands`\\n- Bundled commands: application `.archon/commands/defaults`\\n- Repository workflows: `/.archon/workflows`\\n- Home workflows: `/workflows`\\n- Bundled workflows: application `.archon/workflows/defaults`\\n\\nDo not use `getLegacyHomeWorkflowsPath()` as a read fallback. It exists only to detect retired files and trigger migration guidance.\\n\\n### Use project structure helpers before filesystem operations\\n\\nCall `ensureProjectStructure()` before creating project artifacts, logs, worktrees, or source links unless the caller has already established the required parent directories.\\n\\nWhen creating a source link, use `createProjectSourceSymlink()` rather than directly calling `symlink()`. Its handling of existing clones, empty placeholders, and conflicting links is part of the project lifecycle contract.\\n\\n### Logging from shared code\\n\\nUse `createLogger()` with a stable module namespace. Avoid creating independent Pino roots in consumers. Set the global level early with `setLogLevel()` if startup configuration requires a value other than `LOG_LEVEL`.\\n\\n### Testing\\n\\nThe package uses Bun tests and isolates environment-dependent behavior by saving and restoring relevant environment variables. Filesystem tests use temporary directories and should avoid modifying a real home directory.\\n\\nRun:\\n\\n```sh\\nbun test src/\\nbun x tsc --noEmit\\n```\\n\\nTests cover Docker and local path resolution, custom home directories, project structure creation, symlink safety, environment isolation, logger levels, telemetry opt-out behavior, update caching, and MCP configuration preservation.\",\"other-ragas-evaluator\":\"# Other \u2014 ragas-evaluator\\n\\n# Archon Ragas Evaluator\\n\\nThe `services/ragas-evaluator` module provides an HTTP service for evaluating Archon runtime samples with [Ragas](https://docs.ragas.io/) metrics. It wraps Ragas behind a FastAPI application so the Archon evaluation pipeline can submit workflow, node, and skill samples over HTTP.\\n\\nThe service is packaged as a standalone Python 3.11 container and runs with Uvicorn on port `8000`.\\n\\n## Responsibilities\\n\\nThe evaluator:\\n\\n- Accepts `RagasEvaluationSample` payloads produced by `EvaluationService`.\\n- Runs the configured Ragas metrics against questions, answers, and retrieved contexts.\\n- Supports workflow-, node-, and skill-level evaluation samples.\\n- Returns aggregate and per-component evaluation results.\\n- Preserves golden-sample metadata, including:\\n  - `ground_truth`\\n  - Reference context counts\\n  - Expected tools\\n  - `golden_sample_id`\\n- Reports unevaluable samples as skipped rather than fabricating a score.\\n- Exposes a public health endpoint for readiness and configuration visibility.\\n- Optionally protects evaluation requests with a bearer token.\\n\\nIt does not persist evaluation data itself. Archon is responsible for consuming and persisting the returned evaluation results.\\n\\n## Architecture\\n\\n```mermaid\\nflowchart LR\\n    ES[EvaluationService] --&gt;|POST /evaluate| RE[ragas-evaluator]\\n    RE --&gt; R[Ragas metrics]\\n    RE --&gt; L[OpenAI-compatible LLM]\\n    RE --&gt; E[Embedding model]\\n    RE --&gt;|evaluation response| ES\\n    H[GET /health] --&gt; RE\\n```\\n\\nThe evaluator uses `ragas`, `langchain-openai`, and `datasets` from the Python runtime. The configured judge model and embedding model are accessed through OpenAI or an OpenAI-compatible endpoint.\\n\\n## HTTP API\\n\\n### `GET /health`\\n\\nReturns evaluator readiness and configuration information without requiring credentials.\\n\\nThe response exposes:\\n\\n- Readiness status\\n- Configured judge/LLM model\\n- Configured embedding model\\n- Rubric version\\n- Requested metrics\\n\\nThis endpoint is intended for health checks and operational inspection. It does not run an evaluation.\\n\\n### `POST /evaluate`\\n\\nEvaluates a `RagasEvaluationSample` payload emitted by `EvaluationService`.\\n\\nThe response contains:\\n\\n- `score`\\n- `health_status`\\n- `metrics`\\n- `findings`\\n- `node_results`\\n- `skill_results`\\n\\nThe exact set of populated fields depends on the sample and the requested metrics. Workflow, node, and skill results are included when the submitted evaluation sample contains the corresponding data.\\n\\n#### Evaluation eligibility\\n\\nA sample must contain all of the following to be evaluated:\\n\\n- A real question\\n- An answer\\n- Retrieved contexts\\n\\nIf the trace does not contain enough usable text or context:\\n\\n- No score is invented.\\n- The response reports `evaluator_execution_status=skipped`.\\n- A warning finding is returned.\\n- The sample count is `0`.\\n\\nProvider, network, or other evaluator execution errors remain failed requests. They are not converted into successful scores or skipped evaluations.\\n\\n## Supported metrics\\n\\nThe default metric configuration is:\\n\\n```text\\nfaithfulness,answer_relevancy,context_precision,context_recall\\n```\\n\\nThe metrics are controlled by `RAGAS_METRICS`.\\n\\nEmbedding-backed metrics, such as `answer_relevancy`, require an embedding model. Set:\\n\\n```text\\nRAGAS_EMBEDDING_MODEL=none\\n```\\n\\nto disable embedding-backed evaluation. This supports self-hosted OpenAI-compatible chat endpoints that provide chat completions but do not expose an embeddings API.\\n\\n## Configuration\\n\\n### Required settings\\n\\n| Variable | Description |\\n|---|---|\\n| `OPENAI_API_KEY` | Credential used to access the configured OpenAI-compatible provider. |\\n\\n### Optional settings\\n\\n| Variable | Default | Description |\\n|---|---:|---|\\n| `OPENAI_BASE_URL` | Provider default | Overrides the OpenAI API base URL. Use this for an OpenAI-compatible service. |\\n| `RAGAS_LLM_MODEL` | `gpt-4o-mini` | Judge model used by Ragas. |\\n| `RAGAS_RUBRIC_VERSION` | `ragas-v1` | Version identifier persisted with evaluation results. Bump this before rerunning a frozen anchor calibration. |\\n| `RAGAS_EMBEDDING_MODEL` | `text-embedding-3-small` | Embedding model used by embedding-backed metrics. Set to `none` to disable those metrics. |\\n| `RAGAS_EVALUATOR_TOKEN` | Unset | Optional bearer token required by `POST /evaluate`. |\\n| `RAGAS_REQUEST_TIMEOUT_SECONDS` | `120` | Timeout for evaluator/provider requests. |\\n| `RAGAS_MAX_RETRIES` | `1` | Maximum retry count for evaluator/provider operations. |\\n| `RAGAS_LLM_TEMPERATURE` | `0` | Judge-model temperature. Set to `none` for providers that reject the temperature parameter. |\\n| `RAGAS_METRICS` | `faithfulness,answer_relevancy,context_precision,context_recall` | Comma-separated list of Ragas metrics to request. |\\n\\n### Authentication\\n\\nWhen `RAGAS_EVALUATOR_TOKEN` is configured, callers must provide the matching bearer token when invoking `POST /evaluate`.\\n\\nArchon passes its configured token through:\\n\\n```text\\nARCHON_RAGAS_EVALUATOR_TOKEN\\n```\\n\\nThe health endpoint is explicitly available without credentials.\\n\\n## Archon integration\\n\\nArchon connects to this service using the following settings:\\n\\n| Archon setting | Default/example | Purpose |\\n|---|---|---|\\n| `ARCHON_RAGAS_EVALUATOR_URL` | `http://ragas-evaluator:8000/evaluate` | URL used by Archon to submit evaluation samples. |\\n| `ARCHON_RAGAS_EVALUATOR_TIMEOUT_MS` | `120000` | Client-side request timeout in milliseconds. |\\n| `ARCHON_RAGAS_EVALUATOR_TOKEN` | Unset | Bearer token sent when the evaluator requires authentication. |\\n\\nThe evaluator is therefore an external runtime dependency of the Archon evaluation path. Its URL, timeout, and token must be configured consistently on both sides:\\n\\n- The evaluator expects `RAGAS_EVALUATOR_TOKEN`.\\n- Archon sends `ARCHON_RAGAS_EVALUATOR_TOKEN`.\\n\\n## Evaluation flow\\n\\n1. `EvaluationService` produces a `RagasEvaluationSample`.\\n2. Archon sends the sample to `POST /evaluate`.\\n3. The evaluator validates whether the sample contains an actual question, answer, and retrieved contexts.\\n4. If the sample is incomplete, the evaluator returns a skipped result with a warning finding.\\n5. Otherwise, the service runs the configured Ragas metrics using the configured judge and embedding models.\\n6. The response includes aggregate score information, metric results, findings, and node/skill results where applicable.\\n7. Archon consumes the response and persists or reports the resulting evaluation data.\\n\\nGolden samples provide additional comparison metadata. Their `ground_truth`, expected context counts, expected tools, and `golden_sample_id` are retained in the persisted metrics for later analysis and calibration.\\n\\n## Container image\\n\\nThe service is built from `python:3.11-slim`.\\n\\nThe Dockerfile:\\n\\n1. Sets `/app` as the working directory.\\n2. Installs dependencies from `requirements.txt`.\\n3. Copies `app.py` into the image.\\n4. Exposes port `8000`.\\n5. Starts the FastAPI application with Uvicorn.\\n\\nRuntime command:\\n\\n```bash\\nuvicorn app:app \\\\\\n  --host 0.0.0.0 \\\\\\n  --port 8000 \\\\\\n  --loop asyncio\\n```\\n\\nThe container also sets:\\n\\n```text\\nPYTHONDONTWRITEBYTECODE=1\\nPYTHONUNBUFFERED=1\\nPIP_NO_CACHE_DIR=1\\n```\\n\\nThese settings avoid bytecode files, make logs immediately available, and prevent pip's cache from being retained in the image.\\n\\n## Dependencies\\n\\nPinned runtime dependencies are defined in `requirements.txt`:\\n\\n- `fastapi==0.115.6` \u2014 HTTP application framework.\\n- `uvicorn[standard]==0.34.0` \u2014 ASGI server.\\n- `ragas==0.2.9` \u2014 Evaluation metrics.\\n- `datasets==3.2.0` \u2014 Dataset structures used by the evaluation stack.\\n- `langchain-openai==0.2.14` \u2014 OpenAI-compatible LLM and embedding integrations.\\n\\nThe service currently consists of the container definition, dependency specification, and `app.py` application entry point. No additional internal module call graph or in-process service calls are defined for this module.\\n\\n## Operational considerations\\n\\n- Set `OPENAI_API_KEY` before starting the service.\\n- Configure `OPENAI_BASE_URL` when using an OpenAI-compatible provider.\\n- Ensure the selected provider supports the configured metrics:\\n  - Chat-model access is required for judge-based metrics.\\n  - Embedding access is required for embedding-backed metrics.\\n- Set `RAGAS_EMBEDDING_MODEL=none` when the provider has no embeddings endpoint.\\n- Keep `RAGAS_REQUEST_TIMEOUT_SECONDS` aligned with Archon's `ARCHON_RAGAS_EVALUATOR_TIMEOUT_MS`.\\n- Use `RAGAS_EVALUATOR_TOKEN` and `ARCHON_RAGAS_EVALUATOR_TOKEN` together when the evaluation endpoint must be protected.\\n- Treat `RAGAS_RUBRIC_VERSION` as part of evaluation-result provenance. Change it when the evaluation rubric or calibration baseline changes.\\n- Use `GET /health` for readiness checks without exposing evaluator credentials.\",\"other-readme-md\":\"# Other \u2014 README.md\\n\\n# Archon README\\n\\nArchon \u662f\u9762\u5411 AI \u7f16\u7a0b Agent \u7684\u5f00\u6e90\u5de5\u4f5c\u6d41\u7f16\u6392\u5de5\u5177\u3002\u5b83\u5c06\u8f6f\u4ef6\u5f00\u53d1\u6d41\u7a0b\u5b9a\u4e49\u4e3a\u53ef\u63d0\u4ea4\u3001\u53ef\u590d\u7528\u7684 YAML \u5de5\u4f5c\u6d41\uff0c\u4f7f\u89c4\u5212\u3001\u5b9e\u73b0\u3001\u6d4b\u8bd5\u3001\u5ba1\u67e5\u548c Pull Request \u521b\u5efa\u7b49\u6b65\u9aa4\u6309\u56fa\u5b9a\u7ed3\u6784\u6267\u884c\u3002\\n\\nREADME \u662f\u9879\u76ee\u7684\u4e3b\u8981\u5165\u53e3\u6587\u6863\uff0c\u9762\u5411\u4f7f\u7528\u8005\u548c\u8d21\u732e\u8005\u8bf4\u660e\uff1a\\n\\n- Archon \u89e3\u51b3\u7684\u95ee\u9898\u53ca\u5176\u5de5\u4f5c\u65b9\u5f0f\\n- \u5b89\u88c5\u548c\u9996\u6b21\u914d\u7f6e\u8def\u5f84\\n- Web UI\u3001CLI \u4e0e\u5916\u90e8\u5e73\u53f0\u9002\u914d\u5668\\n- \u5185\u7f6e\u5de5\u4f5c\u6d41\u4e0e\u81ea\u5b9a\u4e49\u6269\u5c55\u70b9\\n- \u7cfb\u7edf\u67b6\u6784\u3001\u6587\u6863\u5165\u53e3\u3001\u9065\u6d4b\u4e0e\u8d21\u732e\u65b9\u5f0f\\n\\n\u5b83\u4e0d\u5305\u542b\u53ef\u6267\u884c\u4ee3\u7801\u3001\u51fd\u6570\u6216\u7c7b\uff0c\u4e5f\u6ca1\u6709\u76f4\u63a5\u8c03\u7528\u5173\u7cfb\uff1b\u5176\u4f5c\u7528\u662f\u8fde\u63a5\u9879\u76ee\u7684\u5b89\u88c5\u811a\u672c\u3001CLI\u3001\u5de5\u4f5c\u6d41\u6587\u4ef6\u3001\u914d\u7f6e\u3001Web UI \u548c\u5728\u7ebf\u6587\u6863\u3002\\n\\n## \u6838\u5fc3\u6a21\u578b\uff1a\u786e\u5b9a\u6027\u7684 AI \u5f00\u53d1\u6d41\u7a0b\\n\\n\u666e\u901a AI \u7f16\u7a0b\u8bf7\u6c42\u901a\u5e38\u662f\u4e00\u6b21\u6027\u5bf9\u8bdd\uff1a\u6a21\u578b\u81ea\u884c\u51b3\u5b9a\u662f\u5426\u5148\u89c4\u5212\u3001\u662f\u5426\u6267\u884c\u6d4b\u8bd5\u3001\u662f\u5426\u9075\u5faa PR \u6a21\u677f\u3002Archon \u5c06\u8fd9\u4e9b\u51b3\u7b56\u4e2d\u7684\u6d41\u7a0b\u90e8\u5206\u63d0\u53d6\u4e3a\u5de5\u4f5c\u6d41\u5b9a\u4e49\u3002\\n\\n\u5de5\u4f5c\u6d41\u8d1f\u8d23\u63a7\u5236\uff1a\\n\\n- \u8282\u70b9\u6267\u884c\u987a\u5e8f\\n- \u8282\u70b9\u4f9d\u8d56\u5173\u7cfb\\n- \u5faa\u73af\u4e0e\u7ed3\u675f\u6761\u4ef6\\n- \u6d4b\u8bd5\u3001\u811a\u672c\u548c Git \u64cd\u4f5c\u7b49\u786e\u5b9a\u6027\u5173\u5361\\n- \u4eba\u5de5\u5ba1\u6279\u7b49\u5f85\u70b9\\n- AI Agent \u5728\u4f55\u5904\u53c2\u4e0e\u89c4\u5212\u3001\u5b9e\u73b0\u6216\u5ba1\u67e5\\n\\nAI \u4ecd\u8d1f\u8d23\u9700\u8981\u63a8\u7406\u7684\u5de5\u4f5c\uff0c\u4f8b\u5982\u63a2\u7d22\u4ee3\u7801\u3001\u751f\u6210\u5b9e\u73b0\u3001\u89e3\u91ca\u6d4b\u8bd5\u5931\u8d25\u6216\u5ba1\u67e5\u53d8\u66f4\uff1bArchon \u5219\u4fdd\u8bc1\u8fd9\u4e9b\u5de5\u4f5c\u5728\u65e2\u5b9a\u6d41\u7a0b\u4e2d\u6267\u884c\u3002\\n\\n```mermaid\\nflowchart TD\\n    A[CLI / Web UI / Chat Platform] --&gt; B[Orchestrator]\\n    B --&gt; C[Command Handler]\\n    B --&gt; D[Workflow Executor]\\n    D --&gt; E[YAML Workflow DAG]\\n    E --&gt; F[AI Assistant]\\n    E --&gt; G[Bash / Git / Tests]\\n    B --&gt; H[SQLite or PostgreSQL]\\n```\\n\\n## \u5de5\u4f5c\u6d41\u5b9a\u4e49\\n\\n\u9879\u76ee\u5de5\u4f5c\u6d41\u5b58\u653e\u5728\u76ee\u6807\u4ed3\u5e93\u7684 `.archon/workflows/` \u76ee\u5f55\u4e2d\uff0c\u4ee5 YAML \u5b9a\u4e49\u8282\u70b9\u56fe\u3002README \u4e2d\u7684 `build-feature.yaml` \u5c55\u793a\u4e86\u5178\u578b\u7684\u529f\u80fd\u5f00\u53d1\u6d41\u7a0b\uff1a\\n\\n1. `plan`\uff1a\u8ba9 AI \u63a2\u7d22\u4ee3\u7801\u5e93\u5e76\u751f\u6210\u5b9e\u73b0\u8ba1\u5212\u3002\\n2. `implement`\uff1a\u4f9d\u8d56 `plan`\uff0c\u901a\u8fc7 `loop` \u53cd\u590d\u5b9e\u73b0\u4efb\u52a1\u5e76\u8fd0\u884c\u9a8c\u8bc1\u3002\\n3. `run-tests`\uff1a\u4f9d\u8d56 `implement`\uff0c\u6267\u884c `bun run validate`\u3002\\n4. `review`\uff1a\u4f9d\u8d56\u6d4b\u8bd5\u7ed3\u679c\uff0c\u8ba9 AI \u6839\u636e\u8ba1\u5212\u5ba1\u67e5\u5e76\u4fee\u590d\u95ee\u9898\u3002\\n5. `approve`\uff1a\u901a\u8fc7\u4ea4\u4e92\u5f0f\u5faa\u73af\u6682\u505c\uff0c\u7b49\u5f85\u4eba\u5de5\u5ba1\u6279\u6216\u53cd\u9988\u3002\\n6. `create-pr`\uff1a\u5ba1\u6279\u5b8c\u6210\u540e\u63a8\u9001\u5206\u652f\u5e76\u521b\u5efa Pull Request\u3002\\n\\n### \u5e38\u7528\u8282\u70b9\u5b57\u6bb5\\n\\nREADME \u793a\u4f8b\u4e2d\u4f7f\u7528\u7684\u5b57\u6bb5\u5305\u62ec\uff1a\\n\\n| \u5b57\u6bb5 | \u542b\u4e49 |\\n|---|---|\\n| `id` | \u8282\u70b9\u7684\u552f\u4e00\u6807\u8bc6\uff0c\u4f9b\u4f9d\u8d56\u5173\u7cfb\u5f15\u7528\u3002 |\\n| `depends_on` | \u524d\u7f6e\u8282\u70b9\u5217\u8868\uff1b\u53ea\u6709\u4f9d\u8d56\u5b8c\u6210\u540e\uff0c\u5f53\u524d\u8282\u70b9\u624d\u80fd\u5f00\u59cb\u3002 |\\n| `prompt` | \u4ea4\u7ed9 AI \u52a9\u624b\u6267\u884c\u7684\u4efb\u52a1\u8bf4\u660e\u3002 |\\n| `bash` | \u8981\u6267\u884c\u7684\u786e\u5b9a\u6027 shell \u547d\u4ee4\uff0c\u4e0d\u8981\u6c42 AI \u53c2\u4e0e\u3002 |\\n| `loop` | \u5c06\u8282\u70b9\u914d\u7f6e\u4e3a\u5faa\u73af\u8282\u70b9\uff0c\u76f4\u5230\u6ee1\u8db3\u7ed3\u675f\u6761\u4ef6\u3002 |\\n| `until` | \u5faa\u73af\u7ed3\u675f\u6761\u4ef6\uff0c\u4f8b\u5982 `ALL_TASKS_COMPLETE` \u6216 `APPROVED`\u3002 |\\n| `fresh_context` | \u6bcf\u6b21\u5faa\u73af\u8fed\u4ee3\u4f7f\u7528\u65b0\u7684 AI \u4f1a\u8bdd\u4e0a\u4e0b\u6587\u3002 |\\n| `interactive` | \u5141\u8bb8\u6d41\u7a0b\u6682\u505c\u5e76\u7b49\u5f85\u7528\u6237\u8f93\u5165\uff0c\u901a\u5e38\u7528\u4e8e\u5ba1\u6279\u5173\u5361\u3002 |\\n\\n\u5de5\u4f5c\u6d41\u53ef\u540c\u65f6\u5305\u542b AI \u8282\u70b9\u548c\u786e\u5b9a\u6027\u8282\u70b9\u3002\u63a8\u8350\u5728\u4ee3\u7801\u751f\u6210\u3001\u8ba1\u5212\u548c\u5ba1\u67e5\u7b49\u9700\u8981\u63a8\u7406\u7684\u5730\u65b9\u4f7f\u7528 `prompt`\uff0c\u5728\u6d4b\u8bd5\u3001\u683c\u5f0f\u5316\u3001\u9759\u6001\u68c0\u67e5\u548c\u5df2\u77e5\u811a\u672c\u64cd\u4f5c\u4e2d\u4f7f\u7528 `bash`\u3002\\n\\n### \u5de5\u4f5c\u6d41\u8986\u76d6\u4e0e\u5171\u4eab\\n\\nArchon \u63d0\u4f9b\u9ed8\u8ba4\u5de5\u4f5c\u6d41\uff0c\u9879\u76ee\u4e5f\u53ef\u4ee5\u5b9a\u4e49\u540c\u540d\u6587\u4ef6\u8fdb\u884c\u8986\u76d6\uff1a\\n\\n- \u5185\u7f6e\u9ed8\u8ba4\u5de5\u4f5c\u6d41\uff1a`.archon/workflows/defaults/`\\n- \u9879\u76ee\u81ea\u5b9a\u4e49\u5de5\u4f5c\u6d41\uff1a`.archon/workflows/`\\n- \u53ef\u590d\u7528 AI \u547d\u4ee4\uff1a`.archon/commands/`\\n\\n\u5c06 `.archon/workflows/` \u548c `.archon/commands/` \u63d0\u4ea4\u5230 Git \u540e\uff0c\u56e2\u961f\u6210\u5458\u53ef\u4ee5\u5728\u76f8\u540c\u4ed3\u5e93\u4e2d\u8fd0\u884c\u76f8\u540c\u6d41\u7a0b\u548c\u7ea6\u675f\u3002\\n\\n\u6709\u5173\u5b8c\u6574 YAML \u8bed\u6cd5\u548c\u8282\u70b9\u7c7b\u578b\uff0c\u53c2\u89c1[\u7f16\u5199\u5de5\u4f5c\u6d41](https://archon.diy/guides/authoring-workflows/)\u3002\u6709\u5173 Markdown \u547d\u4ee4\u5b9a\u4e49\uff0c\u53c2\u89c1[\u7f16\u5199\u547d\u4ee4](https://archon.diy/guides/authoring-commands/)\u3002\\n\\n## \u5b89\u88c5\u8def\u5f84\\n\\nREADME \u63d0\u4f9b\u4e24\u79cd\u4e3b\u8981\u5b89\u88c5\u65b9\u5f0f\u3002\\n\\n### \u5b8c\u6574\u5b89\u88c5\\n\\n\u9002\u7528\u4e8e\u9996\u6b21\u4f7f\u7528\u8005\uff0c\u6216\u5e0c\u671b\u4f7f\u7528\u5f15\u5bfc\u5f0f\u914d\u7f6e\u3001Web UI \u548c\u5e73\u53f0\u96c6\u6210\u7684\u573a\u666f\u3002\\n\\n\u524d\u7f6e\u4f9d\u8d56\uff1a\\n\\n- [Bun](https://bun.sh)\\n- [Claude Code](https://claude.ai/code)\\n- [GitHub CLI](https://cli.github.com/)\\n\\n\u4ece\u6e90\u7801\u542f\u52a8\uff1a\\n\\n```bash\\ngit clone https://github.com/coleam00/Archon\\ncd Archon\\nbun install\\nclaude\\n```\\n\\n\u7136\u540e\u5728 Claude Code \u4e2d\u8f93\u5165\uff1a\\n\\n```text\\nSet up Archon\\n```\\n\\n\u5b89\u88c5\u5411\u5bfc\u8d1f\u8d23\u914d\u7f6e\u51ed\u636e\u548c\u5e73\u53f0\u9009\u9879\uff0c\u5e76\u5c06 Archon skill \u5b89\u88c5\u5230\u76ee\u6807\u9879\u76ee\u4e2d\u3002\\n\\n### \u5feb\u901f\u5b89\u88c5\\n\\n\u9002\u7528\u4e8e\u5df2\u7ecf\u914d\u7f6e Claude Code\u3001\u53ea\u9700\u8981\u72ec\u7acb CLI \u7684\u7528\u6237\u3002\\n\\n```bash\\ncurl -fsSL https://archon.diy/install | bash\\n```\\n\\nWindows PowerShell\uff1a\\n\\n```powershell\\nirm https://archon.diy/install.ps1 | iex\\n```\\n\\n\u4e5f\u53ef\u4ee5\u901a\u8fc7 Homebrew \u5b89\u88c5\uff1a\\n\\n```bash\\nbrew install coleam00/archon/archon\\n```\\n\\n\u7f16\u8bd1\u540e\u7684 CLI \u4e8c\u8fdb\u5236\u6587\u4ef6\u4e0d\u5305\u542b Claude Code\uff0c\u56e0\u6b64\u5fc5\u987b\u80fd\u591f\u5b9a\u4f4d Claude \u53ef\u6267\u884c\u6587\u4ef6\u3002\u4f7f\u7528 `CLAUDE_BIN_PATH`\uff1a\\n\\n```bash\\nexport CLAUDE_BIN_PATH=\\\"$HOME/.local/bin/claude\\\"\\n```\\n\\nWindows\uff1a\\n\\n```powershell\\n$env:CLAUDE_BIN_PATH = \\\"$env:USERPROFILE\\\\.local\\\\bin\\\\claude.exe\\\"\\n```\\n\\n\u4e5f\u53ef\u4ee5\u901a\u8fc7 `~/.archon/config.yaml` \u4e2d\u7684 `assistants.claude.claudeBinaryPath` \u914d\u7f6e\u3002\\n\\n&gt; Docker \u955c\u50cf\u5df2\u5305\u542b Claude Code\uff0c\u4e0d\u9700\u8981\u5355\u72ec\u8bbe\u7f6e\u8be5\u8def\u5f84\u3002\\n\\n## \u5728\u76ee\u6807\u9879\u76ee\u4e2d\u4f7f\u7528\\n\\nArchon \u5e94\u4ece\u9700\u8981\u4fee\u6539\u7684\u76ee\u6807\u4ed3\u5e93\u8fd0\u884c\uff0c\u800c\u4e0d\u662f\u4ece Archon \u81ea\u8eab\u4ed3\u5e93\u8fd0\u884c\uff1a\\n\\n```bash\\ncd /path/to/your/project\\nclaude\\n```\\n\\n\u968f\u540e\u53ef\u76f4\u63a5\u5411 Agent \u63cf\u8ff0\u4efb\u52a1\uff1a\\n\\n```text\\nUse archon to fix issue #42\\n```\\n\\n\u4e5f\u53ef\u4ee5\u8be2\u95ee\u53ef\u7528\u5de5\u4f5c\u6d41\u53ca\u5176\u4f7f\u7528\u573a\u666f\uff1a\\n\\n```text\\nWhat archon workflows do I have? When would I use each one?\\n```\\n\\nAgent \u4f1a\u8d1f\u8d23\u9009\u62e9\u5de5\u4f5c\u6d41\u3001\u5efa\u7acb\u547d\u540d\u5206\u652f\u548c\u521b\u5efa\u9694\u79bb worktree\u3002\u9996\u6b21\u4f7f\u7528\u65f6\uff0c\u9879\u76ee\u4f1a\u81ea\u52a8\u6ce8\u518c\u3002\\n\\n## \u5185\u7f6e\u5de5\u4f5c\u6d41\\n\\nREADME \u5217\u51fa\u4e86 17 \u4e2a\u9ed8\u8ba4\u5de5\u4f5c\u6d41\u3002\u5b83\u4eec\u8986\u76d6\u4ece\u901a\u7528\u95ee\u7b54\u5230\u5b8c\u6574 PR \u751f\u547d\u5468\u671f\u7684\u5e38\u89c1\u5f00\u53d1\u4efb\u52a1\u3002\\n\\n| \u5de5\u4f5c\u6d41 | \u4e3b\u8981\u7528\u9014 |\\n|---|---|\\n| `archon-assist` | \u901a\u7528\u95ee\u7b54\u3001\u8c03\u8bd5\u548c\u4ee3\u7801\u5e93\u63a2\u7d22\u3002 |\\n| `archon-fix-github-issue` | \u4ece GitHub Issue \u5206\u7c7b\u3001\u8c03\u67e5\u3001\u5b9e\u73b0\u3001\u9a8c\u8bc1\u5230 PR \u548c\u81ea\u4fee\u590d\u3002 |\\n| `archon-idea-to-pr` | \u5c06\u529f\u80fd\u60f3\u6cd5\u8f6c\u6362\u4e3a\u89c4\u5212\u3001\u5b9e\u73b0\u3001\u9a8c\u8bc1\u3001\u5e76\u884c\u5ba1\u67e5\u548c PR\u3002 |\\n| `archon-plan-to-pr` | \u6267\u884c\u5df2\u6709\u8ba1\u5212\u5e76\u5b8c\u6210\u5b9e\u73b0\u3001\u9a8c\u8bc1\u3001\u5ba1\u67e5\u548c PR\u3002 |\\n| `archon-issue-review-full` | \u9488\u5bf9 GitHub Issue \u7684\u5b8c\u6574\u4fee\u590d\u548c\u591a Agent \u5ba1\u67e5\u6d41\u7a0b\u3002 |\\n| `archon-smart-pr-review` | \u6839\u636e PR \u590d\u6742\u5ea6\u9009\u62e9\u5b9a\u5411\u5ba1\u67e5\u6d41\u7a0b\u5e76\u6c47\u603b\u7ed3\u8bba\u3002 |\\n| `archon-comprehensive-pr-review` | \u8fd0\u884c\u4e94\u4e2a\u5e76\u884c\u5ba1\u67e5\u5458\u5e76\u81ea\u52a8\u5904\u7406\u53d1\u73b0\u7684\u95ee\u9898\u3002 |\\n| `archon-create-issue` | \u6536\u96c6\u4e0a\u4e0b\u6587\u3001\u8c03\u67e5\u95ee\u9898\u5e76\u521b\u5efa GitHub Issue\u3002 |\\n| `archon-validate-pr` | \u6bd4\u8f83\u4e3b\u5206\u652f\u4e0e\u529f\u80fd\u5206\u652f\uff0c\u6267\u884c\u5168\u9762 PR \u9a8c\u8bc1\u3002 |\\n| `archon-resolve-conflicts` | \u68c0\u6d4b\u3001\u5206\u6790\u3001\u89e3\u51b3\u5e76\u9a8c\u8bc1\u5408\u5e76\u51b2\u7a81\u3002 |\\n| `archon-feature-development` | \u6309\u8ba1\u5212\u5b9e\u73b0\u529f\u80fd\u3001\u9a8c\u8bc1\u5e76\u521b\u5efa PR\u3002 |\\n| `archon-architect` | \u67b6\u6784\u63a2\u7d22\u3001\u590d\u6742\u5ea6\u964d\u4f4e\u548c\u4ee3\u7801\u5e93\u5065\u5eb7\u5ea6\u6539\u8fdb\u3002 |\\n| `archon-refactor-safely` | \u5e26\u7c7b\u578b\u68c0\u67e5\u548c\u884c\u4e3a\u9a8c\u8bc1\u5173\u5361\u7684\u91cd\u6784\u3002 |\\n| `archon-ralph-dag` | \u57fa\u4e8e PRD \u7684\u8fed\u4ee3\u5f0f\u7528\u6237\u6545\u4e8b\u5b9e\u73b0\u3002 |\\n| `archon-remotion-generate` | \u4f7f\u7528 AI \u521b\u5efa\u6216\u4fee\u6539 Remotion \u89c6\u9891\u5408\u6210\u3002 |\\n| `archon-test-loop-dag` | \u7528\u4e8e\u9a8c\u8bc1\u5faa\u73af\u8282\u70b9\u884c\u4e3a\u7684\u6d4b\u8bd5\u5de5\u4f5c\u6d41\u3002 |\\n| `archon-piv-loop` | \u5728\u6bcf\u6b21\u89c4\u5212\u3001\u5b9e\u73b0\u548c\u9a8c\u8bc1\u8fed\u4ee3\u95f4\u5f15\u5165\u4eba\u5de5\u5ba1\u67e5\u3002 |\\n\\n\u4f7f\u7528 CLI \u67e5\u770b\u5b9e\u9645\u53ef\u7528\u5de5\u4f5c\u6d41\uff1a\\n\\n```bash\\narchon workflow list\\n```\\n\\n\u9879\u76ee\u5185\u7684\u540c\u540d\u5de5\u4f5c\u6d41\u4f1a\u8986\u76d6\u5185\u7f6e\u9ed8\u8ba4\u7248\u672c\uff0c\u56e0\u6b64\u8be5\u547d\u4ee4\u5e94\u4f5c\u4e3a\u5f53\u524d\u73af\u5883\u7684\u6743\u5a01\u7ed3\u679c\u3002\\n\\n## Web UI \u4e0e\u5e73\u53f0\u9002\u914d\u5668\\n\\nArchon \u652f\u6301\u4ece\u591a\u4e2a\u5165\u53e3\u89e6\u53d1\u76f8\u540c\u7684\u7f16\u6392\u6d41\u7a0b\uff1a\\n\\n- CLI\\n- Web UI\\n- Telegram\\n- Slack\\n- Discord\\n- GitHub Webhooks\\n\\nWeb \u4eea\u8868\u76d8\u53ef\u901a\u8fc7\u4ee5\u4e0b\u65b9\u5f0f\u542f\u52a8\uff1a\\n\\n- \u4e8c\u8fdb\u5236\u5b89\u88c5\uff1a`archon serve`\\n- \u6e90\u7801\u5b89\u88c5\uff1a\u5728 Archon \u4ed3\u5e93\u6839\u76ee\u5f55\u8fd0\u884c `bun run dev`\\n\\nWeb UI \u7684\u4e3b\u8981\u529f\u80fd\u5305\u62ec\uff1a\\n\\n| \u9875\u9762 | \u529f\u80fd |\\n|---|---|\\n| \u5bf9\u8bdd | \u4e0e Agent \u5bf9\u8bdd\uff0c\u67e5\u770b\u5b9e\u65f6\u6d41\u5f0f\u54cd\u5e94\u548c\u5de5\u5177\u8c03\u7528\u3002 |\\n| \u4eea\u8868\u76d8 | \u67e5\u770b\u8fd0\u884c\u4e2d\u7684\u5de5\u4f5c\u6d41\uff0c\u5e76\u6309\u9879\u76ee\u3001\u72b6\u6001\u548c\u65e5\u671f\u7b5b\u9009\u5386\u53f2\u8bb0\u5f55\u3002 |\\n| \u5de5\u4f5c\u6d41\u6784\u5efa\u5668 | \u4ee5\u62d6\u62fd\u65b9\u5f0f\u521b\u5efa\u5305\u542b DAG \u548c\u5faa\u73af\u8282\u70b9\u7684\u5de5\u4f5c\u6d41\u3002 |\\n| \u5de5\u4f5c\u6d41\u6267\u884c | \u67e5\u770b\u6b63\u5728\u8fd0\u884c\u6216\u5df2\u7ecf\u5b8c\u6210\u7684\u5de5\u4f5c\u6d41\u7684\u9010\u6b65\u6267\u884c\u72b6\u6001\u3002 |\\n\\n\u5728\u804a\u5929\u4fa7\u680f\u4e2d\u901a\u8fc7\u201c\u9879\u76ee\u201d\u65c1\u7684 **+** \u53ef\u6ce8\u518c\u9879\u76ee\u3002\u9879\u76ee\u53ef\u4ee5\u901a\u8fc7 GitHub URL \u6216\u672c\u5730\u8def\u5f84\u6dfb\u52a0\u3002\\n\\n\u4e0d\u540c\u5e73\u53f0\u4ec5\u662f\u8f93\u5165\u9002\u914d\u5668\uff1a\u4ece CLI\u3001Web UI\u3001Slack\u3001Telegram \u6216 GitHub \u89e6\u53d1\u7684\u4f1a\u8bdd\u548c\u5de5\u4f5c\u6d41\u6d3b\u52a8\u90fd\u6c47\u96c6\u5230\u7edf\u4e00\u7684\u76d1\u63a7\u754c\u9762\u3002\\n\\n\u5e73\u53f0\u914d\u7f6e\u6587\u6863\uff1a\\n\\n- [Telegram](https://archon.diy/adapters/telegram/)\\n- [Slack](https://archon.diy/adapters/slack/)\\n- [GitHub Webhooks](https://archon.diy/adapters/github/)\\n- [Discord](https://archon.diy/adapters/community/discord/)\\n- [Web UI](https://archon.diy/adapters/web/)\\n\\n## \u7cfb\u7edf\u67b6\u6784\\n\\nREADME \u5c06 Archon \u63cf\u8ff0\u4e3a\u56db\u5c42\u7cfb\u7edf\uff1a\\n\\n1. **\u5e73\u53f0\u9002\u914d\u5668**  \\n   \u63a5\u6536\u6765\u81ea Web UI\u3001CLI \u548c\u804a\u5929\u5e73\u53f0\u7684\u6d88\u606f\u6216\u4e8b\u4ef6\u3002\\n\\n2. **\u7f16\u6392\u5668**  \\n   \u8d1f\u8d23\u6d88\u606f\u8def\u7531\u548c\u4e0a\u4e0b\u6587\u7ba1\u7406\uff0c\u5e76\u5c06\u8bf7\u6c42\u4ea4\u7ed9\u547d\u4ee4\u5904\u7406\u3001\u5de5\u4f5c\u6d41\u6267\u884c\u6216 AI \u52a9\u624b\u5c42\u3002\\n\\n3. **\u6267\u884c\u4e0e AI \u5c42**  \\n   - \u547d\u4ee4\u5904\u7406\u5668\u6267\u884c\u659c\u6760\u547d\u4ee4\u3002\\n   - \u5de5\u4f5c\u6d41\u6267\u884c\u5668\u89e3\u6790\u548c\u6267\u884c YAML \u5de5\u4f5c\u6d41\u3002\\n   - AI \u52a9\u624b\u5ba2\u6237\u7aef\u8fde\u63a5 Claude\u3001Codex \u6216 Pi\u3002\\n\\n4. **\u6301\u4e45\u5316\u5c42**  \\n   \u4f7f\u7528 SQLite \u6216 PostgreSQL \u5b58\u50a8\u4ee3\u7801\u5e93\u3001\u4f1a\u8bdd\u3001workflow run\u3001\u9694\u79bb\u73af\u5883\u3001\u6d88\u606f\u548c\u5de5\u4f5c\u6d41\u4e8b\u4ef6\u7b49\u72b6\u6001\u3002\\n\\n\u72ec\u7acb git worktree \u662f\u6267\u884c\u9694\u79bb\u7684\u91cd\u8981\u673a\u5236\u3002\u6bcf\u4e2a\u5de5\u4f5c\u6d41\u8fd0\u884c\u5728\u81ea\u5df1\u7684\u5de5\u4f5c\u76ee\u5f55\u548c\u5206\u652f\u4e2d\uff0c\u4f7f\u591a\u4e2a\u4efb\u52a1\u53ef\u4ee5\u5e76\u884c\u6267\u884c\uff0c\u907f\u514d\u76f8\u4e92\u8986\u76d6\u672a\u63d0\u4ea4\u7684\u53d8\u66f4\u3002\\n\\n## \u9065\u6d4b\\n\\n\u6bcf\u6b21\u5de5\u4f5c\u6d41\u542f\u52a8\u65f6\uff0cArchon \u4f1a\u53d1\u9001\u533f\u540d\u7684 `workflow_invoked` \u4e8b\u4ef6\uff0c\u7528\u4e8e\u5e2e\u52a9\u7ef4\u62a4\u8005\u4e86\u89e3\u9ed8\u8ba4\u5de5\u4f5c\u6d41\u7684\u4f7f\u7528\u60c5\u51b5\u3002\\n\\n\u6536\u96c6\u7684\u6570\u636e\u5305\u62ec\uff1a\\n\\n- \u5de5\u4f5c\u6d41\u540d\u79f0\\n- \u5de5\u4f5c\u6d41\u63cf\u8ff0\\n- \u89e6\u53d1\u5e73\u53f0\uff0c\u4f8b\u5982 `cli`\u3001`web` \u6216 `slack`\\n- Archon \u7248\u672c\\n- \u5b58\u653e\u5728 `~/.archon/telemetry-id` \u7684\u968f\u673a\u5b89\u88c5 UUID\\n\\n\u4e0d\u4f1a\u6536\u96c6\uff1a\\n\\n- \u6e90\u4ee3\u7801\\n- Prompt\u3001\u6d88\u606f\u6216 AI \u8f93\u51fa\\n- Git \u8fdc\u7aef\u3001\u6587\u4ef6\u8def\u5f84\u6216\u7528\u6237\u540d\\n- Token \u6216\u5176\u4ed6\u51ed\u636e\\n- \u5de5\u4f5c\u6d41\u8282\u70b9\u8be6\u60c5\\n\\n\u5173\u95ed\u9065\u6d4b\uff1a\\n\\n```bash\\nARCHON_TELEMETRY_DISABLED=1\\n```\\n\\n\u6216\uff1a\\n\\n```bash\\nDO_NOT_TRACK=1\\n```\\n\\n\u901a\u8fc7\u8bbe\u7f6e `POSTHOG_API_KEY` \u548c `POSTHOG_HOST`\uff0c\u53ef\u5c06\u9065\u6d4b\u53d1\u9001\u5230\u81ea\u6258\u7ba1 PostHog \u6216\u53e6\u4e00 PostHog \u9879\u76ee\u3002\\n\\n## \u9879\u76ee\u6587\u6863\u5165\u53e3\\n\\nREADME \u94fe\u63a5\u5230 [archon.diy](https://archon.diy)\uff0c\u5b8c\u6574\u6587\u6863\u6309\u4ee5\u4e0b\u4e3b\u9898\u7ec4\u7ec7\uff1a\\n\\n- [\u5feb\u901f\u5165\u95e8](https://archon.diy/getting-started/overview/)\\n- [Archon \u4e4b\u4e66](https://archon.diy/book/)\\n- [CLI \u53c2\u8003](https://archon.diy/reference/cli/)\\n- [\u5de5\u4f5c\u6d41\u7f16\u5199](https://archon.diy/guides/authoring-workflows/)\\n- [\u547d\u4ee4\u7f16\u5199](https://archon.diy/guides/authoring-commands/)\\n- [\u914d\u7f6e\u53c2\u8003](https://archon.diy/reference/configuration/)\\n- [AI \u52a9\u624b\u914d\u7f6e](https://archon.diy/getting-started/ai-assistants/)\\n- [\u90e8\u7f72](https://archon.diy/deployment/)\\n- [\u67b6\u6784\u53c2\u8003](https://archon.diy/reference/architecture/)\\n- [\u6545\u969c\u6392\u67e5](https://archon.diy/reference/troubleshooting/)\\n\\n## \u8d21\u732e\u4e0e\u8bb8\u53ef\u8bc1\\n\\n\u8d21\u732e\u524d\u5e94\u9605\u8bfb\u4ed3\u5e93\u4e2d\u7684 [`CONTRIBUTING.md`](CONTRIBUTING.md)\uff0c\u5e76\u901a\u8fc7 GitHub Issues \u67e5\u627e\u53ef\u53c2\u4e0e\u7684\u5de5\u4f5c\u3002\\n\\n\u9879\u76ee\u4f7f\u7528 [MIT License](LICENSE)\u3002\",\"other-sandbox\":\"# Other \u2014 sandbox\\n\\n# Other \u2014 sandbox\\n\\n`@archon/sandbox` provides the E2B-backed execution environment used by workflows, orchestration agents, and sandbox-aware providers. It manages sandbox creation and reuse, repository preparation, command execution, file access, skill installation, streaming output, and sandbox cleanup.\\n\\nThe package is private and exports its TypeScript source directly:\\n\\n```ts\\nimport {\\n  SandboxManager,\\n  SandboxProvider,\\n  StreamParser,\\n  getSandboxFileOps,\\n  pauseSandboxForRun,\\n  releaseSandboxForRun,\\n} from '@archon/sandbox';\\n```\\n\\n## Responsibilities\\n\\nThe module is divided into four main areas:\\n\\n- **`SandboxManager`** \u2014 owns sandbox acquisition, caching, restoration, repositories, commands, skills, and files.\\n- **`SandboxProvider`** \u2014 adapts sandbox command execution to the provider interface used by orchestration and workflow code.\\n- **`StreamParser`** \u2014 converts line-oriented command output into provider message chunks and extracts model/token metadata.\\n- **File and lifecycle helpers** \u2014 provide stateless file handles and best-effort pause/release operations.\\n\\nThe manager persists sandbox associations through an injected `ISandboxStore`; it does not directly depend on a database implementation.\\n\\n## Architecture\\n\\n```mermaid\\nflowchart TD\\n    A[Workflow or orchestrator] --&gt; B[SandboxManager]\\n    A --&gt; C[SandboxProvider]\\n    B --&gt; D[E2B Sandbox]\\n    B --&gt; E[ISandboxStore]\\n    C --&gt; F[runCommand]\\n    F --&gt; G[StreamParser]\\n    G --&gt; H[Message chunks]\\n    I[Lifecycle helper] --&gt; D\\n    I --&gt; E\\n```\\n\\n## Public exports\\n\\n`src/index.ts` exports:\\n\\n```ts\\nexport type {\\n  SandboxRecord,\\n  ISandboxStore,\\n  SandboxConfig,\\n  CreateSandboxParams,\\n} from './types';\\n\\nexport { SandboxManager } from './manager';\\nexport { SandboxProvider } from './provider';\\nexport type { SandboxQueryOptions } from './provider';\\nexport { StreamParser } from './stream-parser';\\n\\nexport {\\n  getSandboxFileOps,\\n  releaseSandboxForRun,\\n  pauseSandboxForRun,\\n} from './file-helpers';\\n```\\n\\n`CreateWorkerSandboxParams` is used internally by `SandboxManager` and `ISandboxStore` integrations, although it is not re-exported from the package entry point.\\n\\n## Sandbox records and storage\\n\\n`SandboxManager` receives an `ISandboxStore` in its constructor. The store is responsible for persisting records with fields represented by `SandboxRecord`, including:\\n\\n- database record ID\\n- conversation ID\\n- E2B sandbox ID\\n- template or image identifier\\n- codebase name\\n- clone path\\n- lifecycle status\\n- timestamps\\n\\nThe manager uses these store operations:\\n\\n- `getByConversationId()` to locate an existing active sandbox\\n- `create()` after creating a new sandbox\\n- `createForWorker()` when a worker conversation inherits a parent sandbox\\n- `updateClonePath()` after deferred repository cloning\\n- `updateStatus()` when a sandbox is released\\n\\nA worker conversation and its parent may have separate records pointing to the same `sandbox_id`. Cleanup therefore accepts multiple conversation IDs and deduplicates the E2B sandbox IDs before killing them.\\n\\n## `SandboxManager`\\n\\n### Construction\\n\\n```ts\\nconst manager = new SandboxManager(store, config);\\n```\\n\\nThe constructor accepts:\\n\\n- an `ISandboxStore`\\n- a `SandboxConfig` containing E2B credentials and sandbox behavior such as:\\n  - `apiKey`\\n  - optional private `domain`\\n  - `template`\\n  - optional `timeoutMs`\\n  - optional `cloneBasePath`\\n  - optional static `envs`\\n  - optional `icodeHost`\\n  - optional `icodeTokenApi`\\n\\nThe manager maintains in-memory state per instance:\\n\\n- `cache` \u2014 reusable sandbox handles keyed by conversation ID\\n- `creating` \u2014 in-flight creation promises, preventing duplicate creation\\n- `cloning` \u2014 in-flight deferred clone promises, preventing duplicate repository clones\\n- `heartbeats` \u2014 reference-counted renewal timers keyed by sandbox ID\\n\\nThe E2B control-plane semaphore is shared across all manager instances in the process. Its default concurrency is 12 and can be changed with:\\n\\n```text\\nSANDBOX_E2B_MAX_CONCURRENCY\\n```\\n\\nInvalid, non-integer, or less-than-one values fall back to 12.\\n\\n### `getOrCreate()`\\n\\n```ts\\nawait manager.getOrCreate(\\n  conversationDbId,\\n  codebases,\\n  runtimeEnvs,\\n  onProgress,\\n  imageOverride\\n);\\n```\\n\\nReturns:\\n\\n```ts\\n{\\n  sbx: Sandbox;\\n  clonePath: string | null;\\n}\\n```\\n\\nThe acquisition flow is:\\n\\n1. Check the in-memory cache.\\n2. Probe the cached E2B handle with `probeCachedSandbox()`.\\n3. If the cached sandbox is running:\\n   - optionally perform deferred cloning\\n   - renew the sandbox when its remaining lifetime is below the renewal threshold\\n   - return the cached handle\\n4. If the cached handle is paused or unavailable, remove it from the cache.\\n5. Look up an active record through `ISandboxStore`.\\n6. For an active record, call `connectOrRebuildAndEnsureCloned()`.\\n7. If no active record exists, deduplicate concurrent creation and call `create()`.\\n\\nA stale cached handle is never returned. This is important because a paused sandbox invalidates the old envd connection. The manager instead reconnects to or restores the same persisted `sandbox_id`.\\n\\n### New sandbox creation\\n\\n`create()` prepares merged environment variables:\\n\\n```ts\\n{\\n  ...(config.envs ?? {}),\\n  ...(runtimeEnvs ?? {}),\\n  CONVERSATION_ID: conversationDbId,\\n}\\n```\\n\\nRuntime values override static configuration values.\\n\\nCreation is delegated to `spawnSandbox()`, which:\\n\\n- calls `Sandbox.create()`\\n- applies `config.template`\\n- passes E2B API credentials and timeout settings\\n- enables PVC-backed storage with `agent-sandbox/usePVC`\\n- configures `lifecycle.onTimeout` as `'pause'`\\n- adds workflow and conversation metadata\\n- optionally routes a custom image through the `agent-sandbox/image` metadata key\\n- waits for Claude Code readiness with `waitForClaude()`\\n\\nOnly sandbox creation and Claude readiness are retried. There are up to two retries after the initial attempt. `onProgress` receives messages such as:\\n\\n```text\\n\u26a0\ufe0f \u6c99\u7bb1\u521b\u5efa\u5931\u8d25\uff0c\u6b63\u5728\u91cd\u8bd5 (1/2)...\\n```\\n\\nRepository cloning is deliberately not retried by the sandbox creation loop. Clone failures generally indicate invalid credentials, an invalid repository, or a command-level problem rather than a transient sandbox creation failure.\\n\\nAfter creation, the manager:\\n\\n1. Initializes the Claude configuration symlink with `initClaudeSymlink()`.\\n2. Clones requested codebases with `cloneAll()`.\\n3. Persists the sandbox record with `store.create()`.\\n4. Caches the sandbox handle.\\n\\n### Reconnecting to an existing sandbox\\n\\n`connectOrRebuild()` uses `Sandbox.getFullInfo()` rather than the E2B connect API. This supports private deployments where the connect endpoint is unavailable.\\n\\nSupported states:\\n\\n- **`running`** \u2014 constructs a `Sandbox` instance from the returned envd connection information, applies the configured timeout, initializes Claude state, and caches the handle.\\n- **`paused`** \u2014 calls `restoreFromPaused()`.\\n- Any other state \u2014 throws an error such as:\\n\\n```text\\nsandbox  is in unexpected state: \\n```\\n\\nIf `getFullInfo()` fails, the error is surfaced to the caller. The manager does not silently create a replacement while an active record still points to the unavailable sandbox.\\n\\n### Paused sandbox restoration\\n\\n`restoreFromPaused()` restores the same sandbox through the private control-plane endpoint:\\n\\n```text\\nPOST http://api./sandboxes//restore\\n```\\n\\nThe request includes:\\n\\n- `X-API-KEY`\\n- JSON content type\\n- a timeout in seconds derived from `config.timeoutMs`\\n\\nA private `config.domain` is required. Without it, restoration throws:\\n\\n```text\\nsandbox  is paused but no domain configured for restore\\n```\\n\\nNon-OK responses also throw, for example:\\n\\n```text\\nsandbox  restore failed: 503\\n```\\n\\nThe restore response supplies the new sandbox ID and envd connection details. The manager constructs a new E2B handle, waits for Claude readiness, initializes the Claude symlink, and preserves the record\u2019s existing `clone_path`. This keeps the repository and intermediate workflow artifacts in place.\\n\\n### Repository cloning\\n\\nRepositories are processed by:\\n\\n```text\\ncloneAll()\\n  \u2192 resolveOrCloneProject()\\n      \u2192 checkoutBranch()     // existing repository\\n      \u2192 cloneProject()       // missing repository\\n```\\n\\nThe destination is based on `cloneBasePath`, defaulting to `/workspace`:\\n\\n```text\\n/\\n```\\n\\nFor an existing PVC-backed repository:\\n\\n- the repository is reused\\n- a requested branch is fetched and checked out\\n- checkout failures are logged and do not invalidate the repository\\n\\nFor a missing repository:\\n\\n1. `cloneProject()` requests an icode Git token from inside the sandbox.\\n2. The token response must contain `data.token`.\\n3. The repository is cloned using the configured icode host.\\n4. The last useful stderr/stdout line is included in clone errors.\\n\\nBranch names are accepted only when they match:\\n\\n```regex\\n^[\\\\w./-]+$\\n```\\n\\nUnsafe branch names are omitted from both clone and checkout commands.\\n\\n### Deferred cloning and concurrency\\n\\nA sandbox can be created before a codebase is known. In that case, its `clonePath` remains `null`.\\n\\nA later call to `getOrCreate()` with codebases invokes `cloneAllOnce()`. The in-flight promise is keyed by conversation ID, so concurrent workflow nodes share one clone operation:\\n\\n```ts\\nconst [first, second] = await Promise.all([\\n  manager.getOrCreate(conversationId, codebases),\\n  manager.getOrCreate(conversationId, codebases),\\n]);\\n```\\n\\nOnly one `git clone` is issued. Both callers receive the resulting clone path.\\n\\nFailure to persist the clone path with `store.updateClonePath()` is logged but does not discard a successful clone. The in-memory result remains usable.\\n\\n### `runScript()`\\n\\n```ts\\nawait manager.runScript(conversationDbId, script, {\\n  cwd,\\n  envs,\\n  runtimeEnvs,\\n  timeoutMs,\\n  codebases,\\n  imageOverride,\\n});\\n```\\n\\n`runScript()` ensures the sandbox and requested repositories exist before running the command.\\n\\nWorking-directory selection is handled by `resolveSandboxCwd()`:\\n\\n- an explicit non-`/workspace` `cwd` is respected\\n- otherwise, an available `clonePath` is preferred\\n- otherwise, the requested/default `/workspace` is used\\n\\nRuntime environment variables and per-command `envs` are merged, with `envs` taking precedence.\\n\\nThe method starts a sandbox renewal heartbeat before invoking `sbx.commands.run()` and stops it in a `finally` block. This happens for both successful and failed commands.\\n\\nA non-zero shell exit produces `SandboxScriptExitError` with:\\n\\n- the exit code\\n- stderr and stdout details\\n- a message in the form:\\n\\n```text\\nbash node failed in sandbox (exit 42): \n\\n```\\n\\nInfrastructure errors from `commands.run()` are rethrown unchanged when no shell exit result is available. The manager does not invent an exit code for transport or E2B service failures.\\n\\n### Sandbox renewal\\n\\nThe manager uses the following renewal policy:\\n\\n- inspect lifetime with `getInfo()`\\n- renew when less than five minutes remain\\n- extend the sandbox to approximately 30 minutes from the current time, accounting for elapsed time since creation\\n- use a two-minute heartbeat while commands are running\\n\\n`startHeartbeat()` uses reference counting per sandbox ID. Concurrent commands share one interval; the timer is removed only after the final caller invokes its returned stop function.\\n\\nThe returned stop function is idempotent. Renewal errors are logged and swallowed so they do not interrupt command execution.\\n\\n### `ensureSkillsInSandbox()`\\n\\n```ts\\nawait manager.ensureSkillsInSandbox(\\n  conversationDbId,\\n  skills,\\n  runtimeEnvs,\\n  onProgress,\\n  imageOverride\\n);\\n```\\n\\nAn empty skills array returns immediately without creating or looking up a sandbox.\\n\\nFor each skill, the manager checks:\\n\\n```sh\\n[ -d \\\"$HOME/.claude/skills/\\\" ] &amp;&amp; echo installed || echo missing\\n```\\n\\nMissing skills are installed with:\\n\\n```sh\\nducc skill install \\n```\\n\\nInstallation:\\n\\n- runs serially to avoid concurrent settings conflicts\\n- retries up to three times\\n- reports progress through `onProgress`\\n- throws the final command or exit-status error if all attempts fail\\n\\nThe check and installation commands receive `runtimeEnvs`.\\n\\n### Claude initialization and token injection\\n\\n`initClaudeSymlink()` ensures:\\n\\n```text\\n/home/developer/.claude \u2192 /workspace/.claude\\n```\\n\\nThe operation is designed to be repeatable and non-destructive:\\n\\n- an existing correct symlink is retained\\n- a real directory is copied into the PVC with `cp -an`\\n- the old directory is removed only after copying\\n- `ln -sfn` establishes the final symlink\\n\\nWhen credentials are provided, the method also attempts to:\\n\\n- write `UGATE_TOKEN` to the per-user UUAP token file\\n- write `GIT_TOKEN` to `~/.netrc` with mode `600`\\n\\nCredential injection failures are logged but do not fail sandbox creation.\\n\\n### File methods on `SandboxManager`\\n\\nThe manager also exposes sandbox-scoped file helpers:\\n\\n- `writeFilesToSandbox()` reads local files and writes them below `/workspace/artifacts`\\n- `writeTextFileToSandbox()` writes text directly to a requested sandbox path\\n- `fileExistsInSandbox()` returns `false` when the E2B existence check fails\\n- `listFiles()` recursively returns file paths and excludes directories; errors result in `[]`\\n- `readFileBytes()` reads with `format: 'bytes'` and returns a `Buffer`\\n\\n`writeFilesToSandbox()`:\\n\\n- returns destination paths\\n- skips unreadable local files\\n- preserves relative subdirectories in each file\u2019s `name`\\n- rejects absolute names and `..` traversal attempts\\n- quotes generated `mkdir -p` directory commands to prevent shell injection\\n\\n## `getSandboxFileOps()`\\n\\n```ts\\nconst files = await getSandboxFileOps(sandboxId, {\\n  apiKey,\\n  domain,\\n});\\n\\nawait files.write('/workspace/result.txt', 'content');\\nconst text = await files.read('/workspace/result.txt');\\nconst present = await files.exists('/workspace/result.txt');\\n```\\n\\nThe returned handle exposes only:\\n\\n```ts\\n{\\n  read(path): Promise;\\n  write(path, content): Promise;\\n  exists(path): Promise;\\n}\\n```\\n\\nIt is intentionally stateless and does not own sandbox lifecycle. Dropping the handle does not kill or close the sandbox. Destruction remains the responsibility of `releaseSandboxForRun()`.\\n\\n`getSandboxFileOps()`:\\n\\n1. Resolves API options from explicit configuration or `E2B_API_KEY` and `E2B_DOMAIN`.\\n2. Calls `Sandbox.getFullInfo()`.\\n3. Constructs an E2B handle using the returned envd credentials.\\n4. Performs file operations through `sbx.files`.\\n\\nAll requests use a ten-minute request timeout. `exists()` converts any E2B error into `false`, which is useful for missing files and unavailable paths.\\n\\nThis helper is used by sandbox file routes, case information routes, workflow export code, and standalone file-operation scripts.\\n\\n## Sandbox lifecycle helpers\\n\\n### `pauseSandboxForRun()`\\n\\n```ts\\nawait pauseSandboxForRun(conversationId, store);\\n```\\n\\nPausing preserves the sandbox filesystem and intermediate artifacts for a possible retry.\\n\\nBehavior:\\n\\n- looks up the conversation record\\n- calls static `Sandbox.pause(record.sandbox_id, apiOpts)`\\n- leaves the database record active\\n- logs and swallows lookup or pause errors\\n\\nIt must not be replaced with `releaseSandboxForRun()` when a retry may occur. Killing the sandbox is irreversible; pausing allows the manager to restore the same sandbox later.\\n\\n### `releaseSandboxForRun()`\\n\\n```ts\\nawait releaseSandboxForRun(conversationId, store);\\n\\nawait releaseSandboxForRun(\\n  [workerConversationId, parentConversationId],\\n  store\\n);\\n```\\n\\nThis is the destructive cleanup path. It:\\n\\n1. Normalizes a single ID or readonly array of IDs.\\n2. Looks up all available records.\\n3. Deduplicates their `sandbox_id` values.\\n4. Calls static `Sandbox.kill()` once per distinct sandbox.\\n5. Marks every retrieved record as `'expired'`.\\n\\nStatic `Sandbox.kill()` is used instead of connecting to the sandbox and calling instance `kill()`. Static control-plane deletion works for both running and paused snapshots, whereas connecting to a paused snapshot may fail.\\n\\nThe function is best-effort and safe for fire-and-forget usage:\\n\\n- store lookup failures are logged\\n- kill failures are logged\\n- status update failures are logged\\n- no error is propagated\\n- records are marked expired even if the E2B kill fails\\n\\n## `SandboxProvider`\\n\\n`SandboxProvider` adapts sandbox command execution to the provider abstraction used by the rest of the application.\\n\\nIts main execution path is:\\n\\n```text\\nsendQuery()\\n  \u2192 runCommand()\\n      \u2192 parseLine()\\n          \u2192 toMessageChunk()\\n              \u2192 extractTokens()\\n```\\n\\nThe provider is used by:\\n\\n- workflow DAG node execution\\n- scheduled task orchestration\\n- title generation\\n- runtime-trace intelligence\\n- UI replay assertion generation\\n\\nIt is created through `buildSandboxProvider()` and participates in provider registry operations through `getType()` and `getCapabilities()`.\\n\\n`SandboxQueryOptions` is exported for callers that need to configure provider queries.\\n\\n## `StreamParser`\\n\\n`StreamParser` handles line-oriented output from sandbox commands. It is instantiated by `SandboxProvider` and used by `runCommand()` to parse each output line.\\n\\nThe parser responsibilities include:\\n\\n- `parseLine()` \u2014 interpret a command-output line\\n- `toMessageChunk()` \u2014 convert parsed data into a provider message chunk\\n- `extractTokens()` \u2014 extract token usage or token-related metadata\\n- `inferSingleModel()` \u2014 infer a model when the stream identifies one\\n- `nonEmptyString()` \u2014 normalize and validate string values used by parsed events\\n\\nA typical provider response path is:\\n\\n```text\\nsandbox command output\\n  \u2192 StreamParser.parseLine()\\n  \u2192 StreamParser.toMessageChunk()\\n  \u2192 provider message stream\\n```\\n\\nMalformed or empty fields are normalized before they reach consumers, preventing empty model or message values from entering the provider stream.\\n\\n## Error and resilience behavior\\n\\nThe module distinguishes between recoverable infrastructure conditions and command failures:\\n\\n- Sandbox creation retries transient `Sandbox.create()` or Claude readiness failures.\\n- Repository clone failures are surfaced and are not retried by sandbox creation.\\n- Existing repository checkout failures are logged, and the current repository state is retained.\\n- Skill installation retries command failures up to three times.\\n- File existence and recursive listing helpers convert lookup failures to safe negative results.\\n- Lifecycle helpers log and swallow failures.\\n- Command exit failures become `SandboxScriptExitError`.\\n- E2B transport failures without an exit result are preserved as infrastructure errors.\\n- Cached paused or dead handles are discarded and reconnected or restored through the persisted record.\\n\\n## Integration points\\n\\nImportant consumers outside this package include:\\n\\n- `buildSandboxProvider()` \u2014 constructs the provider and manager used by orchestration.\\n- `dispatchWorkflowRunToAiKu()` \u2014 obtains sandbox execution and file access.\\n- `createWorkflowDeps()` \u2014 exposes `runScript()`, `listFiles()`, and `readFileBytes()` to workflows.\\n- `dispatchOrchestratorWorkflow()` and `handleMessage()` \u2014 write generated files into the sandbox.\\n- `registerSandboxFileRoutes()` and `registerCaseInfoRoutes()` \u2014 use `getSandboxFileOps()`.\\n- `cancelWorkflowRunAndCloseRuntimeTrace()` \u2014 invokes `releaseSandboxForRun()`.\\n- `workflow-run-actions.ts` \u2014 invokes `pauseSandboxForRun()` when a run may be retried.\\n- `dispatchBackgroundWorkflow()` \u2014 coordinates worker records and shared sandbox IDs.\\n\\n## Development and testing\\n\\nPackage scripts:\\n\\n```sh\\nbun test\\nbun run type-check\\n```\\n\\nThe configured test script runs:\\n\\n```sh\\nbun test src/file-helpers.test.ts\\nbun test src/manager.test.ts\\nbun test src/provider.test.ts\\nbun test src/stream-parser.test.ts\\n```\\n\\nTests mock the `e2b` module before importing the module under test. This is necessary because E2B is used both through static control-plane methods such as `Sandbox.create()`, `Sandbox.getFullInfo()`, `Sandbox.pause()`, and `Sandbox.kill()`, and through constructed sandbox instances.\\n\\nWhen changing lifecycle behavior, update tests for both:\\n\\n- the E2B operation performed\\n- the persisted `SandboxRecord` status and clone path\\n\\nIn particular, preserve the distinction between:\\n\\n- **pause** \u2014 keeps the record active and preserves artifacts\\n- **release** \u2014 kills the sandbox and expires all associated records\\n- **reconnect/restore** \u2014 reuses the existing `sandbox_id` rather than creating a replacement whenever possible\",\"other-schemathesis-reports\":\"# Other \u2014 schemathesis-reports\\n\\n# Other \u2014 schemathesis-reports\\n\\n## Purpose\\n\\nThe `docs/schemathesis-reports` module stores Schemathesis API-conformance test artifacts for the service running at:\\n\\n```text\\nhttp://127.0.0.1:3090\\n```\\n\\nIt is a documentation and test-results module, not executable application code. The artifacts capture failures discovered while testing the OpenAPI-described API through coverage, fuzzing, and stateful testing.\\n\\nThe module contains:\\n\\n- A machine-readable JSON report for automation and detailed analysis.\\n- A Markdown report for human review, triage, and historical comparison.\\n\\nThere are no functions, classes, internal calls, outgoing calls, or incoming calls associated with this module.\\n\\n## Files\\n\\n### `docs/schemathesis-reports/2026-06-04-20-05.json`\\n\\nThe canonical structured report for the run executed at `2026-06-04 20:05`.\\n\\nTop-level fields:\\n\\n| Field | Description |\\n|---|---|\\n| `date` | Report date, `2026-06-04`. |\\n| `failures` | Array of individual Schemathesis failure records. |\\n| `total_ops` | Number of API operations selected for testing: `155`. |\\n| `tested_ops` | Number of selected operations actually tested: `155`. |\\n| `phases` | Per-phase pass, failure, and skip counts. |\\n\\n### `docs/schemathesis-reports/2026-06-04-20-05.md`\\n\\nA Chinese-language, human-readable rendering of the JSON report. It includes:\\n\\n- Run metadata.\\n- Phase summaries.\\n- Failure-type distribution.\\n- Comparison with the previous report.\\n- Individual failure entries with reproduction commands.\\n\\nThe Markdown file is intended for review rather than parsing. When updating tooling, use the JSON report as the source of structured data.\\n\\n## Report model\\n\\nEach entry in `failures` describes one failed check:\\n\\n```json\\n{\\n  \\\"method\\\": \\\"GET\\\",\\n  \\\"path\\\": \\\"/api/uic/search\\\",\\n  \\\"check_name\\\": \\\"response_schema_conformance\\\",\\n  \\\"message\\\": \\\"Response violates schema ...\\\",\\n  \\\"curl\\\": \\\"curl -X GET ...\\\"\\n}\\n```\\n\\n### `method`\\n\\nThe OpenAPI operation method associated with the failure, such as `GET`, `POST`, `PUT`, `PATCH`, or `DELETE`.\\n\\nFor unsupported-method failures, the reproduction command uses `TRACE`. For example, the operation is recorded as:\\n\\n```text\\nPOST /api/auth/logout\\n```\\n\\nbut the command is:\\n\\n```bash\\ncurl -X TRACE ... /api/auth/logout\\n```\\n\\nThis means the report is testing whether the route returns `405 Method Not Allowed` for a method that is not declared in the OpenAPI specification.\\n\\nStateful failures use:\\n\\n```text\\n\\\"method\\\": \\\"Stateful\\\"\\n```\\n\\nbecause they describe a multi-request state transition rather than one OpenAPI operation.\\n\\n### `path`\\n\\nThe OpenAPI route template or route-like path used by the test. The report contains both `{parameter}` and `:parameter` forms, for example:\\n\\n```text\\n/api/workflows/runs/{runId}\\n/api/workflows-v2/:id\\n/api/product-spaces/:productId/groups/:groupId\\n```\\n\\nWhen a concrete request is needed, the `curl` field shows the generated value, such as `/api/workflows/runs/0`.\\n\\n### `check_name`\\n\\nThe Schemathesis check that failed. The run contains the following check types:\\n\\n- `unsupported_method`\\n- `not_a_server_error`\\n- `status_code_conformance`\\n- `positive_data_acceptance`\\n- `response_schema_conformance`\\n- `use_after_free`\\n\\n### `message`\\n\\nThe detailed diagnostic emitted by Schemathesis. It may include:\\n\\n- The received HTTP status.\\n- The statuses documented by OpenAPI.\\n- The expected behavior for unsupported methods.\\n- A schema path and validation error.\\n- Stateful test context.\\n\\n### `curl`\\n\\nA reproducible request generated by Schemathesis. It includes the relevant method, headers, query parameters, and path values.\\n\\nMost requests use the test identity header:\\n\\n```http\\nX-Test-User: admin\\n```\\n\\nJSON operations may also include:\\n\\n```http\\nContent-Type: application/json\\n```\\n\\nSensitive values can be filtered in generated output. For example, the UUAP request contains `[Filtered]` values.\\n\\n## Test phases\\n\\nThe run reports four phases:\\n\\n| Phase | Passed | Failed | Skipped |\\n|---|---:|---:|---:|\\n| Coverage | 26 | 129 | 0 |\\n| Fuzzing | 92 | 63 | 0 |\\n| Stateful | 475 | 30 | 107 |\\n| Examples | 0 | 0 | 156 |\\n\\nThe `Examples` phase was skipped because the OpenAPI document did not define examples.\\n\\n`total_ops` and `tested_ops` refer to API operations, while phase counters refer to generated test cases. Therefore, phase totals should not be added together and compared directly with `total_ops`.\\n\\n```mermaid\\nflowchart LR\\n    Spec[OpenAPI specification] --&gt; S[Schemathesis run]\\n    S --&gt; C[Coverage]\\n    S --&gt; F[Fuzzing]\\n    S --&gt; ST[Stateful]\\n    S --&gt; R[JSON report]\\n    R --&gt; M[Markdown report]\\n```\\n\\n## Failure categories\\n\\nThe Markdown summary groups failures into the following categories:\\n\\n| Category | Count | Meaning |\\n|---|---:|---|\\n| Unsupported HTTP method | 115 | An undeclared method, primarily `TRACE`, returned `404` instead of `405`. |\\n| Server error | 33 | The endpoint returned a server error for generated input. |\\n| Undocumented status code | 32 | The response status was not listed in the OpenAPI operation. |\\n| Valid data rejected | 13 | Schema-compliant generated input was rejected. |\\n| Response schema violation | 2 | The response body did not satisfy its documented schema. |\\n| Resource accessible after deletion | 1 | A deleted resource could still be retrieved. |\\n\\nA single operation can appear more than once because multiple checks may fail for the same request. For example, `POST /api/auth/test-login` has both:\\n\\n- `not_a_server_error`\\n- `status_code_conformance`\\n\\nwith the same reproduction command.\\n\\n## Important findings\\n\\n### Unsupported methods return `404` instead of `405`\\n\\nThis is the dominant failure pattern. Routes across authentication, workflows, evaluations, runtime traces, conversations, product spaces, and codebases return:\\n\\n```text\\nTRACE -&gt; 404\\n```\\n\\nSchemathesis expects:\\n\\n```text\\nTRACE -&gt; 405 Method Not Allowed\\n```\\n\\nAffected examples include:\\n\\n```text\\n/api/auth/config\\n/api/api/health\\n/api/workflows\\n/api/runtime/traces\\n/api/evaluations/workflows/{runId}\\n/api/conversations/{id}\\n```\\n\\nThe report specifically recommends returning `405` for methods not listed in the OpenAPI specification. Implementations should also consider including an `Allow` header containing the supported methods.\\n\\nVerify a route with:\\n\\n```bash\\ncurl -i -X TRACE \\\\\\n  -H 'X-Test-User: admin' \\\\\\n  'http://127.0.0.1:3090/api/health'\\n```\\n\\nThe expected response is an HTTP `405`, not `404`.\\n\\n&gt; Note: The report contains the path `/api/api/health` only as an abbreviated example if copied incorrectly; the actual recorded route is `/api/health`.\\n\\n### Undocumented status codes\\n\\nSeveral operations return statuses that are not declared in their OpenAPI definitions:\\n\\n- `GET /api/auth/uuap/callback`\\n  - Received `200`\\n  - Documented `302`\\n- `GET /api/runtime/traces/alerts?status=AAA`\\n  - Received `400`\\n  - Documented `200, 500`\\n- `GET /api/runtime/traces/archives/compare?left=`\\n  - Received `400`\\n  - Documented `200, 404, 500`\\n- `GET /api/uic/search`\\n  - Received `400`\\n  - Documented `200, 403`\\n- `GET /api/workflows/runs?runQualityScope=AAA`\\n  - Received `400`\\n  - Documented `200, 500`\\n\\nContributors should determine whether the implementation or the OpenAPI contract is authoritative:\\n\\n- If the status represents correct validation behavior, document `400`.\\n- If the endpoint should redirect or normalize the request, fix the handler.\\n- Keep status documentation aligned with actual error handling.\\n\\n### Server errors on generated input\\n\\nThe `not_a_server_error` failures identify operations that produced a server error rather than a handled client or domain response. Examples include:\\n\\n```text\\nPOST /api/conversations\\nPOST /api/auth/test-login\\nPOST /api/auth/token-exchange\\nPOST /api/codebases\\nPOST /api/product-spaces\\nPUT /api/runtime/traces/pricing\\nPATCH /api/config/assistants\\nPOST /api/workflows/{name}/run\\nGET /api/conversations/{id}/messages\\n```\\n\\nReproduce the minimal form first, then inspect application logs:\\n\\n```bash\\ncurl -i -X POST \\\\\\n  -H 'X-Test-User: admin' \\\\\\n  -H 'Content-Type: application/json' \\\\\\n  'http://127.0.0.1:3090/api/conversations'\\n```\\n\\nThe generated request may be intentionally sparse or contain fuzzed query/path values. A server error may indicate missing validation, an unhandled dependency failure, or an invalid assumption about authenticated test data.\\n\\n### Schema-compliant requests are rejected\\n\\nThe `positive_data_acceptance` check reports operations that reject data generated from the declared request schema. Affected endpoints include:\\n\\n```text\\nPOST /api/auth/ugate-token\\nPOST /api/case/info/update\\nPOST /api/workflows-v2\\nPUT /api/auth/icafe-space\\nGET /api/commands\\nGET /api/workflows\\nPUT /api/workflows/{name}\\nDELETE /api/workflows/{name}\\nPOST /api/conversations/{id}/message\\nGET /api/workflows/runs\\n```\\n\\nThese failures do not necessarily indicate that every request is invalid. They indicate a mismatch between the OpenAPI input schema and the handler's accepted input or preconditions.\\n\\nWhen fixing one:\\n\\n1. Copy the generated `curl` request.\\n2. Record the actual response status and body.\\n3. Compare the generated request against the OpenAPI schema.\\n4. Check route-level authorization and resource-existence requirements.\\n5. Either broaden implementation acceptance or tighten the OpenAPI schema.\\n\\n### Response schema violations\\n\\n`GET /api/uic/search?q=0` returned an object missing the required `displayName` property:\\n\\n```json\\n{\\n  \\\"email\\\": \\\"01_zt@baidu.com\\\",\\n  \\\"type\\\": \\\"user\\\",\\n  \\\"username\\\": \\\"01_zt\\\"\\n}\\n```\\n\\nThe documented `UicSearchResult` schema requires:\\n\\n```text\\nusername\\ndisplayName\\nemail\\ntype\\n```\\n\\nThe response handler should populate `displayName`, or the schema should be changed if the field is not guaranteed by the underlying UIC data source.\\n\\nThe stateful run also found a type violation for a conversation response:\\n\\n```text\\n/api/conversations/web-1780574638579-8t62yw\\n```\\n\\nThe `hidden` property was returned as numeric `0`, although the schema requires a Boolean.\\n\\n### Deleted resources remain accessible\\n\\nThe stateful test deleted a conversation and then retrieved it successfully:\\n\\n```text\\nDELETE /api/conversations/web-1780574638579-8t62yw\\nGET    /api/conversations/web-1780574638579-8t62yw\\n```\\n\\nThe second request returned `200 OK`; Schemathesis expected `404 Not Found`.\\n\\nThis indicates either:\\n\\n- The delete operation did not persist the deletion.\\n- The read path uses stale data.\\n- The resource is soft-deleted but the read contract does not document that behavior.\\n- The stateful test is using inconsistent storage or transaction boundaries.\\n\\nThe intended behavior should be made explicit in both the handler and OpenAPI response definitions.\\n\\n## Authentication and external redirects\\n\\nThe report uses the `X-Test-User: admin` header for local requests. Authentication-related endpoints include:\\n\\n```text\\n/api/auth/logout\\n/api/auth/test-login\\n/api/auth/token-exchange\\n/api/auth/ugate-token\\n/api/auth/icafe-space\\n/api/auth/config\\n/api/auth/me\\n/api/auth/uuap\\n/api/auth/uuap/callback\\n```\\n\\n`GET /api/auth/uuap` causes an external authorization request to `https://uuap.baidu.com/authorize`. The report records a filtered cookie and app key. Do not commit unfiltered credentials, cookies, or authorization tokens into future reports.\\n\\nThe callback behavior is expected to redirect with `302`, but the observed request to:\\n\\n```text\\n/login?error=auth_failed\\n```\\n\\nreturned `200`. This should be investigated as a redirect-contract or test-environment issue.\\n\\n## Historical comparison\\n\\nThe Markdown report compares this run with another run on the same date:\\n\\n- New failures: `1`\\n- Fixed failures: `2`\\n- Net change: `-1`\\n\\nNew failure:\\n\\n```text\\nDELETE /api/workflows/{name}\\n```\\n\\nFixed failures:\\n\\n```text\\nPATCH /api/combos/{id}\\nStateful tests \u2014 resource creation followed by access\\n```\\n\\nThe historical comparison is present in the Markdown artifact, but no comparison object is included in the JSON schema. Consumers requiring trend analysis should compare report files by parsing `failures`, normalizing `(method, path, check_name)`, and treating repeated checks on the same operation as separate failure records.\\n\\n## Working with the artifacts\\n\\n### Reproduce a reported failure\\n\\nUse the `curl` value directly, subject to replacing filtered or environment-specific values:\\n\\n```bash\\ncurl -i -X GET \\\\\\n  -H 'X-Test-User: admin' \\\\\\n  'http://127.0.0.1:3090/api/uic/search?q=0'\\n```\\n\\nAdd `-i` or `-v` when investigating status, headers, redirects, or transport behavior.\\n\\n### Triage by check type\\n\\nRecommended order:\\n\\n1. `not_a_server_error` \u2014 unhandled failures can obscure other contract issues.\\n2. `response_schema_conformance` \u2014 response shape and type violations affect clients.\\n3. `status_code_conformance` \u2014 align implementation and OpenAPI status declarations.\\n4. `positive_data_acceptance` \u2014 resolve request-schema and precondition mismatches.\\n5. `unsupported_method` \u2014 fix method fallback behavior consistently at the router or middleware layer.\\n6. `use_after_free` \u2014 verify persistence and deletion semantics in stateful flows.\\n\\n### Avoid treating every failure as an independent defect\\n\\nThe report is generated at test-case granularity. One root cause can produce many failures:\\n\\n- A shared router fallback can account for most of the `unsupported_method` failures.\\n- A common error middleware can account for multiple undocumented `400` statuses.\\n- A shared serialization model can account for several response schema violations.\\n- Missing test fixtures or dependencies can affect many positive-data and server-error checks.\\n\\nGroup failures by shared route subsystem before assigning fixes.\\n\\n## Current scope and limitations\\n\\n- The artifacts describe one run against a local server on port `3090`.\\n- The report does not contain application stack traces or source-level ownership.\\n- No execution flow was detected for this module because it contains static report files only.\\n- The OpenAPI document did not provide examples, so all `Examples` tests were skipped.\\n- Generated fuzzing values can be malformed, empty, Unicode-heavy, or otherwise unusual by design.\\n- Stateful checks depend on test ordering and resource lifecycle; they should not be interpreted as isolated single-request tests.\\n- Reproduction commands may contain placeholder identifiers such as `0`, `:id`, or generated conversation IDs.\\n\\n## Contribution guidance\\n\\nWhen adding a new report:\\n\\n1. Preserve the Schemathesis JSON structure.\\n2. Store it under `docs/schemathesis-reports/` using the timestamped naming convention:\\n   ```text\\n   YYYY-MM-DD-HH-MM.json\\n   YYYY-MM-DD-HH-MM.md\\n   ```\\n3. Keep the Markdown summary synchronized with the JSON data.\\n4. Preserve complete `curl` commands unless they contain secrets; filter credentials and cookies.\\n5. Do not manually remove duplicate failures unless the report-generation process explicitly deduplicates them.\\n6. Update historical comparisons using stable keys based on the operation path and `check_name`.\\n7. Link fixes to the affected API implementation and OpenAPI definition rather than modifying the report to hide a failure.\",\"other-server\":\"# Other \u2014 server\\n\\n# Other \u2014 Server Module\\n\\n`@archon/server` is the Bun-based backend package for Archon. It hosts the HTTP API, authentication and health endpoints, workflow execution interfaces, external integration routes, server-side persistence, and real-time web delivery.\\n\\nThe package entry point is `src/index.ts`:\\n\\n```json\\n{\\n  \\\"main\\\": \\\"./src/index.ts\\\",\\n  \\\"type\\\": \\\"module\\\"\\n}\\n```\\n\\nRun the server locally with:\\n\\n```bash\\nbun run dev\\n```\\n\\nRun the production-style process with:\\n\\n```bash\\nbun run start\\n```\\n\\nThe package uses workspace dependencies for core domain behavior and infrastructure:\\n\\n- `@archon/core` \u2014 database access, message storage, and shared types.\\n- `@archon/workflows` \u2014 workflow execution and `WorkflowEventEmitter`.\\n- `@archon/auth` \u2014 authentication integration.\\n- `@archon/adapters` and `@archon/providers` \u2014 platform and model-provider integrations.\\n- `@archon/git`, `@archon/sandbox`, and `@archon/paths` \u2014 repository, sandbox, and runtime-path/logging support.\\n- `hono` and `@hono/zod-openapi` \u2014 HTTP routing and OpenAPI route definitions.\\n\\n## Server Responsibilities\\n\\nThe server composes several responsibilities:\\n\\n1. **HTTP API registration**\\n   - `startServer` in `src/index.ts` registers route groups such as health, webhooks, knowledge, product spaces, runtime traces, observability, evaluations, workflow APIs, and conversation APIs.\\n   - The API uses Hono/OpenAPI route registration and is tested through route, contract, and scenario suites.\\n\\n2. **Conversation and assistant-message persistence**\\n   - `MessagePersistence` buffers streamed assistant content and tool activity before storing messages through `@archon/core/db/messages`.\\n\\n3. **Server-Sent Events (SSE)**\\n   - `SSETransport` manages conversation SSE subscriptions, fan-out to multiple subscribers, reconnect buffering, and delayed cleanup.\\n\\n4. **Workflow event delivery**\\n   - `WorkflowEventBridge` subscribes to `@archon/workflows/event-emitter`, converts internal workflow events into frontend SSE payloads, and emits them through `SSETransport`.\\n\\n5. **Startup and shutdown lifecycle**\\n   - Server startup creates the transport, persistence layer, and workflow bridge.\\n   - Startup begins periodic persistence flushing and invokes workflow restart recovery through `recoverOrphanedWorkflows`.\\n   - Shutdown flushes buffered messages with `MessagePersistence.flushAll()` and stops transport resources.\\n\\n```mermaid\\nflowchart LR\\n  Client[Web client] --&gt;|HTTP / SSE| Server[src/index.ts]\\n  Server --&gt; Routes[Route modules]\\n  Server --&gt; Transport[SSETransport]\\n  Server --&gt; Persistence[MessagePersistence]\\n  Server --&gt; Bridge[WorkflowEventBridge]\\n  Bridge --&gt; Emitter[WorkflowEventEmitter]\\n  Persistence --&gt; DB[@archon/core/db/messages]\\n  Transport --&gt; Client\\n```\\n\\n## HTTP API Composition\\n\\n`src/index.ts` is the application composition boundary. It wires route registration functions into the server application. The call graph identifies registrations including:\\n\\n- `registerHealthRoutes`\\n- `registerWebhookRoutes`\\n- `registerKnowledgeRoutes`\\n- `registerKnowledgeChatRoutes`\\n- `registerKnowledgeProxyRoutes`\\n- `registerProductSpaceRoutes`\\n\\nThe package also contains routes and corresponding test coverage for domains including:\\n\\n- authentication (`routes/auth.ts`)\\n- conversations and message dispatch\\n- workflows and workflow runs\\n- workflow v2 and commands v2\\n- codebases and combos\\n- providers and configuration\\n- knowledge and knowledge proxy APIs\\n- GitCase, BOS, case information, and InfoFlow\\n- runtime traces, observability, personnel usage, and evaluations\\n- UI replay and sandbox-file APIs\\n- inbound GitHub, Gitea, and GitLab webhooks\\n\\nRoute code should use the shared route helpers such as `registerOpenApiRoute`, `jsonError`, and `apiError` where appropriate. This keeps OpenAPI metadata, validation, and error shape behavior consistent.\\n\\n### API Contract Discipline\\n\\nThe API test layout is intentionally layered:\\n\\n| Test suite | Purpose |\\n| --- | --- |\\n| `src/api-tests/contract.test.ts` | Verifies generated endpoint inventory, source locations, contracts, and coverage ownership. |\\n| Route tests under `src/routes/*.test.ts` | Exercise endpoint-specific behavior. |\\n| `src/api-tests/scenario.test.ts` | Starts a fresh SQLite-backed server and smoke-tests high-value API domains. |\\n\\nRun all API tests with:\\n\\n```bash\\nbun run test:api\\n```\\n\\nRun the complete server test suite with:\\n\\n```bash\\nbun run test\\n```\\n\\n`contract.test.ts` uses `scripts/generate-api-inventory` and compares the result to committed fixtures. When adding, removing, or materially changing endpoints, update the API inventory and coverage matrix expected by this test suite.\\n\\n## Real-Time Web Adapter\\n\\nThe web adapter in `src/adapters/web/` separates three related concerns:\\n\\n| Component | Responsibility |\\n| --- | --- |\\n| `SSETransport` | Maintains live SSE streams, reconnect buffering, event replay, fan-out, and stream cleanup. |\\n| `WorkflowEventBridge` | Maps workflow executor events to frontend SSE events and forwards them through `SSETransport`. |\\n| `MessagePersistence` | Buffers assistant text and tools into frontend-compatible message segments, then persists them. |\\n\\nThe separation is important:\\n\\n- Transport does **not** persist messages.\\n- Persistence does **not** own client connections.\\n- The bridge does **not** execute workflows; it converts and relays workflow-emitter events.\\n\\n## `SSETransport`\\n\\n`SSETransport` in `src/adapters/web/transport.ts` is the server-side delivery layer for SSE streams.\\n\\n### `SSEWriter`\\n\\nA transport stream implements:\\n\\n```ts\\nexport interface SSEWriter {\\n  writeSSE(data: { data: string; event?: string; id?: string }): Promise;\\n  close(): Promise;\\n  readonly closed: boolean;\\n}\\n```\\n\\nThe transport serializes payloads as SSE `data` fields. Callers pass already-serialized JSON strings.\\n\\n### Stream Registration and Fan-Out\\n\\nUse `registerStream(conversationId, stream)` to attach a connection:\\n\\n```ts\\ntransport.registerStream(conversationId, stream);\\n```\\n\\nA conversation can have multiple concurrent streams. Internally, `SSETransport` stores:\\n\\n```ts\\nMap&gt;\\n```\\n\\nThis supports simultaneous subscribers, such as a web application and another UI surface observing the same conversation or workflow. Registering a second stream does not close or replace the first stream.\\n\\n`emit(conversationId, event)` sends an event to every open stream:\\n\\n```ts\\nawait transport.emit(conversationId, JSON.stringify({ type: 'text', content: '...' }));\\n```\\n\\n`emitWorkflowEvent(conversationId, event)` is the fire-and-forget equivalent used by workflow delivery paths:\\n\\n```ts\\ntransport.emitWorkflowEvent(conversationId, event);\\n```\\n\\nBoth methods buffer events when no live subscriber exists.\\n\\n### Disconnect and Reconnect Semantics\\n\\n`removeStream(conversationId, expectedStream?)` removes an individual stream. Supplying the stream instance is important for race safety:\\n\\n```ts\\ntransport.removeStream(conversationId, stream);\\n```\\n\\nThe `expectedStream` guard ensures a stale abort callback cannot remove another, newer stream. This specifically protects rapid reconnect cycles such as those caused by React StrictMode.\\n\\nCleanup occurs only after the **last** stream for a conversation disappears. `SSETransport` schedules the optional `onCleanup` callback after a reconnect grace period:\\n\\n```ts\\nnew SSETransport(onCleanup, graceMs);\\n```\\n\\nThe default grace period is `RECONNECT_GRACE_MS` (`5_000` ms). Re-registering a stream before the timer fires cancels cleanup.\\n\\nThis avoids tearing down conversation-related state while a client is briefly disconnected.\\n\\n### Event Buffering\\n\\nWhen no stream is active, `emit()` and `emitWorkflowEvent()` call `bufferEvent()` rather than dropping the event immediately.\\n\\nBuffer behavior:\\n\\n- Events are retained for `EVENT_BUFFER_TTL_MS` (`60_000` ms).\\n- At most `EVENT_BUFFER_MAX` (`500`) events are retained per conversation.\\n- The oldest event is dropped on overflow.\\n- Overflow warnings use `EVICTION_WARN_THROTTLE_MS` (`5_000` ms) throttling per conversation.\\n- Buffers are replayed only when the stream set transitions from empty to non-empty.\\n- A second concurrent subscriber does not receive a duplicate replay after the first subscriber drains the buffer.\\n- Buffered events are automatically cleared shortly after their TTL expires.\\n\\nThe module enforces this invariant at load time:\\n\\n```ts\\nEVENT_BUFFER_TTL_MS &gt;= RECONNECT_GRACE_MS\\n```\\n\\nThis prevents events emitted during an expected reconnect window from expiring before the client can reconnect.\\n\\n### Failed or Closed Streams\\n\\nThe transport treats `SSEWriter.closed` as authoritative:\\n\\n- Closed streams are pruned during registration and removal.\\n- `hasActiveStream(conversationId)` returns `true` only if at least one stream is open.\\n- Write failures remove and close the failed stream.\\n- A periodic zombie reaper started by `start()` scans stream sets every five minutes and removes closed streams.\\n\\n### Lifecycle\\n\\n```ts\\ntransport.start();\\n```\\n\\n`start()` begins zombie-stream reclamation and logs `web.adapter_ready`.\\n\\n```ts\\ntransport.stop();\\n```\\n\\n`stop()`:\\n\\n- stops the zombie reaper;\\n- closes all open streams;\\n- clears stream state;\\n- cancels pending cleanup timers;\\n- clears buffered events and their timers;\\n- logs `web.adapter_stopped`.\\n\\nCall `stop()` during server shutdown rather than relying on connection teardown alone.\\n\\n## `WorkflowEventBridge`\\n\\n`WorkflowEventBridge` in `src/adapters/web/workflow-bridge.ts` translates events from `WorkflowEventEmitter` into frontend-compatible SSE JSON.\\n\\n### Lifecycle\\n\\nConstruct the bridge with the shared transport:\\n\\n```ts\\nconst bridge = new WorkflowEventBridge(transport);\\nbridge.start();\\n```\\n\\n`start()` obtains the singleton workflow emitter through `getWorkflowEventEmitter()` and subscribes to all `WorkflowEmitterEvent` values.\\n\\nFor each mapped event, the bridge emits to:\\n\\n1. The conversation associated with `event.runId`, when the emitter can resolve one.\\n2. The special `__dashboard__` stream.\\n\\nThis allows a dashboard subscriber to observe workflow activity without attaching to every individual conversation.\\n\\nCall `bridge.stop()` to unsubscribe and clear output callbacks.\\n\\n### Event Mapping\\n\\n`mapWorkflowEvent(event)` is the primary mapper:\\n\\n```ts\\nexport function mapWorkflowEvent(event: WorkflowEmitterEvent): string | null\\n```\\n\\nIt returns a serialized SSE payload or `null` when the event should not reach the workflow SSE channel.\\n\\nKey mappings include:\\n\\n| Workflow event | SSE payload |\\n| --- | --- |\\n| `workflow_started` | `workflow_status` with `status: \\\"running\\\"` |\\n| `workflow_completed` | `workflow_status` with `status: \\\"completed\\\"` |\\n| `workflow_failed` | `workflow_status` with `status: \\\"failed\\\"` and `error` |\\n| `workflow_cancelled` | `workflow_status` with `status: \\\"cancelled\\\"` |\\n| `approval_pending` | paused `workflow_status` with an `approval` payload, except `user_pause`, which sends `approval: null` |\\n| `node_started` | `dag_node` with `status: \\\"running\\\"` |\\n| `node_completed` | `dag_node` with `status: \\\"completed\\\"` |\\n| `node_failed` | `dag_node` with `status: \\\"failed\\\"` and `error` |\\n| `node_skipped` | `dag_node` with `status: \\\"skipped\\\"` or `\\\"completed\\\"` for `reason: \\\"prior_success\\\"` |\\n| `tool_started` | `workflow_tool_activity` with `status: \\\"started\\\"` |\\n| `tool_completed` | `workflow_tool_activity` with `status: \\\"completed\\\"` |\\n| `tool_failed` | `workflow_tool_activity` with `status: \\\"failed\\\"` |\\n| `workflow_artifact` | `workflow_artifact` |\\n| `loop_iteration_*` | `workflow_step` |\\n| `loop_back_*` | `loop_back` |\\n\\nThe mapper normalizes `node_skipped` events with `reason: \\\"when_condition_parse_error\\\"` to the frontend-facing reason:\\n\\n```ts\\n\\\"when_condition\\\"\\n```\\n\\nA skipped node with `reason: \\\"prior_success\\\"` becomes `status: \\\"completed\\\"`, representing successful execution in an earlier attempt or resumed run.\\n\\n### Workflow Model Propagation\\n\\nOnly `workflow_started` forwards its resolved `model` value:\\n\\n```ts\\n{\\n  type: 'workflow_status',\\n  status: 'running',\\n  model: event.model\\n}\\n```\\n\\nCompletion and failure events intentionally omit `model`. The frontend can therefore populate a live model indicator as soon as the run begins without treating terminal events as model updates.\\n\\n### Approval Events\\n\\nFor ordinary approval events, the bridge produces a paused workflow status with:\\n\\n```ts\\n{\\n  approval: {\\n    nodeId: event.nodeId,\\n    message: event.message,\\n    type: event.approvalType ?? 'approval',\\n    inputSchema: event.inputSchema // only when present\\n  }\\n}\\n```\\n\\nFor `approvalType: 'user_pause'`, `approval` is explicitly `null`. This distinguishes a user-initiated pause from a workflow node requiring a response.\\n\\n`loop_back_review_pending` is represented as a paused `workflow_status` with an approval object of type `loop_back_review`. Its payload includes the review exits, pending iteration, and optional interval.\\n\\n### Loop-Back Events\\n\\n`mapWorkflowEventToSse(event)` is a pure mapper for internal loop-back events:\\n\\n```ts\\nexport function mapWorkflowEventToSse(\\n  event: LoopBackInternalEvent\\n): LoopBackSseEvent | null\\n```\\n\\nIt converts snake_case executor data into camelCase frontend data.\\n\\nFor example, `loop_back_triggered` becomes:\\n\\n```ts\\n{\\n  type: 'loop_back',\\n  exitNode: 'test',\\n  to: 'dev',\\n  iteration: 2,\\n  interval: ['dev', 'review', 'test'],\\n  status: 'triggered'\\n}\\n```\\n\\n`loop_back_exhausted` may include `max`, sourced from `max_iterations`. `loop_back_resolved` represents a converged feedback loop.\\n\\n### Knowledge Observability Boundary\\n\\nThe bridge deliberately returns `null` for these workflow events:\\n\\n- `knowledge_retrieval_started`\\n- `knowledge_retrieval_completed`\\n- `knowledge_context_injected`\\n- `knowledge_capsule_created`\\n\\nThese events remain in restricted runtime evidence storage. Do not add them to the workflow SSE stream without preserving the intended redaction and access-control boundary.\\n\\n### Worker-to-Parent Bridging\\n\\n`bridgeWorkerEvents(workerConversationId, parentConversationId)` subscribes to events for a worker conversation and forwards mapped SSE events to its parent conversation:\\n\\n```ts\\nconst unsubscribe = bridge.bridgeWorkerEvents(workerConversationId, parentConversationId);\\n```\\n\\nThe returned unsubscribe function must be called when the worker-to-parent association is no longer needed.\\n\\nThe bridge also supports prompt persistence after workflow progress transitions:\\n\\n```ts\\nbridge.setStepTransitionCallback(workerConversationId =&gt; {\\n  // flush worker conversation persistence\\n});\\n```\\n\\nThe callback runs for:\\n\\n- `loop_iteration_completed`\\n- `loop_iteration_failed`\\n- `node_completed`\\n- `node_failed`\\n\\nThis allows workflow logs to be persisted promptly instead of waiting for the 30-second periodic persistence flush.\\n\\n### Output Callbacks\\n\\n`WorkflowEventBridge` has a separate callback mechanism for output text:\\n\\n```ts\\nbridge.registerOutputCallback(conversationId, callback);\\nbridge.emitOutput(conversationId, text);\\nbridge.removeOutputCallback(conversationId);\\n```\\n\\n`emitOutput()` catches callback failures and logs `output_callback_failed`, so a UI callback error cannot interrupt workflow event processing.\\n\\n`clearConversation(conversationId)` removes the associated output callback.\\n\\n## `MessagePersistence`\\n\\n`MessagePersistence` in `src/adapters/web/persistence.ts` turns streamed assistant output into durable message rows.\\n\\nIt is intentionally segment-based: one buffered segment becomes one assistant message row. This preserves the structure that the frontend uses for live chat rendering, especially text/tool/text interleaving.\\n\\n### Construction and Conversation Identity Mapping\\n\\nCreate the persistence layer with an event-emission callback:\\n\\n```ts\\nconst persistence = new MessagePersistence(emitEvent);\\n```\\n\\nThe callback is used to warn a connected client when database persistence fails.\\n\\nBefore a conversation can be persisted, map its platform conversation ID to a database UUID:\\n\\n```ts\\npersistence.setConversationDbId(platformConversationId, dbId);\\n```\\n\\nInternally:\\n\\n```ts\\nMap\\n```\\n\\nis separate from the assistant content buffer.\\n\\n### Buffer Shape\\n\\nEach conversation has an `AssistantBuffer` containing ordered `BufferedSegment` values. A segment contains:\\n\\n- `content`\\n- `toolCalls`\\n- optional `category`\\n- optional workflow metadata:\\n  - `workflowStatus`\\n  - `workflowDispatch`\\n  - `workflowResult`\\n  - `workflowAuthoringRecovery`\\n\\nTool calls retain:\\n\\n- `name`\\n- `input`\\n- `startedAt`\\n- optional `duration`\\n- optional `output`\\n\\nDuring flushing, the internal `startedAt` field is not persisted.\\n\\n### Appending Text\\n\\nUse `appendText()` for assistant text:\\n\\n```ts\\npersistence.appendText(conversationId, message, metadata);\\n```\\n\\nThe method merges text into the current segment unless a new segment is necessary.\\n\\nA new segment is created when:\\n\\n1. The conversation has no existing segments.\\n2. `metadata.segment === 'new'`.\\n3. The preceding segment has tool calls.\\n4. The new text is a workflow status or workflow dispatch status.\\n5. The preceding segment is a workflow status or workflow dispatch status.\\n\\nThis ensures, for example, that text after a tool call becomes a new frontend message rather than appearing inside the preceding tool message.\\n\\n#### Excluded Categories\\n\\nThese categories are intentionally not persisted:\\n\\n```ts\\n'tool_call_formatted'\\n'isolation_context'\\n```\\n\\nThey are logged and dropped by `appendText()`.\\n\\n#### Workflow Status Deduplication\\n\\nWorkflow status entries are deduplicated using:\\n\\n```ts\\n`${workflowStatus.runId}:${workflowStatus.statusType}`\\n```\\n\\nIf a segment with the same workflow run and status type is already buffered, later duplicate status text is ignored. This prevents duplicate workflow status bubbles in persisted chat history.\\n\\n#### Overflow Protection\\n\\nIf the segment count exceeds 50, `appendText()` triggers a best-effort asynchronous `flush(conversationId)` and logs `assistant_buffer_overflow`.\\n\\nThis is a safety valve, not the normal flush mechanism. Contributors should preserve the bounded-buffer behavior when changing segmentation logic.\\n\\n### Appending Tool Calls and Results\\n\\nAdd a tool call with:\\n\\n```ts\\npersistence.appendToolCall(conversationId, {\\n  name: 'bash',\\n  input: { command: 'ls' }\\n});\\n```\\n\\nIf no text segment exists, the method creates an empty segment to hold the tool call.\\n\\nWhen a new tool call arrives in the same segment, the preceding unfinished tool receives a duration based on `Date.now() - startedAt`.\\n\\nAdd a result with:\\n\\n```ts\\npersistence.appendToolResult(conversationId, 'bash', output, duration);\\n```\\n\\nTool results are matched by tool name, scanning from the most recent segment backwards and selecting the last unresolved matching tool call. This is essential when multiple calls use the same tool name.\\n\\nAn empty string output is preserved:\\n\\n```ts\\noutput: ''\\n```\\n\\nThe code intentionally checks:\\n\\n```ts\\ntc.output !== undefined\\n```\\n\\nrather than relying on truthiness.\\n\\nIf there is no buffer or no unresolved matching tool call, the operation is a non-throwing no-op with a warning log.\\n\\n### Finalizing Running Tools\\n\\n```ts\\npersistence.finalizeRunningTools(conversationId);\\n```\\n\\nassigns elapsed durations to the final unresolved tool in each buffered segment. It is intended for lock release or another terminal boundary where a tool may not receive an explicit result event.\\n\\n`flush()` also pre-finalizes final tools before deciding which segments are ready to persist. This ensures terminal tool calls are not indefinitely treated as in-flight.\\n\\n### Flushing\\n\\n```ts\\nawait persistence.flush(conversationId);\\n```\\n\\nFlush behavior is designed around concurrency safety.\\n\\n#### Snapshot Before Awaiting I/O\\n\\n`flush()` obtains the current buffer and clears or detaches it from `assistantBuffer` **before** importing `addMessage` or awaiting database writes.\\n\\nThis prevents a race such as:\\n\\n1. A flush begins for buffered `\\\"hello\\\"`.\\n2. New streamed text `\\\"world\\\"` arrives before the database write finishes.\\n3. The new text must create a fresh buffer rather than being lost when the original flush completes.\\n\\nThis behavior is a critical invariant. Do not move buffer clearing after an `await`.\\n\\n#### Pending Tool Segments\\n\\nSegments with truly in-flight tool calls remain buffered so a later `appendToolResult()` can locate them. Completed segments are placed in the ready set and persisted.\\n\\nBefore this split, the final tool in each segment is assigned a duration when necessary. In practice, this makes terminal tool calls flushable even when no `appendToolResult()` arrives.\\n\\n#### Missing Database ID\\n\\nIf no database UUID is known, `flush()` does not drop ready segments. Instead, it restores them to the buffer, preserving their order ahead of any newly arrived segments.\\n\\nThis handles races between streamed assistant content and conversation creation.\\n\\n#### Database Writes\\n\\nFor each ready, non-empty segment, `flush()` dynamically imports:\\n\\n```ts\\n@archon/core/db/messages\\n```\\n\\nand calls:\\n\\n```ts\\naddMessage(dbId, 'assistant', seg.content, metadata);\\n```\\n\\nMetadata includes only present values:\\n\\n```ts\\n{\\n  toolCalls,\\n  workflowStatus,\\n  workflowDispatch,\\n  workflowResult,\\n  workflowAuthoringRecovery\\n}\\n```\\n\\nA segment with neither text nor tools is skipped.\\n\\n#### Persistence Failures\\n\\nIf persistence throws, `flush()` logs `message_persistence_failed` and invokes the constructor-supplied `emitEvent` callback with a warning event:\\n\\n```ts\\n{\\n  type: 'warning',\\n  message: 'Assistant response could not be saved to history',\\n  timestamp: Date.now()\\n}\\n```\\n\\nThe warning emission is deliberately fire-and-forget. A database persistence failure should not cause a second failure path to interrupt the active response flow.\\n\\n### Retraction\\n\\n```ts\\npersistence.retractLastSegment(conversationId);\\n```\\n\\nUse this when an upstream `emitRetract` event means the most recent streamed text should not enter history.\\n\\nBehavior differs by segment contents:\\n\\n- A text-only final segment is removed.\\n- A final segment with tool calls remains, but its text is cleared.\\n- No buffer is a no-op.\\n\\nTool activity is preserved even if surrounding assistant text is retracted.\\n\\n### Cleanup and Periodic Flush\\n\\n```ts\\nawait persistence.clearConversation(conversationId);\\n```\\n\\n`clearConversation()` attempts a flush first, then removes both buffered content and the platform-to-database ID mapping.\\n\\n```ts\\nawait persistence.flushAll();\\n```\\n\\n`flushAll()` snapshots current conversation IDs and uses `Promise.allSettled()` so one failed conversation flush does not prevent other conversations from flushing.\\n\\nPeriodic flushing is controlled by:\\n\\n```ts\\npersistence.startPeriodicFlush();\\npersistence.stopPeriodicFlush();\\n```\\n\\n`startPeriodicFlush()` is idempotent and flushes every 30 seconds. `stopPeriodicFlush()` is safe when no timer exists and can be called repeatedly.\\n\\nFor test or process-wide reset scenarios:\\n\\n```ts\\npersistence.clearAll();\\n```\\n\\nclears in-memory buffers and database-ID mappings without attempting persistence.\\n\\n## Logging Pattern\\n\\nThe web adapter modules use lazy logger creation:\\n\\n```ts\\nlet cachedLog: ReturnType | undefined;\\n\\nfunction getLog(): ReturnType {\\n  if (!cachedLog) cachedLog = createLogger('adapter.web.transport');\\n  return cachedLog;\\n}\\n```\\n\\nThe same pattern appears in:\\n\\n- `adapter.web.transport`\\n- `adapter.web.persistence`\\n- `adapter.web.bridge`\\n\\nLazy initialization is intentional: tests mock `@archon/paths` before importing the module under test. Creating module-level loggers eagerly would bypass those mocks.\\n\\nWhen adding a logger to these modules, preserve lazy initialization unless there is a compelling reason not to.\\n\\n## External Integration Paths\\n\\nThe server package contains integration clients and route adapters for external services.\\n\\n### Webhooks\\n\\n`registerWebhookRoutes` accepts `WebhookAdapters` for GitHub, Gitea, and GitLab. Each adapter exposes `handleWebhook(...)`.\\n\\nWebhook route behavior includes required signature or token validation:\\n\\n- GitHub requires `x-hub-signature-256`.\\n- Gitea requires `x-gitea-signature`.\\n- GitLab requires `x-gitlab-token`.\\n\\nThe scenario test constructs an `OpenAPIHono` app with fake adapters to verify that valid payloads reach the expected adapter and missing verification headers return `400`.\\n\\n### GitCase and BOS\\n\\nThe package includes `gitcase-client.ts` and `bos-client.ts` for external case-management and object-storage calls. Related route tests cover request handling and client tests cover request construction.\\n\\nWhen changing external-client behavior, keep transport concerns in the client module and route validation/authentication concerns in the route module.\\n\\n### InfoFlow and SLA Notifications\\n\\nThe package supports InfoFlow routes and services, including:\\n\\n- `src/services/infoflow-webhook.test.ts`\\n- `src/services/sla-infoflow-notifier.test.ts`\\n- `src/workers/sla-infoflow-worker.ts`\\n\\nRun the notifier worker with:\\n\\n```bash\\nbun run start:sla-notifier\\n```\\n\\nThe SLA backfill script is available as:\\n\\n```bash\\nbun run backfill:sla\\n```\\n\\n## Workflow Recovery\\n\\nDuring startup, `startServer` invokes `recoverOrphanedWorkflows` from `src/services/workflow-restart-recovery.ts`.\\n\\nThis is the recovery boundary for workflow runs left unfinished by a prior server process. It should remain part of startup sequencing so restart behavior is not dependent on a client reconnecting or manually revisiting a workflow page.\\n\\nWorkflow run access and action logic is separated into services such as:\\n\\n- `workflow-access.ts`\\n- `workflow-run-actions.ts`\\n- `workflow-restart-recovery.ts`\\n- `workflow-run-exporter.ts`\\n\\nRoutes should delegate authorization, state transition, and recovery logic to these services instead of reimplementing it inline.\\n\\n## Development and Contribution Guidelines\\n\\n### Adding a New Workflow Event\\n\\nTo expose a new `WorkflowEmitterEvent` to the frontend:\\n\\n1. Add an exhaustive branch in `mapWorkflowEvent()`.\\n2. Return a stable, frontend-consumable JSON payload or explicitly return `null`.\\n3. Include `runId` and `timestamp` where the event is part of workflow stream state.\\n4. Add mapper tests in `workflow-bridge.test.ts`.\\n5. Consider whether the event belongs on:\\n   - the conversation stream,\\n   - the `__dashboard__` stream,\\n   - restricted persistence only,\\n   - or none of these channels.\\n\\nDo not forward restricted knowledge-observability events without reviewing the access-control and redaction implications.\\n\\n### Changing SSE Behavior\\n\\nWhen changing `SSETransport`, preserve these guarantees:\\n\\n- Multiple subscribers per conversation coexist.\\n- A stale disconnect callback cannot remove another stream.\\n- Cleanup runs only after the last subscriber leaves.\\n- A reconnect within the grace interval cancels cleanup.\\n- Events emitted during a no-stream interval can replay on reconnection.\\n- Replay occurs only once per empty-to-non-empty transition.\\n- Buffer TTL remains greater than or equal to reconnect grace.\\n- Failed writes remove failed streams without affecting healthy subscribers.\\n\\nTests in `transport.test.ts` cover fan-out, reconnection cleanup, buffer overflow warning throttling, failed writes, and shutdown.\\n\\n### Changing Assistant Persistence\\n\\nWhen modifying `MessagePersistence`, preserve these guarantees:\\n\\n- Buffers are detached before asynchronous database work.\\n- New text arriving during a flush is retained in a fresh buffer.\\n- A missing database ID restores, rather than drops, ready segments.\\n- Tool output matches the most recent unresolved call with the requested name.\\n- Empty tool output remains distinct from missing output.\\n- Retraction preserves tool-call records.\\n- Workflow status deduplication uses workflow run ID and status type.\\n- Text after a tool call starts a new segment.\\n- Periodic flush lifecycle methods remain idempotent and safe to repeat.\\n\\nThe focused persistence tests in `persistence.test.ts` document these edge cases and should be updated alongside behavioral changes.\\n\\n## Commands\\n\\n```bash\\n# Development server with file watch\\nbun run dev\\n\\n# Start server\\nbun run start\\n\\n# Run all server tests\\nbun run test\\n\\n# Run API contract, route, and scenario tests\\nbun run test:api\\n\\n# Run TypeScript checking\\nbun run type-check\\n\\n# Configure authentication\\nbun run setup-auth\\n\\n# Run SLA notifier worker\\nbun run start:sla-notifier\\n\\n# Backfill SLA classifications\\nbun run backfill:sla\\n```\",\"other-testing\":\"# Other \u2014 testing\\n\\n# Other \u2014 Testing\\n\\nThe `docs/testing` module documents and supports API contract testing, Specmatic integration, externalized API examples, and browser-based UI replay quality checks.\\n\\nIt is a documentation-and-tooling module rather than a runtime package. The primary implementation lives under `packages/server/src/api-tests`, `packages/server/src/routes`, and `packages/web/e2e`; this module defines how those tests are run, what they cover, and how API and UI changes are validated.\\n\\n## Testing Architecture\\n\\nThe project uses multiple complementary test layers:\\n\\n```mermaid\\nflowchart LR\\n    Routes[Server routes] --&gt; Inventory[API inventory]\\n    Routes --&gt; OpenAPI[Generated OpenAPI]\\n    Inventory --&gt; Contract[Contract gate]\\n    OpenAPI --&gt; Specmatic[Specmatic tests]\\n    Routes --&gt; RouteTests[Route tests]\\n    Server[Fresh SQLite server] --&gt; Scenario[Scenario tests]\\n    Web[Web app] --&gt; Playwright[UI replay tests]\\n```\\n\\nEach layer has a different responsibility:\\n\\n| Layer | Main entry point | Responsibility |\\n|---|---|---|\\n| API inventory and contract | `bun run test:api:contract` | Detect endpoint, schema, source, and coverage-matrix drift |\\n| Route tests | `bun run test:api:routes` | Test handlers, success paths, failure paths, and mocked integrations |\\n| Scenario tests | `bun run test:api:scenario` | Exercise real server flows against fresh SQLite |\\n| Full API gate | `bun run test:api` | Run contract, route, and scenario tests together |\\n| Aiflow scenarios | `bun run test:aiflow:scenario` | Run deterministic Aiflow framework checks and optional external pytest scenarios |\\n| Specmatic | `docs/testing/specmatic-test.sh` | Execute OpenAPI contract tests against a running server |\\n| UI replay | `bun run test:e2e` | Run Playwright browser smoke tests and collect quality evidence |\\n\\nSpecmatic complements the existing API gate. It does not replace inventory, route, or scenario tests.\\n\\n## API Test Gate\\n\\n### Coverage standard\\n\\nEvery server endpoint must be represented in both:\\n\\n```text\\npackages/server/src/api-tests/fixtures/expected-endpoints.json\\npackages/server/src/api-tests/fixtures/coverage-matrix.json\\n```\\n\\nThe endpoint inventory records:\\n\\n- HTTP method and path\\n- Source kind: OpenAPI, raw Hono, or OpenAPI document\\n- Route source file and line\\n- Authentication expectation\\n- Request inputs\\n- Response outputs\\n\\nThe coverage matrix assigns ownership to endpoint behavior:\\n\\n- `contract`: inventory and schema drift checks lock the endpoint\\n- `route`: handler-level tests cover success and important failure cases\\n- `scenario`: a real server scenario covers the endpoint in a user flow\\n- `external`: external dependency behavior is covered by a mock or environment-gated test\\n\\nThe contract gate enforces behavior-owner floors:\\n\\n- Every endpoint with a `route` owner must have route coverage.\\n- Every endpoint with a `scenario` owner must have scenario coverage.\\n\\nRoute ownership is inferred from the route source file and its matching route test file. Scenario ownership is explicit in:\\n\\n```text\\npackages/server/src/api-tests/scenario.test.ts\\n```\\n\\n### API test commands\\n\\nRun the fast inventory and schema gate:\\n\\n```bash\\nbun run test:api:contract\\n```\\n\\nUse this after changing route registration, route schemas, or the inventory generator.\\n\\nRun route-level tests:\\n\\n```bash\\nbun run test:api:routes\\n```\\n\\nRun the fresh SQLite scenario suite:\\n\\n```bash\\nbun run test:api:scenario\\n```\\n\\nRun the complete API gate:\\n\\n```bash\\nbun run test:api\\n```\\n\\nThe route suite includes mocked external dependency coverage for:\\n\\n- BOS upload, download, and preview\\n- InfoFlow send\\n- Knowledge proxy forwarding, build, and rebuild\\n- GitHub, Gitea, and GitLab webhook receivers\\n\\nThese tests are deterministic and do not require live external services.\\n\\n### Updating endpoint fixtures\\n\\nRegenerate fixtures after adding, deleting, renaming, or changing an API endpoint:\\n\\n```bash\\nbun run scripts/generate-api-inventory.ts --write-fixtures\\n```\\n\\nThen validate the generated output:\\n\\n```bash\\nbun run scripts/generate-api-inventory.ts --check\\nbun run test:api:contract\\n```\\n\\nDo not modify `expected-endpoints.json` merely to suppress a failure. An endpoint change should also include the appropriate route or scenario test and a meaningful update to `coverage-matrix.json`.\\n\\n### Gate trigger points\\n\\nPre-commit runs the contract gate only when staged files include API routes, API tests, or the inventory script. This keeps normal commits fast while detecting endpoint drift.\\n\\nCI runs:\\n\\n```bash\\nbun run test:api\\n```\\n\\non Linux. The regular test suite continues to run through:\\n\\n```bash\\nbun run test\\n```\\n\\nNightly or release validation may add environment-gated live checks for BOS, InfoFlow, Knowledge service, webhooks, or browser scenarios. Real external calls must remain behind explicit environment flags.\\n\\n## API Example Fixtures\\n\\nThe files under `docs/testing/examples/` are Specmatic external examples. Each JSON file contains an HTTP request and the expected HTTP response:\\n\\n```json\\n{\\n  \\\"http-request\\\": {\\n    \\\"method\\\": \\\"GET\\\",\\n    \\\"path\\\": \\\"/api/codebases/nonexistent-id\\\",\\n    \\\"headers\\\": {\\n      \\\"X-Test-User\\\": \\\"admin\\\"\\n    }\\n  },\\n  \\\"http-response\\\": {\\n    \\\"status\\\": 404,\\n    \\\"headers\\\": {\\n      \\\"Content-Type\\\": \\\"application/json\\\"\\n    },\\n    \\\"body\\\": {\\n      \\\"error\\\": \\\"Codebase not found\\\"\\n    }\\n  }\\n}\\n```\\n\\nExamples serve two purposes:\\n\\n1. They provide concrete request/response scenarios for contract execution.\\n2. They document expected behavior for common empty-state and error cases.\\n\\nThe current examples cover several categories:\\n\\n- Authentication and user state:\\n  - `get_auth_me.json`\\n  - `get_icafe_space.json`\\n  - `get_ugate_token.json`\\n  - `delete_ugate_token.json`\\n- Configuration:\\n  - `get_config.json`\\n  - `patch_config_assistants.json`\\n  - `get_settings_me.json`\\n- Conversations:\\n  - `get_conversations.json`\\n  - `post_conversations.json`\\n  - `delete_conversations.json`\\n- Codebases:\\n  - `get_codebases.json`\\n  - `get_codebase_by_id_404.json`\\n  - `delete_codebase_by_id_404.json`\\n  - environment-variable examples\\n- Runtime traces and analytics:\\n  - trace lists, health, alerts, archives, aggregates, anomalies, and trends\\n- Evaluations:\\n  - golden samples, human feedback, workflow lists, aggregates, and missing-run behavior\\n- UI replay and workflow endpoints:\\n  - recording, governance, audit, workflow, and not-found examples\\n\\nProtected endpoint examples generally use:\\n\\n```http\\nX-Test-User: admin\\n```\\n\\nThe test server must have test authentication enabled for this header to work.\\n\\n## Specmatic Contract\\n\\nThe minimal OpenAPI contract is:\\n\\n```text\\ndocs/testing/specmatic-doarchon.yaml\\n```\\n\\nIt currently describes low-dependency health, authentication, provider, configuration, conversation, codebase, trace, evaluation, UI replay, Gitcase, and workflow endpoints.\\n\\nThe contract contains:\\n\\n- OpenAPI `3.0.3` metadata\\n- Request and response schemas\\n- Inline examples for selected public endpoints\\n- `X-Test-User` header parameters for protected endpoints\\n- Path parameters such as `{id}`, `{traceId}`, `{runId}`, `{name}`, and `{platformId}`\\n- Error responses for representative not-found and validation scenarios\\n\\nThe first group of endpoints is intentionally small and stable:\\n\\n- `GET /health`\\n- `GET /health/concurrency`\\n- `GET /api/health`\\n- `GET /api/auth/config`\\n- `POST /api/auth/test-login`\\n- `POST /api/auth/logout`\\n- `GET /api/providers`\\n\\nThe contract also includes protected API examples such as `GET /api/config`, `GET /api/conversations`, and runtime trace endpoints.\\n\\nThe service generates OpenAPI through the Hono/Zod route registration layer. In the server code:\\n\\n- `packages/server/src/routes/api.ts` registers `GET /api/openapi.json`.\\n- `packages/server/src/routes/api/helpers.ts` provides `registerOpenApiRoute()` for registering Zod-backed OpenAPI routes.\\n- The web package uses the generated document to produce API types.\\n\\nThe Specmatic contract should therefore be treated as a tested contract snapshot or focused integration contract, not as a second independently maintained route inventory.\\n\\n## Running Specmatic\\n\\n### Prerequisites\\n\\nThe Docker workflow requires:\\n\\n```bash\\ndocker --version\\nbun --version\\n```\\n\\nThe manual workflow uses:\\n\\n- Port `3091` for the isolated doarchon test server\\n- Port `9000` for the Specmatic mock server\\n\\nCheck both ports before starting:\\n\\n```bash\\nlsof -nP -iTCP:3091 -sTCP:LISTEN\\nlsof -nP -iTCP:9000 -sTCP:LISTEN\\n```\\n\\nUsing `3091` avoids accidentally reusing a local server on `3090` that may not have test authentication enabled.\\n\\n### Start a test server\\n\\n```bash\\nTEST_AUTH_ENABLED=true \\\\\\nPORT=3091 \\\\\\nHOST=0.0.0.0 \\\\\\nDATABASE_URL='' \\\\\\nWEB_UI_DEV=true \\\\\\nKNOWLEDGE_API_URL=http://127.0.0.1:1 \\\\\\nLOG_LEVEL=info \\\\\\nbun run start\\n```\\n\\nValidate readiness:\\n\\n```bash\\ncurl http://127.0.0.1:3091/health\\ncurl http://127.0.0.1:3091/api/auth/config\\n```\\n\\nExpected authentication configuration:\\n\\n```json\\n{\\n  \\\"testAuthEnabled\\\": true\\n}\\n```\\n\\nTest login:\\n\\n```bash\\ncurl -X POST http://127.0.0.1:3091/api/auth/test-login \\\\\\n  -H 'Content-Type: application/json' \\\\\\n  -d '{\\\"role\\\":\\\"admin\\\"}'\\n```\\n\\nThe response should contain a `token`. `TEST_AUTH_ENABLED=true` must never be used in production.\\n\\n### Run the one-shot script\\n\\nThe supported convenience script is:\\n\\n```bash\\n./docs/testing/specmatic-test.sh\\n```\\n\\nIt performs the following steps:\\n\\n1. Checks for Docker, Bun, the contract file, and an available service port.\\n2. Starts a test server with SQLite and test authentication.\\n3. Waits for `/health` to become available.\\n4. Runs Specmatic in Docker.\\n5. Prints the Specmatic result and API coverage report.\\n6. Stops the background server through an `EXIT` trap.\\n\\nOverride the service port with:\\n\\n```bash\\nSPECMATIC_SERVICE_PORT=3092 ./docs/testing/specmatic-test.sh\\n```\\n\\nThe script exits with:\\n\\n- `0` when all reported contract tests pass\\n- `1` when failures are detected\\n\\n### Run Specmatic manually\\n\\nRun contract tests against the real service:\\n\\n```bash\\ndocker run --rm \\\\\\n  -v \\\"$PWD/docs/testing/specmatic-doarchon.yaml:/specmatic-doarchon.yaml:ro\\\" \\\\\\n  specmatic/specmatic test /specmatic-doarchon.yaml \\\\\\n  --testBaseURL=http://host.docker.internal:3091\\n```\\n\\nOn Linux, add the host gateway mapping:\\n\\n```bash\\ndocker run --rm \\\\\\n  --add-host=host.docker.internal:host-gateway \\\\\\n  -v \\\"$PWD/docs/testing/specmatic-doarchon.yaml:/specmatic-doarchon.yaml:ro\\\" \\\\\\n  specmatic/specmatic test /specmatic-doarchon.yaml \\\\\\n  --testBaseURL=http://host.docker.internal:3091\\n```\\n\\n### Run a Specmatic mock server\\n\\n```bash\\ndocker run --rm \\\\\\n  -v \\\"$PWD/docs/testing/specmatic-doarchon.yaml:/specmatic-doarchon.yaml:ro\\\" \\\\\\n  -p 9000:9000 \\\\\\n  specmatic/specmatic mock /specmatic-doarchon.yaml \\\\\\n  --host=0.0.0.0 \\\\\\n  --port=9000\\n```\\n\\nThe mock server generates responses from schemas and examples. It is useful for consumer development and API exploration; it does not replace tests against the real server.\\n\\n## Specmatic Coverage Reporting\\n\\n`docs/testing/specmatic-coverage.sh` compares route declarations in:\\n\\n```text\\npackages/server/src/routes\\n```\\n\\nwith operations declared in:\\n\\n```text\\ndocs/testing/specmatic-doarchon.yaml\\n```\\n\\nThe script detects both:\\n\\n```ts\\ncreateRoute({\\n  method: 'get',\\n  path: '/api/example'\\n})\\n```\\n\\nand raw Hono registrations such as:\\n\\n```ts\\napp.get('/api/example', handler)\\n```\\n\\nIt groups operations by API module and prints:\\n\\n- Total operations\\n- Covered operations\\n- Uncovered operations\\n- Per-module coverage\\n- Covered endpoint list\\n- Uncovered endpoint list\\n\\nThis is a source-to-contract coverage report. It is separate from the API inventory gate and should not be interpreted as proof that handler behavior or user scenarios are fully covered.\\n\\n## Aiflow Scenario Gate\\n\\nRun the Aiflow scenario gate:\\n\\n```bash\\nbun run test:aiflow:scenario\\n```\\n\\nThe shell runner supports deterministic static checks and optional Python scenario execution.\\n\\nRun pre-production external pytest P0 scenarios:\\n\\n```bash\\nbash scripts/run-aiflow-scenario-cases.sh --stage preprod\\n```\\n\\nRun development scenarios including Python tests:\\n\\n```bash\\nbash scripts/run-aiflow-scenario-cases.sh \\\\\\n  --stage dev \\\\\\n  --include-python\\n```\\n\\nRun a focused suite:\\n\\n```bash\\nbash scripts/run-aiflow-scenario-cases.sh \\\\\\n  --stage dev \\\\\\n  --include-python \\\\\\n  --suite testcases/aiflow/scenario_test/test_setting_manage.py \\\\\\n  --mark \\\"P0 and auto and not skip and not only_online\\\" \\\\\\n  --pytest-arg -q\\n```\\n\\nRun only the deterministic framework check:\\n\\n```bash\\nbash scripts/run-aiflow-scenario-cases.sh \\\\\\n  --stage dev \\\\\\n  --no-python\\n```\\n\\nThe static check emits JSON containing:\\n\\n- Declared operation count\\n- Used operation count\\n- Files missing default `P0 and auto` gate coverage\\n- P0/automatic tests excluded by `skip`, `skip_test`, or `only_online`\\n\\n## UI Replay Quality\\n\\nThe UI replay system uses Playwright as the executable browser engine.\\n\\nRun the deterministic browser suite:\\n\\n```bash\\nbun run test:e2e\\n```\\n\\nGenerate or inspect the replay report:\\n\\n```bash\\nbun --filter @archon/web test:e2e:report\\n```\\n\\nOpen Playwright\u2019s interactive UI runner:\\n\\n```bash\\nbun run test:e2e:ui\\n```\\n\\nRecord browser actions with codegen:\\n\\n```bash\\nUI_REPLAY_API_PORT=3190 \\\\\\nUI_REPLAY_WEB_PORT=5174 \\\\\\nbun run test:e2e:ui\\n\\nbun run test:e2e:record\\n```\\n\\nConvert a codegen draft into a project test scaffold:\\n\\n```bash\\nbun run test:e2e:scaffold -- \\\\\\n  --name settings-token-flow \\\\\\n  --source /path/to/codegen-draft.ts\\n```\\n\\nGenerated tests are placed under:\\n\\n```text\\npackages/web/e2e/.spec.ts\\n```\\n\\nGenerated code requires manual cleanup. New tests should:\\n\\n- Reuse `loginAsAdmin()` and the `qualityPage` fixture.\\n- Preserve meaningful business assertions.\\n- Remove coordinate-based or incidental selectors.\\n- Avoid real AI provider calls in PR smoke tests.\\n- Use a fake or test provider for message and SSE flows.\\n\\n### Browser test environment\\n\\nPlaywright starts:\\n\\n- `packages/server/src/index.ts`\\n- The Vite web development server\\n\\nDefault ports are:\\n\\n- API: `3190`\\n- Web: `5174`\\n\\nOverride them with:\\n\\n```bash\\nUI_REPLAY_API_PORT=3290 \\\\\\nUI_REPLAY_WEB_PORT=5274 \\\\\\nbun run test:e2e\\n```\\n\\nThe test server uses:\\n\\n- `TEST_AUTH_ENABLED=true`\\n- `DATABASE_URL=''` for SQLite\\n- A temporary `ARCHON_HOME`\\n- `WEB_UI_DEV=true`\\n- `KNOWLEDGE_API_URL=http://127.0.0.1:1`\\n\\nTests authenticate through `/api/auth/test-login`, avoiding UUAP dependencies.\\n\\n### Replay quality checks\\n\\n`packages/web/e2e/fixtures.ts` captures:\\n\\n- Severe console errors\\n- Unhandled page exceptions\\n- Failed requests\\n- Unexpected 5xx responses\\n- Visible button size anomalies\\n- DOM and visual snapshots\\n- Serious and critical accessibility findings through `@axe-core/playwright`\\n- Navigation-load performance\\n- Network errors matching configured ignore rules\\n\\nThe default load threshold is:\\n\\n```text\\nUI_REPLAY_MAX_LOAD_MS=5000\\n```\\n\\nEnable strict accessibility failures with:\\n\\n```bash\\nUI_REPLAY_STRICT_A11Y=true bun run test:e2e\\n```\\n\\nVisual snapshots can be compared against a baseline:\\n\\n```bash\\nUI_REPLAY_VISUAL_BASELINE_DIR=test-results/ui-replay-baseline \\\\\\nbun run test:e2e\\n```\\n\\nWithout a baseline directory, the suite still captures snapshots for later review.\\n\\n### Replay artifacts and upload\\n\\nArtifacts are written to:\\n\\n```text\\ntest-results/ui-replay/\\n```\\n\\nImportant outputs include:\\n\\n- `results.json`: raw Playwright JSON results\\n- `summary.json`: machine-readable Archon replay summary\\n- `summary.md`: human-readable summary\\n- `../ui-replay-report/`: Playwright HTML report\\n- Failure traces, screenshots, videos, and DOM snapshots\\n\\nUpload a report to a running server with:\\n\\n```bash\\nbun --filter @archon/web test:e2e:report -- \\\\\\n  --upload-url http://127.0.0.1:3090/api/ui-replay/runs \\\\\\n  --token \\\"$UI_REPLAY_UPLOAD_TOKEN\\\"\\n```\\n\\nThe server exposes replay runs and evidence through the diagnostics UI. Artifact access is restricted to files below `test-results/ui-replay/`, preventing path traversal and arbitrary absolute-path access.\\n\\nCI currently runs the deterministic UI E2E command in the `web-e2e` observe job and uploads replay artifacts and the Playwright HTML report. The job remains `continue-on-error` until the replay baseline is stable enough to become a hard gate.\\n\\n## Common Troubleshooting\\n\\n### Port conflict\\n\\nIf the server reports `EADDRINUSE`, use an isolated port such as `3091` or override it with `SPECMATIC_SERVICE_PORT`.\\n\\nFor the Specmatic mock, use a different host port while retaining container port `9000`:\\n\\n```bash\\ndocker run --rm \\\\\\n  -v \\\"$PWD/docs/testing/specmatic-doarchon.yaml:/specmatic-doarchon.yaml:ro\\\" \\\\\\n  -p 9001:9000 \\\\\\n  specmatic/specmatic mock /specmatic-doarchon.yaml \\\\\\n  --host=0.0.0.0 \\\\\\n  --port=9000\\n```\\n\\nThe mock is then available at:\\n\\n```text\\nhttp://127.0.0.1:9001\\n```\\n\\n### Test login returns 404\\n\\nCheck:\\n\\n```bash\\ncurl http://127.0.0.1:3091/api/auth/config\\n```\\n\\nIf `testAuthEnabled` is `false`, restart the server with:\\n\\n```bash\\nTEST_AUTH_ENABLED=true\\n```\\n\\n### Protected endpoint returns 401\\n\\nInclude the test user header:\\n\\n```http\\nX-Test-User: admin\\n```\\n\\nOnly run this flow against a test server with test authentication enabled.\\n\\n### Specmatic schema mismatch\\n\\nWhen the real response contains a field missing from the contract, update the OpenAPI schema or generated contract source. For example, provider capabilities may include `agents`; the `ProviderCapabilities` schema permits this through:\\n\\n```yaml\\nadditionalProperties: true\\n```\\n\\nDo not weaken a schema solely to hide an intentional API regression. First determine whether the response, route schema, generated OpenAPI document, and committed test contract are all expected to change.\\n\\n## Contribution Guidelines\\n\\nWhen changing an API:\\n\\n1. Update the route implementation and schema.\\n2. Regenerate API inventory fixtures.\\n3. Add or update route-level tests.\\n4. Add scenario ownership when the endpoint participates in a real user flow.\\n5. Add or update Specmatic examples for stable contract scenarios.\\n6. Run the contract, route, and scenario gates.\\n7. Run Specmatic when the OpenAPI contract or examples change.\\n8. Update UI replay coverage when the change affects a browser workflow.\\n\\nThe proposed Specmatic integration described in `specmatic-integration.md` is an architecture and rollout plan. It should not be treated as an indication that every proposed `contracts/` script or CI command already exists. The currently executable Specmatic assets are:\\n\\n```text\\ndocs/testing/specmatic-doarchon.yaml\\ndocs/testing/specmatic-test.sh\\ndocs/testing/specmatic-coverage.sh\\ndocs/testing/examples/\\n```\\n\\nThe existing API gate remains the authoritative mechanism for endpoint inventory and behavior ownership, while Specmatic validates runtime conformance to the OpenAPI contract and UI replay validates browser-visible behavior.\",\"other-todos-md\":\"# Other \u2014 todos.md\\n\\n# Todos\\n\\n`todos.md` \u662f\u9879\u76ee\u7ea7\u4efb\u52a1\u6e05\u5355\uff0c\u7528\u4e8e\u8bb0\u5f55\u5f85\u5f00\u53d1\u3001\u5df2\u5b8c\u6210\u53ca\u9700\u8981\u8865\u5145\u6d4b\u8bd5\u7684\u529f\u80fd\u53d8\u66f4\u3002\u8be5\u6587\u4ef6\u4e0d\u53c2\u4e0e\u5e94\u7528\u8fd0\u884c\uff0c\u4e5f\u4e0d\u5bfc\u51fa\u51fd\u6570\u3001\u7c7b\u6216\u914d\u7f6e\uff1b\u5b83\u901a\u8fc7\u4efb\u52a1\u63cf\u8ff0\u7ef4\u62a4\u4ea7\u54c1\u9700\u6c42\u4e0e\u4ee3\u7801\u4fee\u6539\u70b9\u4e4b\u95f4\u7684\u5bf9\u5e94\u5173\u7cfb\u3002\\n\\n## \u6587\u4ef6\u5b9a\u4f4d\\n\\n- **\u6a21\u5757\u7c7b\u578b**\uff1a\u9879\u76ee\u4efb\u52a1\u8ffd\u8e2a\u6587\u6863\\n- **\u8fd0\u884c\u65f6\u884c\u4e3a**\uff1a\u65e0\\n- **\u5185\u90e8\u8c03\u7528**\uff1a\u65e0\\n- **\u5bf9\u5916\u8c03\u7528**\uff1a\u65e0\\n- **\u4f9d\u8d56\u5173\u7cfb**\uff1a\u4e0d\u901a\u8fc7 import \u8fde\u63a5\u4ee3\u7801\u6a21\u5757\uff0c\u4ec5\u901a\u8fc7\u6587\u4ef6\u8def\u5f84\u548c\u4efb\u52a1\u8bf4\u660e\u5173\u8054\u4ee3\u7801\u5e93\\n- **\u6267\u884c\u6d41\u7a0b**\uff1a\u65e0\\n\\n\u4efb\u52a1\u6761\u76ee\u901a\u5e38\u5305\u542b\uff1a\\n\\n1. \u529f\u80fd\u6216\u9700\u6c42\u6807\u9898\\n2. \u5b8c\u6210\u65e5\u671f\u6216\u8ba1\u5212\u65e5\u671f\\n3. \u9700\u6c42\u5355\u53f7\uff08\u5982\u679c\u6709\uff09\\n4. \u4e00\u4e2a\u6216\u591a\u4e2a\u5e26\u590d\u9009\u6846\u7684\u5b9e\u73b0\u4efb\u52a1\\n5. \u76ee\u6807\u6e90\u7801\u6587\u4ef6\u3001\u6d4b\u8bd5\u6587\u4ef6\u53ca\u9884\u671f\u4fee\u6539\u5185\u5bb9\\n\\n## \u4efb\u52a1\u72b6\u6001\\n\\n\u4efb\u52a1\u4f7f\u7528 Markdown \u590d\u9009\u6846\u8868\u793a\u72b6\u6001\uff1a\\n\\n```md\\n- [ ] \u5f85\u5b8c\u6210\u4efb\u52a1\\n- [x] \u5df2\u5b8c\u6210\u4efb\u52a1\\n```\\n\\n\u5f53\u524d\u6587\u4ef6\u4e2d\u7684\u5df2\u5b8c\u6210\u4efb\u52a1\u5305\u62ec\uff1a\\n\\n- \u4f7f\u7528\u9ed1\u8272\u65e0\u9650\u7b26\u53f7\u66ff\u6362 favicon\uff0c\u5e76\u5728 `packages/web/index.html` \u4e2d\u914d\u7f6e SVG favicon \u548c PNG fallback\u3002\\n- \u5728 `AikuApiKeyDialog` \u7684\u8bf4\u660e\u533a\u57df\u589e\u52a0 AI-Ku \u63a5\u5165\u6587\u6863\u94fe\u63a5\uff0c\u5e76\u66f4\u65b0\u6e32\u67d3\u6d4b\u8bd5\u3002\\n- \u8c03\u6574\u77e5\u8bc6\u81ea\u68c0\u6587\u6863\u603b\u5f97\u5206\u5c55\u793a\u903b\u8f91\uff0c\u79fb\u9664 `ConversationItem` \u4e2d\u5df2\u5e9f\u5f03\u7684\u9879\u76ee\u548c\u5de5\u4f5c\u6d41\u5c5e\u6027\uff0c\u5e76\u6e05\u7406\u8c03\u7528\u65b9\u6b8b\u7559\u4f20\u53c2\u3002\\n\\n\u5176\u4f59\u6761\u76ee\u4ecd\u6807\u8bb0\u4e3a\u5f85\u5b8c\u6210\uff0c\u4e0d\u80fd\u89c6\u4e3a\u5df2\u7ecf\u5408\u5e76\u6216\u9a8c\u8bc1\u901a\u8fc7\u3002\\n\\n## \u5f85\u529e\u4efb\u52a1\u5206\u7c7b\\n\\n### \u9876\u90e8\u5bfc\u822a\u4e0e\u5168\u5c40\u7a7a\u95f4\\n\\n\u6d89\u53ca `packages/web/src/components/layout/TopNav.tsx` \u53ca\u5176\u6d4b\u8bd5\u6587\u4ef6\uff1a\\n\\n- \u5c06\u300c\u5982\u6d41\u5bf9\u8bdd\u300d\u6309\u94ae\u6587\u6848\u8c03\u6574\u4e3a\u300c\u901a\u8fc7\u5982\u6d41\u5bf9\u8bdd\u300d\u3002\\n- \u4e3a `GlobalSpaceSelector` \u589e\u52a0\u641c\u7d22\u72b6\u6001\u3001\u641c\u7d22\u6846\u3001`Search` \u56fe\u6807\u548c\u8fc7\u6ee4\u5217\u8868\u3002\\n- \u5728\u5934\u50cf\u4e0b\u62c9\u83dc\u5355\u7684\u300c\u7a7a\u95f4\u7ba1\u7406\u300d\u4e0a\u65b9\u589e\u52a0\u300c\u5e2e\u52a9\u6587\u6863\u300d\u5165\u53e3\u3002\\n- \u300c\u5e2e\u52a9\u6587\u6863\u300d\u5e94\u4f7f\u7528 `BookOpen` \u56fe\u6807\uff0c\u5e76\u901a\u8fc7\u65b0\u7a97\u53e3\u6253\u5f00\u6307\u5b9a\u77e5\u8bc6\u5e93 URL\uff0c\u540c\u65f6\u8bbe\u7f6e `rel=\\\"noreferrer\\\"`\u3002\\n\\n\u5bf9\u5e94\u6d4b\u8bd5\u5305\u62ec\uff1a\\n\\n- `packages/web/src/components/layout/TopNav.test.tsx`\\n- `packages/server/src/api-tests/brand-text-regression.test.ts`\\n\\n\u641c\u7d22\u529f\u80fd\u7684\u5b9e\u73b0\u8981\u6c42\u5305\u62ec\uff1a\\n\\n- \u65b0\u589e `query` state\u3002\\n- \u6839\u636e\u641c\u7d22\u5185\u5bb9\u751f\u6210 `filtered` \u5217\u8868\u3002\\n- \u5217\u8868\u6e32\u67d3\u4f7f\u7528 `filtered` \u800c\u4e0d\u662f\u5b8c\u6574\u7a7a\u95f4\u5217\u8868\u3002\\n- \u6240\u6709\u5173\u95ed\u4e0b\u62c9\u83dc\u5355\u7684 `setOpen(false)` \u8def\u5f84\u540c\u65f6\u8c03\u7528 `setQuery('')`\uff0c\u786e\u4fdd\u91cd\u65b0\u6253\u5f00\u65f6\u641c\u7d22\u6761\u4ef6\u5df2\u6e05\u7a7a\u3002\\n- \u6d4b\u8bd5\u901a\u8fc7\u9759\u6001\u65ad\u8a00\u68c0\u67e5 state\u3001placeholder\u3001\u56fe\u6807\u5bfc\u5165\u3001\u8fc7\u6ee4\u53d8\u91cf\u53ca\u6e05\u7406\u903b\u8f91\u3002\\n\\n### \u4f1a\u8bdd\u4fa7\u8fb9\u680f\\n\\n\u4e3b\u8981\u6d89\u53ca\uff1a\\n\\n- `packages/web/src/components/layout/ChatSidebar.tsx`\\n- `packages/web/src/components/layout/ChatSidebar.test.tsx`\\n- `packages/web/src/routes/ChatPage.test.tsx`\\n\\n\u8ba1\u5212\u4e2d\u7684\u4f1a\u8bdd\u4fa7\u8fb9\u680f\u6539\u52a8\u5305\u62ec\uff1a\\n\\n1. **\u6062\u590d\u53ef\u62d6\u52a8\u5bbd\u5ea6\u8c03\u6574**\\n\\n   `ChatSidebar.tsx` \u9700\u8981\u6062\u590d\u88ab E2E-Efficiency-3136 \u79fb\u9664\u7684\u62d6\u62fd\u903b\u8f91\uff0c\u5305\u62ec\uff1a\\n\\n   - `PANEL_MIN`\\n   - `PANEL_MAX`\\n   - `PANEL_DEFAULT`\\n   - `getInitialWidth`\\n   - \u5bbd\u5ea6 state\\n   - `handleMouseDown`\\n\\n   \u53f3\u4fa7\u62d6\u62fd\u533a\u57df\u4f7f\u7528\u900f\u660e handle\uff0c\u4ec5\u4fdd\u7559\u4ee5\u4e0b\u5e03\u5c40\u548c\u4ea4\u4e92\u7c7b\uff1a\\n\\n   ```txt\\n   absolute right-0 top-0 bottom-0 w-1.5 cursor-col-resize\\n   ```\\n\\n   \u4e0d\u5e94\u6dfb\u52a0\u989c\u8272\u3001hover \u6216 transition \u6837\u5f0f\u3002`ChatPage.test.tsx` \u9700\u8981\u9a8c\u8bc1\u6e90\u7801\u4e0d\u5305\u542b `bg-border/50`\uff0c\u5e76\u5305\u542b `cursor-col-resize`\u3002\\n\\n2. **\u6309\u9879\u76ee\u6298\u53e0\u5386\u53f2\u5bf9\u8bdd**\\n\\n   \u9700\u8981\u5728 `ChatSidebar.tsx` \u4e2d\uff1a\\n\\n   - \u65b0\u589e `collapsedGroups` state\u3002\\n   - \u5c06\u9879\u76ee\u5206\u7ec4\u6807\u9898\u6539\u4e3a\u53ef\u70b9\u51fb\u7684 button\u3002\\n   - \u70b9\u51fb\u6807\u9898\u5207\u6362\u5bf9\u5e94\u5206\u7ec4\u7684\u6298\u53e0\u72b6\u6001\u3002\\n   - \u6298\u53e0\u65f6\u9690\u85cf\u7ec4\u5185\u7684 `ConversationItem`\u3002\\n   - \u6298\u53e0\u65f6\u9690\u85cf\u300c\u5c55\u5f00\u5168\u90e8\u300d\u548c\u300c\u6536\u8d77\u300d\u6309\u94ae\u3002\\n   - \u5bfc\u5165\u5e76\u4f7f\u7528 `ChevronDown` \u4e0e `ChevronRight` \u56fe\u6807\uff0c\u6839\u636e\u5c55\u5f00\u72b6\u6001\u663e\u793a\u5bf9\u5e94\u56fe\u6807\u3002\\n\\n   `ChatSidebar.test.tsx` \u9700\u8981\u589e\u52a0\u9759\u6001\u65ad\u8a00\uff0c\u9a8c\u8bc1 `collapsedGroups` state \u5b58\u5728\uff0c\u5e76\u786e\u8ba4\u5206\u7ec4\u6807\u9898\u5305\u542b\u4ea4\u4e92\u5143\u7d20\u3002\\n\\n### \u5feb\u901f\u4e0a\u624b\u4e0e Token \u914d\u7f6e\\n\\n\u6d89\u53ca\u4ee5\u4e0b\u6587\u4ef6\uff1a\\n\\n- `packages/web/src/hooks/useSetupStatus.ts`\\n- `packages/web/src/components/layout/SetupWizardModal.tsx`\\n- `packages/web/src/components/layout/OnboardingWizardModal.tsx`\\n- `packages/web/src/components/settings/TokenSections.tsx`\\n- `packages/web/src/components/layout/SetupWizardModal.render.test.tsx`\\n\\n\u76ee\u6807\u662f\u5c06 OneAPI Token \u4ece\u5feb\u901f\u4e0a\u624b\u6d41\u7a0b\u4e2d\u79fb\u9664\uff0c\u5e76\u5728\u8bbe\u7f6e\u9875\u6807\u8bb0\u4e3a\u9009\u586b\u914d\u7f6e\u3002\\n\\n\u5b9e\u73b0\u8981\u6c42\uff1a\\n\\n- \u5728 `useSetupStatus.ts` \u4e2d\u79fb\u9664 `tokensConfigured` \u5bf9 `oneApi?.configured` \u7684\u4f9d\u8d56\u3002\\n- \u79fb\u9664 `oneApiLoading` \u5bf9\u6574\u4f53 `isLoading` \u72b6\u6001\u7684\u5f71\u54cd\u3002\\n- \u4ece `SetupWizardModal` \u548c `OnboardingWizardModal` \u5220\u9664 ``\u3002\\n- \u4ece `SetupWizardModal` \u7684\u81ea\u52a8\u5173\u95ed\u6761\u4ef6\u4e2d\u5220\u9664 `oneApiStatus?.configured`\u3002\\n- \u6e05\u7406\u5220\u9664\u903b\u8f91\u540e\u4e0d\u518d\u4f7f\u7528\u7684 import \u548c `useQuery`\u3002\\n- \u5728 `TokenSections.tsx` \u7684 `OneApiTokenSection` Card \u6807\u9898\u65c1\u589e\u52a0\u300c\u9009\u586b\u300dbadge\uff0c\u5e76\u4f7f\u6807\u9898\u533a\u57df\u4f7f\u7528 flex \u884c\u5e03\u5c40\u3002\\n- \u66f4\u65b0 `SetupWizardModal.render.test.tsx` \u7684 mock\u3001\u573a\u666f\u548c\u65ad\u8a00\u3002\\n\\n\u9884\u671f\u9a8c\u8bc1\u547d\u4ee4\uff1a\\n\\n```bash\\nbun test packages/web/src/components/layout/SetupWizardModal\\n```\\n\\n### \u77e5\u8bc6\u5b8c\u6574\u6027\u8bc4\u4f30\\n\\n\u6d89\u53ca\uff1a\\n\\n- `packages/web/src/lib/knowledge/api.ts`\\n- `packages/web/src/routes/knowledge/integrity/IntegritySection.tsx`\\n- `packages/web/src/routes/knowledge/integrity/IntegritySection.render.test.tsx`\\n\\n`IntegrityEvaluatorResult` interface \u9700\u8981\u65b0\u589e\u53ef\u9009\u5b57\u6bb5\uff1a\\n\\n```ts\\ntitle_cn?: string\\n```\\n\\n`IntegritySection.tsx` \u4e2d `EvaluatorCard` \u7684\u6807\u9898\u5e94\u6309\u4ee5\u4e0b\u4f18\u5148\u7ea7\u5c55\u793a\uff1a\\n\\n1. `title_cn`\\n2. `summary`\\n3. `name`\\n\\n\u8fd9\u5141\u8bb8\u540e\u7aef\u63d0\u4f9b\u4e2d\u6587\u8bc4\u4f30\u5668\u540d\u79f0\uff0c\u540c\u65f6\u4fdd\u7559\u65e7\u6570\u636e\u7684\u517c\u5bb9\u6027\u3002\u6d4b\u8bd5\u9700\u8981\u589e\u52a0\u5305\u542b `title_cn` \u7684\u6587\u6863\u7ef4\u5ea6\u8bc4\u4f30\u5668\u573a\u666f\uff0c\u5e76\u9a8c\u8bc1\u4e2d\u6587\u6807\u9898\u4f18\u5148\u5c55\u793a\u3002\\n\\n\u9884\u671f\u9a8c\u8bc1\u547d\u4ee4\uff1a\\n\\n```bash\\nbun test packages/web/src/routes/knowledge/integrity/IntegritySection.render.test.tsx\\n```\\n\\n### \u77e5\u8bc6\u65b9\u821f\u5bfc\u5165\\n\\n\u6d89\u53ca\uff1a\\n\\n- `packages/web/src/routes/knowledge/bootstrap/ark-import.tsx`\\n- `packages/web/src/routes/knowledge/bootstrap/ark-import.test.tsx`\\n\\n\u9700\u8981\u4fee\u6b63\u300c\u7c98\u8d34\u4e00\u4e2a\u77e5\u8bc6\u65b9\u821f\u94fe\u63a5\u300d\u8f93\u5165\u6846\u7684 placeholder\uff0c\u5c06\u65e7\u57df\u540d\uff1a\\n\\n```txt\\nhttps://ku.baidu-int.com/\u2026\\n```\\n\\n\u66ff\u6362\u4e3a\uff1a\\n\\n```txt\\nhttps://console.cloud.baidu-int.com/onetool/knowledge/\u2026\\n```\\n\\n\u540c\u65f6\u65b0\u589e `ark-import.test.tsx`\uff0c\u6e32\u67d3 `` \u5e76\u65ad\u8a00\u8f93\u5165\u6846\u663e\u793a\u6b63\u786e\u7684\u77e5\u8bc6\u65b9\u821f\u57df\u540d\u3002\\n\\n## \u4e0e\u4ee3\u7801\u5e93\u7684\u8fde\u63a5\u65b9\u5f0f\\n\\n\u8be5\u6587\u4ef6\u4e0d\u5efa\u7acb\u7a0b\u5e8f\u7ea7\u4f9d\u8d56\uff0c\u800c\u662f\u901a\u8fc7\u660e\u786e\u7684\u8def\u5f84\u5f15\u7528\u6307\u5bfc\u4fee\u6539\u8303\u56f4\u3002\u4f8b\u5982\uff1a\\n\\n- `TopNav.tsx` \u7684\u5bfc\u822a\u53d8\u66f4\u7531 `TopNav.test.tsx` \u548c\u54c1\u724c\u6587\u6848\u56de\u5f52\u6d4b\u8bd5\u8986\u76d6\u3002\\n- `ChatSidebar.tsx` \u7684\u4ea4\u4e92\u53d8\u66f4\u7531\u7ec4\u4ef6\u6d4b\u8bd5\u548c `ChatPage.test.tsx` \u7684\u6e90\u7801\u65ad\u8a00\u8f85\u52a9\u9a8c\u8bc1\u3002\\n- \u8bbe\u7f6e\u5411\u5bfc\u6539\u52a8\u9700\u8981\u540c\u6b65\u66f4\u65b0\u7ec4\u4ef6\u5b9e\u73b0\u3001\u72b6\u6001 hook \u548c\u6e32\u67d3\u6d4b\u8bd5\u3002\\n- \u5b8c\u6574\u6027\u8bc4\u4f30\u7684 API \u7c7b\u578b\u53d8\u66f4\u5fc5\u987b\u4e0e `EvaluatorCard` \u7684\u5c55\u793a\u903b\u8f91\u53ca\u6e32\u67d3\u6d4b\u8bd5\u4fdd\u6301\u4e00\u81f4\u3002\\n- \u77e5\u8bc6\u65b9\u821f placeholder \u53d8\u66f4\u8981\u6c42\u540c\u65f6\u65b0\u589e\u5bf9\u5e94\u7ec4\u4ef6\u6d4b\u8bd5\uff0c\u907f\u514d\u57df\u540d\u56de\u9000\u3002\\n\\n\u56e0\u6b64\uff0c\u5b8c\u6210\u4e00\u9879\u4efb\u52a1\u65f6\u5e94\u540c\u65f6\u68c0\u67e5\u8be5\u6761\u76ee\u5217\u51fa\u7684\u6240\u6709\u6e90\u7801\u548c\u6d4b\u8bd5\u6587\u4ef6\uff0c\u907f\u514d\u53ea\u4fee\u6539 UI \u800c\u9057\u6f0f\u7c7b\u578b\u3001\u72b6\u6001\u903b\u8f91\u6216\u56de\u5f52\u65ad\u8a00\u3002\\n\\n## \u7ef4\u62a4\u7ea6\u5b9a\\n\\n- \u5b8c\u6210\u5e76\u9a8c\u8bc1\u4efb\u52a1\u540e\uff0c\u5c06\u5bf9\u5e94\u590d\u9009\u6846\u4ece `- [ ]` \u66f4\u65b0\u4e3a `- [x]`\u3002\\n- \u4fdd\u7559\u9700\u6c42\u6807\u9898\u3001\u65e5\u671f\u548c\u9700\u6c42\u5355\u53f7\uff0c\u4fbf\u4e8e\u8ffd\u8e2a\u53d8\u66f4\u6765\u6e90\u3002\\n- \u5982\u679c\u5b9e\u73b0\u8fc7\u7a0b\u4e2d\u65b0\u589e\u6216\u5220\u9664\u4e86\u6587\u4ef6\uff0c\u5e94\u540c\u6b65\u66f4\u65b0\u4efb\u52a1\u4e2d\u7684\u8def\u5f84\u63cf\u8ff0\u3002\\n- \u4efb\u52a1\u4e2d\u660e\u786e\u7ed9\u51fa\u7684\u6d4b\u8bd5\u547d\u4ee4\u5e94\u5728\u6807\u8bb0\u5b8c\u6210\u524d\u6267\u884c\u3002\\n- \u5bf9\u4e8e\u9759\u6001\u6e90\u7801\u65ad\u8a00\u4efb\u52a1\uff0c\u6d4b\u8bd5\u4e0d\u4ec5\u8981\u9a8c\u8bc1\u8fd0\u884c\u7ed3\u679c\uff0c\u4e5f\u8981\u9a8c\u8bc1\u6307\u5b9a\u5b9e\u73b0\u6a21\u5f0f\uff0c\u4f8b\u5982 `query`\u3001`filtered`\u3001`cursor-col-resize` \u6216\u7279\u5b9a\u56fe\u6807\u5f15\u7528\u3002\\n- \u540c\u4e00\u6807\u9898\u4e0b\u5e94\u4fdd\u6301\u4efb\u52a1\u7f16\u53f7\u8fde\u7eed\uff1b\u5f53\u524d\u6587\u4ef6\u4e2d\u77e5\u8bc6\u5b8c\u6574\u6027\u8bc4\u4f30\u6761\u76ee\u5b58\u5728\u91cd\u590d\u7684 `T1` \u7f16\u53f7\uff0c\u7ef4\u62a4\u65f6\u53ef\u6309\u5b9e\u9645\u4efb\u52a1\u62c6\u5206\u60c5\u51b5\u4fee\u6b63\u7f16\u53f7\u3002\",\"other-tsconfig-json\":\"# Other \u2014 tsconfig.json\\n\\n# Other \u2014 `tsconfig.json`\\n\\n## Purpose\\n\\n`tsconfig.json` defines the TypeScript compiler environment and project-wide type-checking rules. It is a configuration module rather than executable code:\\n\\n- It has no functions, classes, or runtime behavior.\\n- It has no internal or outgoing calls.\\n- It is consumed by TypeScript-aware tooling such as `tsc`, editors, bundlers, and test runners that support TypeScript configuration.\\n- Its settings affect how TypeScript resolves modules, checks code, and generates build artifacts.\\n\\nThe configuration is intentionally strict and targets modern JavaScript runtimes and bundler-based module resolution.\\n\\n## Configuration\\n\\n### Language and module targets\\n\\n```json\\n{\\n  \\\"target\\\": \\\"ES2022\\\",\\n  \\\"module\\\": \\\"ESNext\\\",\\n  \\\"lib\\\": [\\\"ES2022\\\"]\\n}\\n```\\n\\n- `target: \\\"ES2022\\\"` preserves modern JavaScript syntax up to ES2022 rather than transpiling it to an older runtime target.\\n- `module: \\\"ESNext\\\"` treats source modules as native ECMAScript modules.\\n- `lib: [\\\"ES2022\\\"]` provides TypeScript declarations for ES2022 standard-library APIs.\\n\\nThis combination assumes that the eventual runtime or bundler understands modern ECMAScript syntax and modules.\\n\\n### Type-checking strictness\\n\\n```json\\n{\\n  \\\"strict\\\": true,\\n  \\\"noImplicitReturns\\\": true,\\n  \\\"noFallthroughCasesInSwitch\\\": true\\n}\\n```\\n\\n`strict: true` enables TypeScript\u2019s strict type-checking family, including checks such as strict null handling and strict function typing.\\n\\nAdditional control-flow checks require:\\n\\n- Functions to return consistently when a return value is expected.\\n- `switch` cases to terminate explicitly rather than falling through accidentally.\\n\\nThese settings make type errors and common control-flow mistakes fail during development rather than at runtime.\\n\\n### Module interoperability and resolution\\n\\n```json\\n{\\n  \\\"esModuleInterop\\\": true,\\n  \\\"resolveJsonModule\\\": true,\\n  \\\"moduleResolution\\\": \\\"bundler\\\"\\n}\\n```\\n\\n- `esModuleInterop: true` improves compatibility when importing CommonJS packages using ES-style default imports.\\n- `resolveJsonModule: true` allows JSON files to be imported as typed modules.\\n- `moduleResolution: \\\"bundler\\\"` applies package and import-resolution behavior aligned with modern bundlers. It is appropriate for projects that rely on bundler-managed ESM imports and package exports.\\n\\nThe configuration does not define custom `baseUrl` or `paths` aliases. Imports therefore rely on standard relative paths, package resolution, and the configured bundler behavior.\\n\\n### Declaration and source-map output\\n\\n```json\\n{\\n  \\\"declaration\\\": true,\\n  \\\"declarationMap\\\": true,\\n  \\\"sourceMap\\\": true\\n}\\n```\\n\\nWhen TypeScript emits supported source files, it is configured to produce:\\n\\n- `.d.ts` declaration files for public type information.\\n- Declaration maps linking declarations back to their source files.\\n- JavaScript source maps linking emitted JavaScript back to TypeScript.\\n\\nThese options support library consumption, editor navigation, and debugging generated output. The configuration does not set `outDir`, `rootDir`, or `declarationDir`, so output locations remain controlled by TypeScript defaults or by the tool invoking the compiler.\\n\\n### Unused-code checks\\n\\n```json\\n{\\n  \\\"noUnusedLocals\\\": true,\\n  \\\"noUnusedParameters\\\": true\\n}\\n```\\n\\nThe compiler reports:\\n\\n- Local variables, imports, or declarations that are never used.\\n- Function parameters that are declared but never used.\\n\\nContributors should remove unused declarations or explicitly structure code so that intentionally unused values are accepted by the project\u2019s TypeScript version and tooling.\\n\\n### Build and compatibility settings\\n\\n```json\\n{\\n  \\\"skipLibCheck\\\": true,\\n  \\\"forceConsistentCasingInFileNames\\\": true\\n}\\n```\\n\\n- `skipLibCheck: true` skips type-checking of declaration files in dependencies. This generally reduces compile time and avoids failures caused by incompatible or incomplete third-party declarations, while still checking project source code against those declarations.\\n- `forceConsistentCasingInFileNames: true` ensures import paths use the same filename casing as the filesystem. This prevents code from working on case-insensitive systems while failing on case-sensitive systems.\\n\\n### Ambient type packages\\n\\n```json\\n{\\n  \\\"types\\\": [\\\"bun-types\\\"]\\n}\\n```\\n\\nThe project explicitly includes the `bun-types` package for global Bun runtime and API declarations. TypeScript will use this package when resolving ambient types, so Bun-specific globals and APIs can be type-checked without manually importing their declarations.\\n\\nThe package must be available in the project\u2019s dependencies or development dependencies for type-checking to succeed.\\n\\n## Included files\\n\\n```json\\n{\\n  \\\"include\\\": [\\\"global.d.ts\\\"]\\n}\\n```\\n\\nThis project configuration explicitly includes `global.d.ts` as its root input.\\n\\n`global.d.ts` is intended for ambient declarations that apply across the project, such as:\\n\\n- Global variables or interfaces.\\n- Module declarations for assets or packages without built-in types.\\n- Project-specific type augmentations.\\n\\nBecause the `include` pattern names only `global.d.ts`, ordinary `.ts` or `.tsx` source files are not automatically selected by this configuration through a broader source glob. Tooling that invokes TypeScript with explicit files, uses another configuration, or builds through a separate bundler may still process additional source files.\\n\\nContributors adding global declarations should place them in `global.d.ts` or update the `include` configuration deliberately if additional declaration files are introduced.\\n\\n## Relationship to the rest of the codebase\\n\\n`tsconfig.json` is a project-wide compiler contract rather than a runtime dependency. Other modules do not import it, and it does not import or call any application code. Instead, development and build tools read it to determine:\\n\\n1. Which declarations are available globally.\\n2. Which JavaScript and module features the project may use.\\n3. How imports and JSON files are resolved.\\n4. Which type and control-flow errors are reported.\\n5. Whether declarations and source maps are generated.\\n\\nChanges to this file can therefore affect the entire TypeScript toolchain, including editor diagnostics, CI checks, package builds, and generated type artifacts. Any change should be validated with the repository\u2019s standard type-check or build command.\",\"other-wiki-drafts\":\"# Other \u2014 wiki-drafts\\n\\n# Other \u2014 wiki-drafts\\n\\n## \u529f\u80fd\u6982\u8ff0\\n\\n`docs/wiki-drafts` \u662f\u7528\u4e8e\u751f\u6210\u548c\u7ef4\u62a4\u529f\u80fd\u8bbe\u8ba1\u6587\u6863\u8349\u7a3f\u7684\u6587\u6863\u6a21\u5757\u3002\u5b83\u4e0d\u5305\u542b\u8fd0\u884c\u65f6\u4ee3\u7801\u3001\u53ef\u6267\u884c\u903b\u8f91\u6216\u5bf9\u5916 API\uff0c\u800c\u662f\u901a\u8fc7\u6a21\u677f\u548c\u5df2\u6709\u8bbe\u8ba1\u6587\u6863\u6c89\u6dc0\u4ee3\u7801\u5b9e\u73b0\u7684\u73b0\u72b6\uff0c\u4f9b wiki\u3001\u77e5\u8bc6\u5e93\u548c\u540e\u7eed\u5f00\u53d1\u4f7f\u7528\u3002\\n\\n\u6a21\u5757\u5f53\u524d\u5305\u542b\uff1a\\n\\n| \u6587\u4ef6 | \u7528\u9014 |\\n|---|---|\\n| `docs/wiki-drafts/PROMPT.md` | \u4ece\u73b0\u6709\u4ee3\u7801\u751f\u6210\u8bbe\u8ba1\u6587\u6863\u7684\u6807\u51c6\u6d41\u7a0b\u4e0e Prompt \u6a21\u677f |\\n| `docs/wiki-drafts/feature-workflow-authoring.md` | \u5de5\u4f5c\u6d41 YAML \u7f16\u5199\u89c4\u8303\u4e0e\u52a0\u8f7d\u6821\u9a8c\u7684\u8bbe\u8ba1\u6587\u6863 |\\n| `docs/wiki-drafts/feature-workflow-isolation.md` | \u5de5\u4f5c\u6d41\u9694\u79bb\u73af\u5883\u7684\u8bbe\u8ba1\u6587\u6863 |\\n\\n\u8be5\u6a21\u5757\u7684\u4ea7\u7269\u662f\u201c\u73b0\u72b6\u8bf4\u660e\u201d\uff0c\u800c\u4e0d\u662f\uff1a\\n\\n- \u6b63\u5411\u8bbe\u8ba1\u6216\u9700\u6c42\u6587\u6863\\n- \u4ee3\u7801\u8d28\u91cf\u8bc4\u5ba1\\n- \u95ee\u9898\u6392\u67e5\u62a5\u544a\\n- \u6539\u8fdb\u5efa\u8bae\u6216\u5f85\u529e\u5217\u8868\\n- \u6574\u4e2a\u4ed3\u5e93\u7684\u67b6\u6784\u603b\u89c8\\n\\n\u6a21\u5757\u901a\u8fc7\u7edf\u4e00\u6587\u6863\u7ed3\u6784\u3001\u4ee3\u7801\u7248\u672c\u6eaf\u6e90\u548c\u4e8b\u5b9e\u8fb9\u754c\uff0c\u51cf\u5c11\u4e0d\u540c\u529f\u80fd\u6587\u6863\u4e4b\u95f4\u7684\u7ed3\u6784\u6f02\u79fb\u4e0e\u5185\u5bb9\u77db\u76fe\u3002\\n\\n## \u6587\u6863\u751f\u6210\u89c4\u8303\\n\\n### \u9002\u7528\u8303\u56f4\\n\\n`PROMPT.md` \u89c4\u5b9a\u4e00\u6b21\u53ea\u4e3a\u4e00\u4e2a\u529f\u80fd\u6216\u6a21\u5757\u751f\u6210\u6587\u6863\u3002\u8303\u56f4\u5e94\u5f53\u80fd\u591f\u7528\u4e00\u53e5\u8bdd\u56de\u7b54\u201c\u8fd9\u662f\u4ec0\u4e48\u529f\u80fd\u201d\u3002\\n\\n\u9002\u5408\u7684\u5bf9\u8c61\u5305\u62ec\uff1a\\n\\n- \u5df2\u4e0a\u7ebf\u4f46\u6ca1\u6709\u8bbe\u8ba1\u6587\u6863\u7684\u529f\u80fd\\n- \u6587\u6863\u6563\u843d\u5728\u591a\u4e2a\u4f4d\u7f6e\u3001\u7ed3\u6784\u4e0d\u4e00\u81f4\u7684\u529f\u80fd\\n- \u9700\u8981\u5bfc\u5165\u77e5\u8bc6\u5e93\u6216 wiki \u7684\u5b58\u91cf\u5b9e\u73b0\\n- \u65b0\u529f\u80fd\u5f00\u53d1\u524d\u9700\u8981\u4e86\u89e3\u7684\u73b0\u6709\u5b9e\u73b0\u4e0e\u7ea6\u675f\\n\\n\u4e0d\u9002\u5408\u7684\u5bf9\u8c61\u5305\u62ec\uff1a\\n\\n- \u9700\u8981\u5148\u5b9a\u4e49\u9700\u6c42\u548c\u65b9\u6848\u7684\u6b63\u5411\u8bbe\u8ba1\\n- \u5355\u70b9\u95ee\u9898\u6392\u67e5\\n- \u4ee3\u7801\u8d28\u91cf\u8bc4\u5ba1\\n- \u8de8\u591a\u4e2a\u529f\u80fd\u7684\u6574\u4ed3\u5e93\u67b6\u6784\u8bf4\u660e\\n\\n### \u4ee3\u7801\u7248\u672c\u6eaf\u6e90\\n\\n\u751f\u6210\u524d\u9700\u8981\u8bb0\u5f55\u5f53\u524d\u4ee3\u7801\u7248\u672c\uff1a\\n\\n```bash\\ngit rev-parse --short HEAD\\n```\\n\\n\u751f\u6210\u7684\u6587\u6863\u901a\u8fc7 frontmatter \u4e2d\u7684 `source_commit` \u8bb0\u5f55\u5bf9\u5e94\u4ee3\u7801\u7248\u672c\uff0c\u800c\u4e0d\u662f\u5728\u6b63\u6587\u4e2d\u4f7f\u7528\u5bb9\u6613\u5931\u6548\u7684 `file:line` \u5f15\u7528\u3002\\n\\n\u63a8\u8350\u540c\u65f6\u8bb0\u5f55\u5f85\u8bfb\u6587\u4ef6\u6e05\u5355\uff1a\\n\\n```bash\\nfind &lt;\u6a21\u5757\u8def\u5f84&gt; -type f -name \\\"*.\\\" -not -name \\\"*.test.*\\\"\\n```\\n\\n### \u63a2\u7d22\u9636\u6bb5\\n\\n\u63a2\u7d22\u88ab\u62c6\u5206\u4e3a\u4e24\u4e2a\u5e76\u884c\u89c6\u89d2\uff1a\\n\\n1. **\u5916\u90e8\u89c6\u89d2**\\n   - \u641c\u7d22\u6a21\u5757\u7684\u8c03\u7528\u65b9\u548c\u5f15\u7528\u70b9\\n   - \u8bc6\u522b CLI\u3001HTTP\u3001UI\u3001\u5b9a\u65f6\u4efb\u52a1\u548c\u6d88\u606f\u6d88\u8d39\u5165\u53e3\\n   - \u67e5\u627e\u4ed3\u5e93\u5185\u5df2\u6709\u6587\u6863\\n   - \u67e5\u627e\u6d4b\u8bd5\u6587\u4ef6\u53ca\u4e3b\u8981\u7528\u4f8b\\n   - \u786e\u8ba4\u4f9d\u8d56\u5173\u7cfb\\n\\n2. **\u5185\u90e8\u5b9e\u73b0**\\n   - \u5b8c\u6574\u8bfb\u53d6\u6307\u5b9a\u6a21\u5757\u4e2d\u7684\u975e\u6d4b\u8bd5\u6e90\u6587\u4ef6\\n   - \u5206\u6790\u804c\u8d23\u3001\u63a5\u53e3\u3001\u8c03\u7528\u94fe\u3001\u6570\u636e\u6d41\u3001\u89c4\u5219\u3001\u5f02\u5e38\u548c\u5f71\u54cd\u8303\u56f4\\n   - \u6bcf\u9879\u53d1\u73b0\u4fdd\u7559 `file:line` \u4f9d\u636e\uff0c\u4ec5\u7528\u4e8e\u8c03\u7814\u9636\u6bb5\\n   - \u533a\u5206\u4ee3\u7801\u660e\u786e\u8868\u8fbe\u7684\u4e8b\u5b9e\u4e0e\u5206\u6790\u63a8\u65ad\\n\\n\u63a2\u7d22\u5b8c\u6210\u540e\u9700\u8981\u5355\u72ec\u590d\u6838\u63a8\u65ad\u5185\u5bb9\uff0c\u907f\u514d\u628a\u672a\u7ecf\u4ee3\u7801\u786e\u8ba4\u7684\u7ed3\u8bba\u5199\u5165\u77e5\u8bc6\u5e93\u3002\\n\\n### \u6210\u6587\u9636\u6bb5\\n\\n\u8bbe\u8ba1\u6587\u6863\u5fc5\u987b\u5305\u542b\u4ee5\u4e0b\u516b\u4e2a\u7ae0\u8282\uff0c\u987a\u5e8f\u56fa\u5b9a\uff1a\\n\\n```text\\n## \u529f\u80fd\u6982\u8ff0\\n## \u4f7f\u7528\u573a\u666f\\n## \u53c2\u4e0e\u89d2\u8272\\n## \u7528\u6237\u884c\u4e3a\u4e0e\u4ea4\u4e92\u6d41\u7a0b\\n## \u4e1a\u52a1\u89c4\u5219\u4e0e\u7ea6\u675f\\n## \u5f02\u5e38\u4e0e\u8fb9\u754c\u60c5\u51b5\\n## \u5f71\u54cd\u8303\u56f4\\n## \u9a8c\u6536\u6807\u51c6\\n```\\n\\n\u5373\u4f7f\u67d0\u4e00\u7ae0\u8282\u4e0d\u9002\u7528\uff0c\u4e5f\u5fc5\u987b\u4fdd\u7559\u6807\u9898\u5e76\u5199\u660e\u201c\u65e0\u201d\u6216\u201c\u4e0d\u6d89\u53ca\u201d\u3002\\n\\n\u6b63\u6587\u7ea6\u675f\u5982\u4e0b\uff1a\\n\\n- \u53ea\u63cf\u8ff0\u4ee3\u7801\u5f53\u524d\u884c\u4e3a\\n- \u4e0d\u5199\u6539\u8fdb\u5efa\u8bae\\n- \u4e0d\u8bc4\u4ef7\u4ee3\u7801\u8d28\u91cf\\n- \u58f0\u660e\u4f46\u672a\u4f7f\u7528\u7684\u63a5\u53e3\u8bb0\u5f55\u4e3a\u73b0\u72b6\\n- \u6b63\u6587\u4e0d\u5305\u542b `file:line` \u6216\u884c\u53f7\\n- \u7ed3\u6784\u5316\u4fe1\u606f\u4f18\u5148\u4f7f\u7528\u8868\u683c\\n- \u9996\u6b21\u51fa\u73b0\u7684\u672f\u8bed\u9700\u8981\u89e3\u91ca\\n- \u65e0\u6cd5\u4ece\u4ee3\u7801\u786e\u8ba4\u7684\u5185\u5bb9\u4e0d\u80fd\u5199\u6210\u786e\u5b9a\u4e8b\u5b9e\\n\\n## \u6587\u6863 Frontmatter\\n\\n`feature-workflow-authoring.md` \u548c `feature-workflow-isolation.md` \u5747\u4f7f\u7528 YAML frontmatter\uff1a\\n\\n```yaml\\n---\\ntitle: \u6587\u6863\u6807\u9898\\nfeature_id: \u529f\u80fd\u6807\u8bc6\\nmodule: \u5bf9\u5e94\u6a21\u5757\u6216\u5305\u540d\\ndoc_category: technical_design\\nsource_commit: \u4ee3\u7801\u77ed\u63d0\u4ea4\u54c8\u5e0c\\nsource_branch: \u5206\u652f\u540d\\ngenerated_at: \u751f\u6210\u65e5\u671f\\ngenerated_from: \u6765\u6e90\u4ee3\u7801\u8def\u5f84\\n---\\n```\\n\\n\u5b57\u6bb5\u542b\u4e49\uff1a\\n\\n| \u5b57\u6bb5 | \u8bf4\u660e |\\n|---|---|\\n| `title` | \u6587\u6863\u6807\u9898 |\\n| `feature_id` | \u7a33\u5b9a\u7684\u529f\u80fd\u6807\u8bc6 |\\n| `module` | \u5bf9\u5e94\u7684\u4ee3\u7801\u6a21\u5757\u6216\u5305 |\\n| `doc_category` | \u6587\u6863\u7c7b\u522b\uff0c\u5f53\u524d\u8bbe\u8ba1\u6587\u6863\u4f7f\u7528 `technical_design` |\\n| `source_commit` | \u6587\u6863\u5bf9\u5e94\u7684\u4ee3\u7801\u63d0\u4ea4\u77ed\u54c8\u5e0c |\\n| `source_branch` | \u751f\u6210\u6587\u6863\u65f6\u6240\u5728\u5206\u652f |\\n| `generated_at` | \u6587\u6863\u751f\u6210\u65e5\u671f |\\n| `generated_from` | \u53c2\u4e0e\u5206\u6790\u7684\u6e90\u4ee3\u7801\u76ee\u5f55 |\\n\\n\u5f53\u524d\u5df2\u6709\u6587\u6863\u7684\u4ee3\u7801\u7248\u672c\u548c\u751f\u6210\u4fe1\u606f\u4e3a\uff1a\\n\\n| \u6587\u6863 | `feature_id` | `module` | `source_commit` |\\n|---|---|---|---|\\n| `feature-workflow-authoring.md` | `FEAT-WORKFLOW-AUTHORING-001` | `@archon/workflows` | `2140beae` |\\n| `feature-workflow-isolation.md` | `FEAT-ISOLATION-001` | `@archon/isolation` | `2140beae` |\\n\\n## \u5f53\u524d\u6587\u6863\u5185\u5bb9\\n\\n### `feature-workflow-authoring.md`\\n\\n\u8be5\u6587\u6863\u63cf\u8ff0 `@archon/workflows` \u4e2d\u5de5\u4f5c\u6d41 YAML \u7684\u53d1\u73b0\u3001\u89e3\u6790\u3001\u7ed3\u6784\u6821\u9a8c\u548c\u5916\u90e8\u8d44\u6e90\u6821\u9a8c\u3002\\n\\n\u8986\u76d6\u5185\u5bb9\u5305\u62ec\uff1a\\n\\n- bundled\u3001global\u3001project \u4e09\u4e2a scope \u7684\u8d44\u6e90\u53d1\u73b0\\n- \u5de5\u4f5c\u6d41\u3001command \u548c script \u7684\u4f18\u5148\u7ea7\u5408\u5e76\\n- YAML \u8bed\u6cd5\u548c\u7ed3\u6784\u6821\u9a8c\\n- \u8282\u70b9 schema \u6821\u9a8c\\n- DAG \u73af\u68c0\u6d4b\u548c\u4f9d\u8d56\u5f15\u7528\u6821\u9a8c\\n- \u5b50\u6d41\u7a0b\u5c55\u5f00\u4e0e\u8282\u70b9 ID \u91cd\u5199\\n- command\u3001MCP\u3001skill \u548c script \u7684 Level 3 \u8d44\u6e90\u6821\u9a8c\\n- CLI \u4e0e HTTP \u6821\u9a8c\u5165\u53e3\\n- Builder \u4f7f\u7528\u7684 v2 \u6821\u9a8c\u63a5\u53e3\\n- \u5de5\u4f5c\u6d41\u547d\u540d\u3001\u8282\u70b9\u7c7b\u578b\u3001\u56de\u9000\u8fb9\u3001\u91cd\u8bd5\u548c hooks \u7b49\u89c4\u5219\\n- \u9519\u8bef\u6c47\u603b\u3001\u8b66\u544a\u3001\u964d\u7ea7\u548c\u9759\u9ed8\u4e22\u5f03\u884c\u4e3a\\n- \u4e0e\u6267\u884c\u5f15\u64ce\u3001\u670d\u52a1\u7aef\u5b58\u50a8\u548c\u6784\u5efa\u671f\u5185\u7f6e\u8d44\u6e90\u751f\u6210\u7684\u8fb9\u754c\\n\\n\u8be5\u6587\u6863\u660e\u786e\u8bb0\u5f55\u4e86\u52a0\u8f7d\u671f\u4e0e\u6267\u884c\u671f\u7684\u804c\u8d23\u5206\u754c\u3002\u4f8b\u5982\uff1a\\n\\n- \u52a0\u8f7d\u671f\u68c0\u67e5 DAG \u662f\u5426\u6709\u73af\uff0c\u6267\u884c\u671f\u8d1f\u8d23\u62d3\u6251\u5206\u5c42\u548c\u8c03\u5ea6\\n- \u52a0\u8f7d\u671f\u4e0d\u6821\u9a8c\u6a21\u578b\u540d\uff0c\u6a21\u578b\u540d\u7531\u5382\u5546 SDK \u6216\u670d\u52a1\u7aef v2 \u63a5\u53e3\u5904\u7406\\n- HTTP \u6821\u9a8c\u53ea\u8fd0\u884c Level 1-2\uff0cCLI \u6821\u9a8c\u4f1a\u6267\u884c Level 3\\n- \u5de5\u4f5c\u6d41\u89e3\u6790\u53ea\u590d\u5236\u5b9e\u9645\u91c7\u7eb3\u7684\u9876\u5c42\u5b57\u6bb5\uff0c\u672a\u88ab\u52a0\u8f7d\u51fd\u6570\u590d\u5236\u7684\u5b57\u6bb5\u4f1a\u88ab\u4e22\u5f03\\n\\n### `feature-workflow-isolation.md`\\n\\n\u8be5\u6587\u6863\u63cf\u8ff0 `@archon/isolation` \u4e3a\u5de5\u4f5c\u6d41\u5206\u914d\u72ec\u7acb Git worktree \u7684\u673a\u5236\u3002\\n\\n\u8986\u76d6\u5185\u5bb9\u5305\u62ec\uff1a\\n\\n- issue\u3001PR\u3001review\u3001thread \u548c task \u7684\u9694\u79bb\u73af\u5883\\n- \u9694\u79bb\u73af\u5883\u7684\u590d\u7528\u3001\u9886\u517b\u3001\u521b\u5efa\u548c\u9500\u6bc1\\n- Git worktree \u7684\u5e95\u5c42\u64cd\u4f5c\\n- \u5206\u652f\u540d\u548c worktree \u8def\u5f84\u751f\u6210\u89c4\u5219\\n- \u6309\u4e3b\u4ed3\u8def\u5f84\u52a0\u9501\u7684\u5e76\u53d1\u63a7\u5236\\n- PR \u5206\u652f\u3001fork PR \u548c\u8d77\u70b9\u5206\u652f\u5904\u7406\\n- \u6587\u4ef6\u590d\u5236\u3001submodule \u521d\u59cb\u5316\u548c\u914d\u7f6e\u52a0\u8f7d\\n- Git \u9519\u8bef\u5230\u7528\u6237\u53ef\u8bfb\u63d0\u793a\u7684\u8f6c\u6362\\n- \u521b\u5efa\u5931\u8d25\u3001\u5199\u5e93\u5931\u8d25\u65f6\u7684\u6e05\u7406\u548c\u56de\u6eda\\n- \u4e0e `@archon/core`\u3001`@archon/cli`\u3001`@archon/git` \u548c\u4e0a\u5c42\u5b58\u50a8\u7684\u5173\u7cfb\\n- `IsolationBlockedError` \u7b49\u963b\u585e\u9519\u8bef\u7684\u4f7f\u7528\u65b9\u5f0f\\n- Git\u3001`gh` \u548c\u6587\u4ef6\u7cfb\u7edf\u7684\u5916\u90e8\u4f9d\u8d56\\n\\n\u8be5\u6587\u6863\u8fd8\u8bb0\u5f55\u4e86\u6a21\u5757\u4e0d\u8d1f\u8d23\u7684\u5185\u5bb9\uff1a\\n\\n- \u4e0d\u76f4\u63a5\u843d\u5e93\\n- \u4e0d\u63a8\u9001\u5e73\u53f0\u6d88\u606f\\n- \u4e0d\u51b3\u5b9a\u6e05\u7406\u7b56\u7565\\n- \u4e0d\u68c0\u67e5\u672a\u63d0\u4ea4\u6539\u52a8\\n- \u5f53\u524d\u53ea\u5b9e\u73b0 Git worktree\uff0c\u4e0d\u5b9e\u73b0 container\u3001VM \u6216 remote \u9694\u79bb\\n\\n## \u6587\u6863\u751f\u6210\u6267\u884c\u6d41\\n\\n\u6587\u6863\u751f\u6210\u8fc7\u7a0b\u7531 `PROMPT.md` \u5b9a\u4e49\uff0c\u53ef\u6982\u62ec\u4e3a\u4ee5\u4e0b\u6b65\u9aa4\uff1a\\n\\n1. \u786e\u5b9a\u5355\u4e00\u529f\u80fd\u8303\u56f4\\n2. \u8bb0\u5f55\u4ee3\u7801\u63d0\u4ea4\u54c8\u5e0c\u548c\u6e90\u6587\u4ef6\u6e05\u5355\\n3. \u5e76\u884c\u6267\u884c\u5916\u90e8\u89c6\u89d2\u4e0e\u5185\u90e8\u5b9e\u73b0\u63a2\u7d22\\n4. \u590d\u6838\u63a2\u7d22\u7ed3\u679c\u4e2d\u7684\u63a8\u65ad\\n5. \u4f7f\u7528\u56fa\u5b9a frontmatter \u548c\u516b\u7ae0\u7ed3\u6784\u6210\u6587\\n6. \u5728\u5165\u5e93\u524d\u68c0\u67e5\u7ed3\u6784\u3001\u6eaf\u6e90\u3001\u5165\u53e3\u548c\u65e2\u6709\u6587\u6863\\n7. \u4ee3\u7801\u53d8\u66f4\u540e\u6309\u9700\u6216\u5b9a\u671f\u5237\u65b0\u6587\u6863\\n\\n\u6587\u6863\u5165\u5e93\u524d\u68c0\u67e5\u9879\u5305\u62ec\uff1a\\n\\n- \u516b\u7ae0\u9f50\u5168\u4e14\u987a\u5e8f\u6b63\u786e\\n- \u6b63\u6587\u6ca1\u6709 `file:line` \u6216\u884c\u53f7\\n- \u6b63\u6587\u6ca1\u6709\u6539\u8fdb\u5efa\u8bae\\n- \u63a8\u65ad\u5185\u5bb9\u5df2\u4eba\u5de5\u590d\u6838\u6216\u660e\u786e\u6807\u6ce8\\n- CLI \u547d\u4ee4\u3001HTTP \u8def\u5f84\u7b49\u5165\u53e3\u5df2\u5199\u5168\\n- \u5df2\u68c0\u67e5\u540c\u4e00\u529f\u80fd\u7684\u65e2\u6709\u6587\u6863\\n- \u5df2\u51b3\u5b9a\u662f\u66f4\u65b0\u65e2\u6709\u6587\u6863\u8fd8\u662f\u521b\u5efa\u65b0\u6587\u6863\\n- \u9996\u6b21\u5165\u5e93\u540e\u4fdd\u7559\u6587\u6863 ID\uff0c\u907f\u514d\u91cd\u590d\u521b\u5efa\\n\\n## \u7ef4\u62a4\u65b9\u5f0f\\n\\n\u4ee3\u7801\u53d8\u66f4\u4f1a\u4f7f\u5bf9\u5e94\u8bbe\u8ba1\u6587\u6863\u9010\u6e10\u8fc7\u671f\u3002`PROMPT.md` \u89c4\u5b9a\u4e24\u79cd\u7ef4\u62a4\u65b9\u5f0f\uff1a\\n\\n### \u6309\u9700\u5237\u65b0\\n\\n\u4fee\u6539\u67d0\u4e2a\u6a21\u5757\u540e\uff0c\u91cd\u65b0\u751f\u6210\u8be5\u6a21\u5757\u7684\u6587\u6863\uff0c\u5e76\u901a\u8fc7 `source_commit` \u5224\u65ad\u6587\u6863\u662f\u5426\u9700\u8981\u66f4\u65b0\u3002\\n\\n\u9002\u7528\u4e8e\uff1a\\n\\n- \u6a21\u5757\u8fb9\u754c\u6e05\u6670\\n- \u4ee3\u7801\u53d8\u66f4\u96c6\u4e2d\\n- \u9700\u8981\u53ca\u65f6\u4fdd\u6301\u6587\u6863\u540c\u6b65\u7684\u529f\u80fd\\n\\n### \u5b9a\u671f\u5237\u65b0\\n\\n\u6309\u7167\u7ea6\u5b9a\u5468\u671f\u91cd\u65b0\u751f\u6210\u591a\u4e2a\u6a21\u5757\u7684\u6587\u6863\uff0c\u63a5\u53d7\u5237\u65b0\u5468\u671f\u5185\u5b58\u5728\u4e00\u5b9a\u5185\u5bb9\u504f\u5dee\u3002\\n\\n\u9002\u7528\u4e8e\uff1a\\n\\n- \u6a21\u5757\u8f83\u591a\\n- \u53d8\u66f4\u9891\u7387\u8f83\u4f4e\\n- \u66f4\u5173\u6ce8\u6574\u4f53\u4e00\u81f4\u6027\u800c\u975e\u5373\u65f6\u540c\u6b65\\n\\n\u65e0\u8bba\u91c7\u7528\u54ea\u79cd\u65b9\u5f0f\uff0c\u90fd\u5e94\u4fdd\u7559 `source_commit`\uff0c\u4f7f\u8bfb\u8005\u80fd\u591f\u786e\u8ba4\u6587\u6863\u63cf\u8ff0\u7684\u662f\u54ea\u4e00\u7248\u5b9e\u73b0\u3002\\n\\n## \u4e0e\u4ee3\u7801\u5e93\u7684\u5173\u7cfb\\n\\n`docs/wiki-drafts` \u4e0d\u5c5e\u4e8e\u4efb\u4f55\u8fd0\u884c\u65f6\u5305\uff0c\u4e0d\u53c2\u4e0e\u5e94\u7528\u542f\u52a8\u3001\u5de5\u4f5c\u6d41\u6267\u884c\u3001HTTP \u8bf7\u6c42\u5904\u7406\u6216\u6570\u636e\u5e93\u64cd\u4f5c\u3002\\n\\n\u5b83\u4e0e\u4ee3\u7801\u5e93\u7684\u8fde\u63a5\u4e3b\u8981\u4f53\u73b0\u5728\uff1a\\n\\n- `PROMPT.md` \u7ea6\u675f\u5982\u4f55\u4ece\u4ee3\u7801\u4e2d\u63d0\u53d6\u4e8b\u5b9e\\n- feature \u6587\u6863\u901a\u8fc7 `module` \u548c `generated_from` \u6307\u5411\u5bf9\u5e94\u4ee3\u7801\u6a21\u5757\\n- `source_commit` \u5c06\u6587\u6863\u4e0e\u5177\u4f53\u4ee3\u7801\u7248\u672c\u7ed1\u5b9a\\n- \u6587\u6863\u4e2d\u7684 CLI\u3001HTTP \u8def\u5f84\u3001\u4f9d\u8d56\u5305\u3001\u9519\u8bef\u7c7b\u578b\u548c\u914d\u7f6e\u5b57\u6bb5\u6765\u81ea\u5b9e\u9645\u4ee3\u7801\u5b9e\u73b0\\n- \u6587\u6863\u53ef\u4f5c\u4e3a wiki\u3001\u77e5\u8bc6\u56fe\u8c31\u6216\u540e\u7eed AI \u4e0a\u4e0b\u6587\u7684\u8f93\u5165\\n\\n\u5f53\u524d\u6ca1\u6709\u68c0\u6d4b\u5230\u8be5\u76ee\u5f55\u7684\u5185\u90e8\u8c03\u7528\u56fe\u3001\u4f20\u5165\u8c03\u7528\u65b9\u6216\u4f20\u51fa\u8c03\u7528\u5173\u7cfb\uff1a\\n\\n- Internal calls: none\\n- Incoming calls: none\\n- Outgoing calls: none\\n- Execution flows: none detected\\n\\n\u56e0\u6b64\uff0c\u8be5\u6a21\u5757\u7684\u201c\u6267\u884c\u6d41\u201d\u662f\u6587\u6863\u751f\u6210\u548c\u7ef4\u62a4\u6d41\u7a0b\uff0c\u800c\u4e0d\u662f\u8fd0\u884c\u65f6\u51fd\u6570\u8c03\u7528\u94fe\u3002\\n\\n## \u73b0\u72b6\u8fb9\u754c\\n\\n\u4ee5\u4e0b\u5185\u5bb9\u5c5e\u4e8e\u6587\u6863\u6d41\u7a0b\u672c\u8eab\uff0c\u800c\u4e0d\u662f\u88ab\u8bb0\u5f55\u529f\u80fd\u7684\u8fd0\u884c\u65f6\u884c\u4e3a\uff1a\\n\\n- `PROMPT.md` \u4e2d\u7684\u63a2\u7d22 Prompt\\n- \u56fa\u5b9a\u7684\u516b\u7ae0\u7ed3\u6784\\n- frontmatter \u5b57\u6bb5\u7ea6\u5b9a\\n- \u5165\u5e93\u524d\u68c0\u67e5\u6e05\u5355\\n- \u6587\u6863\u5237\u65b0\u7b56\u7565\\n- \u7981\u6b62\u6539\u8fdb\u5efa\u8bae\u548c\u7981\u6b62\u6b63\u6587\u884c\u53f7\u7684\u5199\u4f5c\u7ea6\u675f\\n\\n\u4ee5\u4e0b\u5185\u5bb9\u5c5e\u4e8e\u5df2\u6709 feature \u6587\u6863\u6240\u63cf\u8ff0\u7684\u5916\u90e8\u6a21\u5757\u884c\u4e3a\uff1a\\n\\n- \u5de5\u4f5c\u6d41 YAML \u7684\u52a0\u8f7d\u3001\u53d1\u73b0\u548c\u6821\u9a8c\u5c5e\u4e8e `@archon/workflows`\\n- \u5de5\u4f5c\u6d41\u9694\u79bb\u73af\u5883\u5c5e\u4e8e `@archon/isolation`\\n- Git \u64cd\u4f5c\u7531 `@archon/git` \u63d0\u4f9b\\n- \u6570\u636e\u5e93\u5b58\u50a8\u548c\u670d\u52a1\u7aef\u8c03\u7528\u7531\u4e0a\u5c42\u6a21\u5757\u8d1f\u8d23\\n\\n`docs/wiki-drafts` \u672c\u8eab\u4e0d\u4f1a\u6267\u884c\u8fd9\u4e9b\u529f\u80fd\uff0c\u4e5f\u4e0d\u4f1a\u9a8c\u8bc1 feature \u6587\u6863\u4e2d\u7684\u8fd0\u884c\u65f6\u884c\u4e3a\u3002\\n\\n## \u9a8c\u6536\u6807\u51c6\\n\\n### \u6587\u6863\u7ed3\u6784\\n\\n- \u6bcf\u4e2a\u529f\u80fd\u6587\u6863\u5305\u542b\u56fa\u5b9a\u7684\u516b\u4e2a\u7ae0\u8282\\n- \u7ae0\u8282\u987a\u5e8f\u4e0d\u53d8\uff0c\u7ae0\u8282\u6570\u91cf\u4e0d\u589e\u4e0d\u51cf\\n- \u67d0\u7ae0\u8282\u65e0\u5185\u5bb9\u65f6\u4fdd\u7559\u6807\u9898\u5e76\u660e\u786e\u5199\u51fa\u201c\u4e0d\u6d89\u53ca\u201d\u6216\u201c\u65e0\u201d\\n- \u6587\u6863\u5305\u542b\u5b8c\u6574 frontmatter\\n\\n### \u5185\u5bb9\u51c6\u786e\u6027\\n\\n- \u63cf\u8ff0\u5bf9\u5e94\u4ee3\u7801\u7248\u672c\u7684\u73b0\u72b6\\n- \u4f7f\u7528\u5b9e\u9645\u6a21\u5757\u3001\u5305\u540d\u3001\u547d\u4ee4\u540d\u3001HTTP \u8def\u5f84\u548c\u9519\u8bef\u7c7b\u578b\\n- \u660e\u786e\u533a\u5206\u6a21\u5757\u804c\u8d23\u8fb9\u754c\u4e0e\u4e0a\u5c42\u804c\u8d23\\n- \u672a\u4f7f\u7528\u63a5\u53e3\u3001\u9759\u9ed8\u4e22\u5f03\u3001\u964d\u7ea7\u548c\u517c\u5bb9\u884c\u4e3a\u6309\u73b0\u72b6\u8bb0\u5f55\\n- \u4e0d\u5c06\u63a8\u65ad\u5199\u6210\u672a\u7ecf\u786e\u8ba4\u7684\u4e8b\u5b9e\\n- \u4e0d\u5728\u6b63\u6587\u4e2d\u4f9d\u8d56\u6613\u5931\u6548\u7684\u884c\u53f7\\n\\n### \u53ef\u7ef4\u62a4\u6027\\n\\n- `source_commit` \u4e0e `generated_from` \u53ef\u5b9a\u4f4d\u6587\u6863\u6765\u6e90\\n- \u4ee3\u7801\u53d8\u66f4\u540e\u80fd\u591f\u5224\u65ad\u6587\u6863\u662f\u5426\u9700\u8981\u5237\u65b0\\n- \u540c\u4e00\u529f\u80fd\u5df2\u6709\u6587\u6863\u65f6\u4f18\u5148\u66f4\u65b0\uff0c\u907f\u514d\u4ea7\u751f\u76f8\u4e92\u77db\u76fe\u7684\u526f\u672c\\n- \u7ed3\u6784\u5316\u4fe1\u606f\u4f7f\u7528\u8868\u683c\uff0c\u4fbf\u4e8e wiki \u5206\u5757\u3001\u68c0\u7d22\u548c\u77e5\u8bc6\u56fe\u8c31\u5904\u7406\\n- \u6587\u6863\u5185\u5bb9\u4e0d\u5305\u542b\u6539\u8fdb\u5efa\u8bae\u6216\u8d28\u91cf\u8bc4\u4ef7\",\"overview\":\"# doarchon \u2014 Wiki\\n\\n# Archon\\n\\nArchon is an open-source workflow engine for AI coding agents. It turns a development process\u2014planning, implementation, verification, review, and pull-request creation\u2014into a reproducible YAML workflow that can run consistently across projects.\\n\\nThe repository contains the workflow runtime, web application, API server, authentication, platform integrations, developer CLI, scheduling, knowledge management, and observability tooling in one system.\\n\\n## Architecture at a glance\\n\\n```mermaid\\nflowchart LR\\n    UI[Web Application UI]\\n    CLI[CLI and Developer Tools]\\n    AUTH[Authentication and Identity]\\n    API[API Server and Integrations]\\n    CORE[Core Runtime]\\n    WF[Workflow Orchestration]\\n    ADAPT[Chat and Platform Adapters]\\n    KNOW[Knowledge Management]\\n    OBS[Observability and Evaluation]\\n\\n    UI --&gt; AUTH\\n    UI --&gt; API\\n    CLI --&gt; CORE\\n    CLI --&gt; WF\\n    AUTH --&gt; API\\n    API --&gt; CORE\\n    API --&gt; ADAPT\\n    API --&gt; WF\\n    CORE --&gt; WF\\n    WF --&gt; ADAPT\\n    CORE --&gt; KNOW\\n    CORE --&gt; OBS\\n    API --&gt; OBS\\n    UI --&gt; OBS\\n```\\n\\n## How the system is organized\\n\\nThe browser client is implemented in `packages/web`. The [Web Application UI](web-application-ui.md) module bootstraps React, establishes providers, handles client-side routing, and renders workflow, knowledge, and observability experiences.\\n\\nThe server entry point is `packages/server/src/index.ts`. [API Server and Integrations](api-server-and-integrations.md) exposes HTTP APIs and connects the application to Web, Telegram, Discord, Slack, GitHub, Gitea, and GitLab surfaces. It also coordinates startup migrations, external service clients, background work, and production web serving.\\n\\nAuthentication is handled by two layers. [Authentication and Identity](authentication-and-identity.md) describes application identity, UUAP SSO or test credentials, system JWTs, and the optional standalone `auth-service/server.js` perimeter service.\\n\\nThe central runtime is composed of shared core services, workflow definitions, providers, paths, Git operations, isolation worktrees, and sandboxes. These lower-level components are used by the [Workflow Orchestration and Scheduling](workflow-orchestration-and-scheduling.md) module, the API server, the CLI, and platform adapters.\\n\\n[Chat and Platform Adapters](chat-and-platform-adapters.md) keeps workflow execution independent from its delivery surface. `CLIAdapter` handles terminal output, while `WebAdapter` supports browser streaming, Server-Sent Events, workflow event forwarding, and buffered persistence.\\n\\n[Knowledge Management](knowledge-management.md) provides product-scoped knowledge spaces used by the knowledge UI, knowledge-aware chat routing, graphs, wikis, governance records, and evaluation artifacts.\\n\\n[Observability, Runtime Tracing, and Evaluation](observability-runtime-tracing-and-evaluation.md) captures API and workflow activity, analyzes traces and failures, applies quality gates, supports replay and evaluation, and exposes operational dashboards. Optional DeepEval and Ragas integrations provide LLM-as-a-judge evaluation.\\n\\n## End-to-end execution flows\\n\\n### 1. Sign in and access the application\\n\\n1. A user signs in through the web application.\\n2. The authentication layer validates UUAP SSO or configured test credentials.\\n3. The server issues a system JWT representing the local user.\\n4. The web client stores the token in its Zustand authentication state.\\n5. Subsequent API requests include the token in their authorization headers.\\n6. Protected server routes resolve the local user before accessing workflows, projects, knowledge, or observability data.\\n\\nThe standalone `auth-service` can be placed at the perimeter when deployment requires reverse-proxy `forward_auth` integration.\\n\\n### 2. Run and monitor a workflow\\n\\n1. A user starts a workflow from the web UI or CLI.\\n2. The client calls the server API to create or retrieve the workflow run.\\n3. The API server delegates execution to the core runtime and workflow orchestration services.\\n4. The orchestration layer resolves workflow steps, providers, project paths, Git state, isolation worktrees, and sandbox requirements.\\n5. Progress is emitted through the appropriate adapter:\\n   - `WebAdapter` streams structured events and SSE messages to the browser.\\n   - `CLIAdapter` renders progress in the terminal and can persist assistant messages.\\n6. Workflow and API activity is recorded by the observability layer.\\n7. The UI updates the run view as execution progresses and displays the final result, errors, artifacts, or approval state.\\n\\nFor example, `WorkflowExecution` retrieves a run through `getWorkflowRun`, which uses the shared API request helpers. Those helpers also record observability events, schedule event flushing, and attach authentication headers.\\n\\n### 3. Approve, reject, or retry paused work\\n\\nWorkflows may pause when a human decision or controlled transition is required. The server exposes operations for approval, rejection, and retry. The orchestration module validates the current run state, performs the transition, and resumes or terminates execution as appropriate.\\n\\nThis keeps long-running work deterministic while allowing human review at defined workflow boundaries.\\n\\n### 4. Schedule and complete background work\\n\\nScheduled tasks create isolated orchestration sessions rather than sharing interactive request state. The scheduler invokes workflow runs, manages project and worktree cleanup, and performs production-only maintenance and notification work.\\n\\nWhen a run completes, Archon can notify users and export messages or artifacts to supported external systems.\\n\\n### 5. Use knowledge and evaluation data\\n\\nKnowledge features are scoped by `product_id`. A product determines the knowledge space, graph, wiki, governance records, and evaluation artifacts available to the user or workflow.\\n\\nChat requests can be routed to a product\u2019s knowledge-aware conversation path. Evaluation results can be governed and promoted as knowledge artifacts, allowing operational findings and validated workflow improvements to become reusable project knowledge.\\n\\n## Repository areas to explore\\n\\nStart with [Web Application UI](web-application-ui.md) if you are working on browser behavior, routing, authentication handoff, or workflow screens.\\n\\nRead [API Server and Integrations](api-server-and-integrations.md) for HTTP routes, server startup, external integrations, adapters, migrations, and background services.\\n\\nRead [Workflow Orchestration and Scheduling](workflow-orchestration-and-scheduling.md) for execution lifecycle, scheduled runs, approvals, retries, cleanup, and notifications.\\n\\nRead [Authentication and Identity](authentication-and-identity.md) before changing login behavior, JWT handling, or perimeter authentication.\\n\\nRead [Chat and Platform Adapters](chat-and-platform-adapters.md) when adding or modifying a delivery surface.\\n\\nRead [Knowledge Management](knowledge-management.md) for product-scoped knowledge flows and evaluation artifact governance.\\n\\nRead [Observability, Runtime Tracing, and Evaluation](observability-runtime-tracing-and-evaluation.md) for tracing, quality gates, dashboards, replay, and evaluation integrations.\\n\\n[CLI and Developer Tools](cli-and-developer-tools.md) covers the distributable CLI, Homebrew packaging, and related developer utilities. [Developer Documentation and Operational Scripts](developer-documentation-and-operational-scripts.md) covers standalone Python tools under `assets/` and `docs/`.\\n\\n## Local development\\n\\nUse the repository\u2019s configured package manager and Node.js version, then install dependencies:\\n\\n```sh\\nnpm install\\n```\\n\\nStart the full development environment with:\\n\\n```sh\\nnpm run dev\\n```\\n\\nWhen working only on one surface, use the focused scripts:\\n\\n```sh\\nnpm run dev:server   # API and server development\\nnpm run dev:web      # Web application development\\nnpm run dev:docs     # Documentation development\\n```\\n\\nBuild the application with:\\n\\n```sh\\nnpm run build\\nnpm run build:web\\nnpm run build:docs\\n```\\n\\nAuthentication-dependent development environments can be initialized with:\\n\\n```sh\\nnpm run setup-auth\\n```\\n\\nConfigure the environment variables and backing services required by the server and integrations before starting the application. Consult the authentication, API, and integration module pages for service-specific configuration.\\n\\n## Validation and testing\\n\\nRun the standard validation pipeline with:\\n\\n```sh\\nnpm run validate\\n```\\n\\nUseful focused checks include:\\n\\n```sh\\nnpm run type-check\\nnpm run lint\\nnpm run format:check\\nnpm test\\nnpm run test:api\\nnpm run test:e2e\\n```\\n\\nAdditional scripts cover sequential, affected, scenario, UI, coverage, security, bundled-artifact, AI-flow, and quality-gate checks. Use `npm run` to inspect the complete script list defined by the repository.\\n\\nFor production-style artifacts, the repository also provides scripts for building binaries, generating checksums, generating bundled workflows, validating bundled skills, and producing quality or coverage reports.\",\"web-application-ui\":\"# Web Application UI\\n\\n# Web Application UI Module\\n\\nThe Web Application UI module is the React entry point for the web client. It bootstraps the application, establishes global providers, handles authentication handoff, configures client-side routing, and supplies a top-level rendering error boundary.\\n\\nThe module consists of:\\n\\n- `packages/web/src/main.tsx` \u2014 browser bootstrap\\n- `packages/web/src/App.tsx` \u2014 application composition, routing, and global error handling\\n\\n## Responsibilities\\n\\nThe module is responsible for:\\n\\n1. Mounting React into the DOM.\\n2. Loading global styles.\\n3. Enabling React `StrictMode`.\\n4. Providing application-wide context:\\n   - Theme state through `ThemeProvider`\\n   - Server-state caching through `QueryClientProvider`\\n   - Project state through `ProjectProvider`\\n   - Observability through `ObservabilityProvider`\\n5. Processing authentication tokens returned through a `?token=` URL parameter.\\n6. Separating public routes from authenticated routes.\\n7. Rendering the shared authenticated `Layout`.\\n8. Redirecting legacy and shorthand URLs.\\n9. Capturing uncaught rendering errors with `ErrorBoundary`.\\n\\n## Application Bootstrap\\n\\n`main.tsx` locates the HTML element with the `root` ID and mounts the application using React\u2019s `createRoot` API:\\n\\n```tsx\\nconst rootElement = document.getElementById('root');\\nif (!rootElement) {\\n  throw new Error('Root element not found');\\n}\\n\\ncreateRoot(rootElement).render(\\n  \\n    \\n  &lt;\\/StrictMode&gt;\\n);\\n```\\n\\nIf the root element is missing, startup stops immediately with an error. The module also imports `index.css`, making the application\u2019s global styles available before rendering.\\n\\n`StrictMode` is enabled in development-oriented React execution. Components should therefore tolerate React\u2019s development-time checks and repeated lifecycle execution.\\n\\n## Provider Composition\\n\\n`App` composes the application-wide providers in the following order:\\n\\n```text\\nErrorBoundary\\n\u2514\u2500\u2500 ThemeProvider\\n    \u2514\u2500\u2500 QueryClientProvider\\n        \u2514\u2500\u2500 ProjectProvider\\n            \u2514\u2500\u2500 BrowserRouter\\n                \u2514\u2500\u2500 ObservabilityProvider\\n                    \u251c\u2500\u2500 TokenReceiver\\n                    \u2514\u2500\u2500 Routes\\n```\\n\\nEach provider establishes context for the components below it:\\n\\n- `ErrorBoundary` catches rendering failures across the application.\\n- `ThemeProvider` supplies theme-related state and behavior.\\n- `QueryClientProvider` exposes the shared `queryClient` from `@/lib/query-client`.\\n- `ProjectProvider` supplies project context.\\n- `BrowserRouter` enables URL-based navigation using the browser history API.\\n- `ObservabilityProvider` supplies observability behavior used by the application and error reporting.\\n\\n`TokenReceiver` and the route tree are descendants of `BrowserRouter`, which is required because `TokenReceiver` uses React Router\u2019s `useSearchParams`.\\n\\n## Runtime Error Handling\\n\\n### `ErrorBoundary`\\n\\n`ErrorBoundary` is a class component that wraps the entire application. It implements:\\n\\n- `getDerivedStateFromError()` to switch into an error state\\n- `componentDidCatch()` to report and log the failure\\n- `render()` to display either the application or a fallback screen\\n\\nWhen a rendering error occurs, `componentDidCatch()` calls:\\n\\n```tsx\\nreportReactError(error, info);\\n```\\n\\nIt also writes structured details to the console, including:\\n\\n- Error message\\n- Error stack\\n- React component stack\\n\\nThe fallback UI displays the error message when available and provides a button that reloads the page with `window.location.reload()`.\\n\\nThis boundary handles rendering errors. It does not replace route-level loading, data-fetching, or API error handling implemented by individual pages and components.\\n\\n## Authentication Token Handoff\\n\\n### `TokenReceiver`\\n\\n`TokenReceiver` handles tokens injected into the URL by the UUAP callback redirect.\\n\\nIts behavior is:\\n\\n1. Read the `token` query parameter using `useSearchParams`.\\n2. Store the token through `useAuthStore(s =&gt; s.setToken)`.\\n3. Remove `token` from the URL.\\n4. Replace the current history entry so the token is not retained in browser history.\\n5. Process the token only once per mounted instance.\\n\\nThe one-time guard is implemented with a ref:\\n\\n```tsx\\nconst handled = useRef(false);\\n```\\n\\nAfter a token is found, `handled.current` is set to `true` before updating the auth store and search parameters. The component renders `null`, so it does not add visible UI.\\n\\nBecause `TokenReceiver` is rendered inside `BrowserRouter`, it can safely use `useSearchParams`. It is also rendered before the route tree, allowing the auth store to receive a callback token as the application initializes.\\n\\n## Routing\\n\\nRouting is configured with React Router\u2019s `Routes`, `Route`, and `Navigate` components.\\n\\nRoutes are divided into:\\n\\n- Public routes that are accessible without the authenticated application shell\\n- Protected routes nested under `ProtectedRoute`\\n- Authenticated pages nested under `Layout`\\n\\n### Public Routes\\n\\nThe following routes are outside `ProtectedRoute`:\\n\\n| Path | Component | Purpose |\\n|---|---|---|\\n| `/login` | `LoginPage` | Login screen |\\n| `/sidebar/run/:runId` | `SidebarRunPage` | Sidebar run view |\\n| `/sidebar/session/:convId` | `SidebarSessionPage` | Sidebar conversation/session view |\\n| `/sidebar/error` | `SidebarErrorPage` | Sidebar error view |\\n| `/sidebar/start` | `SidebarStartPage` | Sidebar start view |\\n| `/sidebar/list` | `SidebarListPage` | Sidebar list view |\\n\\nThese pages also render outside the shared `Layout`.\\n\\n### Protected Application Routes\\n\\nAll existing application pages are nested under:\\n\\n```tsx\\n}&gt;\\n  }&gt;\\n    {/* authenticated routes */}\\n  &lt;\\/Route&gt;\\n&lt;\\/Route&gt;\\n```\\n\\n`ProtectedRoute` controls access to the authenticated section. `Layout` provides the common authenticated page structure for its child routes.\\n\\nThe route table is:\\n\\n| Path | Component |\\n|---|---|\\n| `/` | Redirects to `/chat` |\\n| `/chat` | `ChatPage` |\\n| `/chat/*` | `ChatPage` |\\n| `/dashboard` | `DashboardPage` |\\n| `/console` | `ControlConsolePage` |\\n| `/console/:section` | `ControlConsolePage` |\\n| `/evaluations` | `RealtimeEvaluationPage` |\\n| `/evaluations/usage` | `WorkflowUsagePage` |\\n| `/evaluations/personnel-usage` | `PersonnelUsagePage` |\\n| `/evaluations/sla` | `EvaluationSlaPage` |\\n| `/evaluations/ui-replay` | `UiReplayCenterPage` |\\n| `/evaluations/:section` | `RealtimeEvaluationPage` |\\n| `/traces` | Redirects to `/console/workflows`, preserving the query string |\\n| `/workflows` | `WorkflowSpacePage` |\\n| `/workflows/builder` | `WorkflowBuilderPage` |\\n| `/workflows/detail/:workflowId` | `WorkflowDetailPage` |\\n| `/workflows/runs/:runId` | `WorkflowExecutionPage` |\\n| `/knowledge` | `KnowledgePage` |\\n| `/knowledge/:section` | `KnowledgePage` |\\n| `/settings` | `SettingsPage` |\\n| `/spaces` | `ProductSpacePage` |\\n| `/diagnostics` | `DiagnosticsPage` |\\n\\n### Redirects and Compatibility Routes\\n\\nSeveral routes preserve older or alternate URL forms:\\n\\n- `/` redirects to `/chat`.\\n- `/traces` redirects to `/console/workflows`.\\n- `/workflows/space` redirects to `/workflows`.\\n- `/workflows/market` redirects to `/workflows`.\\n- `/workflows/runs` redirects to `/workflows`.\\n- Unknown authenticated paths redirect to `/chat`.\\n\\n`RuntimeTracesRedirect` handles `/traces` specifically. It uses `useLocation()` to preserve the original query string:\\n\\n```tsx\\nreturn ;\\n```\\n\\nThe `replace` option prevents compatibility redirects from adding an unnecessary history entry.\\n\\n## Routing Architecture\\n\\n```mermaid\\nflowchart TD\\n    Main[\\\"main.tsx\\\"] --&gt; App[\\\"App\\\"]\\n    App --&gt; Boundary[\\\"ErrorBoundary\\\"]\\n    Boundary --&gt; Providers[\\\"Global providers\\\"]\\n    Providers --&gt; Router[\\\"BrowserRouter\\\"]\\n    Router --&gt; Public[\\\"Public routes\\\"]\\n    Router --&gt; Guard[\\\"ProtectedRoute\\\"]\\n    Guard --&gt; Layout[\\\"Layout\\\"]\\n    Layout --&gt; Pages[\\\"Authenticated pages\\\"]\\n    Router --&gt; Redirects[\\\"Navigate redirects\\\"]\\n    Boundary --&gt; Report[\\\"reportReactError\\\"]\\n```\\n\\n## Page and Feature Boundaries\\n\\n`App.tsx` owns route selection but does not implement page-specific behavior. Feature pages are imported from `@/routes`, including:\\n\\n- Chat and dashboard experiences\\n- Workflow browsing, building, details, and execution\\n- Evaluation and usage views\\n- Knowledge and settings pages\\n- Product spaces and diagnostics\\n- Sidebar-specific views\\n\\nThis keeps application composition centralized while allowing each route module to own its feature UI and behavior.\\n\\nThe shared `Layout` is applied only to protected routes. Public pages such as `LoginPage` and the sidebar pages are intentionally mounted outside it.\\n\\n## Data and State Integration\\n\\nThe module connects to application state through imported providers and stores:\\n\\n- `queryClient` provides the shared TanStack Query client.\\n- `ProjectProvider` provides project-level context.\\n- `ThemeProvider` provides theme context.\\n- `useAuthStore` receives callback authentication tokens.\\n- `ObservabilityProvider` integrates application observability.\\n- `reportReactError` receives uncaught React rendering errors.\\n\\nThe module does not directly perform API requests or feature-specific data loading. Those responsibilities remain in the relevant pages, components, hooks, and data-access modules.\\n\\n## Adding or Changing Routes\\n\\nWhen adding a route:\\n\\n1. Import the page component in `App.tsx`.\\n2. Decide whether it is public or protected.\\n3. Add public routes before the `ProtectedRoute` wrapper if it must bypass authentication and `Layout`.\\n4. Add authenticated routes inside the nested `Layout`.\\n5. Check route ordering when using parameterized paths such as `/:section`.\\n6. Add a redirect when retaining a legacy URL.\\n7. Confirm that the fallback route still directs unknown authenticated paths to `/chat`.\\n\\nFor a page that should use the standard authenticated shell, add it alongside the other routes nested under:\\n\\n```tsx\\n}&gt;\\n  }&gt;\\n    {/* new route */}\\n  &lt;\\/Route&gt;\\n&lt;\\/Route&gt;\\n```\\n\\nFor a page that needs a standalone presentation, place it in the public route section or otherwise adjust the route composition deliberately.\\n\\n## Development Considerations\\n\\n- The browser entry point requires an element with `id=\\\"root\\\"`.\\n- `TokenReceiver` must remain inside `BrowserRouter`.\\n- Authentication callback tokens are removed from the URL after being stored.\\n- Rendering failures are surfaced through the top-level fallback and reported with `reportReactError`.\\n- Route redirects use `replace` where the old URL should not remain in browser history.\\n- The application runs under React `StrictMode`; side effects should be written to remain safe under development-time lifecycle checks.\",\"workflow-orchestration-and-scheduling\":\"# Workflow Orchestration and Scheduling\\n\\n# Workflow Orchestration and Scheduling\\n\\nThis module coordinates long-running workflow execution and its operational lifecycle:\\n\\n- Scheduled tasks start isolated orchestration sessions that hand work off to workflow runs.\\n- Paused workflow runs are approved, rejected, or retried through controlled state transitions.\\n- Completed runs can notify users and export artifacts/messages to AI-Ku.\\n- Codebases and isolation worktrees are restored or cleaned up in the background.\\n- Supporting services generate conversation titles and operate production-only SLA notification workers.\\n\\nThe module is split between `packages/core` for reusable domain services and `packages/server` for server-side orchestration, event listeners, and workers.\\n\\n```mermaid\\nflowchart LR\\n  Task[Scheduled task] --&gt; Deps[buildScheduledTaskDeps]\\n  Deps --&gt; Session[Sandbox orchestration session]\\n  Session --&gt; API[Conversation + workflow run APIs]\\n  API --&gt; Run[Workflow run]\\n  Run --&gt; Events[Workflow event emitter]\\n  Events --&gt; Notify[Infoflow notifications]\\n  Events --&gt; Export[AI-Ku auto-export]\\n  Export --&gt; AiKu[AI-Ku ingestion]\\n  Run --&gt; Actions[Approve / reject / retry]\\n```\\n\\n## Scheduled Task Orchestration\\n\\n**Source:** `packages/server/src/services/scheduled-task-deps.ts`\\n\\n`buildScheduledTaskDeps()` creates the production `RunnerDeps` implementation used by the scheduled-task runner. Its primary responsibility is to start an agent orchestration session for a `ScheduledTask`.\\n\\nThe orchestration session does not directly perform the task\u2019s requested work by default. Instead, it receives a prompt instructing it to create a conversation and invoke the workflow-run API. This allows the agent to preprocess, split, or conditionally skip work before dispatching one or more workflow runs.\\n\\n### `buildScheduledTaskDeps()`\\n\\nReturns:\\n\\n- `runOrchestrationSession(task, batchId)`: starts the agent-driven task handoff.\\n- `countBatchRuns(batchId)`: delegates to `countRunsByBatch()` so the runner can summarize workflow runs started for a batch.\\n- `now()`: returns the current `Date`.\\n\\nThe scheduled-task runner owns triggering, rate limiting, and recursion safeguards. This dependency implementation provides the concrete execution behavior.\\n\\n### Orchestration Session Flow\\n\\n`runOrchestrationSession(task, batchId)` performs the following steps:\\n\\n1. Loads merged application configuration with `loadConfig()`.\\n2. Resolves provider configuration and model selection through `resolveSessionModelOptions()`.\\n3. Creates or reuses a hidden web conversation using `getOrCreateConversation()`.\\n   - The platform conversation ID is `sched-run-${task.id}-${batchId}`.\\n   - The task owner, product, codebase, and branch binding are attached where available.\\n4. Builds sandbox-related environment variables:\\n   - `buildSandboxEnvsForUser()` supplies sandbox and optional iCode credentials.\\n   - `buildOneApiEnvForUser()` provides OneAPI configuration when available.\\n5. Attempts to use a sandbox-backed provider through `tryBuildSandboxProvider('scheduled_task_orchestration')`.\\n   - If no sandbox provider can be created, it falls back to `getAgentProvider(providerId)`.\\n6. Signs a fresh owner JWT with `signToken(task.owner_user_id)`.\\n7. Builds the callback instructions with `buildCallbackBlock()`.\\n8. Combines the task prompt and callback instructions with `buildScheduledPrompt()`.\\n9. Streams the agent response through `provider.sendQuery(...)`.\\n10. Returns the most useful available result text:\\n    - `resultText` from a `result` chunk when present.\\n    - Otherwise, the most recent non-empty `assistant` chunk as a fallback explanation.\\n\\nThe session is non-persistent (`persistSession: false`) but is associated with the generated conversation ID for execution context.\\n\\n### Branch Binding\\n\\n`branchesForTask(task)` returns a branch map only when both task fields exist:\\n\\n```ts\\n{ [task.codebase_id]: task.branch }\\n```\\n\\nIf either `codebase_id` or `branch` is absent, it returns `undefined`. This prevents an incomplete repository binding from being sent to `getOrCreateConversation()`.\\n\\n### Prompt Construction\\n\\n#### `buildScheduledPrompt(userPrompt, callbackBlock)`\\n\\nWraps the saved task prompt in a structured Chinese-language instruction document. The prompt explicitly distinguishes:\\n\\n- the **user-defined task instruction**, and\\n- the **agent\u2019s responsibility to hand that instruction to a workflow**.\\n\\nThe user instruction is fenced between:\\n\\n```text\\n&lt;&lt;\\\",\\n  \\\"batchId\\\": \\\"\\\"\\n}\\n```\\n\\nThese fields allow downstream reporting and panel grouping, and they are required for scheduled-run classification.\\n\\n### Model Resolution\\n\\n`resolveSessionModelOptions(config)` mirrors normal conversation model selection:\\n\\n```ts\\nconst providerId = config.assistant;\\nconst assistantConfig = config.assistants[providerId] ?? {};\\nconst model = resolveConversationModel(providerId, assistantConfig);\\n```\\n\\nIt returns:\\n\\n```ts\\n{\\n  assistantConfig,\\n  ...(model ? { model } : {})\\n}\\n```\\n\\nProvider-specific defaults remain in `assistantConfig`; the final selected model is passed separately when one resolves successfully.\\n\\n---\\n\\n## Workflow Run Actions\\n\\n**Source:** `packages/server/src/services/workflow-run-actions.ts`\\n\\nThis service implements state transitions for paused approval gates and failed breakpoint runs. It writes workflow events, updates run metadata and status, persists user-visible decision messages where applicable, and delegates resume behavior to the injected `tryAutoResumeAfterGate()` function.\\n\\n### Shared Types\\n\\n```ts\\ntype WorkflowGateAction = 'approve' | 'reject';\\n```\\n\\n```ts\\ntype TryAutoResumeAfterGate = (\\n  run: WorkflowRun,\\n  action: WorkflowGateAction,\\n  attachedFiles?: AttachedFile[],\\n  extraMessage?: string\\n) =&gt; Promise;\\n```\\n\\n`tryAutoResumeAfterGate()` is intentionally injected because resuming a workflow depends on the calling execution path. These action functions own validation and persistence; the caller owns dispatching the resume mechanism.\\n\\n### `approveWorkflowRunAndResume()`\\n\\n```ts\\napproveWorkflowRunAndResume(\\n  run,\\n  comment,\\n  tryAutoResumeAfterGate,\\n  nodeSupplements?\\n)\\n```\\n\\nApproves a run only when `run.status === 'paused'`. It requires approval metadata with an `approval.nodeId`.\\n\\nBehavior varies by approval type:\\n\\n| Approval type | Persisted behavior |\\n|---|---|\\n| Standard approval gate | Writes `node_completed` and `approval_received`; stores `approval_response: 'approved'` |\\n| `interactive_loop` | Stores `loop_user_input: comment` |\\n| `user_pause` | Stores `loop_user_input` and optional `nodeSupplements` |\\n| `loop_back_review` | Stores resume marker `approval_response: 'approved'` and optional `nodeSupplements` |\\n\\nThe run is updated to `status: 'failed'` as a resume vehicle. This is deliberate: downstream resume logic detects the transition and starts the next execution phase.\\n\\nFor `loop_back_review`, the approval marker is important. The marker distinguishes a controlled resume transition from a real terminal failure so failure aggregation, completion handling, and evaluation logic can exclude it.\\n\\nAfter updating the run, the service:\\n\\n- records a conversation message for ordinary approval gates through `recordGateDecision()`;\\n- records loop-back supplemental context through `recordLoopBackSupplements()` for `loop_back_review`;\\n- calls `tryAutoResumeAfterGate(run, 'approve')`.\\n\\nThe return value indicates whether the workflow was automatically resumed.\\n\\n### `rejectWorkflowRunAndResume()`\\n\\n```ts\\nrejectWorkflowRunAndResume(run, reason, tryAutoResumeAfterGate)\\n```\\n\\nRejects only paused runs.\\n\\nA blank reason is normalized to:\\n\\n```ts\\nconst rejectionReason = reason.trim() || 'Rejected';\\n```\\n\\nThe normalized value is used for events and metadata, while `recordGateDecision()` receives the original user-provided value so an empty rejection does not display an artificial explanation in the conversation history.\\n\\n#### Rejection with `onRejectPrompt`\\n\\nWhen the approval context defines `onRejectPrompt`, rejection may trigger a retry path:\\n\\n1. Writes an `approval_received` event.\\n2. Records the rejection in the parent conversation, best-effort.\\n3. Reads `rejection_count` from metadata.\\n4. Compares the next count to `approval.onRejectMaxAttempts`, defaulting to `3`.\\n5. If below the limit:\\n   - updates the run to `failed`;\\n   - stores `rejection_reason` and incremented `rejection_count`;\\n   - calls `tryAutoResumeAfterGate(run, 'reject')`.\\n\\nWhen the limit is reached, the run is cancelled instead.\\n\\n#### Rejection without `onRejectPrompt`\\n\\nThe service immediately cancels the workflow through `cancelWorkflowRunAndCloseRuntimeTrace()`.\\n\\n### `cancelWorkflowRunAndCloseRuntimeTrace()`\\n\\nThis internal helper performs complete cancellation cleanup:\\n\\n1. Calls `workflowDb.cancelWorkflowRun(runId)`.\\n2. Closes the runtime trace through `runtimeTraceDb.closeWorkflowRunRuntimeTrace()`.\\n   - Trace and spans are marked `cancelled`.\\n   - The closure includes a cancellation reason, error classification, event type, and metadata.\\n3. Ensures the workflow event emitter has a conversation association.\\n4. Emits `workflow_cancelled`.\\n5. Unregisters the run from the event emitter.\\n6. Pauses the run\u2019s sandbox asynchronously with `pauseSandboxForRun()`.\\n\\nEmitting `workflow_cancelled` is necessary for REST-only cancellation paths. A paused DAG executor may not be actively polling the database, so it would otherwise never emit a terminal status event for the frontend.\\n\\n### `breakpointRetryWorkflowRunAndResume()`\\n\\n```ts\\nbreakpointRetryWorkflowRunAndResume(\\n  run,\\n  tryAutoResumeAfterGate,\\n  nodeSupplements?\\n)\\n```\\n\\nRetries a failed workflow from a breakpoint.\\n\\nPreconditions:\\n\\n- `run.status` must be `failed`.\\n- `run.parent_conversation_id` must exist.\\n  - Breakpoint retry is supported only for web-dispatched workflow runs.\\n\\nNon-empty node supplements are filtered and saved to metadata before resuming. The function calls:\\n\\n```ts\\ntryAutoResumeAfterGate(run, 'approve')\\n```\\n\\nA false result is treated as a dispatch failure and throws an error.\\n\\n### Conversation Message Persistence\\n\\n`recordGateDecision()` and `recordLoopBackSupplements()` persist user-facing state into the parent conversation using `messageDb.addMessage()` with `role: 'user'`.\\n\\nPersistence is intentionally fire-and-forget:\\n\\n- failures are logged;\\n- failures do not block approval, rejection, or retry.\\n\\nThis ensures Web history and sidebars can render decisions after a refresh without requiring external IM messages.\\n\\n---\\n\\n## Workflow Event Listeners\\n\\nWorkflow completion, failure, and approval events are emitted through `getWorkflowEventEmitter()`. Two server-side listeners subscribe to this common event stream.\\n\\n### Infoflow Notifications\\n\\n**Source:** `packages/server/src/services/workflow-notification-listener.ts`\\n\\n`startWorkflowNotificationListener()` subscribes to:\\n\\n- `workflow_completed`\\n- `workflow_failed`\\n- `approval_pending`\\n\\nIt returns an unsubscribe function for shutdown or test teardown.\\n\\nThe listener is fire-and-forget: errors are caught and logged as `notification_dispatch_failed` so notification failures do not affect workflow execution.\\n\\n#### Run Metadata Resolution\\n\\nFor each run, the listener resolves and caches `RunInfo`:\\n\\n- owner user ID;\\n- workflow name;\\n- working directory;\\n- approval type;\\n- product-space name;\\n- codebase/project name;\\n- combo name;\\n- parent conversation title;\\n- frontend conversation URL;\\n- sidebar applink;\\n- command scope.\\n\\nWhen a parent conversation exists, it is preferred for notification links and titles. Background runs may execute under a hidden worker conversation, while user-facing workflow messages belong to `parent_conversation_id`.\\n\\n#### Notification Rules\\n\\nNotifications are enabled only when both configuration conditions hold:\\n\\n```ts\\nconfig.infoflow &amp;&amp; config.infoflowEnabled\\n```\\n\\n| Event | Notification status | Additional behavior |\\n|---|---|---|\\n| `workflow_completed` | `completed` | Clears cached run information |\\n| `workflow_failed` | `failed` | Stores `infoflow_recipient` in run metadata when available; clears cache |\\n| `approval_pending` | `awaiting` | Sends actionable approval details unless the gate is `user_pause` |\\n\\nApproval notifications are deduplicated using:\\n\\n```text\\nrunId:nodeId:iteration-or-approval:attempt\\n```\\n\\nThis prevents repeated events for the same gate from notifying repeatedly while allowing notifications for:\\n\\n- later interactive-loop iterations;\\n- a re-paused approval gate after an `onRejectPrompt` attempt.\\n\\n### AI-Ku Auto Export\\n\\n**Source:** `packages/server/src/services/workflow-run-auto-exporter.ts`\\n\\n`startWorkflowRunAutoExporter()` listens for `workflow_completed` events and conditionally dispatches export work to AI-Ku.\\n\\nThe listener:\\n\\n1. Loads the completed workflow run.\\n2. Resolves its YAML definition.\\n3. Parses the workflow with `parseWorkflow()`.\\n4. Checks whether:\\n\\n   ```yaml\\n   ai_ku_sync: true\\n   ```\\n\\n5. Calls `dispatchWorkflowRunToAiKu(runId)` only when the flag is enabled.\\n\\nThe listener resolves workflow YAML in this order:\\n\\n1. `WorkflowRecord.definition` via `workflow_record_id`;\\n2. a YAML file specified by `run.metadata.workflow_file`;\\n3. workflow discovery through `resolveWorkflowYamlWithConfig(run.working_path, run.workflow_name, loadConfig)`.\\n\\nMissing YAML or YAML-resolution failures do not block workflow completion; they cause export to be skipped or logged.\\n\\n---\\n\\n## AI-Ku Workflow Export\\n\\n**Source:** `packages/server/src/services/workflow-run-exporter.ts`\\n\\n`dispatchWorkflowRunToAiKu(runId)` packages a completed workflow\u2019s conversation and sandbox artifacts, uploads them to BOS, and asks AI-Ku to ingest them.\\n\\n### Export Flow\\n\\n```mermaid\\nflowchart TD\\n  Run[Workflow run] --&gt; Job[Knowledge sync job]\\n  Job --&gt; Messages[Export conversation messages]\\n  Job --&gt; Archive[Archive sandbox artifacts]\\n  Messages --&gt; BOS[BOS objects]\\n  Archive --&gt; BOS\\n  BOS --&gt; URLs[Presigned URLs]\\n  URLs --&gt; AiKu[AI-Ku ingest API]\\n  AiKu --&gt; Status[Update sync-job status]\\n```\\n\\n### Preconditions\\n\\nThe exporter throws when:\\n\\n- no workflow run exists for `runId`;\\n- the run has no `conversation_id`;\\n- no active sandbox is associated with the conversation;\\n- sandbox configuration lacks `config.sandbox.apiKey`;\\n- artifact archiving fails.\\n\\n### Idempotency and Job Claiming\\n\\nBefore exporting, the service creates or retrieves a knowledge-sync job:\\n\\n```ts\\ncreateOrGetKnowledgeSyncJob({\\n  workflowRunId: run.id,\\n  productId: run.product_id,\\n  workflowHash,\\n  idempotencyKey: buildIdempotencyKey(run.id, workflowHash),\\n});\\n```\\n\\n`buildIdempotencyKey()` computes a SHA-256 hash over:\\n\\n```text\\n${runId}:1:${workflowHash ?? ''}\\n```\\n\\nIf the existing job is already `accepted`, `processing`, or `completed`, the function returns without repeating upload or dispatch work.\\n\\nOtherwise, it attempts to claim dispatch ownership with:\\n\\n```ts\\nmarkKnowledgeSyncJobDispatching(job.id)\\n```\\n\\nIf the claim fails, another worker owns the operation. The exporter re-reads the job and returns its latest state rather than performing duplicate work.\\n\\n### Messages Package\\n\\nConversation messages are loaded with:\\n\\n```ts\\nmessageDb.listMessages(run.conversation_id, DEFAULT_MESSAGE_LIMIT)\\n```\\n\\nwhere `DEFAULT_MESSAGE_LIMIT` is `1000`.\\n\\nThe exported JSON package includes:\\n\\n- export schema version and timestamp;\\n- workflow identity, status, timing, product ID, file path, hash, and YAML;\\n- conversation ID;\\n- user and assistant messages;\\n- parsed message metadata.\\n\\nMessage metadata is parsed as JSON where possible; raw text is preserved when parsing fails.\\n\\n### Artifact Archive\\n\\nSandbox artifacts are expected in:\\n\\n```text\\n/workspace/artifacts\\n```\\n\\n`buildArtifactsArchiveCommand(run.id)` creates a gzip archive in:\\n\\n```text\\n/tmp/archon-workflow-ai-ku-dispatch\\n```\\n\\nIf the artifact directory does not exist, the command creates an archive containing an empty `artifacts` directory. This gives downstream ingestion a stable artifact payload shape.\\n\\nThe archive is read from the sandbox with `sandbox.files.read(..., { format: 'bytes' })`, written temporarily to the server filesystem, uploaded through `uploadFileToBos()`, and then removed with:\\n\\n```ts\\nrm(localDir, { recursive: true, force: true })\\n```\\n\\n### AI-Ku Dispatch Request\\n\\nAfter uploads, the exporter creates 30-minute presigned URLs with `generateBosPresignedUrl()` and posts them to:\\n\\n```text\\n{knowledgeApiUrl}/products/{effectiveProductId}/workflow-runs/ingest\\n```\\n\\n`effectiveProductId` defaults to `\\\"default\\\"` when the run has no product ID.\\n\\nThe request contains:\\n\\n- workflow name and run ID;\\n- messages and artifacts URLs;\\n- URL expiration duration;\\n- optional product ID;\\n- optional owner username;\\n- optional codebase name;\\n- optional workflow hash.\\n\\nThe request includes the job idempotency key in the `Idempotency-Key` header.\\n\\n### Sync Job Outcomes\\n\\n| AI-Ku response | Stored job state |\\n|---|---|\\n| Accepted with `task_id` | `markKnowledgeSyncJobAccepted()` |\\n| Successful HTTP response but no task ID | `markKnowledgeSyncJobUnknown()` |\\n| Non-successful HTTP response | `markKnowledgeSyncJobFailed()` |\\n| Network error | `markKnowledgeSyncJobUnknown()` |\\n\\nA missing or invalid response body is treated as an uncertain delivery outcome rather than a confirmed success.\\n\\n---\\n\\n## Codebase Restore Service\\n\\n**Source:** `packages/core/src/services/codebase-restore-service.ts`\\n\\nThe restore service detects unavailable codebase working directories and restores recoverable repositories at startup or on demand.\\n\\n### Public API\\n\\n| Function | Purpose |\\n|---|---|\\n| `startCodebaseRestoreService()` | Starts a fire-and-forget startup restore pass |\\n| `restoreCodebasesOnce()` | Restores all codebases selected by restore priority |\\n| `restoreCodebaseById(id)` | Restores one codebase or throws if it does not exist |\\n| `getCodebaseRestoreView(codebase)` | Adds filesystem restore state to a codebase view |\\n| `resetCodebaseRestoreStateForTests()` | Clears in-memory state and in-flight tasks |\\n\\n### Filesystem Statuses\\n\\n```ts\\ntype CodebaseFilesystemStatus =\\n  | 'available'\\n  | 'unavailable'\\n  | 'restoring'\\n  | 'failed'\\n  | 'unrecoverable';\\n```\\n\\n`getCodebaseRestoreView()` derives status from in-memory restore state and live filesystem checks.\\n\\n| Status | Meaning |\\n|---|---|\\n| `available` | Directory is a valid Git work tree |\\n| `unavailable` | Directory is missing and no completed restore state exists |\\n| `restoring` | A restore task is in progress |\\n| `failed` | A recoverable restore attempt failed |\\n| `unrecoverable` | The path or metadata cannot safely be restored |\\n\\n### Restore Detection\\n\\n`pathStatus(defaultCwd)` distinguishes:\\n\\n- `missing`: filesystem path does not exist;\\n- `git`: path is a directory and `git -C  rev-parse --is-inside-work-tree` succeeds;\\n- `not_git`: path exists but is not a usable Git repository.\\n\\nA path that exists but is not a Git repository is never overwritten. It is reported as `unrecoverable`.\\n\\n### Restore Strategies\\n\\n`restoreMissingCodebase(codebase)` uses two recovery paths.\\n\\n#### Git Repository Restore\\n\\nWhen `codebase.repository_url` exists:\\n\\n1. Creates the parent directory.\\n2. Calls `cloneGitRepositoryToPath(repository_url, default_cwd)`.\\n3. Calls `refreshCodebaseCommands(codebase.id, default_cwd)`.\\n\\n#### Managed iCode Repository Restore\\n\\nFor codebases without `repository_url`, restore is allowed only when all conditions hold:\\n\\n- `owner_user_id` exists;\\n- the owner has a configured username;\\n- `codebase.name` resembles an iCode repository path;\\n- `default_cwd` matches the managed workspace path:\\n\\n  ```text\\n  //\\n  ```\\n\\nThe service then calls:\\n\\n```ts\\ncloneIcodeRepositoryToPath(codebase.name, username, codebase.default_cwd)\\n```\\n\\nMissing iCode credentials, identified by an error message containing `ugate token`, are classified as `unrecoverable`.\\n\\n### Concurrency and De-duplication\\n\\n`restoreCodebasesOnce()` restores prioritized codebases with `RESTORE_CONCURRENCY = 2`.\\n\\nPer-codebase de-duplication is maintained through the `inFlight` map. If a restore task is already running for a codebase ID, repeated calls return the same promise rather than starting a second clone.\\n\\nRestore state is held in the process-local `restoreStates` map. It is a view-layer status cache, not persistent database state.\\n\\n---\\n\\n## Isolation Environment Cleanup\\n\\n**Source:** `packages/core/src/services/cleanup-service.ts`\\n\\nThe cleanup service removes unused Git worktrees and branches, handles conversation closure, performs periodic maintenance, and deletes old inactive sessions.\\n\\n### Configuration\\n\\n| Environment variable | Default | Purpose |\\n|---|---:|---|\\n| `STALE_THRESHOLD_DAYS` | `14` | Inactivity threshold for stale environments |\\n| `CLEANUP_INTERVAL_HOURS` | `6` | Interval for scheduled cleanup cycles |\\n| `SESSION_RETENTION_DAYS` | `30` | Retention period for inactive sessions |\\n\\n`STALE_THRESHOLD_DAYS` and `SESSION_RETENTION_DAYS` are exported for use by other modules.\\n\\n### Removing an Environment\\n\\n```ts\\nremoveEnvironment(envId, options?)\\n```\\n\\n`RemoveEnvironmentOptions` supports:\\n\\n```ts\\n{\\n  force?: boolean;\\n  deleteRemoteBranch?: boolean;\\n}\\n```\\n\\nThe result reports independent worktree and branch outcomes:\\n\\n```ts\\n{\\n  worktreeRemoved: boolean;\\n  branchDeleted: boolean | null;\\n  skippedReason?: string;\\n  warnings: string[];\\n}\\n```\\n\\n#### Removal Behavior\\n\\n1. Loads the environment from `isolationEnvDb`.\\n2. Returns a no-op result if it is missing or already `destroyed`.\\n3. Resolves the canonical repository path from the associated codebase, when available.\\n4. Checks whether the worktree path exists.\\n5. When the path exists and `force` is not set:\\n   - checks `hasUncommittedChanges()`;\\n   - skips removal when changes are present.\\n6. Calls `getIsolationProvider().destroy(...)`.\\n   - Branch cleanup is attempted even if the worktree directory is already absent.\\n   - `deleteRemoteBranch` is forwarded when requested.\\n7. Marks the environment `destroyed` in the database.\\n8. Returns provider warnings rather than treating partial branch cleanup as total failure.\\n\\nPath-not-found errors associated with the worktree are treated as external cleanup. In that case, the environment is still marked `destroyed`.\\n\\n### Cleanup on Conversation Close\\n\\n```ts\\nonConversationClosed(platformType, platformConversationId, options?)\\n```\\n\\nForge adapters call this when GitHub, GitLab, or Gitea conversations close.\\n\\nThe function:\\n\\n1. Finds the platform conversation.\\n2. Returns when no isolation environment is associated.\\n3. Deactivates an active session using reason `conversation-closed`.\\n4. Loads the linked environment.\\n5. Clears the closing conversation\u2019s `isolation_env_id`.\\n   - A deleted conversation is tolerated through `ConversationNotFoundError`.\\n6. Checks whether other conversations still reference the environment.\\n7. Removes the environment only if no references remain.\\n\\nWhen `options?.merged` is true, `removeEnvironment()` is called with:\\n\\n```ts\\n{ deleteRemoteBranch: true }\\n```\\n\\n### Scheduled Cleanup\\n\\n```ts\\nrunScheduledCleanup(): Promise\\n```\\n\\nA cleanup cycle processes active environments independently. An error for one environment is recorded and does not stop processing of later environments.\\n\\nFor each active environment:\\n\\n1. If the worktree path is absent, call `removeEnvironment()` to clean residual branch state and mark the database record destroyed.\\n2. Check whether the branch is merged into the repository default branch.\\n3. If merged:\\n   - skip if blocked by uncommitted changes or active conversation references;\\n   - otherwise remove it and request remote branch deletion.\\n4. Skip Telegram-created environments for stale cleanup.\\n5. Check staleness using `isEnvironmentStale()`.\\n6. For stale environments:\\n   - skip if blocked;\\n   - otherwise remove the environment.\\n\\nAfter environment processing, old inactive sessions are removed through:\\n\\n```ts\\nsessionDb.deleteOldSessions(SESSION_RETENTION_DAYS)\\n```\\n\\nThe returned `CleanupReport` includes removed environments, skips with reasons, per-item errors, and `sessionsDeleted`.\\n\\n### Staleness Rules\\n\\n`isEnvironmentStale(env, staleDays)` checks activity in this order:\\n\\n1. Last commit date in the worktree using `getLastCommitDate()`.\\n   - A recent commit means the environment is not stale.\\n2. Environment creation timestamp as fallback.\\n\\nAn environment is stale only when no recent commit exists and its creation age reaches the configured threshold.\\n\\n### User-Initiated Cleanup and Capacity Recovery\\n\\n#### `getWorktreeStatusBreakdown()`\\n\\n```ts\\ngetWorktreeStatusBreakdown(codebaseId, mainRepoPath)\\n```\\n\\nReturns a `WorktreeStatusBreakdown` grouping environments into:\\n\\n- merged;\\n- stale;\\n- active.\\n\\nMerge-check errors are logged and treated as not merged for that environment. Telegram environments are never classified as stale.\\n\\n#### `cleanupStaleWorktrees()`\\n\\n```ts\\ncleanupStaleWorktrees(codebaseId, mainRepoPath)\\n```\\n\\nRemoves stale, non-Telegram environments only when they have:\\n\\n- no uncommitted changes;\\n- no active conversation references.\\n\\nThe unused `_mainRepoPath` parameter remains in the signature for API consistency.\\n\\n#### `cleanupMergedWorktrees()`\\n\\n```ts\\ncleanupMergedWorktrees(codebaseId, mainRepoPath, {\\n  includeClosed?: boolean\\n})\\n```\\n\\nUses multiple signals to decide whether a branch is safe to remove:\\n\\n1. `isBranchMerged()` for merge-commit and fast-forward ancestry;\\n2. `isPatchEquivalent()` for squash-merge detection;\\n3. `getPrState()` for GitHub PR state.\\n\\nA branch is removable when:\\n\\n- it is Git-merged;\\n- it is patch-equivalent to the default branch;\\n- its PR state is `MERGED`;\\n- its PR state is `CLOSED` and `includeClosed` is true.\\n\\nAn `OPEN` PR is specifically reported as:\\n\\n```text\\nPR is open (active review)\\n```\\n\\nPR state is cached per cleanup operation using `Map`.\\n\\n#### `cleanupToMakeRoom()`\\n\\n```ts\\ncleanupToMakeRoom(codebaseId, mainRepoPath)\\n```\\n\\nCurrently delegates to `cleanupMergedWorktrees()`. This is the capacity-recovery entry point used when a worktree limit is reached.\\n\\n### Scheduler Lifecycle\\n\\n```ts\\nstartCleanupScheduler()\\nstopCleanupScheduler()\\nisSchedulerRunning()\\n```\\n\\n`startCleanupScheduler()`:\\n\\n- prevents duplicate interval creation;\\n- runs `runScheduledCleanup()` immediately;\\n- starts subsequent cycles every `CLEANUP_INTERVAL_HOURS`.\\n\\nFailures in initial or interval-driven cleanup are logged and do not create unhandled promise rejections.\\n\\n`stopCleanupScheduler()` clears the module-level interval. `isSchedulerRunning()` is primarily useful for tests and lifecycle assertions.\\n\\n---\\n\\n## Conversation Title Generation\\n\\n**Source:** `packages/core/src/services/title-generator.ts`\\n\\n`generateAndSetTitle()` creates concise AI-generated titles for conversations.\\n\\n```ts\\ngenerateAndSetTitle(\\n  conversationDbId,\\n  userMessage,\\n  assistantType,\\n  cwd,\\n  workflowName?\\n)\\n```\\n\\nThis function is designed for fire-and-forget use by the orchestrator. It catches all errors internally and never rethrows.\\n\\n### Generation Process\\n\\n1. Reads `TITLE_GENERATION_MODEL`.\\n   - When unset, the provider SDK selects its default model.\\n2. Builds a prompt from the user message and optional workflow name.\\n3. Gets the configured provider using `getAgentProvider(assistantType)`.\\n4. Sends a text-only query with:\\n\\n   ```ts\\n   nodeConfig: { allowed_tools: [] }\\n   ```\\n\\n5. Accumulates `assistant` chunks.\\n6. Cleans the generated title:\\n   - strips wrapping quotes;\\n   - strips `Title:` prefixes;\\n   - removes trailing `.`, `!`, and `?`;\\n   - keeps only the first line;\\n   - truncates to `MAX_TITLE_LENGTH` (`100`).\\n7. Writes the title with `conversationDb.updateConversationTitle()`.\\n\\nIf generation produces no usable title, or if generation fails, it falls back to a truncated user message.\\n\\n---\\n\\n## SLA Infoflow Worker\\n\\n**Source:** `packages/server/src/workers/sla-infoflow-worker.ts`\\n\\n`runSlaInfoflowWorker()` runs the SLA notification schedule in a dedicated production worker.\\n\\nThe worker intentionally does not run in API server replicas, preventing each web/API process from creating an independent SLA schedule.\\n\\n### Lifecycle\\n\\n1. Checks `NODE_ENV`.\\n   - Returns without starting unless it is exactly `production`.\\n2. Verifies database connectivity with `pool.query('SELECT 1')`.\\n3. Runs migrations with `runMigrations()`.\\n4. Starts the notifier through `startSlaInfoflowNotifier()`.\\n5. Waits for `SIGINT` or `SIGTERM`.\\n6. Stops the notifier and closes the database pool.\\n\\nThe file can run as an executable module through:\\n\\n```ts\\nif (import.meta.main) {\\n  runSlaInfoflowWorker()\\n}\\n```\\n\\nFatal startup errors set `process.exitCode = 1`.\\n\\n---\\n\\n## Integration Points\\n\\n| Component | Connected subsystem | Role |\\n|---|---|---|\\n| `buildScheduledTaskDeps()` | Scheduled task runner | Provides real orchestration and batch-count dependencies |\\n| `runOrchestrationSession()` | Agent providers, sandbox, conversation API, workflow run API | Converts scheduled prompts into controlled workflow dispatches |\\n| `approveWorkflowRunAndResume()` | Workflow database, event log, runtime traces, sandbox | Persists gate decisions and resumes execution |\\n| `startWorkflowNotificationListener()` | Workflow event emitter, Infoflow | Sends completion, failure, and approval notifications |\\n| `startWorkflowRunAutoExporter()` | Workflow event emitter, AI-Ku exporter | Starts export only for workflows declaring `ai_ku_sync: true` |\\n| `dispatchWorkflowRunToAiKu()` | BOS, sandbox manager, knowledge-sync jobs, AI-Ku | Packages and submits workflow outputs for ingestion |\\n| `startCodebaseRestoreService()` | Codebase DB, Git and iCode clone handlers | Restores missing repository workspaces |\\n| `cleanup-service.ts` | Isolation provider, Git utilities, conversations, sessions | Safely removes obsolete worktrees and branches |\\n| `generateAndSetTitle()` | Orchestrator and agent providers | Asynchronously creates conversation titles |\\n| `runSlaInfoflowWorker()` | SLA notifier and database | Runs production-only SLA scheduling |\\n\\n## Contribution Guidelines\\n\\n### Preserve Fire-and-Forget Boundaries\\n\\nSeveral entry points intentionally isolate secondary failures:\\n\\n- `generateAndSetTitle()`\\n- `startWorkflowNotificationListener()` callbacks\\n- `startWorkflowRunAutoExporter()` callbacks\\n- scheduler timer callbacks\\n- approval-message persistence\\n- sandbox pausing after cancellation\\n\\nDo not allow failures from these non-critical effects to interrupt workflow execution or state transitions.\\n\\n### Keep Workflow Event Handling Idempotent\\n\\nEvent listeners can receive repeated or replayed events. When adding listeners:\\n\\n- deduplicate user-facing side effects where needed;\\n- avoid treating an event emission as proof that a database mutation has not already occurred;\\n- clean per-run caches after terminal completion or failure.\\n\\n### Treat Cleanup as Safety-Critical\\n\\nBefore removing an isolation environment, preserve the existing safeguards:\\n\\n- uncommitted changes block non-forced removal;\\n- active conversation references block removal;\\n- Telegram workspaces are excluded from stale cleanup;\\n- branch deletion can be partial and must surface through `warnings`;\\n- path disappearance should not prevent database reconciliation.\\n\\n### Preserve Scheduled-Run Attribution\\n\\nScheduled workflow runs must retain:\\n\\n```json\\n{\\n  \\\"triggerSource\\\": \\\"scheduled\\\",\\n  \\\"scheduledTaskId\\\": \\\"...\\\",\\n  \\\"batchId\\\": \\\"...\\\"\\n}\\n```\\n\\nThese fields are required for server-side accounting, rate limits, recursion protection, and batch-level reporting.\"};\nvar TREE = [{\"name\":\"Authentication and Identity\",\"slug\":\"authentication-and-identity\",\"files\":[\"packages/server/src/routes/auth.ts\",\"packages/server/src/routes/schemas/auth.schemas.ts\",\"packages/web/src/lib/auth-guard.tsx\",\"packages/web/src/stores/auth-store.ts\",\"auth-service/server.js\"]},{\"name\":\"Chat and Platform Adapters\",\"slug\":\"chat-and-platform-adapters\",\"files\":[\"packages/adapters/src/utils/message-splitting.ts\",\"packages/cli/src/adapters/cli-adapter.ts\",\"packages/server/src/adapters/web.ts\"]},{\"name\":\"CLI and Developer Tools\",\"slug\":\"cli-and-developer-tools\",\"files\":[\"homebrew/archon.rb\"]},{\"name\":\"Workflow Orchestration and Scheduling\",\"slug\":\"workflow-orchestration-and-scheduling\",\"files\":[\"packages/core/src/services/cleanup-service.ts\",\"packages/core/src/services/codebase-restore-service.ts\",\"packages/core/src/services/title-generator.ts\",\"packages/server/src/services/scheduled-task-deps.ts\",\"packages/server/src/services/workflow-run-actions.ts\",\"packages/server/src/services/workflow-run-auto-exporter.ts\",\"packages/server/src/services/workflow-run-exporter.ts\",\"packages/server/src/services/workflow-notification-listener.ts\",\"packages/server/src/workers/sla-infoflow-worker.ts\"]},{\"name\":\"API Server and Integrations\",\"slug\":\"api-server-and-integrations\",\"files\":[\"packages/server/src/index.ts\",\"packages/server/src/gitcase-client.ts\",\"packages/server/src/bos-client.ts\",\"packages/server/src/runtime-config.ts\",\"packages/server/src/services/infoflow-sender.ts\",\"packages/server/src/services/infoflow-webhook.ts\",\"packages/server/src/services/workflow-run-knowledge-sync-dispatcher.ts\",\"packages/server/src/services/sla-infoflow-notifier.ts\",\"packages/server/src/sync-bundled-commands.ts\",\"packages/server/src/sync-bundled-workflows.ts\",\"packages/server/src/sync-project-workflows.ts\",\"packages/server/src/sync-user-workflows.ts\"]},{\"name\":\"Observability, Runtime Tracing, and Evaluation\",\"slug\":\"observability-runtime-tracing-and-evaluation\",\"files\":[],\"children\":[{\"name\":\"Observability, Runtime Tracing, and Evaluation \u2014 core\",\"slug\":\"observability-runtime-tracing-and-evaluation-core\",\"files\":[\"packages/core/src/services/evolution-service.ts\",\"packages/core/src/services/failure-attribution-service.ts\",\"packages/core/src/services/golden-sample-candidate-service.ts\",\"packages/core/src/services/quality-gate-service.ts\",\"packages/core/src/services/runtime-intelligence.ts\"]},{\"name\":\"Observability, Runtime Tracing, and Evaluation \u2014 server\",\"slug\":\"observability-runtime-tracing-and-evaluation-server\",\"files\":[\"packages/server/src/services/evolution-replay.ts\",\"packages/server/src/services/workflow-access.ts\",\"packages/server/src/routes/api/evaluations.ts\",\"packages/server/src/routes/api/evolution.ts\",\"packages/server/src/routes/api/observability.ts\",\"packages/server/src/routes/api/runtime-traces.ts\",\"packages/server/src/routes/api/personnel-usage.ts\"]},{\"name\":\"Observability, Runtime Tracing, and Evaluation \u2014 web\",\"slug\":\"observability-runtime-tracing-and-evaluation-web\",\"files\":[\"packages/web/src/routes/EvaluationSlaPage.tsx\",\"packages/web/src/routes/DiagnosticsPage.tsx\"]},{\"name\":\"Observability, Runtime Tracing, and Evaluation \u2014 deepeval-evaluator\",\"slug\":\"observability-runtime-tracing-and-evaluation-deepeval-evalua\",\"files\":[\"services/deepeval-evaluator/app.py\"]},{\"name\":\"Observability, Runtime Tracing, and Evaluation \u2014 ragas-evaluator\",\"slug\":\"observability-runtime-tracing-and-evaluation-ragas-evaluator\",\"files\":[\"services/ragas-evaluator/app.py\"]}]},{\"name\":\"Knowledge Management\",\"slug\":\"knowledge-management\",\"files\":[\"packages/core/src/services/evaluation-knowledge-artifact-service.ts\",\"packages/server/src/routes/knowledge-router.ts\",\"packages/web/src/routes/KnowledgePage.tsx\"]},{\"name\":\"Web Application UI\",\"slug\":\"web-application-ui\",\"files\":[\"packages/web/src/App.tsx\",\"packages/web/src/main.tsx\"]},{\"name\":\"Developer Documentation and Operational Scripts\",\"slug\":\"developer-documentation-and-operational-scripts\",\"files\":[\"assets/ducc-skills/get-ugate-token/getUgateToken.py\",\"docs/parallel-study/analyze_parallelism.py\"]},{\"name\":\"Other\",\"slug\":\"other\",\"files\":[],\"children\":[{\"name\":\"Other \u2014 AGENTS.md\",\"slug\":\"other-agents-md\",\"files\":[\"AGENTS.md\"]},{\"name\":\"Other \u2014 CLAUDE.md\",\"slug\":\"other-claude-md\",\"files\":[\"CLAUDE.md\"]},{\"name\":\"Other \u2014 Caddyfile.example\",\"slug\":\"other-caddyfile-example\",\"files\":[\"Caddyfile.example\"]},{\"name\":\"Other \u2014 DESIGN.md\",\"slug\":\"other-design-md\",\"files\":[\"DESIGN.md\"]},{\"name\":\"Other \u2014 Dockerfile\",\"slug\":\"other-dockerfile\",\"files\":[\"Dockerfile\"]},{\"name\":\"Other \u2014 Dockerfile.base\",\"slug\":\"other-dockerfile-base\",\"files\":[\"Dockerfile.base\"]},{\"name\":\"Other \u2014 Dockerfile.ci\",\"slug\":\"other-dockerfile-ci\",\"files\":[\"Dockerfile.ci\"]},{\"name\":\"Other \u2014 Dockerfile.user.example\",\"slug\":\"other-dockerfile-user-example\",\"files\":[\"Dockerfile.user.example\"]},{\"name\":\"Other \u2014 Makefile\",\"slug\":\"other-makefile\",\"files\":[\"Makefile\"]},{\"name\":\"Other \u2014 README.md\",\"slug\":\"other-readme-md\",\"files\":[\"README.md\"]},{\"name\":\"Other \u2014 ducc-skills\",\"slug\":\"other-ducc-skills\",\"files\":[\"assets/ducc-skills/cnap/SKILL.md\",\"assets/ducc-skills/cnap/references/baidu-internal-network.md\",\"assets/ducc-skills/cnap/references/cases.md\",\"assets/ducc-skills/cnap/references/cnap-accounts.md\",\"assets/ducc-skills/cnap/references/cnap-applications.md\",\"assets/ducc-skills/cnap/references/cnap-clusters.md\",\"assets/ducc-skills/cnap/references/cnap-cpu-units.md\",\"assets/ducc-skills/cnap/references/cnap-datadist.md\",\"assets/ducc-skills/cnap/references/cnap-environ-vars.md\",\"assets/ducc-skills/cnap/references/cnap-environments.md\",\"assets/ducc-skills/cnap/references/cnap-log-collection.md\",\"assets/ducc-skills/cnap/references/cnap-permissions.md\",\"assets/ducc-skills/cnap/references/cnap-runtime-config.md\",\"assets/ducc-skills/cnap/references/cnap-service-discovery.md\",\"assets/ducc-skills/cnap/references/deploy-babysitter.md\",\"assets/ducc-skills/cnap/references/deploy-troubleshoot.md\",\"assets/ducc-skills/cnap/references/icode.md\",\"assets/ducc-skills/cnap/references/install.md\",\"assets/ducc-skills/cnap/references/iregistry.md\",\"assets/ducc-skills/cnap/references/kubectl.md\",\"assets/ducc-skills/cnap/references/login.md\",\"assets/ducc-skills/cnap/references/oncall.md\",\"assets/ducc-skills/get-ugate-token/SKILL.md\"]},{\"name\":\"Other \u2014 auth-service\",\"slug\":\"other-auth-service\",\"files\":[\"auth-service/Dockerfile\",\"auth-service/package.json\",\"auth-service/test.js\"]},{\"name\":\"Other \u2014 auto-heal.txt\",\"slug\":\"other-auto-heal-txt\",\"files\":[\"auto-heal.txt\"]},{\"name\":\"Other \u2014 bunfig.coverage.toml\",\"slug\":\"other-bunfig-coverage-toml\",\"files\":[\"bunfig.coverage.toml\"]},{\"name\":\"Other \u2014 bunfig.toml\",\"slug\":\"other-bunfig-toml\",\"files\":[\"bunfig.toml\"]},{\"name\":\"Other \u2014 ci.yml\",\"slug\":\"other-ci-yml\",\"files\":[\"ci.yml\"]},{\"name\":\"Other \u2014 deploy\",\"slug\":\"other-deploy\",\"files\":[\"deploy/Dockerfile.user.example\",\"deploy/cloud-init.yml\",\"deploy/docker-compose.override.example.yml\",\"deploy/docker-compose.yml\"]},{\"name\":\"Other \u2014 docker-compose.override.example.yml\",\"slug\":\"other-docker-compose-override-example-yml\",\"files\":[\"docker-compose.override.example.yml\"]},{\"name\":\"Other \u2014 docker-compose.yml\",\"slug\":\"other-docker-compose-yml\",\"files\":[\"docker-compose.yml\"]},{\"name\":\"Other \u2014 docker-entrypoint.sh\",\"slug\":\"other-docker-entrypoint-sh\",\"files\":[\"docker-entrypoint.sh\"]},{\"name\":\"Other \u2014 e2e-dev\",\"slug\":\"other-e2e-dev\",\"files\":[\"docker/e2e-dev/Dockerfile\",\"docker/e2e-dev/Dockerfile.base\",\"docker/e2e-dev/init-claude-workspace.sh\",\"docker/e2e-dev/start_comate_server.sh\"]},{\"name\":\"Other \u2014 docs\",\"slug\":\"other-docs\",\"files\":[\"docs/ai-workflow-builder-design.md\",\"docs/aiflow-skill-design.md\",\"docs/architecture.md\",\"docs/authoring-commands.md\",\"docs/authoring-workflows.md\",\"docs/bundled-workflow-authoring.md\",\"docs/cli-reference.md\",\"docs/cnap-api.md\",\"docs/cr-env.md\",\"docs/cr-rules-code.md\",\"docs/cr-rules-workflow.md\",\"docs/cr-rules.md\",\"docs/document-drawer-design.md\",\"docs/gitcase.md\",\"docs/infoflow-notification-status.md\",\"docs/infoflow-workflow-notification.md\",\"docs/issues.json\",\"docs/knowledge-injection-design.md\",\"docs/loop-back-practice.md\",\"docs/marketing-flow-code-review-redesign.md\",\"docs/marketing-flow-tech-design-step3.md\",\"docs/online-trace-eval-demo-guide.md\",\"docs/online-trace-eval-migration-plan.md\",\"docs/plan-implement-review-loop-parallel.md\",\"docs/product-space-design.md\",\"docs/remove-bundled-system-workflow.md\",\"docs/scheduled-task-practice.md\",\"docs/sla-infoflow-operations.md\",\"docs/standard-dev-flow-artifact-governance-design.md\",\"docs/standard-dev-flow-diagram.md\",\"docs/test-issues.md\",\"docs/ugate-token-adaptation.md\",\"docs/uic-api.md\",\"docs/user-isolation-design.md\",\"docs/uuap-auth.md\",\"docs/workflow-backend-api-chain-api.md\",\"docs/workflow-backend-api-chain-design.md\",\"docs/workflow-loop-back-design.md\",\"docs/workflow-product-space-design.md\",\"docs/workflow-system-analysis.md\",\"docs/workflow-vs-claude-code-comparison.md\",\"docs/workflow-yaml-storage.md\"]},{\"name\":\"Other \u2014 knowledge\",\"slug\":\"other-knowledge\",\"files\":[\"docs/knowledge/baidu-pipeline-docker-build.md\",\"docs/knowledge/kg-self-seal.json\"]},{\"name\":\"Other \u2014 mock\",\"slug\":\"other-mock\",\"files\":[\"docs/mock/\u5de5\u4f5c\u6d41\u4ea7\u54c1\u7a7a\u95f4\u6807\u7b7e-issue.json\",\"docs/mock/\u5de5\u4f5c\u6d41\u5bf9\u8bdd\u6846\u652f\u6301\u6362\u884c-issue.json\"]},{\"name\":\"Other \u2014 parallel-study\",\"slug\":\"other-parallel-study\",\"files\":[\"docs/parallel-study/sample-01-sidebar-pause/issues.json\",\"docs/parallel-study/sample-02-combo-edit/issues.json\",\"docs/parallel-study/sample-03-command-check/issues.json\"]},{\"name\":\"Other \u2014 schemathesis-reports\",\"slug\":\"other-schemathesis-reports\",\"files\":[\"docs/schemathesis-reports/2026-06-04-20-05.json\",\"docs/schemathesis-reports/2026-06-04-20-05.md\"]},{\"name\":\"Other \u2014 superpowers\",\"slug\":\"other-superpowers\",\"files\":[\"docs/superpowers/plans/2026-05-07-icode-codebase-clone.md\",\"docs/superpowers/plans/2026-05-07-uuap-auth.md\",\"docs/superpowers/plans/2026-05-08-icode-clone-icode-cli.md\",\"docs/superpowers/plans/2026-05-12-config-warning-banner.md\",\"docs/superpowers/plans/2026-05-12-oneapi-token.md\",\"docs/superpowers/plans/2026-05-12-setup-wizard-modal.md\",\"docs/superpowers/plans/2026-05-14-sandbox-session-binding.md\",\"docs/superpowers/plans/2026-05-14-workflow-skill-binding.md\",\"docs/superpowers/plans/2026-05-15-comate-auth-token-user-config.md\",\"docs/superpowers/plans/2026-05-18-bug-fix-flow.md\",\"docs/superpowers/plans/2026-05-19-feature-dev-flow.md\",\"docs/superpowers/plans/2026-05-19-superpowers-full-dev-flow.md\",\"docs/superpowers/plans/2026-05-20-bug-fix-flow-clarify.md\",\"docs/superpowers/plans/2026-05-21-ipipe-ducc-cr.md\",\"docs/superpowers/plans/2026-05-21-sandbox-combo-batch-clone.md\",\"docs/superpowers/plans/2026-05-22-fix-gen-ut-uuid-error.md\",\"docs/superpowers/plans/2026-05-22-sandbox-artifacts-dir-simplify.md\",\"docs/superpowers/plans/2026-05-25-gen-ut-workflow-upgrade.md\",\"docs/superpowers/plans/2026-05-25-smart-cr-classification.md\",\"docs/superpowers/plans/2026-05-25-workflow-bash-node-sandbox.md\",\"docs/superpowers/plans/2026-05-26-dev-loop-unit-test-gate.md\",\"docs/superpowers/plans/2026-05-26-metrics-reporter.md\",\"docs/superpowers/plans/2026-05-26-sandbox-file-upload.md\",\"docs/superpowers/plans/2026-05-27-loop-approval-node-started-event.md\",\"docs/superpowers/plans/2026-05-30-sandbox-auto-renew.md\",\"docs/superpowers/plans/2026-06-02-e2e-flow-enhancement.md\",\"docs/superpowers/plans/2026-06-02-impact-analysis-command.md\",\"docs/superpowers/plans/2026-06-03-e2e-flow-cnap-deploy-refactor.md\",\"docs/superpowers/plans/2026-06-04-sandbox-release-on-cancel-abandon.md\",\"docs/superpowers/plans/2026-06-04-schemathesis-integration.md\",\"docs/superpowers/plans/2026-06-09-subworkflow.md\",\"docs/superpowers/plans/2026-06-10-workflow-user-pause.md\",\"docs/superpowers/plans/2026-06-11-concurrent-pause-context.md\",\"docs/superpowers/plans/2026-06-12-auto-publish-node-artifacts.md\",\"docs/superpowers/plans/2026-06-12-auto-publish-readback-refactor.md\",\"docs/superpowers/plans/2026-06-13-ai-workflow-builder.md\",\"docs/superpowers/plans/2026-06-16-breakpoint-retry-clarify.md\",\"docs/superpowers/plans/2026-06-16-chat-page-deliverables-grouping-optimize-workflow.md\",\"docs/superpowers/plans/2026-06-16-inline-composer-context-controls.md\",\"docs/superpowers/plans/2026-06-17-aiflow-optimize-existing-workflow.md\",\"docs/superpowers/plans/2026-06-18-aiflow-ku-doc-recognition.md\",\"docs/superpowers/plans/2026-06-18-onboarding-run-to-new-chat.md\",\"docs/superpowers/plans/2026-06-18-require-project-on-new-conversation.md\",\"docs/superpowers/plans/2026-06-22-commit-time-metrics-reporting.md\",\"docs/superpowers/plans/2026-06-22-workflow-draft-staging.md\",\"docs/superpowers/plans/2026-06-23-aiflow-skill-integration.md\",\"docs/superpowers/plans/2026-06-24-interactive-loop-structured-input.md\",\"docs/superpowers/plans/2026-06-24-sandbox-heartbeat-renew.md\",\"docs/superpowers/plans/2026-06-25-dag-loop-back.md\",\"docs/superpowers/plans/2026-06-26-all-workflow-infoflow-notification.md\",\"docs/superpowers/plans/2026-06-30-breakpoint-retry-move-to-statusbar.md\",\"docs/superpowers/plans/2026-06-30-marketing-flow-test-loop-back.md\",\"docs/superpowers/plans/2026-06-30-workflow-model-dropdown.md\",\"docs/superpowers/plans/2026-07-01-aiflow-loop-back-authoring.md\",\"docs/superpowers/plans/2026-07-02-builder-dag-node-run-status.md\",\"docs/superpowers/plans/2026-07-02-command-market-and-management.md\",\"docs/superpowers/plans/2026-07-02-marketing-flow-merge-to-dev.md\",\"docs/superpowers/plans/2026-07-03-scheduled-tasks.md\",\"docs/superpowers/plans/2026-07-06-command-discovery-mirror-workflow.md\",\"docs/superpowers/plans/2026-07-06-infoflow-robot-api-and-reply.md\",\"docs/superpowers/plans/2026-07-07-backfill-forked-workflow-commands.md\",\"docs/superpowers/plans/2026-07-07-conversation-workflow-scope-badge.md\",\"docs/superpowers/plans/2026-07-07-scheduled-task-ducc-callback.md\",\"docs/superpowers/plans/2026-07-07-workflow-draft-preview-run.md\",\"docs/superpowers/plans/2026-07-08-workflow-version-updated-at.md\",\"docs/superpowers/plans/2026-07-09-infoflow-reply-session-identifier.md\",\"docs/superpowers/plans/2026-07-09-infoflow-sidebar-part1-bubble-card.md\",\"docs/superpowers/plans/2026-07-09-infoflow-sidebar-part2-oauth.md\",\"docs/superpowers/plans/2026-07-09-infoflow-sidebar-part3-web-page.md\",\"docs/superpowers/plans/2026-07-10-scheduled-tasks-space-scoped.md\",\"docs/superpowers/plans/2026-07-13-aiflow-new-conversation-unpublished-draft-guard.md\",\"docs/superpowers/plans/2026-07-13-session-deliverables-enhancements.md\",\"docs/superpowers/plans/2026-07-14-on-reject-session-resume.md\",\"docs/superpowers/plans/2026-07-14-sidebar-sse-realtime.md\",\"docs/superpowers/plans/2026-07-15-aiflow-cli-skill.md\",\"docs/superpowers/plans/2026-07-15-anthropic-workflow-to-aiflow-convert.md\",\"docs/superpowers/plans/2026-07-15-artifact-drawer-auto-refresh.md\",\"docs/superpowers/plans/2026-07-16-infoflow-bubble-session-entry.md\",\"docs/superpowers/plans/2026-07-16-infoflow-sidebar-artifact-panel.md\",\"docs/superpowers/plans/2026-07-17-workflow-authoring-space-command.md\",\"docs/superpowers/plans/2026-07-18-platform-only-cli.md\",\"docs/superpowers/plans/2026-07-20-command-delete.md\",\"docs/superpowers/plans/2026-07-21-aiflow-skill-platform-cli.md\",\"docs/superpowers/plans/2026-07-21-anthropic-workflow-package-convert.md\",\"docs/superpowers/plans/2026-07-21-infoflow-abandon-workflow-button.md\",\"docs/superpowers/plans/2026-07-22-standard-dev-flow.md\",\"docs/superpowers/plans/2026-07-23-workflow-command-source-from-db.md\",\"docs/superpowers/plans/2026-07-24-downstream-refresh-upstream-artifacts.md\",\"docs/superpowers/plans/2026-07-27-loop-back-human-review.md\",\"docs/superpowers/plans/2026-07-27-online-event-data-governance.md\",\"docs/superpowers/plans/2026-07-27-workflow-custom-sandbox-image.md\",\"docs/superpowers/plans/2026-07-29-combo-multi-codebase-workflow.md\",\"docs/superpowers/plans/2026-07-29-workflow-restart-recovery.md\",\"docs/superpowers/plans/2026-07-30-conversation-turn-collapse.md\",\"docs/superpowers/plans/2026-07-30-session-task-model-switch.md\",\"docs/superpowers/plans/2026-07-31-try-it-list.md\",\"docs/superpowers/specs/2026-05-07-icode-codebase-clone-design.md\",\"docs/superpowers/specs/2026-05-07-uuap-auth-design.md\",\"docs/superpowers/specs/2026-05-12-config-warning-banner-design.md\",\"docs/superpowers/specs/2026-05-12-oneapi-token-design.md\",\"docs/superpowers/specs/2026-05-12-setup-wizard-modal-design.md\",\"docs/superpowers/specs/2026-05-14-sandbox-session-binding-design.md\",\"docs/superpowers/specs/2026-05-14-workflow-skill-binding-design.md\",\"docs/superpowers/specs/2026-05-15-comate-auth-token-user-config-design.md\",\"docs/superpowers/specs/2026-05-18-bug-fix-flow-design.md\",\"docs/superpowers/specs/2026-05-19-feature-dev-flow-design.md\",\"docs/superpowers/specs/2026-05-19-superpowers-full-dev-flow-design.md\",\"docs/superpowers/specs/2026-05-20-bug-fix-flow-clarify-design.md\",\"docs/superpowers/specs/2026-05-21-ipipe-ducc-cr-design.md\",\"docs/superpowers/specs/2026-05-22-sandbox-artifacts-dir-simplify-design.md\",\"docs/superpowers/specs/2026-05-25-gen-ut-workflow-design.md\",\"docs/superpowers/specs/2026-05-25-smart-cr-classification-design.md\",\"docs/superpowers/specs/2026-05-26-bun-in-e2e-dev-image-design.md\",\"docs/superpowers/specs/2026-05-26-dev-loop-unit-test-gate-design.md\",\"docs/superpowers/specs/2026-05-26-metrics-reporter-design.md\",\"docs/superpowers/specs/2026-05-26-sandbox-file-upload-design.md\",\"docs/superpowers/specs/2026-05-30-sandbox-auto-renew-design.md\",\"docs/superpowers/specs/2026-06-02-impact-analysis-command-design.md\",\"docs/superpowers/specs/2026-06-04-sandbox-release-on-cancel-abandon-design.md\",\"docs/superpowers/specs/2026-06-04-schemathesis-integration-design.md\",\"docs/superpowers/specs/2026-06-09-product-space-global-filter-design.md\",\"docs/superpowers/specs/2026-06-09-subworkflow-design.md\",\"docs/superpowers/specs/2026-06-10-workflow-user-pause-design.md\",\"docs/superpowers/specs/2026-06-11-concurrent-pause-context-design.md\",\"docs/superpowers/specs/2026-06-11-workflow-product-space-refactor-design.md\",\"docs/superpowers/specs/2026-06-12-auto-publish-node-artifacts-design.md\",\"docs/superpowers/specs/2026-06-13-ai-workflow-builder-design.md\",\"docs/superpowers/specs/2026-06-16-breakpoint-retry-clarify-ai-nodes-only-design.md\",\"docs/superpowers/specs/2026-06-16-breakpoint-retry-clarify-design.md\",\"docs/superpowers/specs/2026-06-16-chat-page-deliverables-grouping-optimize-workflow-design.md\",\"docs/superpowers/specs/2026-06-16-onboarding-wizard-design.md\",\"docs/superpowers/specs/2026-06-16-workflow-builder-run-flow-design.md\",\"docs/superpowers/specs/2026-06-17-aiflow-optimize-existing-workflow-design.md\",\"docs/superpowers/specs/2026-06-18-aiflow-ku-doc-recognition-design.md\",\"docs/superpowers/specs/2026-06-18-onboarding-run-to-new-chat-design.md\",\"docs/superpowers/specs/2026-06-18-require-project-on-new-conversation-design.md\",\"docs/superpowers/specs/2026-06-22-commit-time-metrics-reporting-design.md\",\"docs/superpowers/specs/2026-06-22-workflow-draft-staging-design.md\",\"docs/superpowers/specs/2026-06-23-aiflow-skill-integration-design.md\",\"docs/superpowers/specs/2026-06-23-interactive-loop-structured-input-design.md\",\"docs/superpowers/specs/2026-06-24-interactive-loop-structured-input-design.md\",\"docs/superpowers/specs/2026-06-24-sandbox-heartbeat-renew-design.md\",\"docs/superpowers/specs/2026-06-25-codebase-branch-list-design.md\",\"docs/superpowers/specs/2026-06-25-dag-loop-back-design.md\",\"docs/superpowers/specs/2026-06-26-all-workflow-infoflow-notification-design.md\",\"docs/superpowers/specs/2026-06-30-breakpoint-retry-move-to-statusbar-design.md\",\"docs/superpowers/specs/2026-06-30-marketing-flow-dynamic-branch-design.md\",\"docs/superpowers/specs/2026-06-30-marketing-flow-test-loop-back-design.md\",\"docs/superpowers/specs/2026-06-30-space-private-command-db-design.md\",\"docs/superpowers/specs/2026-06-30-workflow-model-dropdown-design.md\",\"docs/superpowers/specs/2026-07-01-aiflow-loop-back-authoring-design.md\",\"docs/superpowers/specs/2026-07-02-builder-dag-node-run-status-design.md\",\"docs/superpowers/specs/2026-07-02-command-market-and-management-design.md\",\"docs/superpowers/specs/2026-07-02-marketing-flow-merge-to-dev-design.md\",\"docs/superpowers/specs/2026-07-03-scheduled-tasks-design.md\",\"docs/superpowers/specs/2026-07-06-infoflow-robot-api-and-reply-design.md\",\"docs/superpowers/specs/2026-07-07-backfill-forked-workflow-commands-design.md\",\"docs/superpowers/specs/2026-07-07-conversation-workflow-scope-badge-design.md\",\"docs/superpowers/specs/2026-07-07-scheduled-task-ducc-callback-design.md\",\"docs/superpowers/specs/2026-07-07-workflow-draft-preview-run-design.md\",\"docs/superpowers/specs/2026-07-08-workflow-version-updated-at-design.md\",\"docs/superpowers/specs/2026-07-09-infoflow-reply-session-identifier-design.md\",\"docs/superpowers/specs/2026-07-09-infoflow-sidebar-run-detail-design.md\",\"docs/superpowers/specs/2026-07-10-scheduled-tasks-space-scoped-design.md\",\"docs/superpowers/specs/2026-07-11-marketing-flow-clarify-design.md\",\"docs/superpowers/specs/2026-07-13-aiflow-new-conversation-unpublished-draft-guard-design.md\",\"docs/superpowers/specs/2026-07-13-session-deliverables-enhancements-design.md\",\"docs/superpowers/specs/2026-07-14-on-reject-session-resume-design.md\",\"docs/superpowers/specs/2026-07-14-sidebar-sse-realtime-design.md\",\"docs/superpowers/specs/2026-07-15-aiflow-cli-skill-design.md\",\"docs/superpowers/specs/2026-07-15-anthropic-workflow-to-aiflow-convert-design.md\",\"docs/superpowers/specs/2026-07-15-artifact-drawer-auto-refresh-design.md\",\"docs/superpowers/specs/2026-07-16-infoflow-bubble-session-entry-design.md\",\"docs/superpowers/specs/2026-07-16-infoflow-sidebar-artifact-panel-design.md\",\"docs/superpowers/specs/2026-07-17-workflow-authoring-space-command-design.md\",\"docs/superpowers/specs/2026-07-18-platform-only-cli-design.md\",\"docs/superpowers/specs/2026-07-20-command-delete-design.md\",\"docs/superpowers/specs/2026-07-21-aiflow-skill-platform-cli-design.md\",\"docs/superpowers/specs/2026-07-21-anthropic-workflow-package-convert-design.md\",\"docs/superpowers/specs/2026-07-21-infoflow-abandon-workflow-button-design.md\",\"docs/superpowers/specs/2026-07-22-standard-dev-flow-design.md\",\"docs/superpowers/specs/2026-07-23-workflow-command-source-from-db-design.md\",\"docs/superpowers/specs/2026-07-27-loop-back-human-review-design.md\",\"docs/superpowers/specs/2026-07-27-online-event-data-governance-design.md\",\"docs/superpowers/specs/2026-07-27-workflow-custom-sandbox-image-design.md\",\"docs/superpowers/specs/2026-07-29-combo-multi-codebase-workflow-design.md\",\"docs/superpowers/specs/2026-07-29-workflow-restart-recovery-design.md\",\"docs/superpowers/specs/2026-07-30-conversation-turn-collapse-design.md\",\"docs/superpowers/specs/2026-07-30-session-task-model-switch-design.md\",\"docs/superpowers/specs/2026-07-31-try-it-list-design.md\",\"docs/superpowers/test-plans/2026-06-23-workflow-draft-staging-test-plan.md\",\"docs/superpowers/test-plans/db-inspect-guide.md\"]},{\"name\":\"Other \u2014 testing\",\"slug\":\"other-testing\",\"files\":[\"docs/testing/api-test-gate.md\",\"docs/testing/examples/delete_codebase_by_id_404.json\",\"docs/testing/examples/delete_codebase_env_key_404.json\",\"docs/testing/examples/delete_conversations.json\",\"docs/testing/examples/delete_ugate_token.json\",\"docs/testing/examples/get_alert_rules.json\",\"docs/testing/examples/get_alerts.json\",\"docs/testing/examples/get_alerts_preview.json\",\"docs/testing/examples/get_anomalies.json\",\"docs/testing/examples/get_archives.json\",\"docs/testing/examples/get_auth_me.json\",\"docs/testing/examples/get_codebase_by_id_404.json\",\"docs/testing/examples/get_codebase_env_404.json\",\"docs/testing/examples/get_codebases.json\",\"docs/testing/examples/get_comate_auth_token.json\",\"docs/testing/examples/get_combos.json\",\"docs/testing/examples/get_commands.json\",\"docs/testing/examples/get_config.json\",\"docs/testing/examples/get_conversations.json\",\"docs/testing/examples/get_cost_trends.json\",\"docs/testing/examples/get_evaluation_workflow_run_404.json\",\"docs/testing/examples/get_evaluations_aggregates.json\",\"docs/testing/examples/get_evaluations_workflows.json\",\"docs/testing/examples/get_failure_aggregates.json\",\"docs/testing/examples/get_gitcase_spaces.json\",\"docs/testing/examples/get_golden_samples.json\",\"docs/testing/examples/get_human_feedback.json\",\"docs/testing/examples/get_icafe_space.json\",\"docs/testing/examples/get_intelligence.json\",\"docs/testing/examples/get_product_spaces.json\",\"docs/testing/examples/get_product_spaces_mine.json\",\"docs/testing/examples/get_recording_guide.json\",\"docs/testing/examples/get_reliability.json\",\"docs/testing/examples/get_schema_migrations.json\",\"docs/testing/examples/get_schema_migrations_summary.json\",\"docs/testing/examples/get_settings_me.json\",\"docs/testing/examples/get_slow_node_trends.json\",\"docs/testing/examples/get_stale_runs.json\",\"docs/testing/examples/get_trace_by_id_404.json\",\"docs/testing/examples/get_traces.json\",\"docs/testing/examples/get_traces_health.json\",\"docs/testing/examples/get_ugate_token.json\",\"docs/testing/examples/get_ui_replay_audit_events.json\",\"docs/testing/examples/get_ui_replay_governance.json\",\"docs/testing/examples/get_ui_replay_quality_rules.json\",\"docs/testing/examples/get_ui_replay_recordings.json\",\"docs/testing/examples/get_ui_replay_runs.json\",\"docs/testing/examples/get_update_check.json\",\"docs/testing/examples/get_usage_aggregates.json\",\"docs/testing/examples/get_version_effectiveness.json\",\"docs/testing/examples/get_workflow_aggregates.json\",\"docs/testing/examples/get_workflow_by_name_404.json\",\"docs/testing/examples/get_workflow_run_by_id_404.json\",\"docs/testing/examples/get_workflow_run_by_worker_404.json\",\"docs/testing/examples/get_workflow_v2_by_id_404.json\",\"docs/testing/examples/patch_config_assistants.json\",\"docs/testing/examples/post_conversations.json\",\"docs/testing/examples/put_codebase_env_404.json\",\"docs/testing/specmatic-coverage.sh\",\"docs/testing/specmatic-doarchon-docker-test-guide.md\",\"docs/testing/specmatic-doarchon.yaml\",\"docs/testing/specmatic-integration.md\",\"docs/testing/specmatic-test.sh\",\"docs/testing/ui-replay-quality.md\"]},{\"name\":\"Other \u2014 wiki-drafts\",\"slug\":\"other-wiki-drafts\",\"files\":[\"docs/wiki-drafts/PROMPT.md\",\"docs/wiki-drafts/feature-workflow-authoring.md\",\"docs/wiki-drafts/feature-workflow-isolation.md\"]},{\"name\":\"Other \u2014 eslint.config.mjs\",\"slug\":\"other-eslint-config-mjs\",\"files\":[\"eslint.config.mjs\"]},{\"name\":\"Other \u2014 migrations\",\"slug\":\"other-migrations\",\"files\":[\"migrations/000_combined.sql\",\"migrations/001_initial_schema.sql\",\"migrations/001_user_isolation.sql\",\"migrations/002_command_templates.sql\",\"migrations/002_product_spaces.sql\",\"migrations/003_add_worktree.sql\",\"migrations/004_worktree_sharing.sql\",\"migrations/005_isolation_abstraction.sql\",\"migrations/006_isolation_environments.sql\",\"migrations/007_drop_legacy_columns.sql\",\"migrations/008_workflow_runs.sql\",\"migrations/009_workflow_last_activity.sql\",\"migrations/010_immutable_sessions.sql\",\"migrations/011_partial_unique_constraint.sql\",\"migrations/012_workflow_events.sql\",\"migrations/013_conversation_titles.sql\",\"migrations/014_message_history.sql\",\"migrations/015_background_dispatch.sql\",\"migrations/016_session_ended_reason.sql\",\"migrations/017_drop_command_templates.sql\",\"migrations/018_fix_workflow_status_default.sql\",\"migrations/019_workflow_resume_path.sql\",\"migrations/020_codebase_env_vars.sql\",\"migrations/021_add_allow_env_keys_to_codebases.sql\",\"migrations/022_ugate_tokens.sql\",\"migrations/023_codebase_combos.sql\",\"migrations/023_runtime_trace.sql\",\"migrations/024_runtime_trace_alerts.sql\",\"migrations/024_ugate_token_icafe_space.sql\",\"migrations/025_runtime_trace_schema_migrations.sql\",\"migrations/026_runtime_trace_issue_id.sql\",\"migrations/027_workflow_evaluations.sql\",\"migrations/028_dedupe_workflow_evaluations.sql\",\"migrations/029_workflow_run_history_governance.sql\",\"migrations/030_evaluation_objective_datasets.sql\",\"migrations/031_trace_event_skill_name.sql\",\"migrations/032_runtime_trace_governance_indexes.sql\",\"migrations/032_sandbox.sql\",\"migrations/032_workflows_product_space.sql\",\"migrations/033_runtime_trace_schema_backfill.sql\",\"migrations/034_runtime_trace_query_indexes.sql\",\"migrations/035_space_codebases.sql\",\"migrations/035_workflow_run_access_scope.sql\",\"migrations/036_evolution_candidates.sql\",\"migrations/037_messages_created_at_timestamptz.sql\",\"migrations/038_error_details.sql\",\"migrations/039_message_knowledge_columns.sql\",\"migrations/040_ui_replay_persistence.sql\",\"migrations/041_ui_replay_audit.sql\",\"migrations/042_personal_space.sql\",\"migrations/042_workflow_definition_versions.sql\",\"migrations/043_workflow_project_source.sql\",\"migrations/044_observability_events.sql\",\"migrations/045_observability_user_activity_indexes.sql\",\"migrations/045_workflow_name_unique_per_space.sql\",\"migrations/047_conversations_product_space.sql\",\"migrations/048_observability_sla_performance_indexes.sql\",\"migrations/048_workflow_drafts.sql\",\"migrations/049_observability_sla_bucket_snapshots.sql\",\"migrations/051_conversation_branches.sql\",\"migrations/051_loop_back_state.sql\",\"migrations/052_space_commands.sql\",\"migrations/052_workflow_models.sql\",\"migrations/053_workflow_models_backfill.sql\",\"migrations/054_commands_market.sql\",\"migrations/055_workflow_run_command_scope.sql\",\"migrations/056_command_source_type.sql\",\"migrations/057_scheduled_tasks.sql\",\"migrations/058_workflow_run_trigger_source.sql\",\"migrations/059_scheduled_task_branch.sql\",\"migrations/060_scheduled_task_rename_prompt.sql\",\"migrations/061_workflow_version.sql\",\"migrations/062_scheduled_task_product_required.sql\",\"migrations/062_web_verify_steps.sql\",\"migrations/063_observability_sla_user_operation_metrics.sql\",\"migrations/063_user_department_profiles.sql\",\"migrations/064_sla_notification_deliveries.sql\",\"migrations/064_workflow_run_original_started_at.sql\",\"migrations/065_workflow_usage_index.sql\",\"migrations/066_observability_sla_snapshot_retention.sql\",\"migrations/067_observability_active_probe_history_index.sql\",\"migrations/068_observability_traffic_signal_covering_index.sql\",\"migrations/069_workflow_run_codebase_name.sql\",\"migrations/070_observability_sla_schema_reconciliation.sql\",\"migrations/071_observability_sla_online_indexes.sql\",\"migrations/072_observability_sla_snapshot_environment_signals.sql\",\"migrations/073_observability_sla_coverage_lookup_index.sql\",\"migrations/074_observability_sla_dirty_update_triggers.sql\",\"migrations/075_observability_sla_workflow_dirty_triggers.sql\",\"migrations/076_observability_sla_v5_frontend_noise_rebuild.sql\",\"migrations/077_sla_breach_monitoring.sql\",\"migrations/078_observability_sla_integrity_remediation.sql\",\"migrations/079_observability_sla_snapshot_generation.sql\",\"migrations/080_observability_sla_attribution_epoch_fence.sql\",\"migrations/081_observability_dashboard_facts.sql\",\"migrations/082_observability_sla_workflow_owned_failures.sql\",\"migrations/082_workflow_knowledge_observability.sql\",\"migrations/083_evaluation_effect_evidence.sql\",\"migrations/083_workflow_knowledge_sync_jobs.sql\",\"migrations/084_evaluation_benchmark_suites.sql\",\"migrations/084_workflow_knowledge_context_dedup.sql\",\"migrations/085_evaluation_knowledge_artifact_outbox.sql\",\"migrations/086_workflow_models_refresh.sql\",\"migrations/087_evaluation_jobs_runs.sql\",\"migrations/088_observability_sla_attribution_v8_epoch.sql\"]},{\"name\":\"Other \u2014 package.json\",\"slug\":\"other-package-json\",\"files\":[\"package.json\"]},{\"name\":\"Other \u2014 adapters\",\"slug\":\"other-adapters\",\"files\":[\"packages/adapters/package.json\",\"packages/adapters/src/chat/slack/adapter.test.ts\",\"packages/adapters/src/chat/slack/adapter.ts\",\"packages/adapters/src/chat/slack/auth.test.ts\",\"packages/adapters/src/chat/slack/auth.ts\",\"packages/adapters/src/chat/slack/index.ts\",\"packages/adapters/src/chat/slack/types.ts\",\"packages/adapters/src/chat/telegram/adapter.test.ts\",\"packages/adapters/src/chat/telegram/adapter.ts\",\"packages/adapters/src/chat/telegram/auth.test.ts\",\"packages/adapters/src/chat/telegram/auth.ts\",\"packages/adapters/src/chat/telegram/index.ts\",\"packages/adapters/src/chat/telegram/markdown.test.ts\",\"packages/adapters/src/chat/telegram/markdown.ts\",\"packages/adapters/src/chat/telegram/types.ts\",\"packages/adapters/src/community/chat/README.md\",\"packages/adapters/src/community/chat/discord/adapter.test.ts\",\"packages/adapters/src/community/chat/discord/adapter.ts\",\"packages/adapters/src/community/chat/discord/auth.test.ts\",\"packages/adapters/src/community/chat/discord/auth.ts\",\"packages/adapters/src/community/chat/discord/index.ts\",\"packages/adapters/src/community/chat/discord/types.ts\",\"packages/adapters/src/community/forge/README.md\",\"packages/adapters/src/community/forge/gitea/adapter-internals.test.ts\",\"packages/adapters/src/community/forge/gitea/adapter.test.ts\",\"packages/adapters/src/community/forge/gitea/adapter.ts\",\"packages/adapters/src/community/forge/gitea/auth.test.ts\",\"packages/adapters/src/community/forge/gitea/auth.ts\",\"packages/adapters/src/community/forge/gitea/index.ts\",\"packages/adapters/src/community/forge/gitea/types.ts\",\"packages/adapters/src/community/forge/gitlab/adapter-internals.test.ts\",\"packages/adapters/src/community/forge/gitlab/adapter.test.ts\",\"packages/adapters/src/community/forge/gitlab/adapter.ts\",\"packages/adapters/src/community/forge/gitlab/auth.test.ts\",\"packages/adapters/src/community/forge/gitlab/auth.ts\",\"packages/adapters/src/community/forge/gitlab/index.ts\",\"packages/adapters/src/community/forge/gitlab/types.ts\",\"packages/adapters/src/forge/github/adapter.test.ts\",\"packages/adapters/src/forge/github/adapter.ts\",\"packages/adapters/src/forge/github/auth.test.ts\",\"packages/adapters/src/forge/github/auth.ts\",\"packages/adapters/src/forge/github/context.test.ts\",\"packages/adapters/src/forge/github/index.ts\",\"packages/adapters/src/forge/github/types.ts\",\"packages/adapters/src/index.ts\",\"packages/adapters/src/utils/message-splitting.test.ts\",\"packages/adapters/tsconfig.json\"]},{\"name\":\"Other \u2014 auth\",\"slug\":\"other-auth\",\"files\":[\"packages/auth/package.json\",\"packages/auth/src/db.test.ts\",\"packages/auth/src/db.ts\",\"packages/auth/src/deptmember/client.test.ts\",\"packages/auth/src/deptmember/client.ts\",\"packages/auth/src/index.ts\",\"packages/auth/src/jwt.test.ts\",\"packages/auth/src/jwt.ts\",\"packages/auth/src/middleware.test.ts\",\"packages/auth/src/middleware.ts\",\"packages/auth/src/uic/client.test.ts\",\"packages/auth/src/uic/client.ts\",\"packages/auth/src/uuap/client.test.ts\",\"packages/auth/src/uuap/client.ts\",\"packages/auth/src/uuap/types.ts\",\"packages/auth/tsconfig.json\"]},{\"name\":\"Other \u2014 cli\",\"slug\":\"other-cli\",\"files\":[\"packages/cli/package.json\",\"packages/cli/src/adapters/cli-adapter.test.ts\",\"packages/cli/src/aiflow/auth.test.ts\",\"packages/cli/src/aiflow/auth.ts\",\"packages/cli/src/aiflow/client.test.ts\",\"packages/cli/src/aiflow/client.ts\",\"packages/cli/src/aiflow/commands/codebase.test.ts\",\"packages/cli/src/aiflow/commands/codebase.ts\",\"packages/cli/src/aiflow/commands/combo.test.ts\",\"packages/cli/src/aiflow/commands/combo.ts\",\"packages/cli/src/aiflow/commands/conversation.test.ts\",\"packages/cli/src/aiflow/commands/conversation.ts\",\"packages/cli/src/aiflow/commands/run.test.ts\",\"packages/cli/src/aiflow/commands/run.ts\",\"packages/cli/src/aiflow/commands/space.test.ts\",\"packages/cli/src/aiflow/commands/space.ts\",\"packages/cli/src/aiflow/commands/token.test.ts\",\"packages/cli/src/aiflow/commands/token.ts\",\"packages/cli/src/aiflow/commands/workflow.test.ts\",\"packages/cli/src/aiflow/commands/workflow.ts\",\"packages/cli/src/aiflow/file-upload.ts\",\"packages/cli/src/aiflow/format.test.ts\",\"packages/cli/src/aiflow/format.ts\",\"packages/cli/src/aiflow/platform.test.ts\",\"packages/cli/src/aiflow/platform.ts\",\"packages/cli/src/bundled-skill.ts\",\"packages/cli/src/cli-platform.test.ts\",\"packages/cli/src/cli-platform.ts\",\"packages/cli/src/cli.test.ts\",\"packages/cli/src/cli.ts\",\"packages/cli/src/commands/chat.test.ts\",\"packages/cli/src/commands/chat.ts\",\"packages/cli/src/commands/continue.ts\",\"packages/cli/src/commands/doctor.test.ts\",\"packages/cli/src/commands/doctor.ts\",\"packages/cli/src/commands/icafe-space.test.ts\",\"packages/cli/src/commands/icafe-space.ts\",\"packages/cli/src/commands/isolation.test.ts\",\"packages/cli/src/commands/isolation.ts\",\"packages/cli/src/commands/serve-binary.test.ts\",\"packages/cli/src/commands/serve.test.ts\",\"packages/cli/src/commands/serve.ts\",\"packages/cli/src/commands/setup-flow.test.ts\",\"packages/cli/src/commands/setup.test.ts\",\"packages/cli/src/commands/setup.ts\",\"packages/cli/src/commands/skill.test.ts\",\"packages/cli/src/commands/skill.ts\",\"packages/cli/src/commands/ugate-token.test.ts\",\"packages/cli/src/commands/ugate-token.ts\",\"packages/cli/src/commands/validate.ts\",\"packages/cli/src/commands/version.test.ts\",\"packages/cli/src/commands/version.ts\",\"packages/cli/src/commands/workflow.test.ts\",\"packages/cli/src/commands/workflow.ts\",\"packages/cli/tsconfig.json\"]},{\"name\":\"Other \u2014 core\",\"slug\":\"other-core\",\"files\":[\"packages/core/package.json\",\"packages/core/src/config/config-loader.test.ts\",\"packages/core/src/config/config-loader.ts\",\"packages/core/src/config/config-types.ts\",\"packages/core/src/config/index.ts\",\"packages/core/src/db/adapters/index.ts\",\"packages/core/src/db/adapters/postgres.test.ts\",\"packages/core/src/db/adapters/postgres.ts\",\"packages/core/src/db/adapters/sqlite.test.ts\",\"packages/core/src/db/adapters/sqlite.ts\",\"packages/core/src/db/adapters/types.ts\",\"packages/core/src/db/assistant-override.ts\",\"packages/core/src/db/codebases.test.ts\",\"packages/core/src/db/codebases.ts\",\"packages/core/src/db/combos.test.ts\",\"packages/core/src/db/combos.ts\",\"packages/core/src/db/connection.test.ts\",\"packages/core/src/db/connection.ts\",\"packages/core/src/db/conversations.test.ts\",\"packages/core/src/db/conversations.ts\",\"packages/core/src/db/env-vars.test.ts\",\"packages/core/src/db/env-vars.ts\",\"packages/core/src/db/error-details.test.ts\",\"packages/core/src/db/error-details.ts\",\"packages/core/src/db/evaluation-benchmarks.ts\",\"packages/core/src/db/evaluation-evidence.ts\",\"packages/core/src/db/evaluation-knowledge-artifacts.ts\",\"packages/core/src/db/evaluations.test.ts\",\"packages/core/src/db/evaluations.ts\",\"packages/core/src/db/evolution.test.ts\",\"packages/core/src/db/evolution.ts\",\"packages/core/src/db/index.ts\",\"packages/core/src/db/isolation-environments.test.ts\",\"packages/core/src/db/isolation-environments.ts\",\"packages/core/src/db/knowledge-observations.test.ts\",\"packages/core/src/db/knowledge-observations.ts\",\"packages/core/src/db/knowledge-sync-jobs.test.ts\",\"packages/core/src/db/knowledge-sync-jobs.ts\",\"packages/core/src/db/messages.test.ts\",\"packages/core/src/db/messages.ts\",\"packages/core/src/db/migrate.test.ts\",\"packages/core/src/db/migrate.ts\",\"packages/core/src/db/observability.test.ts\",\"packages/core/src/db/observability.ts\",\"packages/core/src/db/personnel-usage.test.ts\",\"packages/core/src/db/personnel-usage.ts\",\"packages/core/src/db/product-spaces.test.ts\",\"packages/core/src/db/product-spaces.ts\",\"packages/core/src/db/runtime-traces.test.ts\",\"packages/core/src/db/runtime-traces.ts\",\"packages/core/src/db/sandbox-environments.test.ts\",\"packages/core/src/db/sandbox-environments.ts\",\"packages/core/src/db/scheduled-tasks.test.ts\",\"packages/core/src/db/scheduled-tasks.ts\",\"packages/core/src/db/sessions.test.ts\",\"packages/core/src/db/sessions.ts\",\"packages/core/src/db/sla-notification-deliveries.test.ts\",\"packages/core/src/db/sla-notification-deliveries.ts\",\"packages/core/src/db/space-commands.test.ts\",\"packages/core/src/db/space-commands.ts\",\"packages/core/src/db/ugate-tokens.test.ts\",\"packages/core/src/db/ugate-tokens.ts\",\"packages/core/src/db/ui-replay.ts\",\"packages/core/src/db/user-settings.test.ts\",\"packages/core/src/db/user-settings.ts\",\"packages/core/src/db/user-workflows.test.ts\",\"packages/core/src/db/user-workflows.ts\",\"packages/core/src/db/users.test.ts\",\"packages/core/src/db/users.ts\",\"packages/core/src/db/web-verify-steps.ts\",\"packages/core/src/db/workflow-definition-versions.test.ts\",\"packages/core/src/db/workflow-definition-versions.ts\",\"packages/core/src/db/workflow-drafts.test.ts\",\"packages/core/src/db/workflow-drafts.ts\",\"packages/core/src/db/workflow-events-loop-back.test.ts\",\"packages/core/src/db/workflow-events.test.ts\",\"packages/core/src/db/workflow-events.ts\",\"packages/core/src/db/workflow-loop-metrics.test.ts\",\"packages/core/src/db/workflow-loop-metrics.ts\",\"packages/core/src/db/workflow-models.test.ts\",\"packages/core/src/db/workflow-models.ts\",\"packages/core/src/db/workflow-run-trigger-source.test.ts\",\"packages/core/src/db/workflows-loop-back.test.ts\",\"packages/core/src/db/workflows-v2.test.ts\",\"packages/core/src/db/workflows-v2.ts\",\"packages/core/src/db/workflows.test.ts\",\"packages/core/src/db/workflows.ts\",\"packages/core/src/evaluation/event-bus.ts\",\"packages/core/src/handlers/clone.test.ts\",\"packages/core/src/handlers/clone.ts\",\"packages/core/src/handlers/command-handler.test.ts\",\"packages/core/src/handlers/command-handler.ts\",\"packages/core/src/handlers/command-handler.workflow-run.test.ts\",\"packages/core/src/handlers/icode-clone.test.ts\",\"packages/core/src/handlers/icode-clone.ts\",\"packages/core/src/index.ts\",\"packages/core/src/knowledge/product-resolver.test.ts\",\"packages/core/src/knowledge/product-resolver.ts\",\"packages/core/src/notifications/infoflow-client.oauth.test.ts\",\"packages/core/src/notifications/infoflow-client.test.ts\",\"packages/core/src/notifications/infoflow-client.ts\",\"packages/core/src/notifications/infoflow-sidebar-link.test.ts\",\"packages/core/src/notifications/infoflow-sidebar-link.ts\",\"packages/core/src/notifications/infoflow.test.ts\",\"packages/core/src/notifications/infoflow.ts\",\"packages/core/src/operations/index.ts\",\"packages/core/src/operations/isolation-operations.test.ts\",\"packages/core/src/operations/isolation-operations.ts\",\"packages/core/src/operations/workflow-operations.test.ts\",\"packages/core/src/operations/workflow-operations.ts\",\"packages/core/src/orchestrator/dispatchBackgroundWorkflow.test.ts\",\"packages/core/src/orchestrator/orchestrator-agent.test.ts\",\"packages/core/src/orchestrator/orchestrator-agent.ts\",\"packages/core/src/orchestrator/orchestrator-isolation.test.ts\",\"packages/core/src/orchestrator/orchestrator.test.ts\",\"packages/core/src/orchestrator/orchestrator.ts\",\"packages/core/src/orchestrator/prompt-builder.test.ts\",\"packages/core/src/orchestrator/prompt-builder.ts\",\"packages/core/src/orchestrator/sandbox-helpers.test.ts\",\"packages/core/src/orchestrator/sandbox-helpers.ts\",\"packages/core/src/orchestrator/workflow-authoring-command-list.test.ts\",\"packages/core/src/orchestrator/workflow-authoring-retry.ts\",\"packages/core/src/orchestrator/workflow-authoring.test.ts\",\"packages/core/src/orchestrator/workflow-authoring.ts\",\"packages/core/src/runtime/alerts.ts\",\"packages/core/src/runtime/cost.test.ts\",\"packages/core/src/runtime/cost.ts\",\"packages/core/src/runtime/emitter.test.ts\",\"packages/core/src/runtime/emitter.ts\",\"packages/core/src/runtime/evaluation-worker.test.ts\",\"packages/core/src/runtime/evaluation-worker.ts\",\"packages/core/src/runtime/ids.test.ts\",\"packages/core/src/runtime/ids.ts\",\"packages/core/src/runtime/index.ts\",\"packages/core/src/runtime/issue-clustering.test.ts\",\"packages/core/src/runtime/issue-clustering.ts\",\"packages/core/src/runtime/observability-bus.test.ts\",\"packages/core/src/runtime/observability-bus.ts\",\"packages/core/src/runtime/policy.test.ts\",\"packages/core/src/runtime/policy.ts\",\"packages/core/src/runtime/redaction.test.ts\",\"packages/core/src/runtime/redaction.ts\",\"packages/core/src/runtime/trace-bus.test.ts\",\"packages/core/src/runtime/trace-bus.ts\",\"packages/core/src/runtime/types.ts\",\"packages/core/src/runtime/workflow-trace-recorder.test.ts\",\"packages/core/src/runtime/workflow-trace-recorder.ts\",\"packages/core/src/scheduling/next-run.test.ts\",\"packages/core/src/scheduling/next-run.ts\",\"packages/core/src/scheduling/sandbox-envs-env.test.ts\",\"packages/core/src/scheduling/sandbox-envs.test.ts\",\"packages/core/src/scheduling/sandbox-envs.ts\",\"packages/core/src/scheduling/scheduled-task-runner.test.ts\",\"packages/core/src/scheduling/scheduled-task-runner.ts\",\"packages/core/src/services/cleanup-service.test.ts\",\"packages/core/src/services/codebase-restore-service.test.ts\",\"packages/core/src/services/evaluation-benchmark-service.test.ts\",\"packages/core/src/services/evaluation-benchmark-service.ts\",\"packages/core/src/services/evaluation-calibration-service.test.ts\",\"packages/core/src/services/evaluation-calibration-service.ts\",\"packages/core/src/services/evaluation-capability-readiness-service.test.ts\",\"packages/core/src/services/evaluation-capability-readiness-service.ts\",\"packages/core/src/services/evaluation-evidence-service.test.ts\",\"packages/core/src/services/evaluation-evidence-service.ts\",\"packages/core/src/services/evaluation-knowledge-artifact-service.test.ts\",\"packages/core/src/services/evaluation-service.test.ts\",\"packages/core/src/services/evaluation-service.ts\",\"packages/core/src/services/evolution-service.test.ts\",\"packages/core/src/services/failure-attribution-service.test.ts\",\"packages/core/src/services/golden-sample-candidate-service.test.ts\",\"packages/core/src/services/quality-gate-service.test.ts\",\"packages/core/src/services/runtime-intelligence.test.ts\",\"packages/core/src/services/title-generator.test.ts\",\"packages/core/src/services/ui-replay-assertions.test.ts\",\"packages/core/src/services/ui-replay-assertions.ts\",\"packages/core/src/state/session-transitions.test.ts\",\"packages/core/src/state/session-transitions.ts\",\"packages/core/src/test/mocks/database.ts\",\"packages/core/src/test/mocks/logger.ts\",\"packages/core/src/test/mocks/platform.ts\",\"packages/core/src/test/setup.ts\",\"packages/core/src/types/index.ts\",\"packages/core/src/utils/commands.test.ts\",\"packages/core/src/utils/commands.ts\",\"packages/core/src/utils/conversation-lock.test.ts\",\"packages/core/src/utils/conversation-lock.ts\",\"packages/core/src/utils/credential-sanitizer.test.ts\",\"packages/core/src/utils/credential-sanitizer.ts\",\"packages/core/src/utils/error-formatter.test.ts\",\"packages/core/src/utils/error-formatter.ts\",\"packages/core/src/utils/error.test.ts\",\"packages/core/src/utils/error.ts\",\"packages/core/src/utils/github-graphql.test.ts\",\"packages/core/src/utils/github-graphql.ts\",\"packages/core/src/utils/path-validation.test.ts\",\"packages/core/src/utils/path-validation.ts\",\"packages/core/src/utils/port-allocation.test.ts\",\"packages/core/src/utils/port-allocation.ts\",\"packages/core/src/utils/worktree-sync.test.ts\",\"packages/core/src/utils/worktree-sync.ts\",\"packages/core/src/workflows/index.ts\",\"packages/core/src/workflows/store-adapter.test.ts\",\"packages/core/src/workflows/store-adapter.ts\",\"packages/core/tsconfig.json\",\"packages/core/tsconfig.tsbuildinfo\"]},{\"name\":\"Other \u2014 docs-web\",\"slug\":\"other-docs-web\",\"files\":[\"packages/docs-web/astro.config.mjs\",\"packages/docs-web/package.json\",\"packages/docs-web/public/CNAME\",\"packages/docs-web/public/install\",\"packages/docs-web/public/install.ps1\",\"packages/docs-web/src/content.config.ts\",\"packages/docs-web/src/content/docs/adapters/community/discord.md\",\"packages/docs-web/src/content/docs/adapters/community/gitea.md\",\"packages/docs-web/src/content/docs/adapters/community/gitlab.md\",\"packages/docs-web/src/content/docs/adapters/github.md\",\"packages/docs-web/src/content/docs/adapters/index.md\",\"packages/docs-web/src/content/docs/adapters/slack.md\",\"packages/docs-web/src/content/docs/adapters/telegram.md\",\"packages/docs-web/src/content/docs/adapters/web.md\",\"packages/docs-web/src/content/docs/book/dag-workflows.md\",\"packages/docs-web/src/content/docs/book/essential-workflows.md\",\"packages/docs-web/src/content/docs/book/first-command.md\",\"packages/docs-web/src/content/docs/book/first-five-minutes.md\",\"packages/docs-web/src/content/docs/book/first-workflow.md\",\"packages/docs-web/src/content/docs/book/hooks-and-quality.md\",\"packages/docs-web/src/content/docs/book/how-it-works.md\",\"packages/docs-web/src/content/docs/book/index.md\",\"packages/docs-web/src/content/docs/book/isolation.md\",\"packages/docs-web/src/content/docs/book/quick-reference.md\",\"packages/docs-web/src/content/docs/book/what-is-archon.md\",\"packages/docs-web/src/content/docs/contributing/adding-a-community-provider.md\",\"packages/docs-web/src/content/docs/contributing/cli-internals.md\",\"packages/docs-web/src/content/docs/contributing/dx-quirks.md\",\"packages/docs-web/src/content/docs/contributing/index.md\",\"packages/docs-web/src/content/docs/contributing/new-developer-guide.md\",\"packages/docs-web/src/content/docs/contributing/releasing.md\",\"packages/docs-web/src/content/docs/deployment/cloud.md\",\"packages/docs-web/src/content/docs/deployment/docker.md\",\"packages/docs-web/src/content/docs/deployment/e2e-testing-wsl.md\",\"packages/docs-web/src/content/docs/deployment/e2e-testing.md\",\"packages/docs-web/src/content/docs/deployment/index.md\",\"packages/docs-web/src/content/docs/deployment/local.md\",\"packages/docs-web/src/content/docs/deployment/windows.md\",\"packages/docs-web/src/content/docs/getting-started/ai-assistants.md\",\"packages/docs-web/src/content/docs/getting-started/concepts.md\",\"packages/docs-web/src/content/docs/getting-started/configuration.md\",\"packages/docs-web/src/content/docs/getting-started/installation.md\",\"packages/docs-web/src/content/docs/getting-started/overview.md\",\"packages/docs-web/src/content/docs/getting-started/quick-start.md\",\"packages/docs-web/src/content/docs/guides/approval-nodes.md\",\"packages/docs-web/src/content/docs/guides/authoring-commands.md\",\"packages/docs-web/src/content/docs/guides/authoring-workflows.md\",\"packages/docs-web/src/content/docs/guides/global-workflows.md\",\"packages/docs-web/src/content/docs/guides/hooks.md\",\"packages/docs-web/src/content/docs/guides/index.md\",\"packages/docs-web/src/content/docs/guides/loop-nodes.md\",\"packages/docs-web/src/content/docs/guides/mcp-servers.md\",\"packages/docs-web/src/content/docs/guides/remotion-workflow.md\",\"packages/docs-web/src/content/docs/guides/script-nodes.md\",\"packages/docs-web/src/content/docs/guides/skills.md\",\"packages/docs-web/src/content/docs/index.mdx\",\"packages/docs-web/src/content/docs/reference/api.md\",\"packages/docs-web/src/content/docs/reference/architecture.md\",\"packages/docs-web/src/content/docs/reference/archon-directories.md\",\"packages/docs-web/src/content/docs/reference/cli.md\",\"packages/docs-web/src/content/docs/reference/commands.md\",\"packages/docs-web/src/content/docs/reference/configuration.md\",\"packages/docs-web/src/content/docs/reference/database.md\",\"packages/docs-web/src/content/docs/reference/index.md\",\"packages/docs-web/src/content/docs/reference/security.md\",\"packages/docs-web/src/content/docs/reference/troubleshooting.md\",\"packages/docs-web/src/content/docs/reference/variables.md\",\"packages/docs-web/src/styles/custom.css\",\"packages/docs-web/tsconfig.json\"]},{\"name\":\"Other \u2014 git\",\"slug\":\"other-git\",\"files\":[\"packages/git/package.json\",\"packages/git/src/branch.ts\",\"packages/git/src/exec.test.ts\",\"packages/git/src/exec.ts\",\"packages/git/src/git.test.ts\",\"packages/git/src/index.ts\",\"packages/git/src/keyed-mutex.test.ts\",\"packages/git/src/keyed-mutex.ts\",\"packages/git/src/repo.ts\",\"packages/git/src/types.ts\",\"packages/git/src/worktree.ts\",\"packages/git/tsconfig.json\"]},{\"name\":\"Other \u2014 isolation\",\"slug\":\"other-isolation\",\"files\":[\"packages/isolation/package.json\",\"packages/isolation/src/errors.test.ts\",\"packages/isolation/src/errors.ts\",\"packages/isolation/src/factory.test.ts\",\"packages/isolation/src/factory.ts\",\"packages/isolation/src/index.ts\",\"packages/isolation/src/pr-state.test.ts\",\"packages/isolation/src/pr-state.ts\",\"packages/isolation/src/providers/worktree.test.ts\",\"packages/isolation/src/providers/worktree.ts\",\"packages/isolation/src/resolver.test.ts\",\"packages/isolation/src/resolver.ts\",\"packages/isolation/src/store.ts\",\"packages/isolation/src/types.ts\",\"packages/isolation/src/worktree-copy.test.ts\",\"packages/isolation/src/worktree-copy.ts\",\"packages/isolation/tsconfig.json\"]},{\"name\":\"Other \u2014 paths\",\"slug\":\"other-paths\",\"files\":[\"packages/paths/package.json\",\"packages/paths/src/archon-paths.test.ts\",\"packages/paths/src/archon-paths.ts\",\"packages/paths/src/bundled-build.test.ts\",\"packages/paths/src/bundled-build.ts\",\"packages/paths/src/env-integration.test.ts\",\"packages/paths/src/env-loader.test.ts\",\"packages/paths/src/env-loader.ts\",\"packages/paths/src/index.ts\",\"packages/paths/src/logger.test.ts\",\"packages/paths/src/logger.ts\",\"packages/paths/src/mcp-init.test.ts\",\"packages/paths/src/mcp-init.ts\",\"packages/paths/src/strip-cwd-env-boot.ts\",\"packages/paths/src/strip-cwd-env.test.ts\",\"packages/paths/src/strip-cwd-env.ts\",\"packages/paths/src/telemetry.test.ts\",\"packages/paths/src/telemetry.ts\",\"packages/paths/src/update-check.test.ts\",\"packages/paths/src/update-check.ts\",\"packages/paths/tsconfig.json\"]},{\"name\":\"Other \u2014 providers\",\"slug\":\"other-providers\",\"files\":[\"packages/providers/package.json\",\"packages/providers/src/claude/binary-resolver-dev.test.ts\",\"packages/providers/src/claude/binary-resolver.test.ts\",\"packages/providers/src/claude/binary-resolver.ts\",\"packages/providers/src/claude/capabilities.ts\",\"packages/providers/src/claude/config.test.ts\",\"packages/providers/src/claude/config.ts\",\"packages/providers/src/claude/index.ts\",\"packages/providers/src/claude/provider.test.ts\",\"packages/providers/src/claude/provider.ts\",\"packages/providers/src/codex/binary-guard.test.ts\",\"packages/providers/src/codex/binary-resolver-dev.test.ts\",\"packages/providers/src/codex/binary-resolver.test.ts\",\"packages/providers/src/codex/binary-resolver.ts\",\"packages/providers/src/codex/capabilities.ts\",\"packages/providers/src/codex/config.test.ts\",\"packages/providers/src/codex/config.ts\",\"packages/providers/src/codex/index.ts\",\"packages/providers/src/codex/provider.test.ts\",\"packages/providers/src/codex/provider.ts\",\"packages/providers/src/community/pi/capabilities.ts\",\"packages/providers/src/community/pi/config.test.ts\",\"packages/providers/src/community/pi/config.ts\",\"packages/providers/src/community/pi/event-bridge.test.ts\",\"packages/providers/src/community/pi/event-bridge.ts\",\"packages/providers/src/community/pi/index.ts\",\"packages/providers/src/community/pi/model-ref.test.ts\",\"packages/providers/src/community/pi/model-ref.ts\",\"packages/providers/src/community/pi/options-translator.test.ts\",\"packages/providers/src/community/pi/options-translator.ts\",\"packages/providers/src/community/pi/provider-lazy-load.test.ts\",\"packages/providers/src/community/pi/provider.test.ts\",\"packages/providers/src/community/pi/provider.ts\",\"packages/providers/src/community/pi/registration.ts\",\"packages/providers/src/community/pi/resource-loader.ts\",\"packages/providers/src/community/pi/session-resolver.test.ts\",\"packages/providers/src/community/pi/session-resolver.ts\",\"packages/providers/src/community/pi/ui-context-stub.test.ts\",\"packages/providers/src/community/pi/ui-context-stub.ts\",\"packages/providers/src/errors.ts\",\"packages/providers/src/index.ts\",\"packages/providers/src/registry.test.ts\",\"packages/providers/src/registry.ts\",\"packages/providers/src/test/mocks/logger.ts\",\"packages/providers/src/types.ts\",\"packages/providers/src/workflow-models.test.ts\",\"packages/providers/src/workflow-models.ts\",\"packages/providers/tsconfig.json\"]},{\"name\":\"Other \u2014 sandbox\",\"slug\":\"other-sandbox\",\"files\":[\"packages/sandbox/package.json\",\"packages/sandbox/src/file-helpers.test.ts\",\"packages/sandbox/src/file-helpers.ts\",\"packages/sandbox/src/index.ts\",\"packages/sandbox/src/manager.test.ts\",\"packages/sandbox/src/manager.ts\",\"packages/sandbox/src/provider.test.ts\",\"packages/sandbox/src/provider.ts\",\"packages/sandbox/src/semaphore.test.ts\",\"packages/sandbox/src/semaphore.ts\",\"packages/sandbox/src/stream-parser.test.ts\",\"packages/sandbox/src/stream-parser.ts\",\"packages/sandbox/src/types.ts\",\"packages/sandbox/tsconfig.json\"]},{\"name\":\"Other \u2014 server\",\"slug\":\"other-server\",\"files\":[\"packages/server/package.json\",\"packages/server/src/adapters/web/persistence.test.ts\",\"packages/server/src/adapters/web/persistence.ts\",\"packages/server/src/adapters/web/transport.test.ts\",\"packages/server/src/adapters/web/transport.ts\",\"packages/server/src/adapters/web/workflow-bridge-loop-back.test.ts\",\"packages/server/src/adapters/web/workflow-bridge.test.ts\",\"packages/server/src/adapters/web/workflow-bridge.ts\",\"packages/server/src/api-tests/brand-text-regression.test.ts\",\"packages/server/src/api-tests/contract.test.ts\",\"packages/server/src/api-tests/scenario.test.ts\",\"packages/server/src/api-tests/scheduled-tasks.test.ts\",\"packages/server/src/api-tests/workflow-run-product-scope.test.ts\",\"packages/server/src/api-tests/workflow-run-scheduled-gates.test.ts\",\"packages/server/src/api-tests/workflow-run-upload.test.ts\",\"packages/server/src/bos-client.test.ts\",\"packages/server/src/gitcase-client.test.ts\",\"packages/server/src/routes/api.bos.test.ts\",\"packages/server/src/routes/api.case-info.test.ts\",\"packages/server/src/routes/api.codebases.test.ts\",\"packages/server/src/routes/api.combos.test.ts\",\"packages/server/src/routes/api.commands-v2.test.ts\",\"packages/server/src/routes/api.commands-v2.ts\",\"packages/server/src/routes/api.conversations.test.ts\",\"packages/server/src/routes/api.debug-session.test.ts\",\"packages/server/src/routes/api.evaluations.test.ts\",\"packages/server/src/routes/api.gitcase.test.ts\",\"packages/server/src/routes/api.health.test.ts\",\"packages/server/src/routes/api.helpers.test.ts\",\"packages/server/src/routes/api.infoflow-webhook.test.ts\",\"packages/server/src/routes/api.infoflow.test.ts\",\"packages/server/src/routes/api.knowledge-chat-proxy.ts\",\"packages/server/src/routes/api.knowledge-chat.ts\",\"packages/server/src/routes/api.knowledge-proxy.test.ts\",\"packages/server/src/routes/api.knowledge-proxy.ts\",\"packages/server/src/routes/api.knowledge-sync-callback.test.ts\",\"packages/server/src/routes/api.knowledge.test.ts\",\"packages/server/src/routes/api.knowledge.ts\",\"packages/server/src/routes/api.messages.test.ts\",\"packages/server/src/routes/api.observability.test.ts\",\"packages/server/src/routes/api.personnel-usage.test.ts\",\"packages/server/src/routes/api.product-spaces.test.ts\",\"packages/server/src/routes/api.product-spaces.ts\",\"packages/server/src/routes/api.providers.test.ts\",\"packages/server/src/routes/api.runtime-traces.test.ts\",\"packages/server/src/routes/api.sandbox-file.test.ts\",\"packages/server/src/routes/api.ts\",\"packages/server/src/routes/api.ui-replay.test.ts\",\"packages/server/src/routes/api.web-verify-steps.test.ts\",\"packages/server/src/routes/api.webhooks.test.ts\",\"packages/server/src/routes/api.workflow-runs.test.ts\",\"packages/server/src/routes/api.workflows-v2.test.ts\",\"packages/server/src/routes/api.workflows-v2.ts\",\"packages/server/src/routes/api.workflows.test.ts\",\"packages/server/src/routes/api/bos-download.ts\",\"packages/server/src/routes/api/bos-preview.ts\",\"packages/server/src/routes/api/bos-upload.ts\",\"packages/server/src/routes/api/case-info.ts\",\"packages/server/src/routes/api/codebases.ts\",\"packages/server/src/routes/api/combos.ts\",\"packages/server/src/routes/api/conversations.ts\",\"packages/server/src/routes/api/debug-session.ts\",\"packages/server/src/routes/api/gitcase.ts\",\"packages/server/src/routes/api/helpers.ts\",\"packages/server/src/routes/api/infoflow-crypto.test.ts\",\"packages/server/src/routes/api/infoflow-crypto.ts\",\"packages/server/src/routes/api/infoflow-oauth.test.ts\",\"packages/server/src/routes/api/infoflow-oauth.ts\",\"packages/server/src/routes/api/infoflow-reply-routing.test.ts\",\"packages/server/src/routes/api/infoflow-reply-routing.ts\",\"packages/server/src/routes/api/infoflow-webhook.ts\",\"packages/server/src/routes/api/infoflow.ts\",\"packages/server/src/routes/api/knowledge-sync-callback.ts\",\"packages/server/src/routes/api/product-access.ts\",\"packages/server/src/routes/api/sandbox-file.ts\",\"packages/server/src/routes/api/scheduled-tasks.ts\",\"packages/server/src/routes/api/system.ts\",\"packages/server/src/routes/api/ui-replay.ts\",\"packages/server/src/routes/api/web-verify-steps.ts\",\"packages/server/src/routes/api/workflow-runs.ts\",\"packages/server/src/routes/api/workflows.ts\",\"packages/server/src/routes/api/zip-decompress.test.ts\",\"packages/server/src/routes/api/zip-decompress.ts\",\"packages/server/src/routes/auth.test.ts\",\"packages/server/src/routes/command-frontmatter.test.ts\",\"packages/server/src/routes/command-frontmatter.ts\",\"packages/server/src/routes/command-references.test.ts\",\"packages/server/src/routes/command-references.ts\",\"packages/server/src/routes/health.test.ts\",\"packages/server/src/routes/health.ts\",\"packages/server/src/routes/openapi-defaults.ts\",\"packages/server/src/routes/schemas/case-info.schemas.ts\",\"packages/server/src/routes/schemas/codebase.schemas.ts\",\"packages/server/src/routes/schemas/combo.schemas.ts\",\"packages/server/src/routes/schemas/command-v2.schemas.ts\",\"packages/server/src/routes/schemas/common.schemas.ts\",\"packages/server/src/routes/schemas/config.schemas.ts\",\"packages/server/src/routes/schemas/conversation.schemas.ts\",\"packages/server/src/routes/schemas/evaluation.schemas.ts\",\"packages/server/src/routes/schemas/evolution.schemas.ts\",\"packages/server/src/routes/schemas/gitcase.schemas.ts\",\"packages/server/src/routes/schemas/observability.schemas.ts\",\"packages/server/src/routes/schemas/personnel-usage.schemas.ts\",\"packages/server/src/routes/schemas/product-space.schemas.ts\",\"packages/server/src/routes/schemas/provider.schemas.ts\",\"packages/server/src/routes/schemas/runtime.schemas.ts\",\"packages/server/src/routes/schemas/scheduled-tasks.schemas.ts\",\"packages/server/src/routes/schemas/settings.schemas.ts\",\"packages/server/src/routes/schemas/system.schemas.ts\",\"packages/server/src/routes/schemas/ui-replay.schemas.ts\",\"packages/server/src/routes/schemas/web-verify.schemas.ts\",\"packages/server/src/routes/schemas/workflow.schemas.test.ts\",\"packages/server/src/routes/schemas/workflow.schemas.ts\",\"packages/server/src/routes/webhooks.ts\",\"packages/server/src/runtime-config.test.ts\",\"packages/server/src/scripts/backfill-forked-workflow-commands.ts\",\"packages/server/src/scripts/backfill-product-commands.ts\",\"packages/server/src/scripts/backfill-sla-classifications.ts\",\"packages/server/src/scripts/migrate-space-commands.ts\",\"packages/server/src/scripts/setup-auth.ts\",\"packages/server/src/services/callback-block.test.ts\",\"packages/server/src/services/infoflow-sender.test.ts\",\"packages/server/src/services/infoflow-webhook.test.ts\",\"packages/server/src/services/sla-infoflow-notifier.test.ts\",\"packages/server/src/services/workflow-access.test.ts\",\"packages/server/src/services/workflow-notification-listener.test.ts\",\"packages/server/src/services/workflow-restart-recovery.integration.test.ts\",\"packages/server/src/services/workflow-restart-recovery.test.ts\",\"packages/server/src/services/workflow-restart-recovery.ts\",\"packages/server/src/services/workflow-run-actions.test.ts\",\"packages/server/src/services/workflow-run-exporter.test.ts\",\"packages/server/src/services/workflow-run-knowledge-sync-dispatcher.test.ts\",\"packages/server/src/sync-bundled-commands.test.ts\",\"packages/server/src/sync-bundled-workflows.test.ts\",\"packages/server/src/sync-project-workflows.test.ts\",\"packages/server/src/sync-user-workflows.test.ts\",\"packages/server/src/test/workflow-mock-factories.ts\",\"packages/server/src/workers/sla-infoflow-worker.test.ts\",\"packages/server/tsconfig.json\",\"packages/server/tsconfig.tsbuildinfo\"]},{\"name\":\"Other \u2014 web\",\"slug\":\"other-web\",\"files\":[\"packages/web/components.json\",\"packages/web/e2e/chat-primary-flow.spec.ts\",\"packages/web/e2e/console-flow.spec.ts\",\"packages/web/e2e/dashboard-paused-delete-flow.spec.ts\",\"packages/web/e2e/dashboard-review-flow.spec.ts\",\"packages/web/e2e/diagnostics-flow.spec.ts\",\"packages/web/e2e/evaluation-center-flow.spec.ts\",\"packages/web/e2e/fixtures.ts\",\"packages/web/e2e/governance-smoke.spec.ts\",\"packages/web/e2e/knowledge-eval-real.spec.ts\",\"packages/web/e2e/knowledge-flow.spec.ts\",\"packages/web/e2e/mock-helpers.ts\",\"packages/web/e2e/settings-flow.spec.ts\",\"packages/web/e2e/space-admin-flow.spec.ts\",\"packages/web/e2e/traces-redirect-flow.spec.ts\",\"packages/web/e2e/ui-replay-center-flow.spec.ts\",\"packages/web/e2e/ui-replay-smoke.spec.ts\",\"packages/web/e2e/workflow-run-flow.spec.ts\",\"packages/web/index.html\",\"packages/web/package.json\",\"packages/web/playwright.config.ts\",\"packages/web/postcss.config.mjs\",\"packages/web/src/App.sidebar-routes.test.ts\",\"packages/web/src/components/chat/ArtifactRail.tsx\",\"packages/web/src/components/chat/BreakpointRetry.tsx\",\"packages/web/src/components/chat/ChatInterface.tsx\",\"packages/web/src/components/chat/ComposerContextControls.test.tsx\",\"packages/web/src/components/chat/ComposerContextControls.tsx\",\"packages/web/src/components/chat/ErrorCard.tsx\",\"packages/web/src/components/chat/FileAttachmentChips.tsx\",\"packages/web/src/components/chat/InputRequestForm.test.tsx\",\"packages/web/src/components/chat/InputRequestForm.tsx\",\"packages/web/src/components/chat/LockIndicator.tsx\",\"packages/web/src/components/chat/MessageBubble.strip.test.ts\",\"packages/web/src/components/chat/MessageBubble.tsx\",\"packages/web/src/components/chat/MessageInput.test.tsx\",\"packages/web/src/components/chat/MessageInput.tsx\",\"packages/web/src/components/chat/MessageList.tsx\",\"packages/web/src/components/chat/ToolCallCard.tsx\",\"packages/web/src/components/chat/TryItList.test.ts\",\"packages/web/src/components/chat/TryItList.tsx\",\"packages/web/src/components/chat/WorkflowApprovalBar.tsx\",\"packages/web/src/components/chat/WorkflowProgressCard.tsx\",\"packages/web/src/components/chat/WorkflowSelector.test.tsx\",\"packages/web/src/components/chat/WorkflowSelector.tsx\",\"packages/web/src/components/chat/WorkflowStatusBar.tsx\",\"packages/web/src/components/chat/markdownLink.tsx\",\"packages/web/src/components/chat/strip-input-request.ts\",\"packages/web/src/components/chat/workflow-groups.test.ts\",\"packages/web/src/components/chat/workflow-groups.ts\",\"packages/web/src/components/commands/CommandCard.tsx\",\"packages/web/src/components/commands/CommandDetailDialog.tsx\",\"packages/web/src/components/commands/CommandEditorDialog.theme.test.ts\",\"packages/web/src/components/commands/CommandEditorDialog.tsx\",\"packages/web/src/components/commands/CommandList.tsx\",\"packages/web/src/components/commands/DeleteCommandDialog.tsx\",\"packages/web/src/components/commands/ForkCommandDialog.tsx\",\"packages/web/src/components/conversations/ConversationItem.tsx\",\"packages/web/src/components/dashboard/ConfirmRunActionDialog.tsx\",\"packages/web/src/components/dashboard/DashboardFilters.tsx\",\"packages/web/src/components/dashboard/DashboardTabCount.test.tsx\",\"packages/web/src/components/dashboard/SettingsConcurrencySection.test.ts\",\"packages/web/src/components/dashboard/StatusBoard.tsx\",\"packages/web/src/components/dashboard/StatusSummaryBar.test.tsx\",\"packages/web/src/components/dashboard/WorkflowHistoryTable.tsx\",\"packages/web/src/components/dashboard/WorkflowRunCard.test.ts\",\"packages/web/src/components/dashboard/WorkflowRunCard.tsx\",\"packages/web/src/components/dashboard/WorkflowRunGroup.tsx\",\"packages/web/src/components/document-drawer/DocumentDrawer.tsx\",\"packages/web/src/components/document-drawer/DocumentDrawerContent.tsx\",\"packages/web/src/components/document-drawer/LogDrawer.tsx\",\"packages/web/src/components/document-drawer/MindMapViewer.tsx\",\"packages/web/src/components/document-drawer/SyncGitCaseDialog.tsx\",\"packages/web/src/components/document-drawer/transformCaseJson.ts\",\"packages/web/src/components/knowledge/graph/ArchView.tsx\",\"packages/web/src/components/knowledge/graph/EntityCreateDialog.tsx\",\"packages/web/src/components/knowledge/graph/EntityDetailLegend.tsx\",\"packages/web/src/components/knowledge/graph/EntityDetailSheet.tsx\",\"packages/web/src/components/knowledge/graph/EntityListTable.tsx\",\"packages/web/src/components/knowledge/graph/GraphCanvas.tsx\",\"packages/web/src/components/knowledge/graph/GraphToolbar.tsx\",\"packages/web/src/components/knowledge/graph/RelationEditDialog.tsx\",\"packages/web/src/components/layout/AppSidebar.test.tsx\",\"packages/web/src/components/layout/AppSidebar.tsx\",\"packages/web/src/components/layout/BackendStatusBanner.tsx\",\"packages/web/src/components/layout/Header.tsx\",\"packages/web/src/components/layout/Layout.tsx\",\"packages/web/src/components/layout/OnboardingWizardModal.tsx\",\"packages/web/src/components/layout/OneApiTokenDialog.tsx\",\"packages/web/src/components/layout/SetupWizardModal.render.test.tsx\",\"packages/web/src/components/layout/SetupWizardModal.test.ts\",\"packages/web/src/components/layout/SetupWizardModal.tsx\",\"packages/web/src/components/layout/Sidebar.test.tsx\",\"packages/web/src/components/layout/brand-constants.ts\",\"packages/web/src/components/layout/topnav-utils.ts\",\"packages/web/src/components/observability/ObservabilityProvider.tsx\",\"packages/web/src/components/product-space/AddGroupDialog.tsx\",\"packages/web/src/components/product-space/AddMemberDialog.tsx\",\"packages/web/src/components/product-space/GroupTable.tsx\",\"packages/web/src/components/product-space/MemberTable.tsx\",\"packages/web/src/components/product-space/ProductSpaceForm.tsx\",\"packages/web/src/components/product-space/ProductSpaceSelector.tsx\",\"packages/web/src/components/product-space/SpaceComboSection.tsx\",\"packages/web/src/components/product-space/SpaceProjectsSection.delete-confirm.test.ts\",\"packages/web/src/components/product-space/SpaceProjectsSection.tsx\",\"packages/web/src/components/product-space/SpaceScheduledTasksSection.tsx\",\"packages/web/src/components/settings/TokenSections.mutation.test.tsx\",\"packages/web/src/components/settings/TokenSections.test.tsx\",\"packages/web/src/components/settings/TokenSections.tsx\",\"packages/web/src/components/sidebar/AllConversationsView.tsx\",\"packages/web/src/components/sidebar/ProjectDetail.tsx\",\"packages/web/src/components/sidebar/ProjectSelector.tsx\",\"packages/web/src/components/sidebar/SearchBar.test.tsx\",\"packages/web/src/components/sidebar/SearchBar.tsx\",\"packages/web/src/components/sidebar/SidebarAbandonBar.test.tsx\",\"packages/web/src/components/sidebar/SidebarAbandonBar.tsx\",\"packages/web/src/components/sidebar/SidebarArtifactList.test.tsx\",\"packages/web/src/components/sidebar/SidebarArtifactList.tsx\",\"packages/web/src/components/sidebar/SidebarArtifactPanel.test.tsx\",\"packages/web/src/components/sidebar/SidebarArtifactPanel.tsx\",\"packages/web/src/components/sidebar/SidebarArtifactView.test.tsx\",\"packages/web/src/components/sidebar/SidebarArtifactView.tsx\",\"packages/web/src/components/sidebar/SidebarComposer.test.tsx\",\"packages/web/src/components/sidebar/SidebarComposer.tsx\",\"packages/web/src/components/sidebar/SidebarConfirmDialog.test.tsx\",\"packages/web/src/components/sidebar/SidebarConfirmDialog.tsx\",\"packages/web/src/components/sidebar/SidebarDetailHeader.test.tsx\",\"packages/web/src/components/sidebar/SidebarDetailHeader.tsx\",\"packages/web/src/components/sidebar/SidebarRunDetail.test.tsx\",\"packages/web/src/components/sidebar/SidebarRunDetail.tsx\",\"packages/web/src/components/sidebar/WorkflowInvoker.test.tsx\",\"packages/web/src/components/sidebar/WorkflowInvoker.tsx\",\"packages/web/src/components/sidebar/open-external.ts\",\"packages/web/src/components/sidebar/sidebar-artifact-css.test.ts\",\"packages/web/src/components/sidebar/sidebar-artifacts.test.ts\",\"packages/web/src/components/sidebar/sidebar-artifacts.ts\",\"packages/web/src/components/sidebar/sidebar-auth.test.ts\",\"packages/web/src/components/sidebar/sidebar-auth.ts\",\"packages/web/src/components/sidebar/sidebar-download.test.ts\",\"packages/web/src/components/sidebar/sidebar-download.ts\",\"packages/web/src/components/sidebar/sidebar-turn-css.test.ts\",\"packages/web/src/components/sidebar/sidebar.css\",\"packages/web/src/components/sidebar/useSidebarAuthGuard.test.ts\",\"packages/web/src/components/sidebar/useSidebarAuthGuard.ts\",\"packages/web/src/components/sidebar/useSidebarRun.ts\",\"packages/web/src/components/ui/adapters.test.tsx\",\"packages/web/src/components/ui/alert-dialog.tsx\",\"packages/web/src/components/ui/badge.tsx\",\"packages/web/src/components/ui/button.tsx\",\"packages/web/src/components/ui/card.tsx\",\"packages/web/src/components/ui/collapsible.tsx\",\"packages/web/src/components/ui/combobox.tsx\",\"packages/web/src/components/ui/dialog.tsx\",\"packages/web/src/components/ui/dropdown-menu.tsx\",\"packages/web/src/components/ui/input.tsx\",\"packages/web/src/components/ui/popover.tsx\",\"packages/web/src/components/ui/primitives.test.tsx\",\"packages/web/src/components/ui/resizable.tsx\",\"packages/web/src/components/ui/scroll-area.tsx\",\"packages/web/src/components/ui/select.tsx\",\"packages/web/src/components/ui/separator.tsx\",\"packages/web/src/components/ui/sheet.tsx\",\"packages/web/src/components/ui/switch.tsx\",\"packages/web/src/components/ui/tabs.tsx\",\"packages/web/src/components/ui/textarea.tsx\",\"packages/web/src/components/ui/tooltip.tsx\",\"packages/web/src/components/ui/two-level-menu.tsx\",\"packages/web/src/components/workflows/AiBuilderPanel.autofix.test.ts\",\"packages/web/src/components/workflows/AiBuilderPanel.convert.test.tsx\",\"packages/web/src/components/workflows/AiBuilderPanel.tsx\",\"packages/web/src/components/workflows/ArtifactSummary.tsx\",\"packages/web/src/components/workflows/ArtifactViewerModal.tsx\",\"packages/web/src/components/workflows/AuthoringModelSelect.tsx\",\"packages/web/src/components/workflows/BuilderToolbar.tsx\",\"packages/web/src/components/workflows/CommandPicker.tsx\",\"packages/web/src/components/workflows/DagNodeComponent.test.ts\",\"packages/web/src/components/workflows/DagNodeComponent.tsx\",\"packages/web/src/components/workflows/DagNodeProgress.tsx\",\"packages/web/src/components/workflows/ExecutionDagNode.tsx\",\"packages/web/src/components/workflows/ForkWorkflowDialog.tsx\",\"packages/web/src/components/workflows/ImportAnthropicWorkflowDialog.test.ts\",\"packages/web/src/components/workflows/ImportAnthropicWorkflowDialog.tsx\",\"packages/web/src/components/workflows/LoopBackEdge.render.test.tsx\",\"packages/web/src/components/workflows/LoopBackEdge.test.tsx\",\"packages/web/src/components/workflows/LoopBackEdge.tsx\",\"packages/web/src/components/workflows/NodeInspector.tsx\",\"packages/web/src/components/workflows/NodeLibrary.tsx\",\"packages/web/src/components/workflows/NodePalette.tsx\",\"packages/web/src/components/workflows/PopularWorkflows.tsx\",\"packages/web/src/components/workflows/QuickAddPicker.tsx\",\"packages/web/src/components/workflows/StatusBar.tsx\",\"packages/web/src/components/workflows/StatusIcon.tsx\",\"packages/web/src/components/workflows/StepLogs.tsx\",\"packages/web/src/components/workflows/ValidationPanel.tsx\",\"packages/web/src/components/workflows/WorkflowBuilder.theme.test.ts\",\"packages/web/src/components/workflows/WorkflowBuilder.toolbar.test.ts\",\"packages/web/src/components/workflows/WorkflowBuilder.tsx\",\"packages/web/src/components/workflows/WorkflowCanvas.nodeLabel.test.ts\",\"packages/web/src/components/workflows/WorkflowCanvas.test.ts\",\"packages/web/src/components/workflows/WorkflowCanvas.tsx\",\"packages/web/src/components/workflows/WorkflowCard.test.ts\",\"packages/web/src/components/workflows/WorkflowCard.tsx\",\"packages/web/src/components/workflows/WorkflowDagViewer.tsx\",\"packages/web/src/components/workflows/WorkflowDetail.tsx\",\"packages/web/src/components/workflows/WorkflowExecution.tsx\",\"packages/web/src/components/workflows/WorkflowList.delete-confirm.test.ts\",\"packages/web/src/components/workflows/WorkflowList.sidebar-filter.test.ts\",\"packages/web/src/components/workflows/WorkflowList.tsx\",\"packages/web/src/components/workflows/WorkflowLogs.tsx\",\"packages/web/src/components/workflows/WorkflowModelSelect.tsx\",\"packages/web/src/components/workflows/WorkflowScopeBadge.tsx\",\"packages/web/src/components/workflows/WorkflowSourceBadge.test.ts\",\"packages/web/src/components/workflows/WorkflowSourceBadge.tsx\",\"packages/web/src/components/workflows/WorkflowSpaceSelector.tsx\",\"packages/web/src/components/workflows/YamlCodeView.test.ts\",\"packages/web/src/components/workflows/YamlCodeView.tsx\",\"packages/web/src/components/workflows/use-popular-workflows.test.ts\",\"packages/web/src/components/workflows/use-popular-workflows.ts\",\"packages/web/src/contexts/OnboardingContext.tsx\",\"packages/web/src/contexts/ProjectContext.model-memory.test.ts\",\"packages/web/src/contexts/ProjectContext.tsx\",\"packages/web/src/contexts/ThemeContext.tsx\",\"packages/web/src/contexts/TokenValidationContext.test.tsx\",\"packages/web/src/contexts/TokenValidationContext.tsx\",\"packages/web/src/contexts/model-memory.ts\",\"packages/web/src/hooks/stream-hooks.test.ts\",\"packages/web/src/hooks/useApiAvailability.test.ts\",\"packages/web/src/hooks/useApiAvailability.ts\",\"packages/web/src/hooks/useAutoScroll.ts\",\"packages/web/src/hooks/useBuilderKeyboard.test.ts\",\"packages/web/src/hooks/useBuilderKeyboard.ts\",\"packages/web/src/hooks/useBuilderUndo.ts\",\"packages/web/src/hooks/useBuilderValidation.ts\",\"packages/web/src/hooks/useClickOutside.ts\",\"packages/web/src/hooks/useConversationStream.test.ts\",\"packages/web/src/hooks/useConversationStream.ts\",\"packages/web/src/hooks/useDashboardSSE.ts\",\"packages/web/src/hooks/useDocumentDrawer.ts\",\"packages/web/src/hooks/useEvaluationSSE.ts\",\"packages/web/src/hooks/useFileAttachments.ts\",\"packages/web/src/hooks/useKeyboardShortcuts.ts\",\"packages/web/src/hooks/useObservabilitySSE.ts\",\"packages/web/src/hooks/usePollingWhenRunning.test.ts\",\"packages/web/src/hooks/usePollingWhenRunning.ts\",\"packages/web/src/hooks/useProviders.ts\",\"packages/web/src/hooks/useRuntimeTraceSSE.ts\",\"packages/web/src/hooks/useSSE.ts\",\"packages/web/src/hooks/useServerValidation.test.ts\",\"packages/web/src/hooks/useServerValidation.ts\",\"packages/web/src/hooks/useSetupStatus.ts\",\"packages/web/src/hooks/useWorkflowDraftSync.test.ts\",\"packages/web/src/hooks/useWorkflowDraftSync.ts\",\"packages/web/src/hooks/useWorkflowModels.ts\",\"packages/web/src/index.css\",\"packages/web/src/lib/api-availability.test.ts\",\"packages/web/src/lib/api-availability.ts\",\"packages/web/src/lib/api.test.ts\",\"packages/web/src/lib/api.ts\",\"packages/web/src/lib/artifact-grouping.test.ts\",\"packages/web/src/lib/artifact-grouping.ts\",\"packages/web/src/lib/breakpoint-retry.test.ts\",\"packages/web/src/lib/breakpoint-retry.ts\",\"packages/web/src/lib/chat-message-reducer.test.ts\",\"packages/web/src/lib/chat-message-reducer.ts\",\"packages/web/src/lib/clarify-request.test.ts\",\"packages/web/src/lib/codebase-input.test.ts\",\"packages/web/src/lib/codebase-input.ts\",\"packages/web/src/lib/command-categories.ts\",\"packages/web/src/lib/composer-persistence.test.ts\",\"packages/web/src/lib/composer-persistence.ts\",\"packages/web/src/lib/conversation-grouping.test.ts\",\"packages/web/src/lib/conversation-grouping.ts\",\"packages/web/src/lib/currency.test.ts\",\"packages/web/src/lib/currency.ts\",\"packages/web/src/lib/dag-layout-loop-back.test.ts\",\"packages/web/src/lib/dag-layout.test.ts\",\"packages/web/src/lib/dag-layout.ts\",\"packages/web/src/lib/dashboard-tab-count.ts\",\"packages/web/src/lib/extract-message-artifacts.test.ts\",\"packages/web/src/lib/extract-message-artifacts.ts\",\"packages/web/src/lib/file-attachments.test.ts\",\"packages/web/src/lib/file-attachments.ts\",\"packages/web/src/lib/format.test.ts\",\"packages/web/src/lib/format.ts\",\"packages/web/src/lib/keyboard.ts\",\"packages/web/src/lib/knowledge/api-key.test.ts\",\"packages/web/src/lib/knowledge/api-key.ts\",\"packages/web/src/lib/knowledge/api.graph-inspection.test.ts\",\"packages/web/src/lib/knowledge/api.test.ts\",\"packages/web/src/lib/knowledge/api.ts\",\"packages/web/src/lib/knowledge/arch-constants.tsx\",\"packages/web/src/lib/knowledge/build-status.test.ts\",\"packages/web/src/lib/knowledge/build-status.ts\",\"packages/web/src/lib/knowledge/constants.ts\",\"packages/web/src/lib/knowledge/entity-form.test.ts\",\"packages/web/src/lib/knowledge/entity-form.ts\",\"packages/web/src/lib/knowledge/force-graph.ts\",\"packages/web/src/lib/knowledge/mock-data.ts\",\"packages/web/src/lib/knowledge/relation-target.test.ts\",\"packages/web/src/lib/knowledge/relation-target.ts\",\"packages/web/src/lib/knowledge/source-parser.ts\",\"packages/web/src/lib/knowledge/types.ts\",\"packages/web/src/lib/knowledge/wiki-api.ts\",\"packages/web/src/lib/knowledge/wiki-version-api.ts\",\"packages/web/src/lib/message-cache.test.ts\",\"packages/web/src/lib/message-cache.ts\",\"packages/web/src/lib/message-mapper.test.ts\",\"packages/web/src/lib/message-mapper.ts\",\"packages/web/src/lib/message-turns.test.ts\",\"packages/web/src/lib/message-turns.ts\",\"packages/web/src/lib/observability-query-keys.ts\",\"packages/web/src/lib/observability.test.ts\",\"packages/web/src/lib/observability.ts\",\"packages/web/src/lib/onboarding-nav.test.ts\",\"packages/web/src/lib/onboarding-nav.ts\",\"packages/web/src/lib/overflow-utils.test.ts\",\"packages/web/src/lib/overflow-utils.ts\",\"packages/web/src/lib/project-scope.test.ts\",\"packages/web/src/lib/project-scope.ts\",\"packages/web/src/lib/query-client.ts\",\"packages/web/src/lib/runtime-config.ts\",\"packages/web/src/lib/runtime-trace-insights.test.ts\",\"packages/web/src/lib/runtime-trace-insights.ts\",\"packages/web/src/lib/scheduled-task-polling.test.ts\",\"packages/web/src/lib/scheduled-task-polling.ts\",\"packages/web/src/lib/select-initial-node.test.ts\",\"packages/web/src/lib/select-initial-node.ts\",\"packages/web/src/lib/session-status-colors.test.ts\",\"packages/web/src/lib/session-status-colors.ts\",\"packages/web/src/lib/session-url-validation.test.ts\",\"packages/web/src/lib/session-url-validation.ts\",\"packages/web/src/lib/settings-copy.test.ts\",\"packages/web/src/lib/settings-copy.ts\",\"packages/web/src/lib/sidebar-progress.test.ts\",\"packages/web/src/lib/sidebar-progress.ts\",\"packages/web/src/lib/status-summary-bar-utils.ts\",\"packages/web/src/lib/types.ts\",\"packages/web/src/lib/utils.ts\",\"packages/web/src/lib/workflow-builder-canvas-status.test.ts\",\"packages/web/src/lib/workflow-builder-canvas-status.ts\",\"packages/web/src/lib/workflow-draft-content.test.ts\",\"packages/web/src/lib/workflow-draft-content.ts\",\"packages/web/src/lib/workflow-events.test.ts\",\"packages/web/src/lib/workflow-events.ts\",\"packages/web/src/lib/workflow-history-table-styles.test.ts\",\"packages/web/src/lib/workflow-history-table-styles.ts\",\"packages/web/src/lib/workflow-metadata.test.ts\",\"packages/web/src/lib/workflow-metadata.ts\",\"packages/web/src/lib/workflow-node-type.test.ts\",\"packages/web/src/lib/workflow-node-type.ts\",\"packages/web/src/lib/workflow-run-state.test.ts\",\"packages/web/src/lib/workflow-run-state.ts\",\"packages/web/src/lib/workflow-scope.test.ts\",\"packages/web/src/lib/workflow-scope.ts\",\"packages/web/src/lib/workflow-stage-mapping.ts\",\"packages/web/src/lib/workflow-usage-timing.test.ts\",\"packages/web/src/lib/workflow-usage-timing.ts\",\"packages/web/src/lib/workflow-usage-trace.test.ts\",\"packages/web/src/lib/workflow-usage-trace.ts\",\"packages/web/src/lib/workflow-utils.test.ts\",\"packages/web/src/lib/workflow-utils.ts\",\"packages/web/src/routes/ChatPage.test.tsx\",\"packages/web/src/routes/ChatPage.tsx\",\"packages/web/src/routes/ControlConsolePage.tsx\",\"packages/web/src/routes/DashboardPage.tsx\",\"packages/web/src/routes/EvaluationSlaPage.render.test.tsx\",\"packages/web/src/routes/EvaluationSlaPage.test.ts\",\"packages/web/src/routes/EvaluationSlaPage.theme.test.tsx\",\"packages/web/src/routes/LoginPage.tsx\",\"packages/web/src/routes/PersonnelUsagePage.test.tsx\",\"packages/web/src/routes/PersonnelUsagePage.tsx\",\"packages/web/src/routes/ProductSpacePage.tsx\",\"packages/web/src/routes/RealtimeEvaluationPage.tsx\",\"packages/web/src/routes/SettingsPage.tsx\",\"packages/web/src/routes/SidebarListPage.test.tsx\",\"packages/web/src/routes/SidebarListPage.tsx\",\"packages/web/src/routes/SidebarRunPage.test.tsx\",\"packages/web/src/routes/SidebarRunPage.tsx\",\"packages/web/src/routes/SidebarStartPage.test.tsx\",\"packages/web/src/routes/SidebarStartPage.tsx\",\"packages/web/src/routes/WorkflowBuilderPage.tsx\",\"packages/web/src/routes/WorkflowDetailPage.tsx\",\"packages/web/src/routes/WorkflowExecutionPage.tsx\",\"packages/web/src/routes/WorkflowSpacePage.tsx\",\"packages/web/src/routes/WorkflowUsagePage.tsx\",\"packages/web/src/routes/control-console/debug.tsx\",\"packages/web/src/routes/control-console/governance.tsx\",\"packages/web/src/routes/control-console/overview.render.test.tsx\",\"packages/web/src/routes/control-console/overview.test.ts\",\"packages/web/src/routes/control-console/overview.tsx\",\"packages/web/src/routes/control-console/runForScope.test.ts\",\"packages/web/src/routes/control-console/shared.test.ts\",\"packages/web/src/routes/control-console/shared.tsx\",\"packages/web/src/routes/control-console/topology.test.tsx\",\"packages/web/src/routes/control-console/topology.tsx\",\"packages/web/src/routes/control-console/workflows.raw-download.test.tsx\",\"packages/web/src/routes/control-console/workflows.scroll.test.tsx\",\"packages/web/src/routes/control-console/workflows.select-trace.test.tsx\",\"packages/web/src/routes/control-console/workflows.spacing.test.ts\",\"packages/web/src/routes/control-console/workflows.trace-list.test.ts\",\"packages/web/src/routes/control-console/workflows.tsx\",\"packages/web/src/routes/knowledge/AikuApiKeyDialog.render.test.tsx\",\"packages/web/src/routes/knowledge/AikuApiKeyDialog.state.test.tsx\",\"packages/web/src/routes/knowledge/AikuApiKeyDialog.test.tsx\",\"packages/web/src/routes/knowledge/AikuApiKeyDialog.tsx\",\"packages/web/src/routes/knowledge/DocsSection.tsx\",\"packages/web/src/routes/knowledge/GraphSection.tsx\",\"packages/web/src/routes/knowledge/QualitySection.tsx\",\"packages/web/src/routes/knowledge/audit/AuditSection.test.tsx\",\"packages/web/src/routes/knowledge/audit/AuditSection.tsx\",\"packages/web/src/routes/knowledge/bootstrap/ark-import.tsx\",\"packages/web/src/routes/knowledge/bootstrap/doc-upload-button.test.tsx\",\"packages/web/src/routes/knowledge/bootstrap/doc-upload-button.tsx\",\"packages/web/src/routes/knowledge/bootstrap/index.tsx\",\"packages/web/src/routes/knowledge/bootstrap/smart-fill.test.tsx\",\"packages/web/src/routes/knowledge/bootstrap/smart-fill.tsx\",\"packages/web/src/routes/knowledge/bootstrap/step-testcases.test.tsx\",\"packages/web/src/routes/knowledge/bootstrap/step-testcases.tsx\",\"packages/web/src/routes/knowledge/bootstrap/step1-browse.test.tsx\",\"packages/web/src/routes/knowledge/bootstrap/step1-browse.tsx\",\"packages/web/src/routes/knowledge/bootstrap/step1.test.tsx\",\"packages/web/src/routes/knowledge/bootstrap/step1.tsx\",\"packages/web/src/routes/knowledge/bootstrap/step2.tsx\",\"packages/web/src/routes/knowledge/bootstrap/step3.tsx\",\"packages/web/src/routes/knowledge/bootstrap/ui.test.tsx\",\"packages/web/src/routes/knowledge/bootstrap/ui.tsx\",\"packages/web/src/routes/knowledge/eval/EvalHistorySheet.test.tsx\",\"packages/web/src/routes/knowledge/eval/EvalHistorySheet.tsx\",\"packages/web/src/routes/knowledge/eval/EvalQuestionCreate.test.tsx\",\"packages/web/src/routes/knowledge/eval/EvalQuestionCreate.tsx\",\"packages/web/src/routes/knowledge/eval/EvalQuestionEdit.test.tsx\",\"packages/web/src/routes/knowledge/eval/EvalQuestionEdit.tsx\",\"packages/web/src/routes/knowledge/eval/EvalSection.test.tsx\",\"packages/web/src/routes/knowledge/eval/EvalSection.tsx\",\"packages/web/src/routes/knowledge/eval/EvalSetDetail.test.tsx\",\"packages/web/src/routes/knowledge/eval/EvalSetDetail.tsx\",\"packages/web/src/routes/knowledge/eval/EvalSetHistorySheet.test.tsx\",\"packages/web/src/routes/knowledge/eval/EvalSetHistorySheet.tsx\",\"packages/web/src/routes/knowledge/eval/EvalSetList.test.tsx\",\"packages/web/src/routes/knowledge/eval/EvalSetList.tsx\",\"packages/web/src/routes/knowledge/eval/FeedbackImportSheet.test.tsx\",\"packages/web/src/routes/knowledge/eval/FeedbackImportSheet.tsx\",\"packages/web/src/routes/knowledge/eval/dimensions.test.ts\",\"packages/web/src/routes/knowledge/eval/dimensions.ts\",\"packages/web/src/routes/knowledge/evaluation/CaseResultDrawer.test.tsx\",\"packages/web/src/routes/knowledge/evaluation/CaseResultDrawer.tsx\",\"packages/web/src/routes/knowledge/evaluation/EvaluationSection.test.tsx\",\"packages/web/src/routes/knowledge/evaluation/EvaluationSection.tsx\",\"packages/web/src/routes/knowledge/evaluation/LatestRunSummary.test.tsx\",\"packages/web/src/routes/knowledge/evaluation/LatestRunSummary.tsx\",\"packages/web/src/routes/knowledge/evaluation/RunDetail.test.tsx\",\"packages/web/src/routes/knowledge/evaluation/RunDetail.tsx\",\"packages/web/src/routes/knowledge/evaluation/RunList.test.tsx\",\"packages/web/src/routes/knowledge/evaluation/RunList.tsx\",\"packages/web/src/routes/knowledge/evaluation/RunReport.test.tsx\",\"packages/web/src/routes/knowledge/evaluation/RunReport.tsx\",\"packages/web/src/routes/knowledge/evaluation/TriggerRunDialog.test.tsx\",\"packages/web/src/routes/knowledge/evaluation/TriggerRunDialog.tsx\",\"packages/web/src/routes/knowledge/evaluation/api-hooks.ts\",\"packages/web/src/routes/knowledge/evaluation/index.ts\",\"packages/web/src/routes/knowledge/evaluation/shared.test.tsx\",\"packages/web/src/routes/knowledge/evaluation/shared.tsx\",\"packages/web/src/routes/knowledge/governance/CandidateDetailDialog.test.tsx\",\"packages/web/src/routes/knowledge/governance/CandidateDetailDialog.tsx\",\"packages/web/src/routes/knowledge/governance/CandidateReviewPanel.test.tsx\",\"packages/web/src/routes/knowledge/governance/CandidateReviewPanel.tsx\",\"packages/web/src/routes/knowledge/governance/GovernanceSection.test.tsx\",\"packages/web/src/routes/knowledge/governance/GovernanceSection.tsx\",\"packages/web/src/routes/knowledge/governance/InspectionReportDetail.test.tsx\",\"packages/web/src/routes/knowledge/governance/InspectionReportDetail.tsx\",\"packages/web/src/routes/knowledge/governance/helpers.test.tsx\",\"packages/web/src/routes/knowledge/governance/helpers.tsx\",\"packages/web/src/routes/knowledge/graph/ArchitectureViewPage.test.tsx\",\"packages/web/src/routes/knowledge/graph/ArchitectureViewPage.tsx\",\"packages/web/src/routes/knowledge/graph/EntityBrowserPage.test.tsx\",\"packages/web/src/routes/knowledge/graph/EntityBrowserPage.tsx\",\"packages/web/src/routes/knowledge/graph/GraphPage.test.tsx\",\"packages/web/src/routes/knowledge/graph/GraphPage.tsx\",\"packages/web/src/routes/knowledge/integrity/IntegritySection.render.test.tsx\",\"packages/web/src/routes/knowledge/integrity/IntegritySection.test.tsx\",\"packages/web/src/routes/knowledge/integrity/IntegritySection.tsx\",\"packages/web/src/routes/knowledge/shared.test.ts\",\"packages/web/src/routes/knowledge/shared.tsx\",\"packages/web/src/routes/knowledge/usage/UsageStatsSection.test.tsx\",\"packages/web/src/routes/knowledge/usage/UsageStatsSection.tsx\",\"packages/web/src/routes/knowledge/useKnowledgeBuildStatus.ts\",\"packages/web/src/routes/knowledge/wiki/WikiChangeBanner.tsx\",\"packages/web/src/routes/knowledge/wiki/WikiComposePane.test.tsx\",\"packages/web/src/routes/knowledge/wiki/WikiComposePane.tsx\",\"packages/web/src/routes/knowledge/wiki/WikiDiffView.tsx\",\"packages/web/src/routes/knowledge/wiki/WikiDocPane.test.tsx\",\"packages/web/src/routes/knowledge/wiki/WikiDocPane.tsx\",\"packages/web/src/routes/knowledge/wiki/WikiHistoryDialog.tsx\",\"packages/web/src/routes/knowledge/wiki/WikiPendingPane.test.tsx\",\"packages/web/src/routes/knowledge/wiki/WikiPendingPane.tsx\",\"packages/web/src/routes/knowledge/wiki/WikiSection.test.tsx\",\"packages/web/src/routes/knowledge/wiki/WikiSection.tsx\",\"packages/web/src/routes/knowledge/wiki/WikiTree.test.tsx\",\"packages/web/src/routes/knowledge/wiki/WikiTree.tsx\",\"packages/web/src/routes/realtime-evaluation/RealtimeEvaluationChrome.tsx\",\"packages/web/src/routes/realtime-evaluation/RealtimeEvaluationContent.tsx\",\"packages/web/src/routes/realtime-evaluation/WorkflowUsageSection.tsx\",\"packages/web/src/routes/realtime-evaluation/evaluation-view-model.test.ts\",\"packages/web/src/routes/realtime-evaluation/evaluation-view-model.ts\",\"packages/web/src/routes/realtime-evaluation/shared.test.ts\",\"packages/web/src/routes/realtime-evaluation/shared.tsx\",\"packages/web/src/routes/realtime-evaluation/useRealtimeEvaluationPageState.test.tsx\",\"packages/web/src/routes/realtime-evaluation/useRealtimeEvaluationPageState.ts\",\"packages/web/src/routes/realtime-evaluation/workflow-usage-metrics.test.ts\",\"packages/web/src/routes/sidebar-common.tsx\",\"packages/web/src/routes/ui-replay/UiReplayCenterPage.tsx\",\"packages/web/src/routes/ui-replay/browserReplay.ts\",\"packages/web/src/routes/ui-replay/codegen.ts\",\"packages/web/src/routes/ui-replay/components.tsx\",\"packages/web/src/routes/ui-replay/constants.ts\",\"packages/web/src/routes/ui-replay/format.ts\",\"packages/web/src/routes/ui-replay/types.ts\",\"packages/web/src/routes/ui-replay/useIframeRecorder.ts\",\"packages/web/src/stores/auth-store.test.ts\",\"packages/web/src/stores/product-space-store.test.ts\",\"packages/web/src/stores/product-space-store.ts\",\"packages/web/src/stores/sidebar-store.ts\",\"packages/web/src/stores/workflow-space-store.test.ts\",\"packages/web/src/stores/workflow-space-store.ts\",\"packages/web/src/stores/workflow-store-loop-back-hydrate.test.ts\",\"packages/web/src/stores/workflow-store-loop-back.test.ts\",\"packages/web/src/stores/workflow-store.test.ts\",\"packages/web/src/stores/workflow-store.ts\",\"packages/web/tsconfig.json\",\"packages/web/vite.config.ts\"]},{\"name\":\"Other \u2014 workflows\",\"slug\":\"other-workflows\",\"files\":[\"packages/workflows/package.json\",\"packages/workflows/src/artifact-publisher.test.ts\",\"packages/workflows/src/artifact-publisher.ts\",\"packages/workflows/src/combo-codebases.test.ts\",\"packages/workflows/src/combo-codebases.ts\",\"packages/workflows/src/command-discovery.test.ts\",\"packages/workflows/src/command-discovery.ts\",\"packages/workflows/src/command-validation.test.ts\",\"packages/workflows/src/command-validation.ts\",\"packages/workflows/src/condition-evaluator.test.ts\",\"packages/workflows/src/condition-evaluator.ts\",\"packages/workflows/src/dag-executor-loop-back-resume.test.ts\",\"packages/workflows/src/dag-executor-loop-back-review.test.ts\",\"packages/workflows/src/dag-executor-loop-back.test.ts\",\"packages/workflows/src/dag-executor.test.ts\",\"packages/workflows/src/dag-executor.ts\",\"packages/workflows/src/defaults/bundled-defaults.test.ts\",\"packages/workflows/src/defaults/bundled-defaults.ts\",\"packages/workflows/src/deps.ts\",\"packages/workflows/src/event-emitter.test.ts\",\"packages/workflows/src/event-emitter.ts\",\"packages/workflows/src/executor-preamble.test.ts\",\"packages/workflows/src/executor-shared.test.ts\",\"packages/workflows/src/executor-shared.ts\",\"packages/workflows/src/executor.model-resolution.test.ts\",\"packages/workflows/src/executor.test.ts\",\"packages/workflows/src/executor.ts\",\"packages/workflows/src/extract-input-request.test.ts\",\"packages/workflows/src/hooks.test.ts\",\"packages/workflows/src/knowledge-governor.test.ts\",\"packages/workflows/src/knowledge-governor.ts\",\"packages/workflows/src/knowledge-mode.test.ts\",\"packages/workflows/src/knowledge-mode.ts\",\"packages/workflows/src/knowledge-observability.test.ts\",\"packages/workflows/src/knowledge-observability.ts\",\"packages/workflows/src/load-command-prompt.test.ts\",\"packages/workflows/src/loader-loop-back.test.ts\",\"packages/workflows/src/loader.test.ts\",\"packages/workflows/src/loader.ts\",\"packages/workflows/src/logger.test.ts\",\"packages/workflows/src/logger.ts\",\"packages/workflows/src/loop-back-e2e.test.ts\",\"packages/workflows/src/loop-back-interval.test.ts\",\"packages/workflows/src/loop-back-interval.ts\",\"packages/workflows/src/router.test.ts\",\"packages/workflows/src/router.ts\",\"packages/workflows/src/runtime-check.test.ts\",\"packages/workflows/src/schemas.test.ts\",\"packages/workflows/src/schemas/dag-node.ts\",\"packages/workflows/src/schemas/hooks.ts\",\"packages/workflows/src/schemas/index.ts\",\"packages/workflows/src/schemas/input-request.test.ts\",\"packages/workflows/src/schemas/input-request.ts\",\"packages/workflows/src/schemas/loop-back.test.ts\",\"packages/workflows/src/schemas/loop-back.ts\",\"packages/workflows/src/schemas/loop-metrics.ts\",\"packages/workflows/src/schemas/loop.ts\",\"packages/workflows/src/schemas/retry.ts\",\"packages/workflows/src/schemas/workflow-run-loop-back.test.ts\",\"packages/workflows/src/schemas/workflow-run.ts\",\"packages/workflows/src/schemas/workflow.test.ts\",\"packages/workflows/src/schemas/workflow.ts\",\"packages/workflows/src/script-discovery.test.ts\",\"packages/workflows/src/script-discovery.ts\",\"packages/workflows/src/script-node-deps.test.ts\",\"packages/workflows/src/skill-installer.test.ts\",\"packages/workflows/src/skill-installer.ts\",\"packages/workflows/src/store.ts\",\"packages/workflows/src/test-utils.ts\",\"packages/workflows/src/utils/duration.test.ts\",\"packages/workflows/src/utils/duration.ts\",\"packages/workflows/src/utils/idle-timeout.test.ts\",\"packages/workflows/src/utils/idle-timeout.ts\",\"packages/workflows/src/utils/tool-formatter.test.ts\",\"packages/workflows/src/utils/tool-formatter.ts\",\"packages/workflows/src/utils/variable-substitution.test.ts\",\"packages/workflows/src/utils/variable-substitution.ts\",\"packages/workflows/src/validation-parser.test.ts\",\"packages/workflows/src/validation-parser.ts\",\"packages/workflows/src/validator.test.ts\",\"packages/workflows/src/validator.ts\",\"packages/workflows/src/version-snapshot.test.ts\",\"packages/workflows/src/version-snapshot.ts\",\"packages/workflows/src/workflow-discovery.ts\",\"packages/workflows/tsconfig.json\"]},{\"name\":\"Other \u2014 scripts\",\"slug\":\"other-scripts\",\"files\":[\"scripts/build-binaries.sh\",\"scripts/build.sh\",\"scripts/check-aiflow-pytest-scenarios.py\",\"scripts/check-bundled-skill.ts\",\"scripts/check-sla-reliability.sql\",\"scripts/checksums.sh\",\"scripts/clean-dev-branches.sh\",\"scripts/coverage-gate.test.ts\",\"scripts/coverage-gate.ts\",\"scripts/cr-classify.sh\",\"scripts/delete-dev-workflows.sql\",\"scripts/gen-workflow-syntax-doc.test.ts\",\"scripts/gen-workflow-syntax-doc.ts\",\"scripts/generate-api-inventory.test.ts\",\"scripts/generate-api-inventory.ts\",\"scripts/generate-bundled-defaults.ts\",\"scripts/gitnexus-init.sh\",\"scripts/install.ps1\",\"scripts/install.sh\",\"scripts/install_aiflow.sh\",\"scripts/ipipe-cr.sh\",\"scripts/quality-report.ts\",\"scripts/ragas-e2e-stress.ts\",\"scripts/run-aiflow-scenario-cases.sh\",\"scripts/run-coverage.ts\",\"scripts/security-secrets.sh\",\"scripts/select-affected.ts\",\"scripts/sync-versions.sh\",\"scripts/test-sandbox-file-ops.ts\",\"scripts/test-uic-search.ts\",\"scripts/trigger-workflow.sh\",\"scripts/tsconfig.json\",\"scripts/ui-replay-report.ts\",\"scripts/ui-replay-scaffold.ts\",\"scripts/update-homebrew.sh\",\"scripts/upload-aiflow-bos.sh\",\"scripts/validate-setup.sh\",\"scripts/verify-space-commands.ts\"]},{\"name\":\"Other \u2014 db-governance\",\"slug\":\"other-db-governance\",\"files\":[\"scripts/db-governance/00_preflight.sql\",\"scripts/db-governance/01_shrink_observability_events.sql\",\"scripts/db-governance/02_shrink_trace_events.sql\",\"scripts/db-governance/03_shrink_workflow_events.sql\",\"scripts/db-governance/04_verify_after_shrink.sql\",\"scripts/db-governance/05_drop_old_tables.sql\",\"scripts/db-governance/10_rolling_cleanup.sql\",\"scripts/db-governance/README.md\"]},{\"name\":\"Other \u2014 deepeval-evaluator\",\"slug\":\"other-deepeval-evaluator\",\"files\":[\"services/deepeval-evaluator/Dockerfile\",\"services/deepeval-evaluator/README.md\",\"services/deepeval-evaluator/requirements.txt\"]},{\"name\":\"Other \u2014 ragas-evaluator\",\"slug\":\"other-ragas-evaluator\",\"files\":[\"services/ragas-evaluator/Dockerfile\",\"services/ragas-evaluator/README.md\",\"services/ragas-evaluator/requirements.txt\"]},{\"name\":\"Other \u2014 todos.md\",\"slug\":\"other-todos-md\",\"files\":[\"todos.md\"]},{\"name\":\"Other \u2014 tsconfig.json\",\"slug\":\"other-tsconfig-json\",\"files\":[\"tsconfig.json\"]}]}];\nvar META = {\"fromCommit\":\"2140beaeb29b0d9bc19f7c9569a759a820c12769\",\"generatedAt\":\"2026-08-04T08:41:18.959Z\",\"model\":\"gpt-5.6-terra\",\"moduleFiles\":{\"Authentication and Identity\":[\"packages/server/src/routes/auth.ts\",\"packages/server/src/routes/schemas/auth.schemas.ts\",\"packages/web/src/lib/auth-guard.tsx\",\"packages/web/src/stores/auth-store.ts\",\"auth-service/server.js\"],\"Chat and Platform Adapters\":[\"packages/adapters/src/utils/message-splitting.ts\",\"packages/cli/src/adapters/cli-adapter.ts\",\"packages/server/src/adapters/web.ts\"],\"CLI and Developer Tools\":[\"homebrew/archon.rb\"],\"Workflow Orchestration and Scheduling\":[\"packages/core/src/services/cleanup-service.ts\",\"packages/core/src/services/codebase-restore-service.ts\",\"packages/core/src/services/title-generator.ts\",\"packages/server/src/services/scheduled-task-deps.ts\",\"packages/server/src/services/workflow-run-actions.ts\",\"packages/server/src/services/workflow-run-auto-exporter.ts\",\"packages/server/src/services/workflow-run-exporter.ts\",\"packages/server/src/services/workflow-notification-listener.ts\",\"packages/server/src/workers/sla-infoflow-worker.ts\"],\"API Server and Integrations\":[\"packages/server/src/index.ts\",\"packages/server/src/gitcase-client.ts\",\"packages/server/src/bos-client.ts\",\"packages/server/src/runtime-config.ts\",\"packages/server/src/services/infoflow-sender.ts\",\"packages/server/src/services/infoflow-webhook.ts\",\"packages/server/src/services/workflow-run-knowledge-sync-dispatcher.ts\",\"packages/server/src/services/sla-infoflow-notifier.ts\",\"packages/server/src/sync-bundled-commands.ts\",\"packages/server/src/sync-bundled-workflows.ts\",\"packages/server/src/sync-project-workflows.ts\",\"packages/server/src/sync-user-workflows.ts\"],\"Observability, Runtime Tracing, and Evaluation\":[\"packages/core/src/services/evolution-service.ts\",\"packages/core/src/services/failure-attribution-service.ts\",\"packages/core/src/services/golden-sample-candidate-service.ts\",\"packages/core/src/services/quality-gate-service.ts\",\"packages/core/src/services/runtime-intelligence.ts\",\"packages/server/src/services/evolution-replay.ts\",\"packages/server/src/services/workflow-access.ts\",\"packages/server/src/routes/api/evaluations.ts\",\"packages/server/src/routes/api/evolution.ts\",\"packages/server/src/routes/api/observability.ts\",\"packages/server/src/routes/api/runtime-traces.ts\",\"packages/server/src/routes/api/personnel-usage.ts\",\"packages/web/src/routes/EvaluationSlaPage.tsx\",\"packages/web/src/routes/DiagnosticsPage.tsx\",\"services/deepeval-evaluator/app.py\",\"services/ragas-evaluator/app.py\"],\"Observability, Runtime Tracing, and Evaluation \u2014 core\":[\"packages/core/src/services/evolution-service.ts\",\"packages/core/src/services/failure-attribution-service.ts\",\"packages/core/src/services/golden-sample-candidate-service.ts\",\"packages/core/src/services/quality-gate-service.ts\",\"packages/core/src/services/runtime-intelligence.ts\"],\"Observability, Runtime Tracing, and Evaluation \u2014 server\":[\"packages/server/src/services/evolution-replay.ts\",\"packages/server/src/services/workflow-access.ts\",\"packages/server/src/routes/api/evaluations.ts\",\"packages/server/src/routes/api/evolution.ts\",\"packages/server/src/routes/api/observability.ts\",\"packages/server/src/routes/api/runtime-traces.ts\",\"packages/server/src/routes/api/personnel-usage.ts\"],\"Observability, Runtime Tracing, and Evaluation \u2014 web\":[\"packages/web/src/routes/EvaluationSlaPage.tsx\",\"packages/web/src/routes/DiagnosticsPage.tsx\"],\"Observability, Runtime Tracing, and Evaluation \u2014 deepeval-evaluator\":[\"services/deepeval-evaluator/app.py\"],\"Observability, Runtime Tracing, and Evaluation \u2014 ragas-evaluator\":[\"services/ragas-evaluator/app.py\"],\"Knowledge Management\":[\"packages/core/src/services/evaluation-knowledge-artifact-service.ts\",\"packages/server/src/routes/knowledge-router.ts\",\"packages/web/src/routes/KnowledgePage.tsx\"],\"Web Application UI\":[\"packages/web/src/App.tsx\",\"packages/web/src/main.tsx\"],\"Developer Documentation and Operational Scripts\":[\"assets/ducc-skills/get-ugate-token/getUgateToken.py\",\"docs/parallel-study/analyze_parallelism.py\"],\"Other\":[\"AGENTS.md\",\"CLAUDE.md\",\"Caddyfile.example\",\"DESIGN.md\",\"Dockerfile\",\"Dockerfile.base\",\"Dockerfile.ci\",\"Dockerfile.user.example\",\"Makefile\",\"README.md\",\"assets/ducc-skills/cnap/SKILL.md\",\"assets/ducc-skills/cnap/references/baidu-internal-network.md\",\"assets/ducc-skills/cnap/references/cases.md\",\"assets/ducc-skills/cnap/references/cnap-accounts.md\",\"assets/ducc-skills/cnap/references/cnap-applications.md\",\"assets/ducc-skills/cnap/references/cnap-clusters.md\",\"assets/ducc-skills/cnap/references/cnap-cpu-units.md\",\"assets/ducc-skills/cnap/references/cnap-datadist.md\",\"assets/ducc-skills/cnap/references/cnap-environ-vars.md\",\"assets/ducc-skills/cnap/references/cnap-environments.md\",\"assets/ducc-skills/cnap/references/cnap-log-collection.md\",\"assets/ducc-skills/cnap/references/cnap-permissions.md\",\"assets/ducc-skills/cnap/references/cnap-runtime-config.md\",\"assets/ducc-skills/cnap/references/cnap-service-discovery.md\",\"assets/ducc-skills/cnap/references/deploy-babysitter.md\",\"assets/ducc-skills/cnap/references/deploy-troubleshoot.md\",\"assets/ducc-skills/cnap/references/icode.md\",\"assets/ducc-skills/cnap/references/install.md\",\"assets/ducc-skills/cnap/references/iregistry.md\",\"assets/ducc-skills/cnap/references/kubectl.md\",\"assets/ducc-skills/cnap/references/login.md\",\"assets/ducc-skills/cnap/references/oncall.md\",\"assets/ducc-skills/get-ugate-token/SKILL.md\",\"auth-service/Dockerfile\",\"auth-service/package.json\",\"auth-service/test.js\",\"auto-heal.txt\",\"bunfig.coverage.toml\",\"bunfig.toml\",\"ci.yml\",\"deploy/Dockerfile.user.example\",\"deploy/cloud-init.yml\",\"deploy/docker-compose.override.example.yml\",\"deploy/docker-compose.yml\",\"docker-compose.override.example.yml\",\"docker-compose.yml\",\"docker-entrypoint.sh\",\"docker/e2e-dev/Dockerfile\",\"docker/e2e-dev/Dockerfile.base\",\"docker/e2e-dev/init-claude-workspace.sh\",\"docker/e2e-dev/start_comate_server.sh\",\"docs/ai-workflow-builder-design.md\",\"docs/aiflow-skill-design.md\",\"docs/architecture.md\",\"docs/authoring-commands.md\",\"docs/authoring-workflows.md\",\"docs/bundled-workflow-authoring.md\",\"docs/cli-reference.md\",\"docs/cnap-api.md\",\"docs/cr-env.md\",\"docs/cr-rules-code.md\",\"docs/cr-rules-workflow.md\",\"docs/cr-rules.md\",\"docs/document-drawer-design.md\",\"docs/gitcase.md\",\"docs/infoflow-notification-status.md\",\"docs/infoflow-workflow-notification.md\",\"docs/issues.json\",\"docs/knowledge-injection-design.md\",\"docs/loop-back-practice.md\",\"docs/marketing-flow-code-review-redesign.md\",\"docs/marketing-flow-tech-design-step3.md\",\"docs/online-trace-eval-demo-guide.md\",\"docs/online-trace-eval-migration-plan.md\",\"docs/plan-implement-review-loop-parallel.md\",\"docs/product-space-design.md\",\"docs/remove-bundled-system-workflow.md\",\"docs/scheduled-task-practice.md\",\"docs/sla-infoflow-operations.md\",\"docs/standard-dev-flow-artifact-governance-design.md\",\"docs/standard-dev-flow-diagram.md\",\"docs/test-issues.md\",\"docs/ugate-token-adaptation.md\",\"docs/uic-api.md\",\"docs/user-isolation-design.md\",\"docs/uuap-auth.md\",\"docs/workflow-backend-api-chain-api.md\",\"docs/workflow-backend-api-chain-design.md\",\"docs/workflow-loop-back-design.md\",\"docs/workflow-product-space-design.md\",\"docs/workflow-system-analysis.md\",\"docs/workflow-vs-claude-code-comparison.md\",\"docs/workflow-yaml-storage.md\",\"docs/knowledge/baidu-pipeline-docker-build.md\",\"docs/knowledge/kg-self-seal.json\",\"docs/mock/\u5de5\u4f5c\u6d41\u4ea7\u54c1\u7a7a\u95f4\u6807\u7b7e-issue.json\",\"docs/mock/\u5de5\u4f5c\u6d41\u5bf9\u8bdd\u6846\u652f\u6301\u6362\u884c-issue.json\",\"docs/parallel-study/sample-01-sidebar-pause/issues.json\",\"docs/parallel-study/sample-02-combo-edit/issues.json\",\"docs/parallel-study/sample-03-command-check/issues.json\",\"docs/schemathesis-reports/2026-06-04-20-05.json\",\"docs/schemathesis-reports/2026-06-04-20-05.md\",\"docs/superpowers/plans/2026-05-07-icode-codebase-clone.md\",\"docs/superpowers/plans/2026-05-07-uuap-auth.md\",\"docs/superpowers/plans/2026-05-08-icode-clone-icode-cli.md\",\"docs/superpowers/plans/2026-05-12-config-warning-banner.md\",\"docs/superpowers/plans/2026-05-12-oneapi-token.md\",\"docs/superpowers/plans/2026-05-12-setup-wizard-modal.md\",\"docs/superpowers/plans/2026-05-14-sandbox-session-binding.md\",\"docs/superpowers/plans/2026-05-14-workflow-skill-binding.md\",\"docs/superpowers/plans/2026-05-15-comate-auth-token-user-config.md\",\"docs/superpowers/plans/2026-05-18-bug-fix-flow.md\",\"docs/superpowers/plans/2026-05-19-feature-dev-flow.md\",\"docs/superpowers/plans/2026-05-19-superpowers-full-dev-flow.md\",\"docs/superpowers/plans/2026-05-20-bug-fix-flow-clarify.md\",\"docs/superpowers/plans/2026-05-21-ipipe-ducc-cr.md\",\"docs/superpowers/plans/2026-05-21-sandbox-combo-batch-clone.md\",\"docs/superpowers/plans/2026-05-22-fix-gen-ut-uuid-error.md\",\"docs/superpowers/plans/2026-05-22-sandbox-artifacts-dir-simplify.md\",\"docs/superpowers/plans/2026-05-25-gen-ut-workflow-upgrade.md\",\"docs/superpowers/plans/2026-05-25-smart-cr-classification.md\",\"docs/superpowers/plans/2026-05-25-workflow-bash-node-sandbox.md\",\"docs/superpowers/plans/2026-05-26-dev-loop-unit-test-gate.md\",\"docs/superpowers/plans/2026-05-26-metrics-reporter.md\",\"docs/superpowers/plans/2026-05-26-sandbox-file-upload.md\",\"docs/superpowers/plans/2026-05-27-loop-approval-node-started-event.md\",\"docs/superpowers/plans/2026-05-30-sandbox-auto-renew.md\",\"docs/superpowers/plans/2026-06-02-e2e-flow-enhancement.md\",\"docs/superpowers/plans/2026-06-02-impact-analysis-command.md\",\"docs/superpowers/plans/2026-06-03-e2e-flow-cnap-deploy-refactor.md\",\"docs/superpowers/plans/2026-06-04-sandbox-release-on-cancel-abandon.md\",\"docs/superpowers/plans/2026-06-04-schemathesis-integration.md\",\"docs/superpowers/plans/2026-06-09-subworkflow.md\",\"docs/superpowers/plans/2026-06-10-workflow-user-pause.md\",\"docs/superpowers/plans/2026-06-11-concurrent-pause-context.md\",\"docs/superpowers/plans/2026-06-12-auto-publish-node-artifacts.md\",\"docs/superpowers/plans/2026-06-12-auto-publish-readback-refactor.md\",\"docs/superpowers/plans/2026-06-13-ai-workflow-builder.md\",\"docs/superpowers/plans/2026-06-16-breakpoint-retry-clarify.md\",\"docs/superpowers/plans/2026-06-16-chat-page-deliverables-grouping-optimize-workflow.md\",\"docs/superpowers/plans/2026-06-16-inline-composer-context-controls.md\",\"docs/superpowers/plans/2026-06-17-aiflow-optimize-existing-workflow.md\",\"docs/superpowers/plans/2026-06-18-aiflow-ku-doc-recognition.md\",\"docs/superpowers/plans/2026-06-18-onboarding-run-to-new-chat.md\",\"docs/superpowers/plans/2026-06-18-require-project-on-new-conversation.md\",\"docs/superpowers/plans/2026-06-22-commit-time-metrics-reporting.md\",\"docs/superpowers/plans/2026-06-22-workflow-draft-staging.md\",\"docs/superpowers/plans/2026-06-23-aiflow-skill-integration.md\",\"docs/superpowers/plans/2026-06-24-interactive-loop-structured-input.md\",\"docs/superpowers/plans/2026-06-24-sandbox-heartbeat-renew.md\",\"docs/superpowers/plans/2026-06-25-dag-loop-back.md\",\"docs/superpowers/plans/2026-06-26-all-workflow-infoflow-notification.md\",\"docs/superpowers/plans/2026-06-30-breakpoint-retry-move-to-statusbar.md\",\"docs/superpowers/plans/2026-06-30-marketing-flow-test-loop-back.md\",\"docs/superpowers/plans/2026-06-30-workflow-model-dropdown.md\",\"docs/superpowers/plans/2026-07-01-aiflow-loop-back-authoring.md\",\"docs/superpowers/plans/2026-07-02-builder-dag-node-run-status.md\",\"docs/superpowers/plans/2026-07-02-command-market-and-management.md\",\"docs/superpowers/plans/2026-07-02-marketing-flow-merge-to-dev.md\",\"docs/superpowers/plans/2026-07-03-scheduled-tasks.md\",\"docs/superpowers/plans/2026-07-06-command-discovery-mirror-workflow.md\",\"docs/superpowers/plans/2026-07-06-infoflow-robot-api-and-reply.md\",\"docs/superpowers/plans/2026-07-07-backfill-forked-workflow-commands.md\",\"docs/superpowers/plans/2026-07-07-conversation-workflow-scope-badge.md\",\"docs/superpowers/plans/2026-07-07-scheduled-task-ducc-callback.md\",\"docs/superpowers/plans/2026-07-07-workflow-draft-preview-run.md\",\"docs/superpowers/plans/2026-07-08-workflow-version-updated-at.md\",\"docs/superpowers/plans/2026-07-09-infoflow-reply-session-identifier.md\",\"docs/superpowers/plans/2026-07-09-infoflow-sidebar-part1-bubble-card.md\",\"docs/superpowers/plans/2026-07-09-infoflow-sidebar-part2-oauth.md\",\"docs/superpowers/plans/2026-07-09-infoflow-sidebar-part3-web-page.md\",\"docs/superpowers/plans/2026-07-10-scheduled-tasks-space-scoped.md\",\"docs/superpowers/plans/2026-07-13-aiflow-new-conversation-unpublished-draft-guard.md\",\"docs/superpowers/plans/2026-07-13-session-deliverables-enhancements.md\",\"docs/superpowers/plans/2026-07-14-on-reject-session-resume.md\",\"docs/superpowers/plans/2026-07-14-sidebar-sse-realtime.md\",\"docs/superpowers/plans/2026-07-15-aiflow-cli-skill.md\",\"docs/superpowers/plans/2026-07-15-anthropic-workflow-to-aiflow-convert.md\",\"docs/superpowers/plans/2026-07-15-artifact-drawer-auto-refresh.md\",\"docs/superpowers/plans/2026-07-16-infoflow-bubble-session-entry.md\",\"docs/superpowers/plans/2026-07-16-infoflow-sidebar-artifact-panel.md\",\"docs/superpowers/plans/2026-07-17-workflow-authoring-space-command.md\",\"docs/superpowers/plans/2026-07-18-platform-only-cli.md\",\"docs/superpowers/plans/2026-07-20-command-delete.md\",\"docs/superpowers/plans/2026-07-21-aiflow-skill-platform-cli.md\",\"docs/superpowers/plans/2026-07-21-anthropic-workflow-package-convert.md\",\"docs/superpowers/plans/2026-07-21-infoflow-abandon-workflow-button.md\",\"docs/superpowers/plans/2026-07-22-standard-dev-flow.md\",\"docs/superpowers/plans/2026-07-23-workflow-command-source-from-db.md\",\"docs/superpowers/plans/2026-07-24-downstream-refresh-upstream-artifacts.md\",\"docs/superpowers/plans/2026-07-27-loop-back-human-review.md\",\"docs/superpowers/plans/2026-07-27-online-event-data-governance.md\",\"docs/superpowers/plans/2026-07-27-workflow-custom-sandbox-image.md\",\"docs/superpowers/plans/2026-07-29-combo-multi-codebase-workflow.md\",\"docs/superpowers/plans/2026-07-29-workflow-restart-recovery.md\",\"docs/superpowers/plans/2026-07-30-conversation-turn-collapse.md\",\"docs/superpowers/plans/2026-07-30-session-task-model-switch.md\",\"docs/superpowers/plans/2026-07-31-try-it-list.md\",\"docs/superpowers/specs/2026-05-07-icode-codebase-clone-design.md\",\"docs/superpowers/specs/2026-05-07-uuap-auth-design.md\",\"docs/superpowers/specs/2026-05-12-config-warning-banner-design.md\",\"docs/superpowers/specs/2026-05-12-oneapi-token-design.md\",\"docs/superpowers/specs/2026-05-12-setup-wizard-modal-design.md\",\"docs/superpowers/specs/2026-05-14-sandbox-session-binding-design.md\",\"docs/superpowers/specs/2026-05-14-workflow-skill-binding-design.md\",\"docs/superpowers/specs/2026-05-15-comate-auth-token-user-config-design.md\",\"docs/superpowers/specs/2026-05-18-bug-fix-flow-design.md\",\"docs/superpowers/specs/2026-05-19-feature-dev-flow-design.md\",\"docs/superpowers/specs/2026-05-19-superpowers-full-dev-flow-design.md\",\"docs/superpowers/specs/2026-05-20-bug-fix-flow-clarify-design.md\",\"docs/superpowers/specs/2026-05-21-ipipe-ducc-cr-design.md\",\"docs/superpowers/specs/2026-05-22-sandbox-artifacts-dir-simplify-design.md\",\"docs/superpowers/specs/2026-05-25-gen-ut-workflow-design.md\",\"docs/superpowers/specs/2026-05-25-smart-cr-classification-design.md\",\"docs/superpowers/specs/2026-05-26-bun-in-e2e-dev-image-design.md\",\"docs/superpowers/specs/2026-05-26-dev-loop-unit-test-gate-design.md\",\"docs/superpowers/specs/2026-05-26-metrics-reporter-design.md\",\"docs/superpowers/specs/2026-05-26-sandbox-file-upload-design.md\",\"docs/superpowers/specs/2026-05-30-sandbox-auto-renew-design.md\",\"docs/superpowers/specs/2026-06-02-impact-analysis-command-design.md\",\"docs/superpowers/specs/2026-06-04-sandbox-release-on-cancel-abandon-design.md\",\"docs/superpowers/specs/2026-06-04-schemathesis-integration-design.md\",\"docs/superpowers/specs/2026-06-09-product-space-global-filter-design.md\",\"docs/superpowers/specs/2026-06-09-subworkflow-design.md\",\"docs/superpowers/specs/2026-06-10-workflow-user-pause-design.md\",\"docs/superpowers/specs/2026-06-11-concurrent-pause-context-design.md\",\"docs/superpowers/specs/2026-06-11-workflow-product-space-refactor-design.md\",\"docs/superpowers/specs/2026-06-12-auto-publish-node-artifacts-design.md\",\"docs/superpowers/specs/2026-06-13-ai-workflow-builder-design.md\",\"docs/superpowers/specs/2026-06-16-breakpoint-retry-clarify-ai-nodes-only-design.md\",\"docs/superpowers/specs/2026-06-16-breakpoint-retry-clarify-design.md\",\"docs/superpowers/specs/2026-06-16-chat-page-deliverables-grouping-optimize-workflow-design.md\",\"docs/superpowers/specs/2026-06-16-onboarding-wizard-design.md\",\"docs/superpowers/specs/2026-06-16-workflow-builder-run-flow-design.md\",\"docs/superpowers/specs/2026-06-17-aiflow-optimize-existing-workflow-design.md\",\"docs/superpowers/specs/2026-06-18-aiflow-ku-doc-recognition-design.md\",\"docs/superpowers/specs/2026-06-18-onboarding-run-to-new-chat-design.md\",\"docs/superpowers/specs/2026-06-18-require-project-on-new-conversation-design.md\",\"docs/superpowers/specs/2026-06-22-commit-time-metrics-reporting-design.md\",\"docs/superpowers/specs/2026-06-22-workflow-draft-staging-design.md\",\"docs/superpowers/specs/2026-06-23-aiflow-skill-integration-design.md\",\"docs/superpowers/specs/2026-06-23-interactive-loop-structured-input-design.md\",\"docs/superpowers/specs/2026-06-24-interactive-loop-structured-input-design.md\",\"docs/superpowers/specs/2026-06-24-sandbox-heartbeat-renew-design.md\",\"docs/superpowers/specs/2026-06-25-codebase-branch-list-design.md\",\"docs/superpowers/specs/2026-06-25-dag-loop-back-design.md\",\"docs/superpowers/specs/2026-06-26-all-workflow-infoflow-notification-design.md\",\"docs/superpowers/specs/2026-06-30-breakpoint-retry-move-to-statusbar-design.md\",\"docs/superpowers/specs/2026-06-30-marketing-flow-dynamic-branch-design.md\",\"docs/superpowers/specs/2026-06-30-marketing-flow-test-loop-back-design.md\",\"docs/superpowers/specs/2026-06-30-space-private-command-db-design.md\",\"docs/superpowers/specs/2026-06-30-workflow-model-dropdown-design.md\",\"docs/superpowers/specs/2026-07-01-aiflow-loop-back-authoring-design.md\",\"docs/superpowers/specs/2026-07-02-builder-dag-node-run-status-design.md\",\"docs/superpowers/specs/2026-07-02-command-market-and-management-design.md\",\"docs/superpowers/specs/2026-07-02-marketing-flow-merge-to-dev-design.md\",\"docs/superpowers/specs/2026-07-03-scheduled-tasks-design.md\",\"docs/superpowers/specs/2026-07-06-infoflow-robot-api-and-reply-design.md\",\"docs/superpowers/specs/2026-07-07-backfill-forked-workflow-commands-design.md\",\"docs/superpowers/specs/2026-07-07-conversation-workflow-scope-badge-design.md\",\"docs/superpowers/specs/2026-07-07-scheduled-task-ducc-callback-design.md\",\"docs/superpowers/specs/2026-07-07-workflow-draft-preview-run-design.md\",\"docs/superpowers/specs/2026-07-08-workflow-version-updated-at-design.md\",\"docs/superpowers/specs/2026-07-09-infoflow-reply-session-identifier-design.md\",\"docs/superpowers/specs/2026-07-09-infoflow-sidebar-run-detail-design.md\",\"docs/superpowers/specs/2026-07-10-scheduled-tasks-space-scoped-design.md\",\"docs/superpowers/specs/2026-07-11-marketing-flow-clarify-design.md\",\"docs/superpowers/specs/2026-07-13-aiflow-new-conversation-unpublished-draft-guard-design.md\",\"docs/superpowers/specs/2026-07-13-session-deliverables-enhancements-design.md\",\"docs/superpowers/specs/2026-07-14-on-reject-session-resume-design.md\",\"docs/superpowers/specs/2026-07-14-sidebar-sse-realtime-design.md\",\"docs/superpowers/specs/2026-07-15-aiflow-cli-skill-design.md\",\"docs/superpowers/specs/2026-07-15-anthropic-workflow-to-aiflow-convert-design.md\",\"docs/superpowers/specs/2026-07-15-artifact-drawer-auto-refresh-design.md\",\"docs/superpowers/specs/2026-07-16-infoflow-bubble-session-entry-design.md\",\"docs/superpowers/specs/2026-07-16-infoflow-sidebar-artifact-panel-design.md\",\"docs/superpowers/specs/2026-07-17-workflow-authoring-space-command-design.md\",\"docs/superpowers/specs/2026-07-18-platform-only-cli-design.md\",\"docs/superpowers/specs/2026-07-20-command-delete-design.md\",\"docs/superpowers/specs/2026-07-21-aiflow-skill-platform-cli-design.md\",\"docs/superpowers/specs/2026-07-21-anthropic-workflow-package-convert-design.md\",\"docs/superpowers/specs/2026-07-21-infoflow-abandon-workflow-button-design.md\",\"docs/superpowers/specs/2026-07-22-standard-dev-flow-design.md\",\"docs/superpowers/specs/2026-07-23-workflow-command-source-from-db-design.md\",\"docs/superpowers/specs/2026-07-27-loop-back-human-review-design.md\",\"docs/superpowers/specs/2026-07-27-online-event-data-governance-design.md\",\"docs/superpowers/specs/2026-07-27-workflow-custom-sandbox-image-design.md\",\"docs/superpowers/specs/2026-07-29-combo-multi-codebase-workflow-design.md\",\"docs/superpowers/specs/2026-07-29-workflow-restart-recovery-design.md\",\"docs/superpowers/specs/2026-07-30-conversation-turn-collapse-design.md\",\"docs/superpowers/specs/2026-07-30-session-task-model-switch-design.md\",\"docs/superpowers/specs/2026-07-31-try-it-list-design.md\",\"docs/superpowers/test-plans/2026-06-23-workflow-draft-staging-test-plan.md\",\"docs/superpowers/test-plans/db-inspect-guide.md\",\"docs/testing/api-test-gate.md\",\"docs/testing/examples/delete_codebase_by_id_404.json\",\"docs/testing/examples/delete_codebase_env_key_404.json\",\"docs/testing/examples/delete_conversations.json\",\"docs/testing/examples/delete_ugate_token.json\",\"docs/testing/examples/get_alert_rules.json\",\"docs/testing/examples/get_alerts.json\",\"docs/testing/examples/get_alerts_preview.json\",\"docs/testing/examples/get_anomalies.json\",\"docs/testing/examples/get_archives.json\",\"docs/testing/examples/get_auth_me.json\",\"docs/testing/examples/get_codebase_by_id_404.json\",\"docs/testing/examples/get_codebase_env_404.json\",\"docs/testing/examples/get_codebases.json\",\"docs/testing/examples/get_comate_auth_token.json\",\"docs/testing/examples/get_combos.json\",\"docs/testing/examples/get_commands.json\",\"docs/testing/examples/get_config.json\",\"docs/testing/examples/get_conversations.json\",\"docs/testing/examples/get_cost_trends.json\",\"docs/testing/examples/get_evaluation_workflow_run_404.json\",\"docs/testing/examples/get_evaluations_aggregates.json\",\"docs/testing/examples/get_evaluations_workflows.json\",\"docs/testing/examples/get_failure_aggregates.json\",\"docs/testing/examples/get_gitcase_spaces.json\",\"docs/testing/examples/get_golden_samples.json\",\"docs/testing/examples/get_human_feedback.json\",\"docs/testing/examples/get_icafe_space.json\",\"docs/testing/examples/get_intelligence.json\",\"docs/testing/examples/get_product_spaces.json\",\"docs/testing/examples/get_product_spaces_mine.json\",\"docs/testing/examples/get_recording_guide.json\",\"docs/testing/examples/get_reliability.json\",\"docs/testing/examples/get_schema_migrations.json\",\"docs/testing/examples/get_schema_migrations_summary.json\",\"docs/testing/examples/get_settings_me.json\",\"docs/testing/examples/get_slow_node_trends.json\",\"docs/testing/examples/get_stale_runs.json\",\"docs/testing/examples/get_trace_by_id_404.json\",\"docs/testing/examples/get_traces.json\",\"docs/testing/examples/get_traces_health.json\",\"docs/testing/examples/get_ugate_token.json\",\"docs/testing/examples/get_ui_replay_audit_events.json\",\"docs/testing/examples/get_ui_replay_governance.json\",\"docs/testing/examples/get_ui_replay_quality_rules.json\",\"docs/testing/examples/get_ui_replay_recordings.json\",\"docs/testing/examples/get_ui_replay_runs.json\",\"docs/testing/examples/get_update_check.json\",\"docs/testing/examples/get_usage_aggregates.json\",\"docs/testing/examples/get_version_effectiveness.json\",\"docs/testing/examples/get_workflow_aggregates.json\",\"docs/testing/examples/get_workflow_by_name_404.json\",\"docs/testing/examples/get_workflow_run_by_id_404.json\",\"docs/testing/examples/get_workflow_run_by_worker_404.json\",\"docs/testing/examples/get_workflow_v2_by_id_404.json\",\"docs/testing/examples/patch_config_assistants.json\",\"docs/testing/examples/post_conversations.json\",\"docs/testing/examples/put_codebase_env_404.json\",\"docs/testing/specmatic-coverage.sh\",\"docs/testing/specmatic-doarchon-docker-test-guide.md\",\"docs/testing/specmatic-doarchon.yaml\",\"docs/testing/specmatic-integration.md\",\"docs/testing/specmatic-test.sh\",\"docs/testing/ui-replay-quality.md\",\"docs/wiki-drafts/PROMPT.md\",\"docs/wiki-drafts/feature-workflow-authoring.md\",\"docs/wiki-drafts/feature-workflow-isolation.md\",\"eslint.config.mjs\",\"migrations/000_combined.sql\",\"migrations/001_initial_schema.sql\",\"migrations/001_user_isolation.sql\",\"migrations/002_command_templates.sql\",\"migrations/002_product_spaces.sql\",\"migrations/003_add_worktree.sql\",\"migrations/004_worktree_sharing.sql\",\"migrations/005_isolation_abstraction.sql\",\"migrations/006_isolation_environments.sql\",\"migrations/007_drop_legacy_columns.sql\",\"migrations/008_workflow_runs.sql\",\"migrations/009_workflow_last_activity.sql\",\"migrations/010_immutable_sessions.sql\",\"migrations/011_partial_unique_constraint.sql\",\"migrations/012_workflow_events.sql\",\"migrations/013_conversation_titles.sql\",\"migrations/014_message_history.sql\",\"migrations/015_background_dispatch.sql\",\"migrations/016_session_ended_reason.sql\",\"migrations/017_drop_command_templates.sql\",\"migrations/018_fix_workflow_status_default.sql\",\"migrations/019_workflow_resume_path.sql\",\"migrations/020_codebase_env_vars.sql\",\"migrations/021_add_allow_env_keys_to_codebases.sql\",\"migrations/022_ugate_tokens.sql\",\"migrations/023_codebase_combos.sql\",\"migrations/023_runtime_trace.sql\",\"migrations/024_runtime_trace_alerts.sql\",\"migrations/024_ugate_token_icafe_space.sql\",\"migrations/025_runtime_trace_schema_migrations.sql\",\"migrations/026_runtime_trace_issue_id.sql\",\"migrations/027_workflow_evaluations.sql\",\"migrations/028_dedupe_workflow_evaluations.sql\",\"migrations/029_workflow_run_history_governance.sql\",\"migrations/030_evaluation_objective_datasets.sql\",\"migrations/031_trace_event_skill_name.sql\",\"migrations/032_runtime_trace_governance_indexes.sql\",\"migrations/032_sandbox.sql\",\"migrations/032_workflows_product_space.sql\",\"migrations/033_runtime_trace_schema_backfill.sql\",\"migrations/034_runtime_trace_query_indexes.sql\",\"migrations/035_space_codebases.sql\",\"migrations/035_workflow_run_access_scope.sql\",\"migrations/036_evolution_candidates.sql\",\"migrations/037_messages_created_at_timestamptz.sql\",\"migrations/038_error_details.sql\",\"migrations/039_message_knowledge_columns.sql\",\"migrations/040_ui_replay_persistence.sql\",\"migrations/041_ui_replay_audit.sql\",\"migrations/042_personal_space.sql\",\"migrations/042_workflow_definition_versions.sql\",\"migrations/043_workflow_project_source.sql\",\"migrations/044_observability_events.sql\",\"migrations/045_observability_user_activity_indexes.sql\",\"migrations/045_workflow_name_unique_per_space.sql\",\"migrations/047_conversations_product_space.sql\",\"migrations/048_observability_sla_performance_indexes.sql\",\"migrations/048_workflow_drafts.sql\",\"migrations/049_observability_sla_bucket_snapshots.sql\",\"migrations/051_conversation_branches.sql\",\"migrations/051_loop_back_state.sql\",\"migrations/052_space_commands.sql\",\"migrations/052_workflow_models.sql\",\"migrations/053_workflow_models_backfill.sql\",\"migrations/054_commands_market.sql\",\"migrations/055_workflow_run_command_scope.sql\",\"migrations/056_command_source_type.sql\",\"migrations/057_scheduled_tasks.sql\",\"migrations/058_workflow_run_trigger_source.sql\",\"migrations/059_scheduled_task_branch.sql\",\"migrations/060_scheduled_task_rename_prompt.sql\",\"migrations/061_workflow_version.sql\",\"migrations/062_scheduled_task_product_required.sql\",\"migrations/062_web_verify_steps.sql\",\"migrations/063_observability_sla_user_operation_metrics.sql\",\"migrations/063_user_department_profiles.sql\",\"migrations/064_sla_notification_deliveries.sql\",\"migrations/064_workflow_run_original_started_at.sql\",\"migrations/065_workflow_usage_index.sql\",\"migrations/066_observability_sla_snapshot_retention.sql\",\"migrations/067_observability_active_probe_history_index.sql\",\"migrations/068_observability_traffic_signal_covering_index.sql\",\"migrations/069_workflow_run_codebase_name.sql\",\"migrations/070_observability_sla_schema_reconciliation.sql\",\"migrations/071_observability_sla_online_indexes.sql\",\"migrations/072_observability_sla_snapshot_environment_signals.sql\",\"migrations/073_observability_sla_coverage_lookup_index.sql\",\"migrations/074_observability_sla_dirty_update_triggers.sql\",\"migrations/075_observability_sla_workflow_dirty_triggers.sql\",\"migrations/076_observability_sla_v5_frontend_noise_rebuild.sql\",\"migrations/077_sla_breach_monitoring.sql\",\"migrations/078_observability_sla_integrity_remediation.sql\",\"migrations/079_observability_sla_snapshot_generation.sql\",\"migrations/080_observability_sla_attribution_epoch_fence.sql\",\"migrations/081_observability_dashboard_facts.sql\",\"migrations/082_observability_sla_workflow_owned_failures.sql\",\"migrations/082_workflow_knowledge_observability.sql\",\"migrations/083_evaluation_effect_evidence.sql\",\"migrations/083_workflow_knowledge_sync_jobs.sql\",\"migrations/084_evaluation_benchmark_suites.sql\",\"migrations/084_workflow_knowledge_context_dedup.sql\",\"migrations/085_evaluation_knowledge_artifact_outbox.sql\",\"migrations/086_workflow_models_refresh.sql\",\"migrations/087_evaluation_jobs_runs.sql\",\"migrations/088_observability_sla_attribution_v8_epoch.sql\",\"package.json\",\"packages/adapters/package.json\",\"packages/adapters/src/chat/slack/adapter.test.ts\",\"packages/adapters/src/chat/slack/adapter.ts\",\"packages/adapters/src/chat/slack/auth.test.ts\",\"packages/adapters/src/chat/slack/auth.ts\",\"packages/adapters/src/chat/slack/index.ts\",\"packages/adapters/src/chat/slack/types.ts\",\"packages/adapters/src/chat/telegram/adapter.test.ts\",\"packages/adapters/src/chat/telegram/adapter.ts\",\"packages/adapters/src/chat/telegram/auth.test.ts\",\"packages/adapters/src/chat/telegram/auth.ts\",\"packages/adapters/src/chat/telegram/index.ts\",\"packages/adapters/src/chat/telegram/markdown.test.ts\",\"packages/adapters/src/chat/telegram/markdown.ts\",\"packages/adapters/src/chat/telegram/types.ts\",\"packages/adapters/src/community/chat/README.md\",\"packages/adapters/src/community/chat/discord/adapter.test.ts\",\"packages/adapters/src/community/chat/discord/adapter.ts\",\"packages/adapters/src/community/chat/discord/auth.test.ts\",\"packages/adapters/src/community/chat/discord/auth.ts\",\"packages/adapters/src/community/chat/discord/index.ts\",\"packages/adapters/src/community/chat/discord/types.ts\",\"packages/adapters/src/community/forge/README.md\",\"packages/adapters/src/community/forge/gitea/adapter-internals.test.ts\",\"packages/adapters/src/community/forge/gitea/adapter.test.ts\",\"packages/adapters/src/community/forge/gitea/adapter.ts\",\"packages/adapters/src/community/forge/gitea/auth.test.ts\",\"packages/adapters/src/community/forge/gitea/auth.ts\",\"packages/adapters/src/community/forge/gitea/index.ts\",\"packages/adapters/src/community/forge/gitea/types.ts\",\"packages/adapters/src/community/forge/gitlab/adapter-internals.test.ts\",\"packages/adapters/src/community/forge/gitlab/adapter.test.ts\",\"packages/adapters/src/community/forge/gitlab/adapter.ts\",\"packages/adapters/src/community/forge/gitlab/auth.test.ts\",\"packages/adapters/src/community/forge/gitlab/auth.ts\",\"packages/adapters/src/community/forge/gitlab/index.ts\",\"packages/adapters/src/community/forge/gitlab/types.ts\",\"packages/adapters/src/forge/github/adapter.test.ts\",\"packages/adapters/src/forge/github/adapter.ts\",\"packages/adapters/src/forge/github/auth.test.ts\",\"packages/adapters/src/forge/github/auth.ts\",\"packages/adapters/src/forge/github/context.test.ts\",\"packages/adapters/src/forge/github/index.ts\",\"packages/adapters/src/forge/github/types.ts\",\"packages/adapters/src/index.ts\",\"packages/adapters/src/utils/message-splitting.test.ts\",\"packages/adapters/tsconfig.json\",\"packages/auth/package.json\",\"packages/auth/src/db.test.ts\",\"packages/auth/src/db.ts\",\"packages/auth/src/deptmember/client.test.ts\",\"packages/auth/src/deptmember/client.ts\",\"packages/auth/src/index.ts\",\"packages/auth/src/jwt.test.ts\",\"packages/auth/src/jwt.ts\",\"packages/auth/src/middleware.test.ts\",\"packages/auth/src/middleware.ts\",\"packages/auth/src/uic/client.test.ts\",\"packages/auth/src/uic/client.ts\",\"packages/auth/src/uuap/client.test.ts\",\"packages/auth/src/uuap/client.ts\",\"packages/auth/src/uuap/types.ts\",\"packages/auth/tsconfig.json\",\"packages/cli/package.json\",\"packages/cli/src/adapters/cli-adapter.test.ts\",\"packages/cli/src/aiflow/auth.test.ts\",\"packages/cli/src/aiflow/auth.ts\",\"packages/cli/src/aiflow/client.test.ts\",\"packages/cli/src/aiflow/client.ts\",\"packages/cli/src/aiflow/commands/codebase.test.ts\",\"packages/cli/src/aiflow/commands/codebase.ts\",\"packages/cli/src/aiflow/commands/combo.test.ts\",\"packages/cli/src/aiflow/commands/combo.ts\",\"packages/cli/src/aiflow/commands/conversation.test.ts\",\"packages/cli/src/aiflow/commands/conversation.ts\",\"packages/cli/src/aiflow/commands/run.test.ts\",\"packages/cli/src/aiflow/commands/run.ts\",\"packages/cli/src/aiflow/commands/space.test.ts\",\"packages/cli/src/aiflow/commands/space.ts\",\"packages/cli/src/aiflow/commands/token.test.ts\",\"packages/cli/src/aiflow/commands/token.ts\",\"packages/cli/src/aiflow/commands/workflow.test.ts\",\"packages/cli/src/aiflow/commands/workflow.ts\",\"packages/cli/src/aiflow/file-upload.ts\",\"packages/cli/src/aiflow/format.test.ts\",\"packages/cli/src/aiflow/format.ts\",\"packages/cli/src/aiflow/platform.test.ts\",\"packages/cli/src/aiflow/platform.ts\",\"packages/cli/src/bundled-skill.ts\",\"packages/cli/src/cli-platform.test.ts\",\"packages/cli/src/cli-platform.ts\",\"packages/cli/src/cli.test.ts\",\"packages/cli/src/cli.ts\",\"packages/cli/src/commands/chat.test.ts\",\"packages/cli/src/commands/chat.ts\",\"packages/cli/src/commands/continue.ts\",\"packages/cli/src/commands/doctor.test.ts\",\"packages/cli/src/commands/doctor.ts\",\"packages/cli/src/commands/icafe-space.test.ts\",\"packages/cli/src/commands/icafe-space.ts\",\"packages/cli/src/commands/isolation.test.ts\",\"packages/cli/src/commands/isolation.ts\",\"packages/cli/src/commands/serve-binary.test.ts\",\"packages/cli/src/commands/serve.test.ts\",\"packages/cli/src/commands/serve.ts\",\"packages/cli/src/commands/setup-flow.test.ts\",\"packages/cli/src/commands/setup.test.ts\",\"packages/cli/src/commands/setup.ts\",\"packages/cli/src/commands/skill.test.ts\",\"packages/cli/src/commands/skill.ts\",\"packages/cli/src/commands/ugate-token.test.ts\",\"packages/cli/src/commands/ugate-token.ts\",\"packages/cli/src/commands/validate.ts\",\"packages/cli/src/commands/version.test.ts\",\"packages/cli/src/commands/version.ts\",\"packages/cli/src/commands/workflow.test.ts\",\"packages/cli/src/commands/workflow.ts\",\"packages/cli/tsconfig.json\",\"packages/core/package.json\",\"packages/core/src/config/config-loader.test.ts\",\"packages/core/src/config/config-loader.ts\",\"packages/core/src/config/config-types.ts\",\"packages/core/src/config/index.ts\",\"packages/core/src/db/adapters/index.ts\",\"packages/core/src/db/adapters/postgres.test.ts\",\"packages/core/src/db/adapters/postgres.ts\",\"packages/core/src/db/adapters/sqlite.test.ts\",\"packages/core/src/db/adapters/sqlite.ts\",\"packages/core/src/db/adapters/types.ts\",\"packages/core/src/db/assistant-override.ts\",\"packages/core/src/db/codebases.test.ts\",\"packages/core/src/db/codebases.ts\",\"packages/core/src/db/combos.test.ts\",\"packages/core/src/db/combos.ts\",\"packages/core/src/db/connection.test.ts\",\"packages/core/src/db/connection.ts\",\"packages/core/src/db/conversations.test.ts\",\"packages/core/src/db/conversations.ts\",\"packages/core/src/db/env-vars.test.ts\",\"packages/core/src/db/env-vars.ts\",\"packages/core/src/db/error-details.test.ts\",\"packages/core/src/db/error-details.ts\",\"packages/core/src/db/evaluation-benchmarks.ts\",\"packages/core/src/db/evaluation-evidence.ts\",\"packages/core/src/db/evaluation-knowledge-artifacts.ts\",\"packages/core/src/db/evaluations.test.ts\",\"packages/core/src/db/evaluations.ts\",\"packages/core/src/db/evolution.test.ts\",\"packages/core/src/db/evolution.ts\",\"packages/core/src/db/index.ts\",\"packages/core/src/db/isolation-environments.test.ts\",\"packages/core/src/db/isolation-environments.ts\",\"packages/core/src/db/knowledge-observations.test.ts\",\"packages/core/src/db/knowledge-observations.ts\",\"packages/core/src/db/knowledge-sync-jobs.test.ts\",\"packages/core/src/db/knowledge-sync-jobs.ts\",\"packages/core/src/db/messages.test.ts\",\"packages/core/src/db/messages.ts\",\"packages/core/src/db/migrate.test.ts\",\"packages/core/src/db/migrate.ts\",\"packages/core/src/db/observability.test.ts\",\"packages/core/src/db/observability.ts\",\"packages/core/src/db/personnel-usage.test.ts\",\"packages/core/src/db/personnel-usage.ts\",\"packages/core/src/db/product-spaces.test.ts\",\"packages/core/src/db/product-spaces.ts\",\"packages/core/src/db/runtime-traces.test.ts\",\"packages/core/src/db/runtime-traces.ts\",\"packages/core/src/db/sandbox-environments.test.ts\",\"packages/core/src/db/sandbox-environments.ts\",\"packages/core/src/db/scheduled-tasks.test.ts\",\"packages/core/src/db/scheduled-tasks.ts\",\"packages/core/src/db/sessions.test.ts\",\"packages/core/src/db/sessions.ts\",\"packages/core/src/db/sla-notification-deliveries.test.ts\",\"packages/core/src/db/sla-notification-deliveries.ts\",\"packages/core/src/db/space-commands.test.ts\",\"packages/core/src/db/space-commands.ts\",\"packages/core/src/db/ugate-tokens.test.ts\",\"packages/core/src/db/ugate-tokens.ts\",\"packages/core/src/db/ui-replay.ts\",\"packages/core/src/db/user-settings.test.ts\",\"packages/core/src/db/user-settings.ts\",\"packages/core/src/db/user-workflows.test.ts\",\"packages/core/src/db/user-workflows.ts\",\"packages/core/src/db/users.test.ts\",\"packages/core/src/db/users.ts\",\"packages/core/src/db/web-verify-steps.ts\",\"packages/core/src/db/workflow-definition-versions.test.ts\",\"packages/core/src/db/workflow-definition-versions.ts\",\"packages/core/src/db/workflow-drafts.test.ts\",\"packages/core/src/db/workflow-drafts.ts\",\"packages/core/src/db/workflow-events-loop-back.test.ts\",\"packages/core/src/db/workflow-events.test.ts\",\"packages/core/src/db/workflow-events.ts\",\"packages/core/src/db/workflow-loop-metrics.test.ts\",\"packages/core/src/db/workflow-loop-metrics.ts\",\"packages/core/src/db/workflow-models.test.ts\",\"packages/core/src/db/workflow-models.ts\",\"packages/core/src/db/workflow-run-trigger-source.test.ts\",\"packages/core/src/db/workflows-loop-back.test.ts\",\"packages/core/src/db/workflows-v2.test.ts\",\"packages/core/src/db/workflows-v2.ts\",\"packages/core/src/db/workflows.test.ts\",\"packages/core/src/db/workflows.ts\",\"packages/core/src/evaluation/event-bus.ts\",\"packages/core/src/handlers/clone.test.ts\",\"packages/core/src/handlers/clone.ts\",\"packages/core/src/handlers/command-handler.test.ts\",\"packages/core/src/handlers/command-handler.ts\",\"packages/core/src/handlers/command-handler.workflow-run.test.ts\",\"packages/core/src/handlers/icode-clone.test.ts\",\"packages/core/src/handlers/icode-clone.ts\",\"packages/core/src/index.ts\",\"packages/core/src/knowledge/product-resolver.test.ts\",\"packages/core/src/knowledge/product-resolver.ts\",\"packages/core/src/notifications/infoflow-client.oauth.test.ts\",\"packages/core/src/notifications/infoflow-client.test.ts\",\"packages/core/src/notifications/infoflow-client.ts\",\"packages/core/src/notifications/infoflow-sidebar-link.test.ts\",\"packages/core/src/notifications/infoflow-sidebar-link.ts\",\"packages/core/src/notifications/infoflow.test.ts\",\"packages/core/src/notifications/infoflow.ts\",\"packages/core/src/operations/index.ts\",\"packages/core/src/operations/isolation-operations.test.ts\",\"packages/core/src/operations/isolation-operations.ts\",\"packages/core/src/operations/workflow-operations.test.ts\",\"packages/core/src/operations/workflow-operations.ts\",\"packages/core/src/orchestrator/dispatchBackgroundWorkflow.test.ts\",\"packages/core/src/orchestrator/orchestrator-agent.test.ts\",\"packages/core/src/orchestrator/orchestrator-agent.ts\",\"packages/core/src/orchestrator/orchestrator-isolation.test.ts\",\"packages/core/src/orchestrator/orchestrator.test.ts\",\"packages/core/src/orchestrator/orchestrator.ts\",\"packages/core/src/orchestrator/prompt-builder.test.ts\",\"packages/core/src/orchestrator/prompt-builder.ts\",\"packages/core/src/orchestrator/sandbox-helpers.test.ts\",\"packages/core/src/orchestrator/sandbox-helpers.ts\",\"packages/core/src/orchestrator/workflow-authoring-command-list.test.ts\",\"packages/core/src/orchestrator/workflow-authoring-retry.ts\",\"packages/core/src/orchestrator/workflow-authoring.test.ts\",\"packages/core/src/orchestrator/workflow-authoring.ts\",\"packages/core/src/runtime/alerts.ts\",\"packages/core/src/runtime/cost.test.ts\",\"packages/core/src/runtime/cost.ts\",\"packages/core/src/runtime/emitter.test.ts\",\"packages/core/src/runtime/emitter.ts\",\"packages/core/src/runtime/evaluation-worker.test.ts\",\"packages/core/src/runtime/evaluation-worker.ts\",\"packages/core/src/runtime/ids.test.ts\",\"packages/core/src/runtime/ids.ts\",\"packages/core/src/runtime/index.ts\",\"packages/core/src/runtime/issue-clustering.test.ts\",\"packages/core/src/runtime/issue-clustering.ts\",\"packages/core/src/runtime/observability-bus.test.ts\",\"packages/core/src/runtime/observability-bus.ts\",\"packages/core/src/runtime/policy.test.ts\",\"packages/core/src/runtime/policy.ts\",\"packages/core/src/runtime/redaction.test.ts\",\"packages/core/src/runtime/redaction.ts\",\"packages/core/src/runtime/trace-bus.test.ts\",\"packages/core/src/runtime/trace-bus.ts\",\"packages/core/src/runtime/types.ts\",\"packages/core/src/runtime/workflow-trace-recorder.test.ts\",\"packages/core/src/runtime/workflow-trace-recorder.ts\",\"packages/core/src/scheduling/next-run.test.ts\",\"packages/core/src/scheduling/next-run.ts\",\"packages/core/src/scheduling/sandbox-envs-env.test.ts\",\"packages/core/src/scheduling/sandbox-envs.test.ts\",\"packages/core/src/scheduling/sandbox-envs.ts\",\"packages/core/src/scheduling/scheduled-task-runner.test.ts\",\"packages/core/src/scheduling/scheduled-task-runner.ts\",\"packages/core/src/services/cleanup-service.test.ts\",\"packages/core/src/services/codebase-restore-service.test.ts\",\"packages/core/src/services/evaluation-benchmark-service.test.ts\",\"packages/core/src/services/evaluation-benchmark-service.ts\",\"packages/core/src/services/evaluation-calibration-service.test.ts\",\"packages/core/src/services/evaluation-calibration-service.ts\",\"packages/core/src/services/evaluation-capability-readiness-service.test.ts\",\"packages/core/src/services/evaluation-capability-readiness-service.ts\",\"packages/core/src/services/evaluation-evidence-service.test.ts\",\"packages/core/src/services/evaluation-evidence-service.ts\",\"packages/core/src/services/evaluation-knowledge-artifact-service.test.ts\",\"packages/core/src/services/evaluation-service.test.ts\",\"packages/core/src/services/evaluation-service.ts\",\"packages/core/src/services/evolution-service.test.ts\",\"packages/core/src/services/failure-attribution-service.test.ts\",\"packages/core/src/services/golden-sample-candidate-service.test.ts\",\"packages/core/src/services/quality-gate-service.test.ts\",\"packages/core/src/services/runtime-intelligence.test.ts\",\"packages/core/src/services/title-generator.test.ts\",\"packages/core/src/services/ui-replay-assertions.test.ts\",\"packages/core/src/services/ui-replay-assertions.ts\",\"packages/core/src/state/session-transitions.test.ts\",\"packages/core/src/state/session-transitions.ts\",\"packages/core/src/test/mocks/database.ts\",\"packages/core/src/test/mocks/logger.ts\",\"packages/core/src/test/mocks/platform.ts\",\"packages/core/src/test/setup.ts\",\"packages/core/src/types/index.ts\",\"packages/core/src/utils/commands.test.ts\",\"packages/core/src/utils/commands.ts\",\"packages/core/src/utils/conversation-lock.test.ts\",\"packages/core/src/utils/conversation-lock.ts\",\"packages/core/src/utils/credential-sanitizer.test.ts\",\"packages/core/src/utils/credential-sanitizer.ts\",\"packages/core/src/utils/error-formatter.test.ts\",\"packages/core/src/utils/error-formatter.ts\",\"packages/core/src/utils/error.test.ts\",\"packages/core/src/utils/error.ts\",\"packages/core/src/utils/github-graphql.test.ts\",\"packages/core/src/utils/github-graphql.ts\",\"packages/core/src/utils/path-validation.test.ts\",\"packages/core/src/utils/path-validation.ts\",\"packages/core/src/utils/port-allocation.test.ts\",\"packages/core/src/utils/port-allocation.ts\",\"packages/core/src/utils/worktree-sync.test.ts\",\"packages/core/src/utils/worktree-sync.ts\",\"packages/core/src/workflows/index.ts\",\"packages/core/src/workflows/store-adapter.test.ts\",\"packages/core/src/workflows/store-adapter.ts\",\"packages/core/tsconfig.json\",\"packages/core/tsconfig.tsbuildinfo\",\"packages/docs-web/astro.config.mjs\",\"packages/docs-web/package.json\",\"packages/docs-web/public/CNAME\",\"packages/docs-web/public/install\",\"packages/docs-web/public/install.ps1\",\"packages/docs-web/src/content.config.ts\",\"packages/docs-web/src/content/docs/adapters/community/discord.md\",\"packages/docs-web/src/content/docs/adapters/community/gitea.md\",\"packages/docs-web/src/content/docs/adapters/community/gitlab.md\",\"packages/docs-web/src/content/docs/adapters/github.md\",\"packages/docs-web/src/content/docs/adapters/index.md\",\"packages/docs-web/src/content/docs/adapters/slack.md\",\"packages/docs-web/src/content/docs/adapters/telegram.md\",\"packages/docs-web/src/content/docs/adapters/web.md\",\"packages/docs-web/src/content/docs/book/dag-workflows.md\",\"packages/docs-web/src/content/docs/book/essential-workflows.md\",\"packages/docs-web/src/content/docs/book/first-command.md\",\"packages/docs-web/src/content/docs/book/first-five-minutes.md\",\"packages/docs-web/src/content/docs/book/first-workflow.md\",\"packages/docs-web/src/content/docs/book/hooks-and-quality.md\",\"packages/docs-web/src/content/docs/book/how-it-works.md\",\"packages/docs-web/src/content/docs/book/index.md\",\"packages/docs-web/src/content/docs/book/isolation.md\",\"packages/docs-web/src/content/docs/book/quick-reference.md\",\"packages/docs-web/src/content/docs/book/what-is-archon.md\",\"packages/docs-web/src/content/docs/contributing/adding-a-community-provider.md\",\"packages/docs-web/src/content/docs/contributing/cli-internals.md\",\"packages/docs-web/src/content/docs/contributing/dx-quirks.md\",\"packages/docs-web/src/content/docs/contributing/index.md\",\"packages/docs-web/src/content/docs/contributing/new-developer-guide.md\",\"packages/docs-web/src/content/docs/contributing/releasing.md\",\"packages/docs-web/src/content/docs/deployment/cloud.md\",\"packages/docs-web/src/content/docs/deployment/docker.md\",\"packages/docs-web/src/content/docs/deployment/e2e-testing-wsl.md\",\"packages/docs-web/src/content/docs/deployment/e2e-testing.md\",\"packages/docs-web/src/content/docs/deployment/index.md\",\"packages/docs-web/src/content/docs/deployment/local.md\",\"packages/docs-web/src/content/docs/deployment/windows.md\",\"packages/docs-web/src/content/docs/getting-started/ai-assistants.md\",\"packages/docs-web/src/content/docs/getting-started/concepts.md\",\"packages/docs-web/src/content/docs/getting-started/configuration.md\",\"packages/docs-web/src/content/docs/getting-started/installation.md\",\"packages/docs-web/src/content/docs/getting-started/overview.md\",\"packages/docs-web/src/content/docs/getting-started/quick-start.md\",\"packages/docs-web/src/content/docs/guides/approval-nodes.md\",\"packages/docs-web/src/content/docs/guides/authoring-commands.md\",\"packages/docs-web/src/content/docs/guides/authoring-workflows.md\",\"packages/docs-web/src/content/docs/guides/global-workflows.md\",\"packages/docs-web/src/content/docs/guides/hooks.md\",\"packages/docs-web/src/content/docs/guides/index.md\",\"packages/docs-web/src/content/docs/guides/loop-nodes.md\",\"packages/docs-web/src/content/docs/guides/mcp-servers.md\",\"packages/docs-web/src/content/docs/guides/remotion-workflow.md\",\"packages/docs-web/src/content/docs/guides/script-nodes.md\",\"packages/docs-web/src/content/docs/guides/skills.md\",\"packages/docs-web/src/content/docs/index.mdx\",\"packages/docs-web/src/content/docs/reference/api.md\",\"packages/docs-web/src/content/docs/reference/architecture.md\",\"packages/docs-web/src/content/docs/reference/archon-directories.md\",\"packages/docs-web/src/content/docs/reference/cli.md\",\"packages/docs-web/src/content/docs/reference/commands.md\",\"packages/docs-web/src/content/docs/reference/configuration.md\",\"packages/docs-web/src/content/docs/reference/database.md\",\"packages/docs-web/src/content/docs/reference/index.md\",\"packages/docs-web/src/content/docs/reference/security.md\",\"packages/docs-web/src/content/docs/reference/troubleshooting.md\",\"packages/docs-web/src/content/docs/reference/variables.md\",\"packages/docs-web/src/styles/custom.css\",\"packages/docs-web/tsconfig.json\",\"packages/git/package.json\",\"packages/git/src/branch.ts\",\"packages/git/src/exec.test.ts\",\"packages/git/src/exec.ts\",\"packages/git/src/git.test.ts\",\"packages/git/src/index.ts\",\"packages/git/src/keyed-mutex.test.ts\",\"packages/git/src/keyed-mutex.ts\",\"packages/git/src/repo.ts\",\"packages/git/src/types.ts\",\"packages/git/src/worktree.ts\",\"packages/git/tsconfig.json\",\"packages/isolation/package.json\",\"packages/isolation/src/errors.test.ts\",\"packages/isolation/src/errors.ts\",\"packages/isolation/src/factory.test.ts\",\"packages/isolation/src/factory.ts\",\"packages/isolation/src/index.ts\",\"packages/isolation/src/pr-state.test.ts\",\"packages/isolation/src/pr-state.ts\",\"packages/isolation/src/providers/worktree.test.ts\",\"packages/isolation/src/providers/worktree.ts\",\"packages/isolation/src/resolver.test.ts\",\"packages/isolation/src/resolver.ts\",\"packages/isolation/src/store.ts\",\"packages/isolation/src/types.ts\",\"packages/isolation/src/worktree-copy.test.ts\",\"packages/isolation/src/worktree-copy.ts\",\"packages/isolation/tsconfig.json\",\"packages/paths/package.json\",\"packages/paths/src/archon-paths.test.ts\",\"packages/paths/src/archon-paths.ts\",\"packages/paths/src/bundled-build.test.ts\",\"packages/paths/src/bundled-build.ts\",\"packages/paths/src/env-integration.test.ts\",\"packages/paths/src/env-loader.test.ts\",\"packages/paths/src/env-loader.ts\",\"packages/paths/src/index.ts\",\"packages/paths/src/logger.test.ts\",\"packages/paths/src/logger.ts\",\"packages/paths/src/mcp-init.test.ts\",\"packages/paths/src/mcp-init.ts\",\"packages/paths/src/strip-cwd-env-boot.ts\",\"packages/paths/src/strip-cwd-env.test.ts\",\"packages/paths/src/strip-cwd-env.ts\",\"packages/paths/src/telemetry.test.ts\",\"packages/paths/src/telemetry.ts\",\"packages/paths/src/update-check.test.ts\",\"packages/paths/src/update-check.ts\",\"packages/paths/tsconfig.json\",\"packages/providers/package.json\",\"packages/providers/src/claude/binary-resolver-dev.test.ts\",\"packages/providers/src/claude/binary-resolver.test.ts\",\"packages/providers/src/claude/binary-resolver.ts\",\"packages/providers/src/claude/capabilities.ts\",\"packages/providers/src/claude/config.test.ts\",\"packages/providers/src/claude/config.ts\",\"packages/providers/src/claude/index.ts\",\"packages/providers/src/claude/provider.test.ts\",\"packages/providers/src/claude/provider.ts\",\"packages/providers/src/codex/binary-guard.test.ts\",\"packages/providers/src/codex/binary-resolver-dev.test.ts\",\"packages/providers/src/codex/binary-resolver.test.ts\",\"packages/providers/src/codex/binary-resolver.ts\",\"packages/providers/src/codex/capabilities.ts\",\"packages/providers/src/codex/config.test.ts\",\"packages/providers/src/codex/config.ts\",\"packages/providers/src/codex/index.ts\",\"packages/providers/src/codex/provider.test.ts\",\"packages/providers/src/codex/provider.ts\",\"packages/providers/src/community/pi/capabilities.ts\",\"packages/providers/src/community/pi/config.test.ts\",\"packages/providers/src/community/pi/config.ts\",\"packages/providers/src/community/pi/event-bridge.test.ts\",\"packages/providers/src/community/pi/event-bridge.ts\",\"packages/providers/src/community/pi/index.ts\",\"packages/providers/src/community/pi/model-ref.test.ts\",\"packages/providers/src/community/pi/model-ref.ts\",\"packages/providers/src/community/pi/options-translator.test.ts\",\"packages/providers/src/community/pi/options-translator.ts\",\"packages/providers/src/community/pi/provider-lazy-load.test.ts\",\"packages/providers/src/community/pi/provider.test.ts\",\"packages/providers/src/community/pi/provider.ts\",\"packages/providers/src/community/pi/registration.ts\",\"packages/providers/src/community/pi/resource-loader.ts\",\"packages/providers/src/community/pi/session-resolver.test.ts\",\"packages/providers/src/community/pi/session-resolver.ts\",\"packages/providers/src/community/pi/ui-context-stub.test.ts\",\"packages/providers/src/community/pi/ui-context-stub.ts\",\"packages/providers/src/errors.ts\",\"packages/providers/src/index.ts\",\"packages/providers/src/registry.test.ts\",\"packages/providers/src/registry.ts\",\"packages/providers/src/test/mocks/logger.ts\",\"packages/providers/src/types.ts\",\"packages/providers/src/workflow-models.test.ts\",\"packages/providers/src/workflow-models.ts\",\"packages/providers/tsconfig.json\",\"packages/sandbox/package.json\",\"packages/sandbox/src/file-helpers.test.ts\",\"packages/sandbox/src/file-helpers.ts\",\"packages/sandbox/src/index.ts\",\"packages/sandbox/src/manager.test.ts\",\"packages/sandbox/src/manager.ts\",\"packages/sandbox/src/provider.test.ts\",\"packages/sandbox/src/provider.ts\",\"packages/sandbox/src/semaphore.test.ts\",\"packages/sandbox/src/semaphore.ts\",\"packages/sandbox/src/stream-parser.test.ts\",\"packages/sandbox/src/stream-parser.ts\",\"packages/sandbox/src/types.ts\",\"packages/sandbox/tsconfig.json\",\"packages/server/package.json\",\"packages/server/src/adapters/web/persistence.test.ts\",\"packages/server/src/adapters/web/persistence.ts\",\"packages/server/src/adapters/web/transport.test.ts\",\"packages/server/src/adapters/web/transport.ts\",\"packages/server/src/adapters/web/workflow-bridge-loop-back.test.ts\",\"packages/server/src/adapters/web/workflow-bridge.test.ts\",\"packages/server/src/adapters/web/workflow-bridge.ts\",\"packages/server/src/api-tests/brand-text-regression.test.ts\",\"packages/server/src/api-tests/contract.test.ts\",\"packages/server/src/api-tests/scenario.test.ts\",\"packages/server/src/api-tests/scheduled-tasks.test.ts\",\"packages/server/src/api-tests/workflow-run-product-scope.test.ts\",\"packages/server/src/api-tests/workflow-run-scheduled-gates.test.ts\",\"packages/server/src/api-tests/workflow-run-upload.test.ts\",\"packages/server/src/bos-client.test.ts\",\"packages/server/src/gitcase-client.test.ts\",\"packages/server/src/routes/api.bos.test.ts\",\"packages/server/src/routes/api.case-info.test.ts\",\"packages/server/src/routes/api.codebases.test.ts\",\"packages/server/src/routes/api.combos.test.ts\",\"packages/server/src/routes/api.commands-v2.test.ts\",\"packages/server/src/routes/api.commands-v2.ts\",\"packages/server/src/routes/api.conversations.test.ts\",\"packages/server/src/routes/api.debug-session.test.ts\",\"packages/server/src/routes/api.evaluations.test.ts\",\"packages/server/src/routes/api.gitcase.test.ts\",\"packages/server/src/routes/api.health.test.ts\",\"packages/server/src/routes/api.helpers.test.ts\",\"packages/server/src/routes/api.infoflow-webhook.test.ts\",\"packages/server/src/routes/api.infoflow.test.ts\",\"packages/server/src/routes/api.knowledge-chat-proxy.ts\",\"packages/server/src/routes/api.knowledge-chat.ts\",\"packages/server/src/routes/api.knowledge-proxy.test.ts\",\"packages/server/src/routes/api.knowledge-proxy.ts\",\"packages/server/src/routes/api.knowledge-sync-callback.test.ts\",\"packages/server/src/routes/api.knowledge.test.ts\",\"packages/server/src/routes/api.knowledge.ts\",\"packages/server/src/routes/api.messages.test.ts\",\"packages/server/src/routes/api.observability.test.ts\",\"packages/server/src/routes/api.personnel-usage.test.ts\",\"packages/server/src/routes/api.product-spaces.test.ts\",\"packages/server/src/routes/api.product-spaces.ts\",\"packages/server/src/routes/api.providers.test.ts\",\"packages/server/src/routes/api.runtime-traces.test.ts\",\"packages/server/src/routes/api.sandbox-file.test.ts\",\"packages/server/src/routes/api.ts\",\"packages/server/src/routes/api.ui-replay.test.ts\",\"packages/server/src/routes/api.web-verify-steps.test.ts\",\"packages/server/src/routes/api.webhooks.test.ts\",\"packages/server/src/routes/api.workflow-runs.test.ts\",\"packages/server/src/routes/api.workflows-v2.test.ts\",\"packages/server/src/routes/api.workflows-v2.ts\",\"packages/server/src/routes/api.workflows.test.ts\",\"packages/server/src/routes/api/bos-download.ts\",\"packages/server/src/routes/api/bos-preview.ts\",\"packages/server/src/routes/api/bos-upload.ts\",\"packages/server/src/routes/api/case-info.ts\",\"packages/server/src/routes/api/codebases.ts\",\"packages/server/src/routes/api/combos.ts\",\"packages/server/src/routes/api/conversations.ts\",\"packages/server/src/routes/api/debug-session.ts\",\"packages/server/src/routes/api/gitcase.ts\",\"packages/server/src/routes/api/helpers.ts\",\"packages/server/src/routes/api/infoflow-crypto.test.ts\",\"packages/server/src/routes/api/infoflow-crypto.ts\",\"packages/server/src/routes/api/infoflow-oauth.test.ts\",\"packages/server/src/routes/api/infoflow-oauth.ts\",\"packages/server/src/routes/api/infoflow-reply-routing.test.ts\",\"packages/server/src/routes/api/infoflow-reply-routing.ts\",\"packages/server/src/routes/api/infoflow-webhook.ts\",\"packages/server/src/routes/api/infoflow.ts\",\"packages/server/src/routes/api/knowledge-sync-callback.ts\",\"packages/server/src/routes/api/product-access.ts\",\"packages/server/src/routes/api/sandbox-file.ts\",\"packages/server/src/routes/api/scheduled-tasks.ts\",\"packages/server/src/routes/api/system.ts\",\"packages/server/src/routes/api/ui-replay.ts\",\"packages/server/src/routes/api/web-verify-steps.ts\",\"packages/server/src/routes/api/workflow-runs.ts\",\"packages/server/src/routes/api/workflows.ts\",\"packages/server/src/routes/api/zip-decompress.test.ts\",\"packages/server/src/routes/api/zip-decompress.ts\",\"packages/server/src/routes/auth.test.ts\",\"packages/server/src/routes/command-frontmatter.test.ts\",\"packages/server/src/routes/command-frontmatter.ts\",\"packages/server/src/routes/command-references.test.ts\",\"packages/server/src/routes/command-references.ts\",\"packages/server/src/routes/health.test.ts\",\"packages/server/src/routes/health.ts\",\"packages/server/src/routes/openapi-defaults.ts\",\"packages/server/src/routes/schemas/case-info.schemas.ts\",\"packages/server/src/routes/schemas/codebase.schemas.ts\",\"packages/server/src/routes/schemas/combo.schemas.ts\",\"packages/server/src/routes/schemas/command-v2.schemas.ts\",\"packages/server/src/routes/schemas/common.schemas.ts\",\"packages/server/src/routes/schemas/config.schemas.ts\",\"packages/server/src/routes/schemas/conversation.schemas.ts\",\"packages/server/src/routes/schemas/evaluation.schemas.ts\",\"packages/server/src/routes/schemas/evolution.schemas.ts\",\"packages/server/src/routes/schemas/gitcase.schemas.ts\",\"packages/server/src/routes/schemas/observability.schemas.ts\",\"packages/server/src/routes/schemas/personnel-usage.schemas.ts\",\"packages/server/src/routes/schemas/product-space.schemas.ts\",\"packages/server/src/routes/schemas/provider.schemas.ts\",\"packages/server/src/routes/schemas/runtime.schemas.ts\",\"packages/server/src/routes/schemas/scheduled-tasks.schemas.ts\",\"packages/server/src/routes/schemas/settings.schemas.ts\",\"packages/server/src/routes/schemas/system.schemas.ts\",\"packages/server/src/routes/schemas/ui-replay.schemas.ts\",\"packages/server/src/routes/schemas/web-verify.schemas.ts\",\"packages/server/src/routes/schemas/workflow.schemas.test.ts\",\"packages/server/src/routes/schemas/workflow.schemas.ts\",\"packages/server/src/routes/webhooks.ts\",\"packages/server/src/runtime-config.test.ts\",\"packages/server/src/scripts/backfill-forked-workflow-commands.ts\",\"packages/server/src/scripts/backfill-product-commands.ts\",\"packages/server/src/scripts/backfill-sla-classifications.ts\",\"packages/server/src/scripts/migrate-space-commands.ts\",\"packages/server/src/scripts/setup-auth.ts\",\"packages/server/src/services/callback-block.test.ts\",\"packages/server/src/services/infoflow-sender.test.ts\",\"packages/server/src/services/infoflow-webhook.test.ts\",\"packages/server/src/services/sla-infoflow-notifier.test.ts\",\"packages/server/src/services/workflow-access.test.ts\",\"packages/server/src/services/workflow-notification-listener.test.ts\",\"packages/server/src/services/workflow-restart-recovery.integration.test.ts\",\"packages/server/src/services/workflow-restart-recovery.test.ts\",\"packages/server/src/services/workflow-restart-recovery.ts\",\"packages/server/src/services/workflow-run-actions.test.ts\",\"packages/server/src/services/workflow-run-exporter.test.ts\",\"packages/server/src/services/workflow-run-knowledge-sync-dispatcher.test.ts\",\"packages/server/src/sync-bundled-commands.test.ts\",\"packages/server/src/sync-bundled-workflows.test.ts\",\"packages/server/src/sync-project-workflows.test.ts\",\"packages/server/src/sync-user-workflows.test.ts\",\"packages/server/src/test/workflow-mock-factories.ts\",\"packages/server/src/workers/sla-infoflow-worker.test.ts\",\"packages/server/tsconfig.json\",\"packages/server/tsconfig.tsbuildinfo\",\"packages/web/components.json\",\"packages/web/e2e/chat-primary-flow.spec.ts\",\"packages/web/e2e/console-flow.spec.ts\",\"packages/web/e2e/dashboard-paused-delete-flow.spec.ts\",\"packages/web/e2e/dashboard-review-flow.spec.ts\",\"packages/web/e2e/diagnostics-flow.spec.ts\",\"packages/web/e2e/evaluation-center-flow.spec.ts\",\"packages/web/e2e/fixtures.ts\",\"packages/web/e2e/governance-smoke.spec.ts\",\"packages/web/e2e/knowledge-eval-real.spec.ts\",\"packages/web/e2e/knowledge-flow.spec.ts\",\"packages/web/e2e/mock-helpers.ts\",\"packages/web/e2e/settings-flow.spec.ts\",\"packages/web/e2e/space-admin-flow.spec.ts\",\"packages/web/e2e/traces-redirect-flow.spec.ts\",\"packages/web/e2e/ui-replay-center-flow.spec.ts\",\"packages/web/e2e/ui-replay-smoke.spec.ts\",\"packages/web/e2e/workflow-run-flow.spec.ts\",\"packages/web/index.html\",\"packages/web/package.json\",\"packages/web/playwright.config.ts\",\"packages/web/postcss.config.mjs\",\"packages/web/src/App.sidebar-routes.test.ts\",\"packages/web/src/components/chat/ArtifactRail.tsx\",\"packages/web/src/components/chat/BreakpointRetry.tsx\",\"packages/web/src/components/chat/ChatInterface.tsx\",\"packages/web/src/components/chat/ComposerContextControls.test.tsx\",\"packages/web/src/components/chat/ComposerContextControls.tsx\",\"packages/web/src/components/chat/ErrorCard.tsx\",\"packages/web/src/components/chat/FileAttachmentChips.tsx\",\"packages/web/src/components/chat/InputRequestForm.test.tsx\",\"packages/web/src/components/chat/InputRequestForm.tsx\",\"packages/web/src/components/chat/LockIndicator.tsx\",\"packages/web/src/components/chat/MessageBubble.strip.test.ts\",\"packages/web/src/components/chat/MessageBubble.tsx\",\"packages/web/src/components/chat/MessageInput.test.tsx\",\"packages/web/src/components/chat/MessageInput.tsx\",\"packages/web/src/components/chat/MessageList.tsx\",\"packages/web/src/components/chat/ToolCallCard.tsx\",\"packages/web/src/components/chat/TryItList.test.ts\",\"packages/web/src/components/chat/TryItList.tsx\",\"packages/web/src/components/chat/WorkflowApprovalBar.tsx\",\"packages/web/src/components/chat/WorkflowProgressCard.tsx\",\"packages/web/src/components/chat/WorkflowSelector.test.tsx\",\"packages/web/src/components/chat/WorkflowSelector.tsx\",\"packages/web/src/components/chat/WorkflowStatusBar.tsx\",\"packages/web/src/components/chat/markdownLink.tsx\",\"packages/web/src/components/chat/strip-input-request.ts\",\"packages/web/src/components/chat/workflow-groups.test.ts\",\"packages/web/src/components/chat/workflow-groups.ts\",\"packages/web/src/components/commands/CommandCard.tsx\",\"packages/web/src/components/commands/CommandDetailDialog.tsx\",\"packages/web/src/components/commands/CommandEditorDialog.theme.test.ts\",\"packages/web/src/components/commands/CommandEditorDialog.tsx\",\"packages/web/src/components/commands/CommandList.tsx\",\"packages/web/src/components/commands/DeleteCommandDialog.tsx\",\"packages/web/src/components/commands/ForkCommandDialog.tsx\",\"packages/web/src/components/conversations/ConversationItem.tsx\",\"packages/web/src/components/dashboard/ConfirmRunActionDialog.tsx\",\"packages/web/src/components/dashboard/DashboardFilters.tsx\",\"packages/web/src/components/dashboard/DashboardTabCount.test.tsx\",\"packages/web/src/components/dashboard/SettingsConcurrencySection.test.ts\",\"packages/web/src/components/dashboard/StatusBoard.tsx\",\"packages/web/src/components/dashboard/StatusSummaryBar.test.tsx\",\"packages/web/src/components/dashboard/WorkflowHistoryTable.tsx\",\"packages/web/src/components/dashboard/WorkflowRunCard.test.ts\",\"packages/web/src/components/dashboard/WorkflowRunCard.tsx\",\"packages/web/src/components/dashboard/WorkflowRunGroup.tsx\",\"packages/web/src/components/document-drawer/DocumentDrawer.tsx\",\"packages/web/src/components/document-drawer/DocumentDrawerContent.tsx\",\"packages/web/src/components/document-drawer/LogDrawer.tsx\",\"packages/web/src/components/document-drawer/MindMapViewer.tsx\",\"packages/web/src/components/document-drawer/SyncGitCaseDialog.tsx\",\"packages/web/src/components/document-drawer/transformCaseJson.ts\",\"packages/web/src/components/knowledge/graph/ArchView.tsx\",\"packages/web/src/components/knowledge/graph/EntityCreateDialog.tsx\",\"packages/web/src/components/knowledge/graph/EntityDetailLegend.tsx\",\"packages/web/src/components/knowledge/graph/EntityDetailSheet.tsx\",\"packages/web/src/components/knowledge/graph/EntityListTable.tsx\",\"packages/web/src/components/knowledge/graph/GraphCanvas.tsx\",\"packages/web/src/components/knowledge/graph/GraphToolbar.tsx\",\"packages/web/src/components/knowledge/graph/RelationEditDialog.tsx\",\"packages/web/src/components/layout/AppSidebar.test.tsx\",\"packages/web/src/components/layout/AppSidebar.tsx\",\"packages/web/src/components/layout/BackendStatusBanner.tsx\",\"packages/web/src/components/layout/Header.tsx\",\"packages/web/src/components/layout/Layout.tsx\",\"packages/web/src/components/layout/OnboardingWizardModal.tsx\",\"packages/web/src/components/layout/OneApiTokenDialog.tsx\",\"packages/web/src/components/layout/SetupWizardModal.render.test.tsx\",\"packages/web/src/components/layout/SetupWizardModal.test.ts\",\"packages/web/src/components/layout/SetupWizardModal.tsx\",\"packages/web/src/components/layout/Sidebar.test.tsx\",\"packages/web/src/components/layout/brand-constants.ts\",\"packages/web/src/components/layout/topnav-utils.ts\",\"packages/web/src/components/observability/ObservabilityProvider.tsx\",\"packages/web/src/components/product-space/AddGroupDialog.tsx\",\"packages/web/src/components/product-space/AddMemberDialog.tsx\",\"packages/web/src/components/product-space/GroupTable.tsx\",\"packages/web/src/components/product-space/MemberTable.tsx\",\"packages/web/src/components/product-space/ProductSpaceForm.tsx\",\"packages/web/src/components/product-space/ProductSpaceSelector.tsx\",\"packages/web/src/components/product-space/SpaceComboSection.tsx\",\"packages/web/src/components/product-space/SpaceProjectsSection.delete-confirm.test.ts\",\"packages/web/src/components/product-space/SpaceProjectsSection.tsx\",\"packages/web/src/components/product-space/SpaceScheduledTasksSection.tsx\",\"packages/web/src/components/settings/TokenSections.mutation.test.tsx\",\"packages/web/src/components/settings/TokenSections.test.tsx\",\"packages/web/src/components/settings/TokenSections.tsx\",\"packages/web/src/components/sidebar/AllConversationsView.tsx\",\"packages/web/src/components/sidebar/ProjectDetail.tsx\",\"packages/web/src/components/sidebar/ProjectSelector.tsx\",\"packages/web/src/components/sidebar/SearchBar.test.tsx\",\"packages/web/src/components/sidebar/SearchBar.tsx\",\"packages/web/src/components/sidebar/SidebarAbandonBar.test.tsx\",\"packages/web/src/components/sidebar/SidebarAbandonBar.tsx\",\"packages/web/src/components/sidebar/SidebarArtifactList.test.tsx\",\"packages/web/src/components/sidebar/SidebarArtifactList.tsx\",\"packages/web/src/components/sidebar/SidebarArtifactPanel.test.tsx\",\"packages/web/src/components/sidebar/SidebarArtifactPanel.tsx\",\"packages/web/src/components/sidebar/SidebarArtifactView.test.tsx\",\"packages/web/src/components/sidebar/SidebarArtifactView.tsx\",\"packages/web/src/components/sidebar/SidebarComposer.test.tsx\",\"packages/web/src/components/sidebar/SidebarComposer.tsx\",\"packages/web/src/components/sidebar/SidebarConfirmDialog.test.tsx\",\"packages/web/src/components/sidebar/SidebarConfirmDialog.tsx\",\"packages/web/src/components/sidebar/SidebarDetailHeader.test.tsx\",\"packages/web/src/components/sidebar/SidebarDetailHeader.tsx\",\"packages/web/src/components/sidebar/SidebarRunDetail.test.tsx\",\"packages/web/src/components/sidebar/SidebarRunDetail.tsx\",\"packages/web/src/components/sidebar/WorkflowInvoker.test.tsx\",\"packages/web/src/components/sidebar/WorkflowInvoker.tsx\",\"packages/web/src/components/sidebar/open-external.ts\",\"packages/web/src/components/sidebar/sidebar-artifact-css.test.ts\",\"packages/web/src/components/sidebar/sidebar-artifacts.test.ts\",\"packages/web/src/components/sidebar/sidebar-artifacts.ts\",\"packages/web/src/components/sidebar/sidebar-auth.test.ts\",\"packages/web/src/components/sidebar/sidebar-auth.ts\",\"packages/web/src/components/sidebar/sidebar-download.test.ts\",\"packages/web/src/components/sidebar/sidebar-download.ts\",\"packages/web/src/components/sidebar/sidebar-turn-css.test.ts\",\"packages/web/src/components/sidebar/sidebar.css\",\"packages/web/src/components/sidebar/useSidebarAuthGuard.test.ts\",\"packages/web/src/components/sidebar/useSidebarAuthGuard.ts\",\"packages/web/src/components/sidebar/useSidebarRun.ts\",\"packages/web/src/components/ui/adapters.test.tsx\",\"packages/web/src/components/ui/alert-dialog.tsx\",\"packages/web/src/components/ui/badge.tsx\",\"packages/web/src/components/ui/button.tsx\",\"packages/web/src/components/ui/card.tsx\",\"packages/web/src/components/ui/collapsible.tsx\",\"packages/web/src/components/ui/combobox.tsx\",\"packages/web/src/components/ui/dialog.tsx\",\"packages/web/src/components/ui/dropdown-menu.tsx\",\"packages/web/src/components/ui/input.tsx\",\"packages/web/src/components/ui/popover.tsx\",\"packages/web/src/components/ui/primitives.test.tsx\",\"packages/web/src/components/ui/resizable.tsx\",\"packages/web/src/components/ui/scroll-area.tsx\",\"packages/web/src/components/ui/select.tsx\",\"packages/web/src/components/ui/separator.tsx\",\"packages/web/src/components/ui/sheet.tsx\",\"packages/web/src/components/ui/switch.tsx\",\"packages/web/src/components/ui/tabs.tsx\",\"packages/web/src/components/ui/textarea.tsx\",\"packages/web/src/components/ui/tooltip.tsx\",\"packages/web/src/components/ui/two-level-menu.tsx\",\"packages/web/src/components/workflows/AiBuilderPanel.autofix.test.ts\",\"packages/web/src/components/workflows/AiBuilderPanel.convert.test.tsx\",\"packages/web/src/components/workflows/AiBuilderPanel.tsx\",\"packages/web/src/components/workflows/ArtifactSummary.tsx\",\"packages/web/src/components/workflows/ArtifactViewerModal.tsx\",\"packages/web/src/components/workflows/AuthoringModelSelect.tsx\",\"packages/web/src/components/workflows/BuilderToolbar.tsx\",\"packages/web/src/components/workflows/CommandPicker.tsx\",\"packages/web/src/components/workflows/DagNodeComponent.test.ts\",\"packages/web/src/components/workflows/DagNodeComponent.tsx\",\"packages/web/src/components/workflows/DagNodeProgress.tsx\",\"packages/web/src/components/workflows/ExecutionDagNode.tsx\",\"packages/web/src/components/workflows/ForkWorkflowDialog.tsx\",\"packages/web/src/components/workflows/ImportAnthropicWorkflowDialog.test.ts\",\"packages/web/src/components/workflows/ImportAnthropicWorkflowDialog.tsx\",\"packages/web/src/components/workflows/LoopBackEdge.render.test.tsx\",\"packages/web/src/components/workflows/LoopBackEdge.test.tsx\",\"packages/web/src/components/workflows/LoopBackEdge.tsx\",\"packages/web/src/components/workflows/NodeInspector.tsx\",\"packages/web/src/components/workflows/NodeLibrary.tsx\",\"packages/web/src/components/workflows/NodePalette.tsx\",\"packages/web/src/components/workflows/PopularWorkflows.tsx\",\"packages/web/src/components/workflows/QuickAddPicker.tsx\",\"packages/web/src/components/workflows/StatusBar.tsx\",\"packages/web/src/components/workflows/StatusIcon.tsx\",\"packages/web/src/components/workflows/StepLogs.tsx\",\"packages/web/src/components/workflows/ValidationPanel.tsx\",\"packages/web/src/components/workflows/WorkflowBuilder.theme.test.ts\",\"packages/web/src/components/workflows/WorkflowBuilder.toolbar.test.ts\",\"packages/web/src/components/workflows/WorkflowBuilder.tsx\",\"packages/web/src/components/workflows/WorkflowCanvas.nodeLabel.test.ts\",\"packages/web/src/components/workflows/WorkflowCanvas.test.ts\",\"packages/web/src/components/workflows/WorkflowCanvas.tsx\",\"packages/web/src/components/workflows/WorkflowCard.test.ts\",\"packages/web/src/components/workflows/WorkflowCard.tsx\",\"packages/web/src/components/workflows/WorkflowDagViewer.tsx\",\"packages/web/src/components/workflows/WorkflowDetail.tsx\",\"packages/web/src/components/workflows/WorkflowExecution.tsx\",\"packages/web/src/components/workflows/WorkflowList.delete-confirm.test.ts\",\"packages/web/src/components/workflows/WorkflowList.sidebar-filter.test.ts\",\"packages/web/src/components/workflows/WorkflowList.tsx\",\"packages/web/src/components/workflows/WorkflowLogs.tsx\",\"packages/web/src/components/workflows/WorkflowModelSelect.tsx\",\"packages/web/src/components/workflows/WorkflowScopeBadge.tsx\",\"packages/web/src/components/workflows/WorkflowSourceBadge.test.ts\",\"packages/web/src/components/workflows/WorkflowSourceBadge.tsx\",\"packages/web/src/components/workflows/WorkflowSpaceSelector.tsx\",\"packages/web/src/components/workflows/YamlCodeView.test.ts\",\"packages/web/src/components/workflows/YamlCodeView.tsx\",\"packages/web/src/components/workflows/use-popular-workflows.test.ts\",\"packages/web/src/components/workflows/use-popular-workflows.ts\",\"packages/web/src/contexts/OnboardingContext.tsx\",\"packages/web/src/contexts/ProjectContext.model-memory.test.ts\",\"packages/web/src/contexts/ProjectContext.tsx\",\"packages/web/src/contexts/ThemeContext.tsx\",\"packages/web/src/contexts/TokenValidationContext.test.tsx\",\"packages/web/src/contexts/TokenValidationContext.tsx\",\"packages/web/src/contexts/model-memory.ts\",\"packages/web/src/hooks/stream-hooks.test.ts\",\"packages/web/src/hooks/useApiAvailability.test.ts\",\"packages/web/src/hooks/useApiAvailability.ts\",\"packages/web/src/hooks/useAutoScroll.ts\",\"packages/web/src/hooks/useBuilderKeyboard.test.ts\",\"packages/web/src/hooks/useBuilderKeyboard.ts\",\"packages/web/src/hooks/useBuilderUndo.ts\",\"packages/web/src/hooks/useBuilderValidation.ts\",\"packages/web/src/hooks/useClickOutside.ts\",\"packages/web/src/hooks/useConversationStream.test.ts\",\"packages/web/src/hooks/useConversationStream.ts\",\"packages/web/src/hooks/useDashboardSSE.ts\",\"packages/web/src/hooks/useDocumentDrawer.ts\",\"packages/web/src/hooks/useEvaluationSSE.ts\",\"packages/web/src/hooks/useFileAttachments.ts\",\"packages/web/src/hooks/useKeyboardShortcuts.ts\",\"packages/web/src/hooks/useObservabilitySSE.ts\",\"packages/web/src/hooks/usePollingWhenRunning.test.ts\",\"packages/web/src/hooks/usePollingWhenRunning.ts\",\"packages/web/src/hooks/useProviders.ts\",\"packages/web/src/hooks/useRuntimeTraceSSE.ts\",\"packages/web/src/hooks/useSSE.ts\",\"packages/web/src/hooks/useServerValidation.test.ts\",\"packages/web/src/hooks/useServerValidation.ts\",\"packages/web/src/hooks/useSetupStatus.ts\",\"packages/web/src/hooks/useWorkflowDraftSync.test.ts\",\"packages/web/src/hooks/useWorkflowDraftSync.ts\",\"packages/web/src/hooks/useWorkflowModels.ts\",\"packages/web/src/index.css\",\"packages/web/src/lib/api-availability.test.ts\",\"packages/web/src/lib/api-availability.ts\",\"packages/web/src/lib/api.test.ts\",\"packages/web/src/lib/api.ts\",\"packages/web/src/lib/artifact-grouping.test.ts\",\"packages/web/src/lib/artifact-grouping.ts\",\"packages/web/src/lib/breakpoint-retry.test.ts\",\"packages/web/src/lib/breakpoint-retry.ts\",\"packages/web/src/lib/chat-message-reducer.test.ts\",\"packages/web/src/lib/chat-message-reducer.ts\",\"packages/web/src/lib/clarify-request.test.ts\",\"packages/web/src/lib/codebase-input.test.ts\",\"packages/web/src/lib/codebase-input.ts\",\"packages/web/src/lib/command-categories.ts\",\"packages/web/src/lib/composer-persistence.test.ts\",\"packages/web/src/lib/composer-persistence.ts\",\"packages/web/src/lib/conversation-grouping.test.ts\",\"packages/web/src/lib/conversation-grouping.ts\",\"packages/web/src/lib/currency.test.ts\",\"packages/web/src/lib/currency.ts\",\"packages/web/src/lib/dag-layout-loop-back.test.ts\",\"packages/web/src/lib/dag-layout.test.ts\",\"packages/web/src/lib/dag-layout.ts\",\"packages/web/src/lib/dashboard-tab-count.ts\",\"packages/web/src/lib/extract-message-artifacts.test.ts\",\"packages/web/src/lib/extract-message-artifacts.ts\",\"packages/web/src/lib/file-attachments.test.ts\",\"packages/web/src/lib/file-attachments.ts\",\"packages/web/src/lib/format.test.ts\",\"packages/web/src/lib/format.ts\",\"packages/web/src/lib/keyboard.ts\",\"packages/web/src/lib/knowledge/api-key.test.ts\",\"packages/web/src/lib/knowledge/api-key.ts\",\"packages/web/src/lib/knowledge/api.graph-inspection.test.ts\",\"packages/web/src/lib/knowledge/api.test.ts\",\"packages/web/src/lib/knowledge/api.ts\",\"packages/web/src/lib/knowledge/arch-constants.tsx\",\"packages/web/src/lib/knowledge/build-status.test.ts\",\"packages/web/src/lib/knowledge/build-status.ts\",\"packages/web/src/lib/knowledge/constants.ts\",\"packages/web/src/lib/knowledge/entity-form.test.ts\",\"packages/web/src/lib/knowledge/entity-form.ts\",\"packages/web/src/lib/knowledge/force-graph.ts\",\"packages/web/src/lib/knowledge/mock-data.ts\",\"packages/web/src/lib/knowledge/relation-target.test.ts\",\"packages/web/src/lib/knowledge/relation-target.ts\",\"packages/web/src/lib/knowledge/source-parser.ts\",\"packages/web/src/lib/knowledge/types.ts\",\"packages/web/src/lib/knowledge/wiki-api.ts\",\"packages/web/src/lib/knowledge/wiki-version-api.ts\",\"packages/web/src/lib/message-cache.test.ts\",\"packages/web/src/lib/message-cache.ts\",\"packages/web/src/lib/message-mapper.test.ts\",\"packages/web/src/lib/message-mapper.ts\",\"packages/web/src/lib/message-turns.test.ts\",\"packages/web/src/lib/message-turns.ts\",\"packages/web/src/lib/observability-query-keys.ts\",\"packages/web/src/lib/observability.test.ts\",\"packages/web/src/lib/observability.ts\",\"packages/web/src/lib/onboarding-nav.test.ts\",\"packages/web/src/lib/onboarding-nav.ts\",\"packages/web/src/lib/overflow-utils.test.ts\",\"packages/web/src/lib/overflow-utils.ts\",\"packages/web/src/lib/project-scope.test.ts\",\"packages/web/src/lib/project-scope.ts\",\"packages/web/src/lib/query-client.ts\",\"packages/web/src/lib/runtime-config.ts\",\"packages/web/src/lib/runtime-trace-insights.test.ts\",\"packages/web/src/lib/runtime-trace-insights.ts\",\"packages/web/src/lib/scheduled-task-polling.test.ts\",\"packages/web/src/lib/scheduled-task-polling.ts\",\"packages/web/src/lib/select-initial-node.test.ts\",\"packages/web/src/lib/select-initial-node.ts\",\"packages/web/src/lib/session-status-colors.test.ts\",\"packages/web/src/lib/session-status-colors.ts\",\"packages/web/src/lib/session-url-validation.test.ts\",\"packages/web/src/lib/session-url-validation.ts\",\"packages/web/src/lib/settings-copy.test.ts\",\"packages/web/src/lib/settings-copy.ts\",\"packages/web/src/lib/sidebar-progress.test.ts\",\"packages/web/src/lib/sidebar-progress.ts\",\"packages/web/src/lib/status-summary-bar-utils.ts\",\"packages/web/src/lib/types.ts\",\"packages/web/src/lib/utils.ts\",\"packages/web/src/lib/workflow-builder-canvas-status.test.ts\",\"packages/web/src/lib/workflow-builder-canvas-status.ts\",\"packages/web/src/lib/workflow-draft-content.test.ts\",\"packages/web/src/lib/workflow-draft-content.ts\",\"packages/web/src/lib/workflow-events.test.ts\",\"packages/web/src/lib/workflow-events.ts\",\"packages/web/src/lib/workflow-history-table-styles.test.ts\",\"packages/web/src/lib/workflow-history-table-styles.ts\",\"packages/web/src/lib/workflow-metadata.test.ts\",\"packages/web/src/lib/workflow-metadata.ts\",\"packages/web/src/lib/workflow-node-type.test.ts\",\"packages/web/src/lib/workflow-node-type.ts\",\"packages/web/src/lib/workflow-run-state.test.ts\",\"packages/web/src/lib/workflow-run-state.ts\",\"packages/web/src/lib/workflow-scope.test.ts\",\"packages/web/src/lib/workflow-scope.ts\",\"packages/web/src/lib/workflow-stage-mapping.ts\",\"packages/web/src/lib/workflow-usage-timing.test.ts\",\"packages/web/src/lib/workflow-usage-timing.ts\",\"packages/web/src/lib/workflow-usage-trace.test.ts\",\"packages/web/src/lib/workflow-usage-trace.ts\",\"packages/web/src/lib/workflow-utils.test.ts\",\"packages/web/src/lib/workflow-utils.ts\",\"packages/web/src/routes/ChatPage.test.tsx\",\"packages/web/src/routes/ChatPage.tsx\",\"packages/web/src/routes/ControlConsolePage.tsx\",\"packages/web/src/routes/DashboardPage.tsx\",\"packages/web/src/routes/EvaluationSlaPage.render.test.tsx\",\"packages/web/src/routes/EvaluationSlaPage.test.ts\",\"packages/web/src/routes/EvaluationSlaPage.theme.test.tsx\",\"packages/web/src/routes/LoginPage.tsx\",\"packages/web/src/routes/PersonnelUsagePage.test.tsx\",\"packages/web/src/routes/PersonnelUsagePage.tsx\",\"packages/web/src/routes/ProductSpacePage.tsx\",\"packages/web/src/routes/RealtimeEvaluationPage.tsx\",\"packages/web/src/routes/SettingsPage.tsx\",\"packages/web/src/routes/SidebarListPage.test.tsx\",\"packages/web/src/routes/SidebarListPage.tsx\",\"packages/web/src/routes/SidebarRunPage.test.tsx\",\"packages/web/src/routes/SidebarRunPage.tsx\",\"packages/web/src/routes/SidebarStartPage.test.tsx\",\"packages/web/src/routes/SidebarStartPage.tsx\",\"packages/web/src/routes/WorkflowBuilderPage.tsx\",\"packages/web/src/routes/WorkflowDetailPage.tsx\",\"packages/web/src/routes/WorkflowExecutionPage.tsx\",\"packages/web/src/routes/WorkflowSpacePage.tsx\",\"packages/web/src/routes/WorkflowUsagePage.tsx\",\"packages/web/src/routes/control-console/debug.tsx\",\"packages/web/src/routes/control-console/governance.tsx\",\"packages/web/src/routes/control-console/overview.render.test.tsx\",\"packages/web/src/routes/control-console/overview.test.ts\",\"packages/web/src/routes/control-console/overview.tsx\",\"packages/web/src/routes/control-console/runForScope.test.ts\",\"packages/web/src/routes/control-console/shared.test.ts\",\"packages/web/src/routes/control-console/shared.tsx\",\"packages/web/src/routes/control-console/topology.test.tsx\",\"packages/web/src/routes/control-console/topology.tsx\",\"packages/web/src/routes/control-console/workflows.raw-download.test.tsx\",\"packages/web/src/routes/control-console/workflows.scroll.test.tsx\",\"packages/web/src/routes/control-console/workflows.select-trace.test.tsx\",\"packages/web/src/routes/control-console/workflows.spacing.test.ts\",\"packages/web/src/routes/control-console/workflows.trace-list.test.ts\",\"packages/web/src/routes/control-console/workflows.tsx\",\"packages/web/src/routes/knowledge/AikuApiKeyDialog.render.test.tsx\",\"packages/web/src/routes/knowledge/AikuApiKeyDialog.state.test.tsx\",\"packages/web/src/routes/knowledge/AikuApiKeyDialog.test.tsx\",\"packages/web/src/routes/knowledge/AikuApiKeyDialog.tsx\",\"packages/web/src/routes/knowledge/DocsSection.tsx\",\"packages/web/src/routes/knowledge/GraphSection.tsx\",\"packages/web/src/routes/knowledge/QualitySection.tsx\",\"packages/web/src/routes/knowledge/audit/AuditSection.test.tsx\",\"packages/web/src/routes/knowledge/audit/AuditSection.tsx\",\"packages/web/src/routes/knowledge/bootstrap/ark-import.tsx\",\"packages/web/src/routes/knowledge/bootstrap/doc-upload-button.test.tsx\",\"packages/web/src/routes/knowledge/bootstrap/doc-upload-button.tsx\",\"packages/web/src/routes/knowledge/bootstrap/index.tsx\",\"packages/web/src/routes/knowledge/bootstrap/smart-fill.test.tsx\",\"packages/web/src/routes/knowledge/bootstrap/smart-fill.tsx\",\"packages/web/src/routes/knowledge/bootstrap/step-testcases.test.tsx\",\"packages/web/src/routes/knowledge/bootstrap/step-testcases.tsx\",\"packages/web/src/routes/knowledge/bootstrap/step1-browse.test.tsx\",\"packages/web/src/routes/knowledge/bootstrap/step1-browse.tsx\",\"packages/web/src/routes/knowledge/bootstrap/step1.test.tsx\",\"packages/web/src/routes/knowledge/bootstrap/step1.tsx\",\"packages/web/src/routes/knowledge/bootstrap/step2.tsx\",\"packages/web/src/routes/knowledge/bootstrap/step3.tsx\",\"packages/web/src/routes/knowledge/bootstrap/ui.test.tsx\",\"packages/web/src/routes/knowledge/bootstrap/ui.tsx\",\"packages/web/src/routes/knowledge/eval/EvalHistorySheet.test.tsx\",\"packages/web/src/routes/knowledge/eval/EvalHistorySheet.tsx\",\"packages/web/src/routes/knowledge/eval/EvalQuestionCreate.test.tsx\",\"packages/web/src/routes/knowledge/eval/EvalQuestionCreate.tsx\",\"packages/web/src/routes/knowledge/eval/EvalQuestionEdit.test.tsx\",\"packages/web/src/routes/knowledge/eval/EvalQuestionEdit.tsx\",\"packages/web/src/routes/knowledge/eval/EvalSection.test.tsx\",\"packages/web/src/routes/knowledge/eval/EvalSection.tsx\",\"packages/web/src/routes/knowledge/eval/EvalSetDetail.test.tsx\",\"packages/web/src/routes/knowledge/eval/EvalSetDetail.tsx\",\"packages/web/src/routes/knowledge/eval/EvalSetHistorySheet.test.tsx\",\"packages/web/src/routes/knowledge/eval/EvalSetHistorySheet.tsx\",\"packages/web/src/routes/knowledge/eval/EvalSetList.test.tsx\",\"packages/web/src/routes/knowledge/eval/EvalSetList.tsx\",\"packages/web/src/routes/knowledge/eval/FeedbackImportSheet.test.tsx\",\"packages/web/src/routes/knowledge/eval/FeedbackImportSheet.tsx\",\"packages/web/src/routes/knowledge/eval/dimensions.test.ts\",\"packages/web/src/routes/knowledge/eval/dimensions.ts\",\"packages/web/src/routes/knowledge/evaluation/CaseResultDrawer.test.tsx\",\"packages/web/src/routes/knowledge/evaluation/CaseResultDrawer.tsx\",\"packages/web/src/routes/knowledge/evaluation/EvaluationSection.test.tsx\",\"packages/web/src/routes/knowledge/evaluation/EvaluationSection.tsx\",\"packages/web/src/routes/knowledge/evaluation/LatestRunSummary.test.tsx\",\"packages/web/src/routes/knowledge/evaluation/LatestRunSummary.tsx\",\"packages/web/src/routes/knowledge/evaluation/RunDetail.test.tsx\",\"packages/web/src/routes/knowledge/evaluation/RunDetail.tsx\",\"packages/web/src/routes/knowledge/evaluation/RunList.test.tsx\",\"packages/web/src/routes/knowledge/evaluation/RunList.tsx\",\"packages/web/src/routes/knowledge/evaluation/RunReport.test.tsx\",\"packages/web/src/routes/knowledge/evaluation/RunReport.tsx\",\"packages/web/src/routes/knowledge/evaluation/TriggerRunDialog.test.tsx\",\"packages/web/src/routes/knowledge/evaluation/TriggerRunDialog.tsx\",\"packages/web/src/routes/knowledge/evaluation/api-hooks.ts\",\"packages/web/src/routes/knowledge/evaluation/index.ts\",\"packages/web/src/routes/knowledge/evaluation/shared.test.tsx\",\"packages/web/src/routes/knowledge/evaluation/shared.tsx\",\"packages/web/src/routes/knowledge/governance/CandidateDetailDialog.test.tsx\",\"packages/web/src/routes/knowledge/governance/CandidateDetailDialog.tsx\",\"packages/web/src/routes/knowledge/governance/CandidateReviewPanel.test.tsx\",\"packages/web/src/routes/knowledge/governance/CandidateReviewPanel.tsx\",\"packages/web/src/routes/knowledge/governance/GovernanceSection.test.tsx\",\"packages/web/src/routes/knowledge/governance/GovernanceSection.tsx\",\"packages/web/src/routes/knowledge/governance/InspectionReportDetail.test.tsx\",\"packages/web/src/routes/knowledge/governance/InspectionReportDetail.tsx\",\"packages/web/src/routes/knowledge/governance/helpers.test.tsx\",\"packages/web/src/routes/knowledge/governance/helpers.tsx\",\"packages/web/src/routes/knowledge/graph/ArchitectureViewPage.test.tsx\",\"packages/web/src/routes/knowledge/graph/ArchitectureViewPage.tsx\",\"packages/web/src/routes/knowledge/graph/EntityBrowserPage.test.tsx\",\"packages/web/src/routes/knowledge/graph/EntityBrowserPage.tsx\",\"packages/web/src/routes/knowledge/graph/GraphPage.test.tsx\",\"packages/web/src/routes/knowledge/graph/GraphPage.tsx\",\"packages/web/src/routes/knowledge/integrity/IntegritySection.render.test.tsx\",\"packages/web/src/routes/knowledge/integrity/IntegritySection.test.tsx\",\"packages/web/src/routes/knowledge/integrity/IntegritySection.tsx\",\"packages/web/src/routes/knowledge/shared.test.ts\",\"packages/web/src/routes/knowledge/shared.tsx\",\"packages/web/src/routes/knowledge/usage/UsageStatsSection.test.tsx\",\"packages/web/src/routes/knowledge/usage/UsageStatsSection.tsx\",\"packages/web/src/routes/knowledge/useKnowledgeBuildStatus.ts\",\"packages/web/src/routes/knowledge/wiki/WikiChangeBanner.tsx\",\"packages/web/src/routes/knowledge/wiki/WikiComposePane.test.tsx\",\"packages/web/src/routes/knowledge/wiki/WikiComposePane.tsx\",\"packages/web/src/routes/knowledge/wiki/WikiDiffView.tsx\",\"packages/web/src/routes/knowledge/wiki/WikiDocPane.test.tsx\",\"packages/web/src/routes/knowledge/wiki/WikiDocPane.tsx\",\"packages/web/src/routes/knowledge/wiki/WikiHistoryDialog.tsx\",\"packages/web/src/routes/knowledge/wiki/WikiPendingPane.test.tsx\",\"packages/web/src/routes/knowledge/wiki/WikiPendingPane.tsx\",\"packages/web/src/routes/knowledge/wiki/WikiSection.test.tsx\",\"packages/web/src/routes/knowledge/wiki/WikiSection.tsx\",\"packages/web/src/routes/knowledge/wiki/WikiTree.test.tsx\",\"packages/web/src/routes/knowledge/wiki/WikiTree.tsx\",\"packages/web/src/routes/realtime-evaluation/RealtimeEvaluationChrome.tsx\",\"packages/web/src/routes/realtime-evaluation/RealtimeEvaluationContent.tsx\",\"packages/web/src/routes/realtime-evaluation/WorkflowUsageSection.tsx\",\"packages/web/src/routes/realtime-evaluation/evaluation-view-model.test.ts\",\"packages/web/src/routes/realtime-evaluation/evaluation-view-model.ts\",\"packages/web/src/routes/realtime-evaluation/shared.test.ts\",\"packages/web/src/routes/realtime-evaluation/shared.tsx\",\"packages/web/src/routes/realtime-evaluation/useRealtimeEvaluationPageState.test.tsx\",\"packages/web/src/routes/realtime-evaluation/useRealtimeEvaluationPageState.ts\",\"packages/web/src/routes/realtime-evaluation/workflow-usage-metrics.test.ts\",\"packages/web/src/routes/sidebar-common.tsx\",\"packages/web/src/routes/ui-replay/UiReplayCenterPage.tsx\",\"packages/web/src/routes/ui-replay/browserReplay.ts\",\"packages/web/src/routes/ui-replay/codegen.ts\",\"packages/web/src/routes/ui-replay/components.tsx\",\"packages/web/src/routes/ui-replay/constants.ts\",\"packages/web/src/routes/ui-replay/format.ts\",\"packages/web/src/routes/ui-replay/types.ts\",\"packages/web/src/routes/ui-replay/useIframeRecorder.ts\",\"packages/web/src/stores/auth-store.test.ts\",\"packages/web/src/stores/product-space-store.test.ts\",\"packages/web/src/stores/product-space-store.ts\",\"packages/web/src/stores/sidebar-store.ts\",\"packages/web/src/stores/workflow-space-store.test.ts\",\"packages/web/src/stores/workflow-space-store.ts\",\"packages/web/src/stores/workflow-store-loop-back-hydrate.test.ts\",\"packages/web/src/stores/workflow-store-loop-back.test.ts\",\"packages/web/src/stores/workflow-store.test.ts\",\"packages/web/src/stores/workflow-store.ts\",\"packages/web/tsconfig.json\",\"packages/web/vite.config.ts\",\"packages/workflows/package.json\",\"packages/workflows/src/artifact-publisher.test.ts\",\"packages/workflows/src/artifact-publisher.ts\",\"packages/workflows/src/combo-codebases.test.ts\",\"packages/workflows/src/combo-codebases.ts\",\"packages/workflows/src/command-discovery.test.ts\",\"packages/workflows/src/command-discovery.ts\",\"packages/workflows/src/command-validation.test.ts\",\"packages/workflows/src/command-validation.ts\",\"packages/workflows/src/condition-evaluator.test.ts\",\"packages/workflows/src/condition-evaluator.ts\",\"packages/workflows/src/dag-executor-loop-back-resume.test.ts\",\"packages/workflows/src/dag-executor-loop-back-review.test.ts\",\"packages/workflows/src/dag-executor-loop-back.test.ts\",\"packages/workflows/src/dag-executor.test.ts\",\"packages/workflows/src/dag-executor.ts\",\"packages/workflows/src/defaults/bundled-defaults.test.ts\",\"packages/workflows/src/defaults/bundled-defaults.ts\",\"packages/workflows/src/deps.ts\",\"packages/workflows/src/event-emitter.test.ts\",\"packages/workflows/src/event-emitter.ts\",\"packages/workflows/src/executor-preamble.test.ts\",\"packages/workflows/src/executor-shared.test.ts\",\"packages/workflows/src/executor-shared.ts\",\"packages/workflows/src/executor.model-resolution.test.ts\",\"packages/workflows/src/executor.test.ts\",\"packages/workflows/src/executor.ts\",\"packages/workflows/src/extract-input-request.test.ts\",\"packages/workflows/src/hooks.test.ts\",\"packages/workflows/src/knowledge-governor.test.ts\",\"packages/workflows/src/knowledge-governor.ts\",\"packages/workflows/src/knowledge-mode.test.ts\",\"packages/workflows/src/knowledge-mode.ts\",\"packages/workflows/src/knowledge-observability.test.ts\",\"packages/workflows/src/knowledge-observability.ts\",\"packages/workflows/src/load-command-prompt.test.ts\",\"packages/workflows/src/loader-loop-back.test.ts\",\"packages/workflows/src/loader.test.ts\",\"packages/workflows/src/loader.ts\",\"packages/workflows/src/logger.test.ts\",\"packages/workflows/src/logger.ts\",\"packages/workflows/src/loop-back-e2e.test.ts\",\"packages/workflows/src/loop-back-interval.test.ts\",\"packages/workflows/src/loop-back-interval.ts\",\"packages/workflows/src/router.test.ts\",\"packages/workflows/src/router.ts\",\"packages/workflows/src/runtime-check.test.ts\",\"packages/workflows/src/schemas.test.ts\",\"packages/workflows/src/schemas/dag-node.ts\",\"packages/workflows/src/schemas/hooks.ts\",\"packages/workflows/src/schemas/index.ts\",\"packages/workflows/src/schemas/input-request.test.ts\",\"packages/workflows/src/schemas/input-request.ts\",\"packages/workflows/src/schemas/loop-back.test.ts\",\"packages/workflows/src/schemas/loop-back.ts\",\"packages/workflows/src/schemas/loop-metrics.ts\",\"packages/workflows/src/schemas/loop.ts\",\"packages/workflows/src/schemas/retry.ts\",\"packages/workflows/src/schemas/workflow-run-loop-back.test.ts\",\"packages/workflows/src/schemas/workflow-run.ts\",\"packages/workflows/src/schemas/workflow.test.ts\",\"packages/workflows/src/schemas/workflow.ts\",\"packages/workflows/src/script-discovery.test.ts\",\"packages/workflows/src/script-discovery.ts\",\"packages/workflows/src/script-node-deps.test.ts\",\"packages/workflows/src/skill-installer.test.ts\",\"packages/workflows/src/skill-installer.ts\",\"packages/workflows/src/store.ts\",\"packages/workflows/src/test-utils.ts\",\"packages/workflows/src/utils/duration.test.ts\",\"packages/workflows/src/utils/duration.ts\",\"packages/workflows/src/utils/idle-timeout.test.ts\",\"packages/workflows/src/utils/idle-timeout.ts\",\"packages/workflows/src/utils/tool-formatter.test.ts\",\"packages/workflows/src/utils/tool-formatter.ts\",\"packages/workflows/src/utils/variable-substitution.test.ts\",\"packages/workflows/src/utils/variable-substitution.ts\",\"packages/workflows/src/validation-parser.test.ts\",\"packages/workflows/src/validation-parser.ts\",\"packages/workflows/src/validator.test.ts\",\"packages/workflows/src/validator.ts\",\"packages/workflows/src/version-snapshot.test.ts\",\"packages/workflows/src/version-snapshot.ts\",\"packages/workflows/src/workflow-discovery.ts\",\"packages/workflows/tsconfig.json\",\"scripts/build-binaries.sh\",\"scripts/build.sh\",\"scripts/check-aiflow-pytest-scenarios.py\",\"scripts/check-bundled-skill.ts\",\"scripts/check-sla-reliability.sql\",\"scripts/checksums.sh\",\"scripts/clean-dev-branches.sh\",\"scripts/coverage-gate.test.ts\",\"scripts/coverage-gate.ts\",\"scripts/cr-classify.sh\",\"scripts/delete-dev-workflows.sql\",\"scripts/gen-workflow-syntax-doc.test.ts\",\"scripts/gen-workflow-syntax-doc.ts\",\"scripts/generate-api-inventory.test.ts\",\"scripts/generate-api-inventory.ts\",\"scripts/generate-bundled-defaults.ts\",\"scripts/gitnexus-init.sh\",\"scripts/install.ps1\",\"scripts/install.sh\",\"scripts/install_aiflow.sh\",\"scripts/ipipe-cr.sh\",\"scripts/quality-report.ts\",\"scripts/ragas-e2e-stress.ts\",\"scripts/run-aiflow-scenario-cases.sh\",\"scripts/run-coverage.ts\",\"scripts/security-secrets.sh\",\"scripts/select-affected.ts\",\"scripts/sync-versions.sh\",\"scripts/test-sandbox-file-ops.ts\",\"scripts/test-uic-search.ts\",\"scripts/trigger-workflow.sh\",\"scripts/tsconfig.json\",\"scripts/ui-replay-report.ts\",\"scripts/ui-replay-scaffold.ts\",\"scripts/update-homebrew.sh\",\"scripts/upload-aiflow-bos.sh\",\"scripts/validate-setup.sh\",\"scripts/verify-space-commands.ts\",\"scripts/db-governance/00_preflight.sql\",\"scripts/db-governance/01_shrink_observability_events.sql\",\"scripts/db-governance/02_shrink_trace_events.sql\",\"scripts/db-governance/03_shrink_workflow_events.sql\",\"scripts/db-governance/04_verify_after_shrink.sql\",\"scripts/db-governance/05_drop_old_tables.sql\",\"scripts/db-governance/10_rolling_cleanup.sql\",\"scripts/db-governance/README.md\",\"services/deepeval-evaluator/Dockerfile\",\"services/deepeval-evaluator/README.md\",\"services/deepeval-evaluator/requirements.txt\",\"services/ragas-evaluator/Dockerfile\",\"services/ragas-evaluator/README.md\",\"services/ragas-evaluator/requirements.txt\",\"todos.md\",\"tsconfig.json\"],\"Other \u2014 AGENTS.md\":[\"AGENTS.md\"],\"Other \u2014 CLAUDE.md\":[\"CLAUDE.md\"],\"Other \u2014 Caddyfile.example\":[\"Caddyfile.example\"],\"Other \u2014 DESIGN.md\":[\"DESIGN.md\"],\"Other \u2014 Dockerfile\":[\"Dockerfile\"],\"Other \u2014 Dockerfile.base\":[\"Dockerfile.base\"],\"Other \u2014 Dockerfile.ci\":[\"Dockerfile.ci\"],\"Other \u2014 Dockerfile.user.example\":[\"Dockerfile.user.example\"],\"Other \u2014 Makefile\":[\"Makefile\"],\"Other \u2014 README.md\":[\"README.md\"],\"Other \u2014 ducc-skills\":[\"assets/ducc-skills/cnap/SKILL.md\",\"assets/ducc-skills/cnap/references/baidu-internal-network.md\",\"assets/ducc-skills/cnap/references/cases.md\",\"assets/ducc-skills/cnap/references/cnap-accounts.md\",\"assets/ducc-skills/cnap/references/cnap-applications.md\",\"assets/ducc-skills/cnap/references/cnap-clusters.md\",\"assets/ducc-skills/cnap/references/cnap-cpu-units.md\",\"assets/ducc-skills/cnap/references/cnap-datadist.md\",\"assets/ducc-skills/cnap/references/cnap-environ-vars.md\",\"assets/ducc-skills/cnap/references/cnap-environments.md\",\"assets/ducc-skills/cnap/references/cnap-log-collection.md\",\"assets/ducc-skills/cnap/references/cnap-permissions.md\",\"assets/ducc-skills/cnap/references/cnap-runtime-config.md\",\"assets/ducc-skills/cnap/references/cnap-service-discovery.md\",\"assets/ducc-skills/cnap/references/deploy-babysitter.md\",\"assets/ducc-skills/cnap/references/deploy-troubleshoot.md\",\"assets/ducc-skills/cnap/references/icode.md\",\"assets/ducc-skills/cnap/references/install.md\",\"assets/ducc-skills/cnap/references/iregistry.md\",\"assets/ducc-skills/cnap/references/kubectl.md\",\"assets/ducc-skills/cnap/references/login.md\",\"assets/ducc-skills/cnap/references/oncall.md\",\"assets/ducc-skills/get-ugate-token/SKILL.md\"],\"Other \u2014 auth-service\":[\"auth-service/Dockerfile\",\"auth-service/package.json\",\"auth-service/test.js\"],\"Other \u2014 auto-heal.txt\":[\"auto-heal.txt\"],\"Other \u2014 bunfig.coverage.toml\":[\"bunfig.coverage.toml\"],\"Other \u2014 bunfig.toml\":[\"bunfig.toml\"],\"Other \u2014 ci.yml\":[\"ci.yml\"],\"Other \u2014 deploy\":[\"deploy/Dockerfile.user.example\",\"deploy/cloud-init.yml\",\"deploy/docker-compose.override.example.yml\",\"deploy/docker-compose.yml\"],\"Other \u2014 docker-compose.override.example.yml\":[\"docker-compose.override.example.yml\"],\"Other \u2014 docker-compose.yml\":[\"docker-compose.yml\"],\"Other \u2014 docker-entrypoint.sh\":[\"docker-entrypoint.sh\"],\"Other \u2014 e2e-dev\":[\"docker/e2e-dev/Dockerfile\",\"docker/e2e-dev/Dockerfile.base\",\"docker/e2e-dev/init-claude-workspace.sh\",\"docker/e2e-dev/start_comate_server.sh\"],\"Other \u2014 docs\":[\"docs/ai-workflow-builder-design.md\",\"docs/aiflow-skill-design.md\",\"docs/architecture.md\",\"docs/authoring-commands.md\",\"docs/authoring-workflows.md\",\"docs/bundled-workflow-authoring.md\",\"docs/cli-reference.md\",\"docs/cnap-api.md\",\"docs/cr-env.md\",\"docs/cr-rules-code.md\",\"docs/cr-rules-workflow.md\",\"docs/cr-rules.md\",\"docs/document-drawer-design.md\",\"docs/gitcase.md\",\"docs/infoflow-notification-status.md\",\"docs/infoflow-workflow-notification.md\",\"docs/issues.json\",\"docs/knowledge-injection-design.md\",\"docs/loop-back-practice.md\",\"docs/marketing-flow-code-review-redesign.md\",\"docs/marketing-flow-tech-design-step3.md\",\"docs/online-trace-eval-demo-guide.md\",\"docs/online-trace-eval-migration-plan.md\",\"docs/plan-implement-review-loop-parallel.md\",\"docs/product-space-design.md\",\"docs/remove-bundled-system-workflow.md\",\"docs/scheduled-task-practice.md\",\"docs/sla-infoflow-operations.md\",\"docs/standard-dev-flow-artifact-governance-design.md\",\"docs/standard-dev-flow-diagram.md\",\"docs/test-issues.md\",\"docs/ugate-token-adaptation.md\",\"docs/uic-api.md\",\"docs/user-isolation-design.md\",\"docs/uuap-auth.md\",\"docs/workflow-backend-api-chain-api.md\",\"docs/workflow-backend-api-chain-design.md\",\"docs/workflow-loop-back-design.md\",\"docs/workflow-product-space-design.md\",\"docs/workflow-system-analysis.md\",\"docs/workflow-vs-claude-code-comparison.md\",\"docs/workflow-yaml-storage.md\"],\"Other \u2014 knowledge\":[\"docs/knowledge/baidu-pipeline-docker-build.md\",\"docs/knowledge/kg-self-seal.json\"],\"Other \u2014 mock\":[\"docs/mock/\u5de5\u4f5c\u6d41\u4ea7\u54c1\u7a7a\u95f4\u6807\u7b7e-issue.json\",\"docs/mock/\u5de5\u4f5c\u6d41\u5bf9\u8bdd\u6846\u652f\u6301\u6362\u884c-issue.json\"],\"Other \u2014 parallel-study\":[\"docs/parallel-study/sample-01-sidebar-pause/issues.json\",\"docs/parallel-study/sample-02-combo-edit/issues.json\",\"docs/parallel-study/sample-03-command-check/issues.json\"],\"Other \u2014 schemathesis-reports\":[\"docs/schemathesis-reports/2026-06-04-20-05.json\",\"docs/schemathesis-reports/2026-06-04-20-05.md\"],\"Other \u2014 superpowers\":[\"docs/superpowers/plans/2026-05-07-icode-codebase-clone.md\",\"docs/superpowers/plans/2026-05-07-uuap-auth.md\",\"docs/superpowers/plans/2026-05-08-icode-clone-icode-cli.md\",\"docs/superpowers/plans/2026-05-12-config-warning-banner.md\",\"docs/superpowers/plans/2026-05-12-oneapi-token.md\",\"docs/superpowers/plans/2026-05-12-setup-wizard-modal.md\",\"docs/superpowers/plans/2026-05-14-sandbox-session-binding.md\",\"docs/superpowers/plans/2026-05-14-workflow-skill-binding.md\",\"docs/superpowers/plans/2026-05-15-comate-auth-token-user-config.md\",\"docs/superpowers/plans/2026-05-18-bug-fix-flow.md\",\"docs/superpowers/plans/2026-05-19-feature-dev-flow.md\",\"docs/superpowers/plans/2026-05-19-superpowers-full-dev-flow.md\",\"docs/superpowers/plans/2026-05-20-bug-fix-flow-clarify.md\",\"docs/superpowers/plans/2026-05-21-ipipe-ducc-cr.md\",\"docs/superpowers/plans/2026-05-21-sandbox-combo-batch-clone.md\",\"docs/superpowers/plans/2026-05-22-fix-gen-ut-uuid-error.md\",\"docs/superpowers/plans/2026-05-22-sandbox-artifacts-dir-simplify.md\",\"docs/superpowers/plans/2026-05-25-gen-ut-workflow-upgrade.md\",\"docs/superpowers/plans/2026-05-25-smart-cr-classification.md\",\"docs/superpowers/plans/2026-05-25-workflow-bash-node-sandbox.md\",\"docs/superpowers/plans/2026-05-26-dev-loop-unit-test-gate.md\",\"docs/superpowers/plans/2026-05-26-metrics-reporter.md\",\"docs/superpowers/plans/2026-05-26-sandbox-file-upload.md\",\"docs/superpowers/plans/2026-05-27-loop-approval-node-started-event.md\",\"docs/superpowers/plans/2026-05-30-sandbox-auto-renew.md\",\"docs/superpowers/plans/2026-06-02-e2e-flow-enhancement.md\",\"docs/superpowers/plans/2026-06-02-impact-analysis-command.md\",\"docs/superpowers/plans/2026-06-03-e2e-flow-cnap-deploy-refactor.md\",\"docs/superpowers/plans/2026-06-04-sandbox-release-on-cancel-abandon.md\",\"docs/superpowers/plans/2026-06-04-schemathesis-integration.md\",\"docs/superpowers/plans/2026-06-09-subworkflow.md\",\"docs/superpowers/plans/2026-06-10-workflow-user-pause.md\",\"docs/superpowers/plans/2026-06-11-concurrent-pause-context.md\",\"docs/superpowers/plans/2026-06-12-auto-publish-node-artifacts.md\",\"docs/superpowers/plans/2026-06-12-auto-publish-readback-refactor.md\",\"docs/superpowers/plans/2026-06-13-ai-workflow-builder.md\",\"docs/superpowers/plans/2026-06-16-breakpoint-retry-clarify.md\",\"docs/superpowers/plans/2026-06-16-chat-page-deliverables-grouping-optimize-workflow.md\",\"docs/superpowers/plans/2026-06-16-inline-composer-context-controls.md\",\"docs/superpowers/plans/2026-06-17-aiflow-optimize-existing-workflow.md\",\"docs/superpowers/plans/2026-06-18-aiflow-ku-doc-recognition.md\",\"docs/superpowers/plans/2026-06-18-onboarding-run-to-new-chat.md\",\"docs/superpowers/plans/2026-06-18-require-project-on-new-conversation.md\",\"docs/superpowers/plans/2026-06-22-commit-time-metrics-reporting.md\",\"docs/superpowers/plans/2026-06-22-workflow-draft-staging.md\",\"docs/superpowers/plans/2026-06-23-aiflow-skill-integration.md\",\"docs/superpowers/plans/2026-06-24-interactive-loop-structured-input.md\",\"docs/superpowers/plans/2026-06-24-sandbox-heartbeat-renew.md\",\"docs/superpowers/plans/2026-06-25-dag-loop-back.md\",\"docs/superpowers/plans/2026-06-26-all-workflow-infoflow-notification.md\",\"docs/superpowers/plans/2026-06-30-breakpoint-retry-move-to-statusbar.md\",\"docs/superpowers/plans/2026-06-30-marketing-flow-test-loop-back.md\",\"docs/superpowers/plans/2026-06-30-workflow-model-dropdown.md\",\"docs/superpowers/plans/2026-07-01-aiflow-loop-back-authoring.md\",\"docs/superpowers/plans/2026-07-02-builder-dag-node-run-status.md\",\"docs/superpowers/plans/2026-07-02-command-market-and-management.md\",\"docs/superpowers/plans/2026-07-02-marketing-flow-merge-to-dev.md\",\"docs/superpowers/plans/2026-07-03-scheduled-tasks.md\",\"docs/superpowers/plans/2026-07-06-command-discovery-mirror-workflow.md\",\"docs/superpowers/plans/2026-07-06-infoflow-robot-api-and-reply.md\",\"docs/superpowers/plans/2026-07-07-backfill-forked-workflow-commands.md\",\"docs/superpowers/plans/2026-07-07-conversation-workflow-scope-badge.md\",\"docs/superpowers/plans/2026-07-07-scheduled-task-ducc-callback.md\",\"docs/superpowers/plans/2026-07-07-workflow-draft-preview-run.md\",\"docs/superpowers/plans/2026-07-08-workflow-version-updated-at.md\",\"docs/superpowers/plans/2026-07-09-infoflow-reply-session-identifier.md\",\"docs/superpowers/plans/2026-07-09-infoflow-sidebar-part1-bubble-card.md\",\"docs/superpowers/plans/2026-07-09-infoflow-sidebar-part2-oauth.md\",\"docs/superpowers/plans/2026-07-09-infoflow-sidebar-part3-web-page.md\",\"docs/superpowers/plans/2026-07-10-scheduled-tasks-space-scoped.md\",\"docs/superpowers/plans/2026-07-13-aiflow-new-conversation-unpublished-draft-guard.md\",\"docs/superpowers/plans/2026-07-13-session-deliverables-enhancements.md\",\"docs/superpowers/plans/2026-07-14-on-reject-session-resume.md\",\"docs/superpowers/plans/2026-07-14-sidebar-sse-realtime.md\",\"docs/superpowers/plans/2026-07-15-aiflow-cli-skill.md\",\"docs/superpowers/plans/2026-07-15-anthropic-workflow-to-aiflow-convert.md\",\"docs/superpowers/plans/2026-07-15-artifact-drawer-auto-refresh.md\",\"docs/superpowers/plans/2026-07-16-infoflow-bubble-session-entry.md\",\"docs/superpowers/plans/2026-07-16-infoflow-sidebar-artifact-panel.md\",\"docs/superpowers/plans/2026-07-17-workflow-authoring-space-command.md\",\"docs/superpowers/plans/2026-07-18-platform-only-cli.md\",\"docs/superpowers/plans/2026-07-20-command-delete.md\",\"docs/superpowers/plans/2026-07-21-aiflow-skill-platform-cli.md\",\"docs/superpowers/plans/2026-07-21-anthropic-workflow-package-convert.md\",\"docs/superpowers/plans/2026-07-21-infoflow-abandon-workflow-button.md\",\"docs/superpowers/plans/2026-07-22-standard-dev-flow.md\",\"docs/superpowers/plans/2026-07-23-workflow-command-source-from-db.md\",\"docs/superpowers/plans/2026-07-24-downstream-refresh-upstream-artifacts.md\",\"docs/superpowers/plans/2026-07-27-loop-back-human-review.md\",\"docs/superpowers/plans/2026-07-27-online-event-data-governance.md\",\"docs/superpowers/plans/2026-07-27-workflow-custom-sandbox-image.md\",\"docs/superpowers/plans/2026-07-29-combo-multi-codebase-workflow.md\",\"docs/superpowers/plans/2026-07-29-workflow-restart-recovery.md\",\"docs/superpowers/plans/2026-07-30-conversation-turn-collapse.md\",\"docs/superpowers/plans/2026-07-30-session-task-model-switch.md\",\"docs/superpowers/plans/2026-07-31-try-it-list.md\",\"docs/superpowers/specs/2026-05-07-icode-codebase-clone-design.md\",\"docs/superpowers/specs/2026-05-07-uuap-auth-design.md\",\"docs/superpowers/specs/2026-05-12-config-warning-banner-design.md\",\"docs/superpowers/specs/2026-05-12-oneapi-token-design.md\",\"docs/superpowers/specs/2026-05-12-setup-wizard-modal-design.md\",\"docs/superpowers/specs/2026-05-14-sandbox-session-binding-design.md\",\"docs/superpowers/specs/2026-05-14-workflow-skill-binding-design.md\",\"docs/superpowers/specs/2026-05-15-comate-auth-token-user-config-design.md\",\"docs/superpowers/specs/2026-05-18-bug-fix-flow-design.md\",\"docs/superpowers/specs/2026-05-19-feature-dev-flow-design.md\",\"docs/superpowers/specs/2026-05-19-superpowers-full-dev-flow-design.md\",\"docs/superpowers/specs/2026-05-20-bug-fix-flow-clarify-design.md\",\"docs/superpowers/specs/2026-05-21-ipipe-ducc-cr-design.md\",\"docs/superpowers/specs/2026-05-22-sandbox-artifacts-dir-simplify-design.md\",\"docs/superpowers/specs/2026-05-25-gen-ut-workflow-design.md\",\"docs/superpowers/specs/2026-05-25-smart-cr-classification-design.md\",\"docs/superpowers/specs/2026-05-26-bun-in-e2e-dev-image-design.md\",\"docs/superpowers/specs/2026-05-26-dev-loop-unit-test-gate-design.md\",\"docs/superpowers/specs/2026-05-26-metrics-reporter-design.md\",\"docs/superpowers/specs/2026-05-26-sandbox-file-upload-design.md\",\"docs/superpowers/specs/2026-05-30-sandbox-auto-renew-design.md\",\"docs/superpowers/specs/2026-06-02-impact-analysis-command-design.md\",\"docs/superpowers/specs/2026-06-04-sandbox-release-on-cancel-abandon-design.md\",\"docs/superpowers/specs/2026-06-04-schemathesis-integration-design.md\",\"docs/superpowers/specs/2026-06-09-product-space-global-filter-design.md\",\"docs/superpowers/specs/2026-06-09-subworkflow-design.md\",\"docs/superpowers/specs/2026-06-10-workflow-user-pause-design.md\",\"docs/superpowers/specs/2026-06-11-concurrent-pause-context-design.md\",\"docs/superpowers/specs/2026-06-11-workflow-product-space-refactor-design.md\",\"docs/superpowers/specs/2026-06-12-auto-publish-node-artifacts-design.md\",\"docs/superpowers/specs/2026-06-13-ai-workflow-builder-design.md\",\"docs/superpowers/specs/2026-06-16-breakpoint-retry-clarify-ai-nodes-only-design.md\",\"docs/superpowers/specs/2026-06-16-breakpoint-retry-clarify-design.md\",\"docs/superpowers/specs/2026-06-16-chat-page-deliverables-grouping-optimize-workflow-design.md\",\"docs/superpowers/specs/2026-06-16-onboarding-wizard-design.md\",\"docs/superpowers/specs/2026-06-16-workflow-builder-run-flow-design.md\",\"docs/superpowers/specs/2026-06-17-aiflow-optimize-existing-workflow-design.md\",\"docs/superpowers/specs/2026-06-18-aiflow-ku-doc-recognition-design.md\",\"docs/superpowers/specs/2026-06-18-onboarding-run-to-new-chat-design.md\",\"docs/superpowers/specs/2026-06-18-require-project-on-new-conversation-design.md\",\"docs/superpowers/specs/2026-06-22-commit-time-metrics-reporting-design.md\",\"docs/superpowers/specs/2026-06-22-workflow-draft-staging-design.md\",\"docs/superpowers/specs/2026-06-23-aiflow-skill-integration-design.md\",\"docs/superpowers/specs/2026-06-23-interactive-loop-structured-input-design.md\",\"docs/superpowers/specs/2026-06-24-interactive-loop-structured-input-design.md\",\"docs/superpowers/specs/2026-06-24-sandbox-heartbeat-renew-design.md\",\"docs/superpowers/specs/2026-06-25-codebase-branch-list-design.md\",\"docs/superpowers/specs/2026-06-25-dag-loop-back-design.md\",\"docs/superpowers/specs/2026-06-26-all-workflow-infoflow-notification-design.md\",\"docs/superpowers/specs/2026-06-30-breakpoint-retry-move-to-statusbar-design.md\",\"docs/superpowers/specs/2026-06-30-marketing-flow-dynamic-branch-design.md\",\"docs/superpowers/specs/2026-06-30-marketing-flow-test-loop-back-design.md\",\"docs/superpowers/specs/2026-06-30-space-private-command-db-design.md\",\"docs/superpowers/specs/2026-06-30-workflow-model-dropdown-design.md\",\"docs/superpowers/specs/2026-07-01-aiflow-loop-back-authoring-design.md\",\"docs/superpowers/specs/2026-07-02-builder-dag-node-run-status-design.md\",\"docs/superpowers/specs/2026-07-02-command-market-and-management-design.md\",\"docs/superpowers/specs/2026-07-02-marketing-flow-merge-to-dev-design.md\",\"docs/superpowers/specs/2026-07-03-scheduled-tasks-design.md\",\"docs/superpowers/specs/2026-07-06-infoflow-robot-api-and-reply-design.md\",\"docs/superpowers/specs/2026-07-07-backfill-forked-workflow-commands-design.md\",\"docs/superpowers/specs/2026-07-07-conversation-workflow-scope-badge-design.md\",\"docs/superpowers/specs/2026-07-07-scheduled-task-ducc-callback-design.md\",\"docs/superpowers/specs/2026-07-07-workflow-draft-preview-run-design.md\",\"docs/superpowers/specs/2026-07-08-workflow-version-updated-at-design.md\",\"docs/superpowers/specs/2026-07-09-infoflow-reply-session-identifier-design.md\",\"docs/superpowers/specs/2026-07-09-infoflow-sidebar-run-detail-design.md\",\"docs/superpowers/specs/2026-07-10-scheduled-tasks-space-scoped-design.md\",\"docs/superpowers/specs/2026-07-11-marketing-flow-clarify-design.md\",\"docs/superpowers/specs/2026-07-13-aiflow-new-conversation-unpublished-draft-guard-design.md\",\"docs/superpowers/specs/2026-07-13-session-deliverables-enhancements-design.md\",\"docs/superpowers/specs/2026-07-14-on-reject-session-resume-design.md\",\"docs/superpowers/specs/2026-07-14-sidebar-sse-realtime-design.md\",\"docs/superpowers/specs/2026-07-15-aiflow-cli-skill-design.md\",\"docs/superpowers/specs/2026-07-15-anthropic-workflow-to-aiflow-convert-design.md\",\"docs/superpowers/specs/2026-07-15-artifact-drawer-auto-refresh-design.md\",\"docs/superpowers/specs/2026-07-16-infoflow-bubble-session-entry-design.md\",\"docs/superpowers/specs/2026-07-16-infoflow-sidebar-artifact-panel-design.md\",\"docs/superpowers/specs/2026-07-17-workflow-authoring-space-command-design.md\",\"docs/superpowers/specs/2026-07-18-platform-only-cli-design.md\",\"docs/superpowers/specs/2026-07-20-command-delete-design.md\",\"docs/superpowers/specs/2026-07-21-aiflow-skill-platform-cli-design.md\",\"docs/superpowers/specs/2026-07-21-anthropic-workflow-package-convert-design.md\",\"docs/superpowers/specs/2026-07-21-infoflow-abandon-workflow-button-design.md\",\"docs/superpowers/specs/2026-07-22-standard-dev-flow-design.md\",\"docs/superpowers/specs/2026-07-23-workflow-command-source-from-db-design.md\",\"docs/superpowers/specs/2026-07-27-loop-back-human-review-design.md\",\"docs/superpowers/specs/2026-07-27-online-event-data-governance-design.md\",\"docs/superpowers/specs/2026-07-27-workflow-custom-sandbox-image-design.md\",\"docs/superpowers/specs/2026-07-29-combo-multi-codebase-workflow-design.md\",\"docs/superpowers/specs/2026-07-29-workflow-restart-recovery-design.md\",\"docs/superpowers/specs/2026-07-30-conversation-turn-collapse-design.md\",\"docs/superpowers/specs/2026-07-30-session-task-model-switch-design.md\",\"docs/superpowers/specs/2026-07-31-try-it-list-design.md\",\"docs/superpowers/test-plans/2026-06-23-workflow-draft-staging-test-plan.md\",\"docs/superpowers/test-plans/db-inspect-guide.md\"],\"Other \u2014 testing\":[\"docs/testing/api-test-gate.md\",\"docs/testing/examples/delete_codebase_by_id_404.json\",\"docs/testing/examples/delete_codebase_env_key_404.json\",\"docs/testing/examples/delete_conversations.json\",\"docs/testing/examples/delete_ugate_token.json\",\"docs/testing/examples/get_alert_rules.json\",\"docs/testing/examples/get_alerts.json\",\"docs/testing/examples/get_alerts_preview.json\",\"docs/testing/examples/get_anomalies.json\",\"docs/testing/examples/get_archives.json\",\"docs/testing/examples/get_auth_me.json\",\"docs/testing/examples/get_codebase_by_id_404.json\",\"docs/testing/examples/get_codebase_env_404.json\",\"docs/testing/examples/get_codebases.json\",\"docs/testing/examples/get_comate_auth_token.json\",\"docs/testing/examples/get_combos.json\",\"docs/testing/examples/get_commands.json\",\"docs/testing/examples/get_config.json\",\"docs/testing/examples/get_conversations.json\",\"docs/testing/examples/get_cost_trends.json\",\"docs/testing/examples/get_evaluation_workflow_run_404.json\",\"docs/testing/examples/get_evaluations_aggregates.json\",\"docs/testing/examples/get_evaluations_workflows.json\",\"docs/testing/examples/get_failure_aggregates.json\",\"docs/testing/examples/get_gitcase_spaces.json\",\"docs/testing/examples/get_golden_samples.json\",\"docs/testing/examples/get_human_feedback.json\",\"docs/testing/examples/get_icafe_space.json\",\"docs/testing/examples/get_intelligence.json\",\"docs/testing/examples/get_product_spaces.json\",\"docs/testing/examples/get_product_spaces_mine.json\",\"docs/testing/examples/get_recording_guide.json\",\"docs/testing/examples/get_reliability.json\",\"docs/testing/examples/get_schema_migrations.json\",\"docs/testing/examples/get_schema_migrations_summary.json\",\"docs/testing/examples/get_settings_me.json\",\"docs/testing/examples/get_slow_node_trends.json\",\"docs/testing/examples/get_stale_runs.json\",\"docs/testing/examples/get_trace_by_id_404.json\",\"docs/testing/examples/get_traces.json\",\"docs/testing/examples/get_traces_health.json\",\"docs/testing/examples/get_ugate_token.json\",\"docs/testing/examples/get_ui_replay_audit_events.json\",\"docs/testing/examples/get_ui_replay_governance.json\",\"docs/testing/examples/get_ui_replay_quality_rules.json\",\"docs/testing/examples/get_ui_replay_recordings.json\",\"docs/testing/examples/get_ui_replay_runs.json\",\"docs/testing/examples/get_update_check.json\",\"docs/testing/examples/get_usage_aggregates.json\",\"docs/testing/examples/get_version_effectiveness.json\",\"docs/testing/examples/get_workflow_aggregates.json\",\"docs/testing/examples/get_workflow_by_name_404.json\",\"docs/testing/examples/get_workflow_run_by_id_404.json\",\"docs/testing/examples/get_workflow_run_by_worker_404.json\",\"docs/testing/examples/get_workflow_v2_by_id_404.json\",\"docs/testing/examples/patch_config_assistants.json\",\"docs/testing/examples/post_conversations.json\",\"docs/testing/examples/put_codebase_env_404.json\",\"docs/testing/specmatic-coverage.sh\",\"docs/testing/specmatic-doarchon-docker-test-guide.md\",\"docs/testing/specmatic-doarchon.yaml\",\"docs/testing/specmatic-integration.md\",\"docs/testing/specmatic-test.sh\",\"docs/testing/ui-replay-quality.md\"],\"Other \u2014 wiki-drafts\":[\"docs/wiki-drafts/PROMPT.md\",\"docs/wiki-drafts/feature-workflow-authoring.md\",\"docs/wiki-drafts/feature-workflow-isolation.md\"],\"Other \u2014 eslint.config.mjs\":[\"eslint.config.mjs\"],\"Other \u2014 migrations\":[\"migrations/000_combined.sql\",\"migrations/001_initial_schema.sql\",\"migrations/001_user_isolation.sql\",\"migrations/002_command_templates.sql\",\"migrations/002_product_spaces.sql\",\"migrations/003_add_worktree.sql\",\"migrations/004_worktree_sharing.sql\",\"migrations/005_isolation_abstraction.sql\",\"migrations/006_isolation_environments.sql\",\"migrations/007_drop_legacy_columns.sql\",\"migrations/008_workflow_runs.sql\",\"migrations/009_workflow_last_activity.sql\",\"migrations/010_immutable_sessions.sql\",\"migrations/011_partial_unique_constraint.sql\",\"migrations/012_workflow_events.sql\",\"migrations/013_conversation_titles.sql\",\"migrations/014_message_history.sql\",\"migrations/015_background_dispatch.sql\",\"migrations/016_session_ended_reason.sql\",\"migrations/017_drop_command_templates.sql\",\"migrations/018_fix_workflow_status_default.sql\",\"migrations/019_workflow_resume_path.sql\",\"migrations/020_codebase_env_vars.sql\",\"migrations/021_add_allow_env_keys_to_codebases.sql\",\"migrations/022_ugate_tokens.sql\",\"migrations/023_codebase_combos.sql\",\"migrations/023_runtime_trace.sql\",\"migrations/024_runtime_trace_alerts.sql\",\"migrations/024_ugate_token_icafe_space.sql\",\"migrations/025_runtime_trace_schema_migrations.sql\",\"migrations/026_runtime_trace_issue_id.sql\",\"migrations/027_workflow_evaluations.sql\",\"migrations/028_dedupe_workflow_evaluations.sql\",\"migrations/029_workflow_run_history_governance.sql\",\"migrations/030_evaluation_objective_datasets.sql\",\"migrations/031_trace_event_skill_name.sql\",\"migrations/032_runtime_trace_governance_indexes.sql\",\"migrations/032_sandbox.sql\",\"migrations/032_workflows_product_space.sql\",\"migrations/033_runtime_trace_schema_backfill.sql\",\"migrations/034_runtime_trace_query_indexes.sql\",\"migrations/035_space_codebases.sql\",\"migrations/035_workflow_run_access_scope.sql\",\"migrations/036_evolution_candidates.sql\",\"migrations/037_messages_created_at_timestamptz.sql\",\"migrations/038_error_details.sql\",\"migrations/039_message_knowledge_columns.sql\",\"migrations/040_ui_replay_persistence.sql\",\"migrations/041_ui_replay_audit.sql\",\"migrations/042_personal_space.sql\",\"migrations/042_workflow_definition_versions.sql\",\"migrations/043_workflow_project_source.sql\",\"migrations/044_observability_events.sql\",\"migrations/045_observability_user_activity_indexes.sql\",\"migrations/045_workflow_name_unique_per_space.sql\",\"migrations/047_conversations_product_space.sql\",\"migrations/048_observability_sla_performance_indexes.sql\",\"migrations/048_workflow_drafts.sql\",\"migrations/049_observability_sla_bucket_snapshots.sql\",\"migrations/051_conversation_branches.sql\",\"migrations/051_loop_back_state.sql\",\"migrations/052_space_commands.sql\",\"migrations/052_workflow_models.sql\",\"migrations/053_workflow_models_backfill.sql\",\"migrations/054_commands_market.sql\",\"migrations/055_workflow_run_command_scope.sql\",\"migrations/056_command_source_type.sql\",\"migrations/057_scheduled_tasks.sql\",\"migrations/058_workflow_run_trigger_source.sql\",\"migrations/059_scheduled_task_branch.sql\",\"migrations/060_scheduled_task_rename_prompt.sql\",\"migrations/061_workflow_version.sql\",\"migrations/062_scheduled_task_product_required.sql\",\"migrations/062_web_verify_steps.sql\",\"migrations/063_observability_sla_user_operation_metrics.sql\",\"migrations/063_user_department_profiles.sql\",\"migrations/064_sla_notification_deliveries.sql\",\"migrations/064_workflow_run_original_started_at.sql\",\"migrations/065_workflow_usage_index.sql\",\"migrations/066_observability_sla_snapshot_retention.sql\",\"migrations/067_observability_active_probe_history_index.sql\",\"migrations/068_observability_traffic_signal_covering_index.sql\",\"migrations/069_workflow_run_codebase_name.sql\",\"migrations/070_observability_sla_schema_reconciliation.sql\",\"migrations/071_observability_sla_online_indexes.sql\",\"migrations/072_observability_sla_snapshot_environment_signals.sql\",\"migrations/073_observability_sla_coverage_lookup_index.sql\",\"migrations/074_observability_sla_dirty_update_triggers.sql\",\"migrations/075_observability_sla_workflow_dirty_triggers.sql\",\"migrations/076_observability_sla_v5_frontend_noise_rebuild.sql\",\"migrations/077_sla_breach_monitoring.sql\",\"migrations/078_observability_sla_integrity_remediation.sql\",\"migrations/079_observability_sla_snapshot_generation.sql\",\"migrations/080_observability_sla_attribution_epoch_fence.sql\",\"migrations/081_observability_dashboard_facts.sql\",\"migrations/082_observability_sla_workflow_owned_failures.sql\",\"migrations/082_workflow_knowledge_observability.sql\",\"migrations/083_evaluation_effect_evidence.sql\",\"migrations/083_workflow_knowledge_sync_jobs.sql\",\"migrations/084_evaluation_benchmark_suites.sql\",\"migrations/084_workflow_knowledge_context_dedup.sql\",\"migrations/085_evaluation_knowledge_artifact_outbox.sql\",\"migrations/086_workflow_models_refresh.sql\",\"migrations/087_evaluation_jobs_runs.sql\",\"migrations/088_observability_sla_attribution_v8_epoch.sql\"],\"Other \u2014 package.json\":[\"package.json\"],\"Other \u2014 adapters\":[\"packages/adapters/package.json\",\"packages/adapters/src/chat/slack/adapter.test.ts\",\"packages/adapters/src/chat/slack/adapter.ts\",\"packages/adapters/src/chat/slack/auth.test.ts\",\"packages/adapters/src/chat/slack/auth.ts\",\"packages/adapters/src/chat/slack/index.ts\",\"packages/adapters/src/chat/slack/types.ts\",\"packages/adapters/src/chat/telegram/adapter.test.ts\",\"packages/adapters/src/chat/telegram/adapter.ts\",\"packages/adapters/src/chat/telegram/auth.test.ts\",\"packages/adapters/src/chat/telegram/auth.ts\",\"packages/adapters/src/chat/telegram/index.ts\",\"packages/adapters/src/chat/telegram/markdown.test.ts\",\"packages/adapters/src/chat/telegram/markdown.ts\",\"packages/adapters/src/chat/telegram/types.ts\",\"packages/adapters/src/community/chat/README.md\",\"packages/adapters/src/community/chat/discord/adapter.test.ts\",\"packages/adapters/src/community/chat/discord/adapter.ts\",\"packages/adapters/src/community/chat/discord/auth.test.ts\",\"packages/adapters/src/community/chat/discord/auth.ts\",\"packages/adapters/src/community/chat/discord/index.ts\",\"packages/adapters/src/community/chat/discord/types.ts\",\"packages/adapters/src/community/forge/README.md\",\"packages/adapters/src/community/forge/gitea/adapter-internals.test.ts\",\"packages/adapters/src/community/forge/gitea/adapter.test.ts\",\"packages/adapters/src/community/forge/gitea/adapter.ts\",\"packages/adapters/src/community/forge/gitea/auth.test.ts\",\"packages/adapters/src/community/forge/gitea/auth.ts\",\"packages/adapters/src/community/forge/gitea/index.ts\",\"packages/adapters/src/community/forge/gitea/types.ts\",\"packages/adapters/src/community/forge/gitlab/adapter-internals.test.ts\",\"packages/adapters/src/community/forge/gitlab/adapter.test.ts\",\"packages/adapters/src/community/forge/gitlab/adapter.ts\",\"packages/adapters/src/community/forge/gitlab/auth.test.ts\",\"packages/adapters/src/community/forge/gitlab/auth.ts\",\"packages/adapters/src/community/forge/gitlab/index.ts\",\"packages/adapters/src/community/forge/gitlab/types.ts\",\"packages/adapters/src/forge/github/adapter.test.ts\",\"packages/adapters/src/forge/github/adapter.ts\",\"packages/adapters/src/forge/github/auth.test.ts\",\"packages/adapters/src/forge/github/auth.ts\",\"packages/adapters/src/forge/github/context.test.ts\",\"packages/adapters/src/forge/github/index.ts\",\"packages/adapters/src/forge/github/types.ts\",\"packages/adapters/src/index.ts\",\"packages/adapters/src/utils/message-splitting.test.ts\",\"packages/adapters/tsconfig.json\"],\"Other \u2014 auth\":[\"packages/auth/package.json\",\"packages/auth/src/db.test.ts\",\"packages/auth/src/db.ts\",\"packages/auth/src/deptmember/client.test.ts\",\"packages/auth/src/deptmember/client.ts\",\"packages/auth/src/index.ts\",\"packages/auth/src/jwt.test.ts\",\"packages/auth/src/jwt.ts\",\"packages/auth/src/middleware.test.ts\",\"packages/auth/src/middleware.ts\",\"packages/auth/src/uic/client.test.ts\",\"packages/auth/src/uic/client.ts\",\"packages/auth/src/uuap/client.test.ts\",\"packages/auth/src/uuap/client.ts\",\"packages/auth/src/uuap/types.ts\",\"packages/auth/tsconfig.json\"],\"Other \u2014 cli\":[\"packages/cli/package.json\",\"packages/cli/src/adapters/cli-adapter.test.ts\",\"packages/cli/src/aiflow/auth.test.ts\",\"packages/cli/src/aiflow/auth.ts\",\"packages/cli/src/aiflow/client.test.ts\",\"packages/cli/src/aiflow/client.ts\",\"packages/cli/src/aiflow/commands/codebase.test.ts\",\"packages/cli/src/aiflow/commands/codebase.ts\",\"packages/cli/src/aiflow/commands/combo.test.ts\",\"packages/cli/src/aiflow/commands/combo.ts\",\"packages/cli/src/aiflow/commands/conversation.test.ts\",\"packages/cli/src/aiflow/commands/conversation.ts\",\"packages/cli/src/aiflow/commands/run.test.ts\",\"packages/cli/src/aiflow/commands/run.ts\",\"packages/cli/src/aiflow/commands/space.test.ts\",\"packages/cli/src/aiflow/commands/space.ts\",\"packages/cli/src/aiflow/commands/token.test.ts\",\"packages/cli/src/aiflow/commands/token.ts\",\"packages/cli/src/aiflow/commands/workflow.test.ts\",\"packages/cli/src/aiflow/commands/workflow.ts\",\"packages/cli/src/aiflow/file-upload.ts\",\"packages/cli/src/aiflow/format.test.ts\",\"packages/cli/src/aiflow/format.ts\",\"packages/cli/src/aiflow/platform.test.ts\",\"packages/cli/src/aiflow/platform.ts\",\"packages/cli/src/bundled-skill.ts\",\"packages/cli/src/cli-platform.test.ts\",\"packages/cli/src/cli-platform.ts\",\"packages/cli/src/cli.test.ts\",\"packages/cli/src/cli.ts\",\"packages/cli/src/commands/chat.test.ts\",\"packages/cli/src/commands/chat.ts\",\"packages/cli/src/commands/continue.ts\",\"packages/cli/src/commands/doctor.test.ts\",\"packages/cli/src/commands/doctor.ts\",\"packages/cli/src/commands/icafe-space.test.ts\",\"packages/cli/src/commands/icafe-space.ts\",\"packages/cli/src/commands/isolation.test.ts\",\"packages/cli/src/commands/isolation.ts\",\"packages/cli/src/commands/serve-binary.test.ts\",\"packages/cli/src/commands/serve.test.ts\",\"packages/cli/src/commands/serve.ts\",\"packages/cli/src/commands/setup-flow.test.ts\",\"packages/cli/src/commands/setup.test.ts\",\"packages/cli/src/commands/setup.ts\",\"packages/cli/src/commands/skill.test.ts\",\"packages/cli/src/commands/skill.ts\",\"packages/cli/src/commands/ugate-token.test.ts\",\"packages/cli/src/commands/ugate-token.ts\",\"packages/cli/src/commands/validate.ts\",\"packages/cli/src/commands/version.test.ts\",\"packages/cli/src/commands/version.ts\",\"packages/cli/src/commands/workflow.test.ts\",\"packages/cli/src/commands/workflow.ts\",\"packages/cli/tsconfig.json\"],\"Other \u2014 core\":[\"packages/core/package.json\",\"packages/core/src/config/config-loader.test.ts\",\"packages/core/src/config/config-loader.ts\",\"packages/core/src/config/config-types.ts\",\"packages/core/src/config/index.ts\",\"packages/core/src/db/adapters/index.ts\",\"packages/core/src/db/adapters/postgres.test.ts\",\"packages/core/src/db/adapters/postgres.ts\",\"packages/core/src/db/adapters/sqlite.test.ts\",\"packages/core/src/db/adapters/sqlite.ts\",\"packages/core/src/db/adapters/types.ts\",\"packages/core/src/db/assistant-override.ts\",\"packages/core/src/db/codebases.test.ts\",\"packages/core/src/db/codebases.ts\",\"packages/core/src/db/combos.test.ts\",\"packages/core/src/db/combos.ts\",\"packages/core/src/db/connection.test.ts\",\"packages/core/src/db/connection.ts\",\"packages/core/src/db/conversations.test.ts\",\"packages/core/src/db/conversations.ts\",\"packages/core/src/db/env-vars.test.ts\",\"packages/core/src/db/env-vars.ts\",\"packages/core/src/db/error-details.test.ts\",\"packages/core/src/db/error-details.ts\",\"packages/core/src/db/evaluation-benchmarks.ts\",\"packages/core/src/db/evaluation-evidence.ts\",\"packages/core/src/db/evaluation-knowledge-artifacts.ts\",\"packages/core/src/db/evaluations.test.ts\",\"packages/core/src/db/evaluations.ts\",\"packages/core/src/db/evolution.test.ts\",\"packages/core/src/db/evolution.ts\",\"packages/core/src/db/index.ts\",\"packages/core/src/db/isolation-environments.test.ts\",\"packages/core/src/db/isolation-environments.ts\",\"packages/core/src/db/knowledge-observations.test.ts\",\"packages/core/src/db/knowledge-observations.ts\",\"packages/core/src/db/knowledge-sync-jobs.test.ts\",\"packages/core/src/db/knowledge-sync-jobs.ts\",\"packages/core/src/db/messages.test.ts\",\"packages/core/src/db/messages.ts\",\"packages/core/src/db/migrate.test.ts\",\"packages/core/src/db/migrate.ts\",\"packages/core/src/db/observability.test.ts\",\"packages/core/src/db/observability.ts\",\"packages/core/src/db/personnel-usage.test.ts\",\"packages/core/src/db/personnel-usage.ts\",\"packages/core/src/db/product-spaces.test.ts\",\"packages/core/src/db/product-spaces.ts\",\"packages/core/src/db/runtime-traces.test.ts\",\"packages/core/src/db/runtime-traces.ts\",\"packages/core/src/db/sandbox-environments.test.ts\",\"packages/core/src/db/sandbox-environments.ts\",\"packages/core/src/db/scheduled-tasks.test.ts\",\"packages/core/src/db/scheduled-tasks.ts\",\"packages/core/src/db/sessions.test.ts\",\"packages/core/src/db/sessions.ts\",\"packages/core/src/db/sla-notification-deliveries.test.ts\",\"packages/core/src/db/sla-notification-deliveries.ts\",\"packages/core/src/db/space-commands.test.ts\",\"packages/core/src/db/space-commands.ts\",\"packages/core/src/db/ugate-tokens.test.ts\",\"packages/core/src/db/ugate-tokens.ts\",\"packages/core/src/db/ui-replay.ts\",\"packages/core/src/db/user-settings.test.ts\",\"packages/core/src/db/user-settings.ts\",\"packages/core/src/db/user-workflows.test.ts\",\"packages/core/src/db/user-workflows.ts\",\"packages/core/src/db/users.test.ts\",\"packages/core/src/db/users.ts\",\"packages/core/src/db/web-verify-steps.ts\",\"packages/core/src/db/workflow-definition-versions.test.ts\",\"packages/core/src/db/workflow-definition-versions.ts\",\"packages/core/src/db/workflow-drafts.test.ts\",\"packages/core/src/db/workflow-drafts.ts\",\"packages/core/src/db/workflow-events-loop-back.test.ts\",\"packages/core/src/db/workflow-events.test.ts\",\"packages/core/src/db/workflow-events.ts\",\"packages/core/src/db/workflow-loop-metrics.test.ts\",\"packages/core/src/db/workflow-loop-metrics.ts\",\"packages/core/src/db/workflow-models.test.ts\",\"packages/core/src/db/workflow-models.ts\",\"packages/core/src/db/workflow-run-trigger-source.test.ts\",\"packages/core/src/db/workflows-loop-back.test.ts\",\"packages/core/src/db/workflows-v2.test.ts\",\"packages/core/src/db/workflows-v2.ts\",\"packages/core/src/db/workflows.test.ts\",\"packages/core/src/db/workflows.ts\",\"packages/core/src/evaluation/event-bus.ts\",\"packages/core/src/handlers/clone.test.ts\",\"packages/core/src/handlers/clone.ts\",\"packages/core/src/handlers/command-handler.test.ts\",\"packages/core/src/handlers/command-handler.ts\",\"packages/core/src/handlers/command-handler.workflow-run.test.ts\",\"packages/core/src/handlers/icode-clone.test.ts\",\"packages/core/src/handlers/icode-clone.ts\",\"packages/core/src/index.ts\",\"packages/core/src/knowledge/product-resolver.test.ts\",\"packages/core/src/knowledge/product-resolver.ts\",\"packages/core/src/notifications/infoflow-client.oauth.test.ts\",\"packages/core/src/notifications/infoflow-client.test.ts\",\"packages/core/src/notifications/infoflow-client.ts\",\"packages/core/src/notifications/infoflow-sidebar-link.test.ts\",\"packages/core/src/notifications/infoflow-sidebar-link.ts\",\"packages/core/src/notifications/infoflow.test.ts\",\"packages/core/src/notifications/infoflow.ts\",\"packages/core/src/operations/index.ts\",\"packages/core/src/operations/isolation-operations.test.ts\",\"packages/core/src/operations/isolation-operations.ts\",\"packages/core/src/operations/workflow-operations.test.ts\",\"packages/core/src/operations/workflow-operations.ts\",\"packages/core/src/orchestrator/dispatchBackgroundWorkflow.test.ts\",\"packages/core/src/orchestrator/orchestrator-agent.test.ts\",\"packages/core/src/orchestrator/orchestrator-agent.ts\",\"packages/core/src/orchestrator/orchestrator-isolation.test.ts\",\"packages/core/src/orchestrator/orchestrator.test.ts\",\"packages/core/src/orchestrator/orchestrator.ts\",\"packages/core/src/orchestrator/prompt-builder.test.ts\",\"packages/core/src/orchestrator/prompt-builder.ts\",\"packages/core/src/orchestrator/sandbox-helpers.test.ts\",\"packages/core/src/orchestrator/sandbox-helpers.ts\",\"packages/core/src/orchestrator/workflow-authoring-command-list.test.ts\",\"packages/core/src/orchestrator/workflow-authoring-retry.ts\",\"packages/core/src/orchestrator/workflow-authoring.test.ts\",\"packages/core/src/orchestrator/workflow-authoring.ts\",\"packages/core/src/runtime/alerts.ts\",\"packages/core/src/runtime/cost.test.ts\",\"packages/core/src/runtime/cost.ts\",\"packages/core/src/runtime/emitter.test.ts\",\"packages/core/src/runtime/emitter.ts\",\"packages/core/src/runtime/evaluation-worker.test.ts\",\"packages/core/src/runtime/evaluation-worker.ts\",\"packages/core/src/runtime/ids.test.ts\",\"packages/core/src/runtime/ids.ts\",\"packages/core/src/runtime/index.ts\",\"packages/core/src/runtime/issue-clustering.test.ts\",\"packages/core/src/runtime/issue-clustering.ts\",\"packages/core/src/runtime/observability-bus.test.ts\",\"packages/core/src/runtime/observability-bus.ts\",\"packages/core/src/runtime/policy.test.ts\",\"packages/core/src/runtime/policy.ts\",\"packages/core/src/runtime/redaction.test.ts\",\"packages/core/src/runtime/redaction.ts\",\"packages/core/src/runtime/trace-bus.test.ts\",\"packages/core/src/runtime/trace-bus.ts\",\"packages/core/src/runtime/types.ts\",\"packages/core/src/runtime/workflow-trace-recorder.test.ts\",\"packages/core/src/runtime/workflow-trace-recorder.ts\",\"packages/core/src/scheduling/next-run.test.ts\",\"packages/core/src/scheduling/next-run.ts\",\"packages/core/src/scheduling/sandbox-envs-env.test.ts\",\"packages/core/src/scheduling/sandbox-envs.test.ts\",\"packages/core/src/scheduling/sandbox-envs.ts\",\"packages/core/src/scheduling/scheduled-task-runner.test.ts\",\"packages/core/src/scheduling/scheduled-task-runner.ts\",\"packages/core/src/services/cleanup-service.test.ts\",\"packages/core/src/services/codebase-restore-service.test.ts\",\"packages/core/src/services/evaluation-benchmark-service.test.ts\",\"packages/core/src/services/evaluation-benchmark-service.ts\",\"packages/core/src/services/evaluation-calibration-service.test.ts\",\"packages/core/src/services/evaluation-calibration-service.ts\",\"packages/core/src/services/evaluation-capability-readiness-service.test.ts\",\"packages/core/src/services/evaluation-capability-readiness-service.ts\",\"packages/core/src/services/evaluation-evidence-service.test.ts\",\"packages/core/src/services/evaluation-evidence-service.ts\",\"packages/core/src/services/evaluation-knowledge-artifact-service.test.ts\",\"packages/core/src/services/evaluation-service.test.ts\",\"packages/core/src/services/evaluation-service.ts\",\"packages/core/src/services/evolution-service.test.ts\",\"packages/core/src/services/failure-attribution-service.test.ts\",\"packages/core/src/services/golden-sample-candidate-service.test.ts\",\"packages/core/src/services/quality-gate-service.test.ts\",\"packages/core/src/services/runtime-intelligence.test.ts\",\"packages/core/src/services/title-generator.test.ts\",\"packages/core/src/services/ui-replay-assertions.test.ts\",\"packages/core/src/services/ui-replay-assertions.ts\",\"packages/core/src/state/session-transitions.test.ts\",\"packages/core/src/state/session-transitions.ts\",\"packages/core/src/test/mocks/database.ts\",\"packages/core/src/test/mocks/logger.ts\",\"packages/core/src/test/mocks/platform.ts\",\"packages/core/src/test/setup.ts\",\"packages/core/src/types/index.ts\",\"packages/core/src/utils/commands.test.ts\",\"packages/core/src/utils/commands.ts\",\"packages/core/src/utils/conversation-lock.test.ts\",\"packages/core/src/utils/conversation-lock.ts\",\"packages/core/src/utils/credential-sanitizer.test.ts\",\"packages/core/src/utils/credential-sanitizer.ts\",\"packages/core/src/utils/error-formatter.test.ts\",\"packages/core/src/utils/error-formatter.ts\",\"packages/core/src/utils/error.test.ts\",\"packages/core/src/utils/error.ts\",\"packages/core/src/utils/github-graphql.test.ts\",\"packages/core/src/utils/github-graphql.ts\",\"packages/core/src/utils/path-validation.test.ts\",\"packages/core/src/utils/path-validation.ts\",\"packages/core/src/utils/port-allocation.test.ts\",\"packages/core/src/utils/port-allocation.ts\",\"packages/core/src/utils/worktree-sync.test.ts\",\"packages/core/src/utils/worktree-sync.ts\",\"packages/core/src/workflows/index.ts\",\"packages/core/src/workflows/store-adapter.test.ts\",\"packages/core/src/workflows/store-adapter.ts\",\"packages/core/tsconfig.json\",\"packages/core/tsconfig.tsbuildinfo\"],\"Other \u2014 docs-web\":[\"packages/docs-web/astro.config.mjs\",\"packages/docs-web/package.json\",\"packages/docs-web/public/CNAME\",\"packages/docs-web/public/install\",\"packages/docs-web/public/install.ps1\",\"packages/docs-web/src/content.config.ts\",\"packages/docs-web/src/content/docs/adapters/community/discord.md\",\"packages/docs-web/src/content/docs/adapters/community/gitea.md\",\"packages/docs-web/src/content/docs/adapters/community/gitlab.md\",\"packages/docs-web/src/content/docs/adapters/github.md\",\"packages/docs-web/src/content/docs/adapters/index.md\",\"packages/docs-web/src/content/docs/adapters/slack.md\",\"packages/docs-web/src/content/docs/adapters/telegram.md\",\"packages/docs-web/src/content/docs/adapters/web.md\",\"packages/docs-web/src/content/docs/book/dag-workflows.md\",\"packages/docs-web/src/content/docs/book/essential-workflows.md\",\"packages/docs-web/src/content/docs/book/first-command.md\",\"packages/docs-web/src/content/docs/book/first-five-minutes.md\",\"packages/docs-web/src/content/docs/book/first-workflow.md\",\"packages/docs-web/src/content/docs/book/hooks-and-quality.md\",\"packages/docs-web/src/content/docs/book/how-it-works.md\",\"packages/docs-web/src/content/docs/book/index.md\",\"packages/docs-web/src/content/docs/book/isolation.md\",\"packages/docs-web/src/content/docs/book/quick-reference.md\",\"packages/docs-web/src/content/docs/book/what-is-archon.md\",\"packages/docs-web/src/content/docs/contributing/adding-a-community-provider.md\",\"packages/docs-web/src/content/docs/contributing/cli-internals.md\",\"packages/docs-web/src/content/docs/contributing/dx-quirks.md\",\"packages/docs-web/src/content/docs/contributing/index.md\",\"packages/docs-web/src/content/docs/contributing/new-developer-guide.md\",\"packages/docs-web/src/content/docs/contributing/releasing.md\",\"packages/docs-web/src/content/docs/deployment/cloud.md\",\"packages/docs-web/src/content/docs/deployment/docker.md\",\"packages/docs-web/src/content/docs/deployment/e2e-testing-wsl.md\",\"packages/docs-web/src/content/docs/deployment/e2e-testing.md\",\"packages/docs-web/src/content/docs/deployment/index.md\",\"packages/docs-web/src/content/docs/deployment/local.md\",\"packages/docs-web/src/content/docs/deployment/windows.md\",\"packages/docs-web/src/content/docs/getting-started/ai-assistants.md\",\"packages/docs-web/src/content/docs/getting-started/concepts.md\",\"packages/docs-web/src/content/docs/getting-started/configuration.md\",\"packages/docs-web/src/content/docs/getting-started/installation.md\",\"packages/docs-web/src/content/docs/getting-started/overview.md\",\"packages/docs-web/src/content/docs/getting-started/quick-start.md\",\"packages/docs-web/src/content/docs/guides/approval-nodes.md\",\"packages/docs-web/src/content/docs/guides/authoring-commands.md\",\"packages/docs-web/src/content/docs/guides/authoring-workflows.md\",\"packages/docs-web/src/content/docs/guides/global-workflows.md\",\"packages/docs-web/src/content/docs/guides/hooks.md\",\"packages/docs-web/src/content/docs/guides/index.md\",\"packages/docs-web/src/content/docs/guides/loop-nodes.md\",\"packages/docs-web/src/content/docs/guides/mcp-servers.md\",\"packages/docs-web/src/content/docs/guides/remotion-workflow.md\",\"packages/docs-web/src/content/docs/guides/script-nodes.md\",\"packages/docs-web/src/content/docs/guides/skills.md\",\"packages/docs-web/src/content/docs/index.mdx\",\"packages/docs-web/src/content/docs/reference/api.md\",\"packages/docs-web/src/content/docs/reference/architecture.md\",\"packages/docs-web/src/content/docs/reference/archon-directories.md\",\"packages/docs-web/src/content/docs/reference/cli.md\",\"packages/docs-web/src/content/docs/reference/commands.md\",\"packages/docs-web/src/content/docs/reference/configuration.md\",\"packages/docs-web/src/content/docs/reference/database.md\",\"packages/docs-web/src/content/docs/reference/index.md\",\"packages/docs-web/src/content/docs/reference/security.md\",\"packages/docs-web/src/content/docs/reference/troubleshooting.md\",\"packages/docs-web/src/content/docs/reference/variables.md\",\"packages/docs-web/src/styles/custom.css\",\"packages/docs-web/tsconfig.json\"],\"Other \u2014 git\":[\"packages/git/package.json\",\"packages/git/src/branch.ts\",\"packages/git/src/exec.test.ts\",\"packages/git/src/exec.ts\",\"packages/git/src/git.test.ts\",\"packages/git/src/index.ts\",\"packages/git/src/keyed-mutex.test.ts\",\"packages/git/src/keyed-mutex.ts\",\"packages/git/src/repo.ts\",\"packages/git/src/types.ts\",\"packages/git/src/worktree.ts\",\"packages/git/tsconfig.json\"],\"Other \u2014 isolation\":[\"packages/isolation/package.json\",\"packages/isolation/src/errors.test.ts\",\"packages/isolation/src/errors.ts\",\"packages/isolation/src/factory.test.ts\",\"packages/isolation/src/factory.ts\",\"packages/isolation/src/index.ts\",\"packages/isolation/src/pr-state.test.ts\",\"packages/isolation/src/pr-state.ts\",\"packages/isolation/src/providers/worktree.test.ts\",\"packages/isolation/src/providers/worktree.ts\",\"packages/isolation/src/resolver.test.ts\",\"packages/isolation/src/resolver.ts\",\"packages/isolation/src/store.ts\",\"packages/isolation/src/types.ts\",\"packages/isolation/src/worktree-copy.test.ts\",\"packages/isolation/src/worktree-copy.ts\",\"packages/isolation/tsconfig.json\"],\"Other \u2014 paths\":[\"packages/paths/package.json\",\"packages/paths/src/archon-paths.test.ts\",\"packages/paths/src/archon-paths.ts\",\"packages/paths/src/bundled-build.test.ts\",\"packages/paths/src/bundled-build.ts\",\"packages/paths/src/env-integration.test.ts\",\"packages/paths/src/env-loader.test.ts\",\"packages/paths/src/env-loader.ts\",\"packages/paths/src/index.ts\",\"packages/paths/src/logger.test.ts\",\"packages/paths/src/logger.ts\",\"packages/paths/src/mcp-init.test.ts\",\"packages/paths/src/mcp-init.ts\",\"packages/paths/src/strip-cwd-env-boot.ts\",\"packages/paths/src/strip-cwd-env.test.ts\",\"packages/paths/src/strip-cwd-env.ts\",\"packages/paths/src/telemetry.test.ts\",\"packages/paths/src/telemetry.ts\",\"packages/paths/src/update-check.test.ts\",\"packages/paths/src/update-check.ts\",\"packages/paths/tsconfig.json\"],\"Other \u2014 providers\":[\"packages/providers/package.json\",\"packages/providers/src/claude/binary-resolver-dev.test.ts\",\"packages/providers/src/claude/binary-resolver.test.ts\",\"packages/providers/src/claude/binary-resolver.ts\",\"packages/providers/src/claude/capabilities.ts\",\"packages/providers/src/claude/config.test.ts\",\"packages/providers/src/claude/config.ts\",\"packages/providers/src/claude/index.ts\",\"packages/providers/src/claude/provider.test.ts\",\"packages/providers/src/claude/provider.ts\",\"packages/providers/src/codex/binary-guard.test.ts\",\"packages/providers/src/codex/binary-resolver-dev.test.ts\",\"packages/providers/src/codex/binary-resolver.test.ts\",\"packages/providers/src/codex/binary-resolver.ts\",\"packages/providers/src/codex/capabilities.ts\",\"packages/providers/src/codex/config.test.ts\",\"packages/providers/src/codex/config.ts\",\"packages/providers/src/codex/index.ts\",\"packages/providers/src/codex/provider.test.ts\",\"packages/providers/src/codex/provider.ts\",\"packages/providers/src/community/pi/capabilities.ts\",\"packages/providers/src/community/pi/config.test.ts\",\"packages/providers/src/community/pi/config.ts\",\"packages/providers/src/community/pi/event-bridge.test.ts\",\"packages/providers/src/community/pi/event-bridge.ts\",\"packages/providers/src/community/pi/index.ts\",\"packages/providers/src/community/pi/model-ref.test.ts\",\"packages/providers/src/community/pi/model-ref.ts\",\"packages/providers/src/community/pi/options-translator.test.ts\",\"packages/providers/src/community/pi/options-translator.ts\",\"packages/providers/src/community/pi/provider-lazy-load.test.ts\",\"packages/providers/src/community/pi/provider.test.ts\",\"packages/providers/src/community/pi/provider.ts\",\"packages/providers/src/community/pi/registration.ts\",\"packages/providers/src/community/pi/resource-loader.ts\",\"packages/providers/src/community/pi/session-resolver.test.ts\",\"packages/providers/src/community/pi/session-resolver.ts\",\"packages/providers/src/community/pi/ui-context-stub.test.ts\",\"packages/providers/src/community/pi/ui-context-stub.ts\",\"packages/providers/src/errors.ts\",\"packages/providers/src/index.ts\",\"packages/providers/src/registry.test.ts\",\"packages/providers/src/registry.ts\",\"packages/providers/src/test/mocks/logger.ts\",\"packages/providers/src/types.ts\",\"packages/providers/src/workflow-models.test.ts\",\"packages/providers/src/workflow-models.ts\",\"packages/providers/tsconfig.json\"],\"Other \u2014 sandbox\":[\"packages/sandbox/package.json\",\"packages/sandbox/src/file-helpers.test.ts\",\"packages/sandbox/src/file-helpers.ts\",\"packages/sandbox/src/index.ts\",\"packages/sandbox/src/manager.test.ts\",\"packages/sandbox/src/manager.ts\",\"packages/sandbox/src/provider.test.ts\",\"packages/sandbox/src/provider.ts\",\"packages/sandbox/src/semaphore.test.ts\",\"packages/sandbox/src/semaphore.ts\",\"packages/sandbox/src/stream-parser.test.ts\",\"packages/sandbox/src/stream-parser.ts\",\"packages/sandbox/src/types.ts\",\"packages/sandbox/tsconfig.json\"],\"Other \u2014 server\":[\"packages/server/package.json\",\"packages/server/src/adapters/web/persistence.test.ts\",\"packages/server/src/adapters/web/persistence.ts\",\"packages/server/src/adapters/web/transport.test.ts\",\"packages/server/src/adapters/web/transport.ts\",\"packages/server/src/adapters/web/workflow-bridge-loop-back.test.ts\",\"packages/server/src/adapters/web/workflow-bridge.test.ts\",\"packages/server/src/adapters/web/workflow-bridge.ts\",\"packages/server/src/api-tests/brand-text-regression.test.ts\",\"packages/server/src/api-tests/contract.test.ts\",\"packages/server/src/api-tests/scenario.test.ts\",\"packages/server/src/api-tests/scheduled-tasks.test.ts\",\"packages/server/src/api-tests/workflow-run-product-scope.test.ts\",\"packages/server/src/api-tests/workflow-run-scheduled-gates.test.ts\",\"packages/server/src/api-tests/workflow-run-upload.test.ts\",\"packages/server/src/bos-client.test.ts\",\"packages/server/src/gitcase-client.test.ts\",\"packages/server/src/routes/api.bos.test.ts\",\"packages/server/src/routes/api.case-info.test.ts\",\"packages/server/src/routes/api.codebases.test.ts\",\"packages/server/src/routes/api.combos.test.ts\",\"packages/server/src/routes/api.commands-v2.test.ts\",\"packages/server/src/routes/api.commands-v2.ts\",\"packages/server/src/routes/api.conversations.test.ts\",\"packages/server/src/routes/api.debug-session.test.ts\",\"packages/server/src/routes/api.evaluations.test.ts\",\"packages/server/src/routes/api.gitcase.test.ts\",\"packages/server/src/routes/api.health.test.ts\",\"packages/server/src/routes/api.helpers.test.ts\",\"packages/server/src/routes/api.infoflow-webhook.test.ts\",\"packages/server/src/routes/api.infoflow.test.ts\",\"packages/server/src/routes/api.knowledge-chat-proxy.ts\",\"packages/server/src/routes/api.knowledge-chat.ts\",\"packages/server/src/routes/api.knowledge-proxy.test.ts\",\"packages/server/src/routes/api.knowledge-proxy.ts\",\"packages/server/src/routes/api.knowledge-sync-callback.test.ts\",\"packages/server/src/routes/api.knowledge.test.ts\",\"packages/server/src/routes/api.knowledge.ts\",\"packages/server/src/routes/api.messages.test.ts\",\"packages/server/src/routes/api.observability.test.ts\",\"packages/server/src/routes/api.personnel-usage.test.ts\",\"packages/server/src/routes/api.product-spaces.test.ts\",\"packages/server/src/routes/api.product-spaces.ts\",\"packages/server/src/routes/api.providers.test.ts\",\"packages/server/src/routes/api.runtime-traces.test.ts\",\"packages/server/src/routes/api.sandbox-file.test.ts\",\"packages/server/src/routes/api.ts\",\"packages/server/src/routes/api.ui-replay.test.ts\",\"packages/server/src/routes/api.web-verify-steps.test.ts\",\"packages/server/src/routes/api.webhooks.test.ts\",\"packages/server/src/routes/api.workflow-runs.test.ts\",\"packages/server/src/routes/api.workflows-v2.test.ts\",\"packages/server/src/routes/api.workflows-v2.ts\",\"packages/server/src/routes/api.workflows.test.ts\",\"packages/server/src/routes/api/bos-download.ts\",\"packages/server/src/routes/api/bos-preview.ts\",\"packages/server/src/routes/api/bos-upload.ts\",\"packages/server/src/routes/api/case-info.ts\",\"packages/server/src/routes/api/codebases.ts\",\"packages/server/src/routes/api/combos.ts\",\"packages/server/src/routes/api/conversations.ts\",\"packages/server/src/routes/api/debug-session.ts\",\"packages/server/src/routes/api/gitcase.ts\",\"packages/server/src/routes/api/helpers.ts\",\"packages/server/src/routes/api/infoflow-crypto.test.ts\",\"packages/server/src/routes/api/infoflow-crypto.ts\",\"packages/server/src/routes/api/infoflow-oauth.test.ts\",\"packages/server/src/routes/api/infoflow-oauth.ts\",\"packages/server/src/routes/api/infoflow-reply-routing.test.ts\",\"packages/server/src/routes/api/infoflow-reply-routing.ts\",\"packages/server/src/routes/api/infoflow-webhook.ts\",\"packages/server/src/routes/api/infoflow.ts\",\"packages/server/src/routes/api/knowledge-sync-callback.ts\",\"packages/server/src/routes/api/product-access.ts\",\"packages/server/src/routes/api/sandbox-file.ts\",\"packages/server/src/routes/api/scheduled-tasks.ts\",\"packages/server/src/routes/api/system.ts\",\"packages/server/src/routes/api/ui-replay.ts\",\"packages/server/src/routes/api/web-verify-steps.ts\",\"packages/server/src/routes/api/workflow-runs.ts\",\"packages/server/src/routes/api/workflows.ts\",\"packages/server/src/routes/api/zip-decompress.test.ts\",\"packages/server/src/routes/api/zip-decompress.ts\",\"packages/server/src/routes/auth.test.ts\",\"packages/server/src/routes/command-frontmatter.test.ts\",\"packages/server/src/routes/command-frontmatter.ts\",\"packages/server/src/routes/command-references.test.ts\",\"packages/server/src/routes/command-references.ts\",\"packages/server/src/routes/health.test.ts\",\"packages/server/src/routes/health.ts\",\"packages/server/src/routes/openapi-defaults.ts\",\"packages/server/src/routes/schemas/case-info.schemas.ts\",\"packages/server/src/routes/schemas/codebase.schemas.ts\",\"packages/server/src/routes/schemas/combo.schemas.ts\",\"packages/server/src/routes/schemas/command-v2.schemas.ts\",\"packages/server/src/routes/schemas/common.schemas.ts\",\"packages/server/src/routes/schemas/config.schemas.ts\",\"packages/server/src/routes/schemas/conversation.schemas.ts\",\"packages/server/src/routes/schemas/evaluation.schemas.ts\",\"packages/server/src/routes/schemas/evolution.schemas.ts\",\"packages/server/src/routes/schemas/gitcase.schemas.ts\",\"packages/server/src/routes/schemas/observability.schemas.ts\",\"packages/server/src/routes/schemas/personnel-usage.schemas.ts\",\"packages/server/src/routes/schemas/product-space.schemas.ts\",\"packages/server/src/routes/schemas/provider.schemas.ts\",\"packages/server/src/routes/schemas/runtime.schemas.ts\",\"packages/server/src/routes/schemas/scheduled-tasks.schemas.ts\",\"packages/server/src/routes/schemas/settings.schemas.ts\",\"packages/server/src/routes/schemas/system.schemas.ts\",\"packages/server/src/routes/schemas/ui-replay.schemas.ts\",\"packages/server/src/routes/schemas/web-verify.schemas.ts\",\"packages/server/src/routes/schemas/workflow.schemas.test.ts\",\"packages/server/src/routes/schemas/workflow.schemas.ts\",\"packages/server/src/routes/webhooks.ts\",\"packages/server/src/runtime-config.test.ts\",\"packages/server/src/scripts/backfill-forked-workflow-commands.ts\",\"packages/server/src/scripts/backfill-product-commands.ts\",\"packages/server/src/scripts/backfill-sla-classifications.ts\",\"packages/server/src/scripts/migrate-space-commands.ts\",\"packages/server/src/scripts/setup-auth.ts\",\"packages/server/src/services/callback-block.test.ts\",\"packages/server/src/services/infoflow-sender.test.ts\",\"packages/server/src/services/infoflow-webhook.test.ts\",\"packages/server/src/services/sla-infoflow-notifier.test.ts\",\"packages/server/src/services/workflow-access.test.ts\",\"packages/server/src/services/workflow-notification-listener.test.ts\",\"packages/server/src/services/workflow-restart-recovery.integration.test.ts\",\"packages/server/src/services/workflow-restart-recovery.test.ts\",\"packages/server/src/services/workflow-restart-recovery.ts\",\"packages/server/src/services/workflow-run-actions.test.ts\",\"packages/server/src/services/workflow-run-exporter.test.ts\",\"packages/server/src/services/workflow-run-knowledge-sync-dispatcher.test.ts\",\"packages/server/src/sync-bundled-commands.test.ts\",\"packages/server/src/sync-bundled-workflows.test.ts\",\"packages/server/src/sync-project-workflows.test.ts\",\"packages/server/src/sync-user-workflows.test.ts\",\"packages/server/src/test/workflow-mock-factories.ts\",\"packages/server/src/workers/sla-infoflow-worker.test.ts\",\"packages/server/tsconfig.json\",\"packages/server/tsconfig.tsbuildinfo\"],\"Other \u2014 web\":[\"packages/web/components.json\",\"packages/web/e2e/chat-primary-flow.spec.ts\",\"packages/web/e2e/console-flow.spec.ts\",\"packages/web/e2e/dashboard-paused-delete-flow.spec.ts\",\"packages/web/e2e/dashboard-review-flow.spec.ts\",\"packages/web/e2e/diagnostics-flow.spec.ts\",\"packages/web/e2e/evaluation-center-flow.spec.ts\",\"packages/web/e2e/fixtures.ts\",\"packages/web/e2e/governance-smoke.spec.ts\",\"packages/web/e2e/knowledge-eval-real.spec.ts\",\"packages/web/e2e/knowledge-flow.spec.ts\",\"packages/web/e2e/mock-helpers.ts\",\"packages/web/e2e/settings-flow.spec.ts\",\"packages/web/e2e/space-admin-flow.spec.ts\",\"packages/web/e2e/traces-redirect-flow.spec.ts\",\"packages/web/e2e/ui-replay-center-flow.spec.ts\",\"packages/web/e2e/ui-replay-smoke.spec.ts\",\"packages/web/e2e/workflow-run-flow.spec.ts\",\"packages/web/index.html\",\"packages/web/package.json\",\"packages/web/playwright.config.ts\",\"packages/web/postcss.config.mjs\",\"packages/web/src/App.sidebar-routes.test.ts\",\"packages/web/src/components/chat/ArtifactRail.tsx\",\"packages/web/src/components/chat/BreakpointRetry.tsx\",\"packages/web/src/components/chat/ChatInterface.tsx\",\"packages/web/src/components/chat/ComposerContextControls.test.tsx\",\"packages/web/src/components/chat/ComposerContextControls.tsx\",\"packages/web/src/components/chat/ErrorCard.tsx\",\"packages/web/src/components/chat/FileAttachmentChips.tsx\",\"packages/web/src/components/chat/InputRequestForm.test.tsx\",\"packages/web/src/components/chat/InputRequestForm.tsx\",\"packages/web/src/components/chat/LockIndicator.tsx\",\"packages/web/src/components/chat/MessageBubble.strip.test.ts\",\"packages/web/src/components/chat/MessageBubble.tsx\",\"packages/web/src/components/chat/MessageInput.test.tsx\",\"packages/web/src/components/chat/MessageInput.tsx\",\"packages/web/src/components/chat/MessageList.tsx\",\"packages/web/src/components/chat/ToolCallCard.tsx\",\"packages/web/src/components/chat/TryItList.test.ts\",\"packages/web/src/components/chat/TryItList.tsx\",\"packages/web/src/components/chat/WorkflowApprovalBar.tsx\",\"packages/web/src/components/chat/WorkflowProgressCard.tsx\",\"packages/web/src/components/chat/WorkflowSelector.test.tsx\",\"packages/web/src/components/chat/WorkflowSelector.tsx\",\"packages/web/src/components/chat/WorkflowStatusBar.tsx\",\"packages/web/src/components/chat/markdownLink.tsx\",\"packages/web/src/components/chat/strip-input-request.ts\",\"packages/web/src/components/chat/workflow-groups.test.ts\",\"packages/web/src/components/chat/workflow-groups.ts\",\"packages/web/src/components/commands/CommandCard.tsx\",\"packages/web/src/components/commands/CommandDetailDialog.tsx\",\"packages/web/src/components/commands/CommandEditorDialog.theme.test.ts\",\"packages/web/src/components/commands/CommandEditorDialog.tsx\",\"packages/web/src/components/commands/CommandList.tsx\",\"packages/web/src/components/commands/DeleteCommandDialog.tsx\",\"packages/web/src/components/commands/ForkCommandDialog.tsx\",\"packages/web/src/components/conversations/ConversationItem.tsx\",\"packages/web/src/components/dashboard/ConfirmRunActionDialog.tsx\",\"packages/web/src/components/dashboard/DashboardFilters.tsx\",\"packages/web/src/components/dashboard/DashboardTabCount.test.tsx\",\"packages/web/src/components/dashboard/SettingsConcurrencySection.test.ts\",\"packages/web/src/components/dashboard/StatusBoard.tsx\",\"packages/web/src/components/dashboard/StatusSummaryBar.test.tsx\",\"packages/web/src/components/dashboard/WorkflowHistoryTable.tsx\",\"packages/web/src/components/dashboard/WorkflowRunCard.test.ts\",\"packages/web/src/components/dashboard/WorkflowRunCard.tsx\",\"packages/web/src/components/dashboard/WorkflowRunGroup.tsx\",\"packages/web/src/components/document-drawer/DocumentDrawer.tsx\",\"packages/web/src/components/document-drawer/DocumentDrawerContent.tsx\",\"packages/web/src/components/document-drawer/LogDrawer.tsx\",\"packages/web/src/components/document-drawer/MindMapViewer.tsx\",\"packages/web/src/components/document-drawer/SyncGitCaseDialog.tsx\",\"packages/web/src/components/document-drawer/transformCaseJson.ts\",\"packages/web/src/components/knowledge/graph/ArchView.tsx\",\"packages/web/src/components/knowledge/graph/EntityCreateDialog.tsx\",\"packages/web/src/components/knowledge/graph/EntityDetailLegend.tsx\",\"packages/web/src/components/knowledge/graph/EntityDetailSheet.tsx\",\"packages/web/src/components/knowledge/graph/EntityListTable.tsx\",\"packages/web/src/components/knowledge/graph/GraphCanvas.tsx\",\"packages/web/src/components/knowledge/graph/GraphToolbar.tsx\",\"packages/web/src/components/knowledge/graph/RelationEditDialog.tsx\",\"packages/web/src/components/layout/AppSidebar.test.tsx\",\"packages/web/src/components/layout/AppSidebar.tsx\",\"packages/web/src/components/layout/BackendStatusBanner.tsx\",\"packages/web/src/components/layout/Header.tsx\",\"packages/web/src/components/layout/Layout.tsx\",\"packages/web/src/components/layout/OnboardingWizardModal.tsx\",\"packages/web/src/components/layout/OneApiTokenDialog.tsx\",\"packages/web/src/components/layout/SetupWizardModal.render.test.tsx\",\"packages/web/src/components/layout/SetupWizardModal.test.ts\",\"packages/web/src/components/layout/SetupWizardModal.tsx\",\"packages/web/src/components/layout/Sidebar.test.tsx\",\"packages/web/src/components/layout/brand-constants.ts\",\"packages/web/src/components/layout/topnav-utils.ts\",\"packages/web/src/components/observability/ObservabilityProvider.tsx\",\"packages/web/src/components/product-space/AddGroupDialog.tsx\",\"packages/web/src/components/product-space/AddMemberDialog.tsx\",\"packages/web/src/components/product-space/GroupTable.tsx\",\"packages/web/src/components/product-space/MemberTable.tsx\",\"packages/web/src/components/product-space/ProductSpaceForm.tsx\",\"packages/web/src/components/product-space/ProductSpaceSelector.tsx\",\"packages/web/src/components/product-space/SpaceComboSection.tsx\",\"packages/web/src/components/product-space/SpaceProjectsSection.delete-confirm.test.ts\",\"packages/web/src/components/product-space/SpaceProjectsSection.tsx\",\"packages/web/src/components/product-space/SpaceScheduledTasksSection.tsx\",\"packages/web/src/components/settings/TokenSections.mutation.test.tsx\",\"packages/web/src/components/settings/TokenSections.test.tsx\",\"packages/web/src/components/settings/TokenSections.tsx\",\"packages/web/src/components/sidebar/AllConversationsView.tsx\",\"packages/web/src/components/sidebar/ProjectDetail.tsx\",\"packages/web/src/components/sidebar/ProjectSelector.tsx\",\"packages/web/src/components/sidebar/SearchBar.test.tsx\",\"packages/web/src/components/sidebar/SearchBar.tsx\",\"packages/web/src/components/sidebar/SidebarAbandonBar.test.tsx\",\"packages/web/src/components/sidebar/SidebarAbandonBar.tsx\",\"packages/web/src/components/sidebar/SidebarArtifactList.test.tsx\",\"packages/web/src/components/sidebar/SidebarArtifactList.tsx\",\"packages/web/src/components/sidebar/SidebarArtifactPanel.test.tsx\",\"packages/web/src/components/sidebar/SidebarArtifactPanel.tsx\",\"packages/web/src/components/sidebar/SidebarArtifactView.test.tsx\",\"packages/web/src/components/sidebar/SidebarArtifactView.tsx\",\"packages/web/src/components/sidebar/SidebarComposer.test.tsx\",\"packages/web/src/components/sidebar/SidebarComposer.tsx\",\"packages/web/src/components/sidebar/SidebarConfirmDialog.test.tsx\",\"packages/web/src/components/sidebar/SidebarConfirmDialog.tsx\",\"packages/web/src/components/sidebar/SidebarDetailHeader.test.tsx\",\"packages/web/src/components/sidebar/SidebarDetailHeader.tsx\",\"packages/web/src/components/sidebar/SidebarRunDetail.test.tsx\",\"packages/web/src/components/sidebar/SidebarRunDetail.tsx\",\"packages/web/src/components/sidebar/WorkflowInvoker.test.tsx\",\"packages/web/src/components/sidebar/WorkflowInvoker.tsx\",\"packages/web/src/components/sidebar/open-external.ts\",\"packages/web/src/components/sidebar/sidebar-artifact-css.test.ts\",\"packages/web/src/components/sidebar/sidebar-artifacts.test.ts\",\"packages/web/src/components/sidebar/sidebar-artifacts.ts\",\"packages/web/src/components/sidebar/sidebar-auth.test.ts\",\"packages/web/src/components/sidebar/sidebar-auth.ts\",\"packages/web/src/components/sidebar/sidebar-download.test.ts\",\"packages/web/src/components/sidebar/sidebar-download.ts\",\"packages/web/src/components/sidebar/sidebar-turn-css.test.ts\",\"packages/web/src/components/sidebar/sidebar.css\",\"packages/web/src/components/sidebar/useSidebarAuthGuard.test.ts\",\"packages/web/src/components/sidebar/useSidebarAuthGuard.ts\",\"packages/web/src/components/sidebar/useSidebarRun.ts\",\"packages/web/src/components/ui/adapters.test.tsx\",\"packages/web/src/components/ui/alert-dialog.tsx\",\"packages/web/src/components/ui/badge.tsx\",\"packages/web/src/components/ui/button.tsx\",\"packages/web/src/components/ui/card.tsx\",\"packages/web/src/components/ui/collapsible.tsx\",\"packages/web/src/components/ui/combobox.tsx\",\"packages/web/src/components/ui/dialog.tsx\",\"packages/web/src/components/ui/dropdown-menu.tsx\",\"packages/web/src/components/ui/input.tsx\",\"packages/web/src/components/ui/popover.tsx\",\"packages/web/src/components/ui/primitives.test.tsx\",\"packages/web/src/components/ui/resizable.tsx\",\"packages/web/src/components/ui/scroll-area.tsx\",\"packages/web/src/components/ui/select.tsx\",\"packages/web/src/components/ui/separator.tsx\",\"packages/web/src/components/ui/sheet.tsx\",\"packages/web/src/components/ui/switch.tsx\",\"packages/web/src/components/ui/tabs.tsx\",\"packages/web/src/components/ui/textarea.tsx\",\"packages/web/src/components/ui/tooltip.tsx\",\"packages/web/src/components/ui/two-level-menu.tsx\",\"packages/web/src/components/workflows/AiBuilderPanel.autofix.test.ts\",\"packages/web/src/components/workflows/AiBuilderPanel.convert.test.tsx\",\"packages/web/src/components/workflows/AiBuilderPanel.tsx\",\"packages/web/src/components/workflows/ArtifactSummary.tsx\",\"packages/web/src/components/workflows/ArtifactViewerModal.tsx\",\"packages/web/src/components/workflows/AuthoringModelSelect.tsx\",\"packages/web/src/components/workflows/BuilderToolbar.tsx\",\"packages/web/src/components/workflows/CommandPicker.tsx\",\"packages/web/src/components/workflows/DagNodeComponent.test.ts\",\"packages/web/src/components/workflows/DagNodeComponent.tsx\",\"packages/web/src/components/workflows/DagNodeProgress.tsx\",\"packages/web/src/components/workflows/ExecutionDagNode.tsx\",\"packages/web/src/components/workflows/ForkWorkflowDialog.tsx\",\"packages/web/src/components/workflows/ImportAnthropicWorkflowDialog.test.ts\",\"packages/web/src/components/workflows/ImportAnthropicWorkflowDialog.tsx\",\"packages/web/src/components/workflows/LoopBackEdge.render.test.tsx\",\"packages/web/src/components/workflows/LoopBackEdge.test.tsx\",\"packages/web/src/components/workflows/LoopBackEdge.tsx\",\"packages/web/src/components/workflows/NodeInspector.tsx\",\"packages/web/src/components/workflows/NodeLibrary.tsx\",\"packages/web/src/components/workflows/NodePalette.tsx\",\"packages/web/src/components/workflows/PopularWorkflows.tsx\",\"packages/web/src/components/workflows/QuickAddPicker.tsx\",\"packages/web/src/components/workflows/StatusBar.tsx\",\"packages/web/src/components/workflows/StatusIcon.tsx\",\"packages/web/src/components/workflows/StepLogs.tsx\",\"packages/web/src/components/workflows/ValidationPanel.tsx\",\"packages/web/src/components/workflows/WorkflowBuilder.theme.test.ts\",\"packages/web/src/components/workflows/WorkflowBuilder.toolbar.test.ts\",\"packages/web/src/components/workflows/WorkflowBuilder.tsx\",\"packages/web/src/components/workflows/WorkflowCanvas.nodeLabel.test.ts\",\"packages/web/src/components/workflows/WorkflowCanvas.test.ts\",\"packages/web/src/components/workflows/WorkflowCanvas.tsx\",\"packages/web/src/components/workflows/WorkflowCard.test.ts\",\"packages/web/src/components/workflows/WorkflowCard.tsx\",\"packages/web/src/components/workflows/WorkflowDagViewer.tsx\",\"packages/web/src/components/workflows/WorkflowDetail.tsx\",\"packages/web/src/components/workflows/WorkflowExecution.tsx\",\"packages/web/src/components/workflows/WorkflowList.delete-confirm.test.ts\",\"packages/web/src/components/workflows/WorkflowList.sidebar-filter.test.ts\",\"packages/web/src/components/workflows/WorkflowList.tsx\",\"packages/web/src/components/workflows/WorkflowLogs.tsx\",\"packages/web/src/components/workflows/WorkflowModelSelect.tsx\",\"packages/web/src/components/workflows/WorkflowScopeBadge.tsx\",\"packages/web/src/components/workflows/WorkflowSourceBadge.test.ts\",\"packages/web/src/components/workflows/WorkflowSourceBadge.tsx\",\"packages/web/src/components/workflows/WorkflowSpaceSelector.tsx\",\"packages/web/src/components/workflows/YamlCodeView.test.ts\",\"packages/web/src/components/workflows/YamlCodeView.tsx\",\"packages/web/src/components/workflows/use-popular-workflows.test.ts\",\"packages/web/src/components/workflows/use-popular-workflows.ts\",\"packages/web/src/contexts/OnboardingContext.tsx\",\"packages/web/src/contexts/ProjectContext.model-memory.test.ts\",\"packages/web/src/contexts/ProjectContext.tsx\",\"packages/web/src/contexts/ThemeContext.tsx\",\"packages/web/src/contexts/TokenValidationContext.test.tsx\",\"packages/web/src/contexts/TokenValidationContext.tsx\",\"packages/web/src/contexts/model-memory.ts\",\"packages/web/src/hooks/stream-hooks.test.ts\",\"packages/web/src/hooks/useApiAvailability.test.ts\",\"packages/web/src/hooks/useApiAvailability.ts\",\"packages/web/src/hooks/useAutoScroll.ts\",\"packages/web/src/hooks/useBuilderKeyboard.test.ts\",\"packages/web/src/hooks/useBuilderKeyboard.ts\",\"packages/web/src/hooks/useBuilderUndo.ts\",\"packages/web/src/hooks/useBuilderValidation.ts\",\"packages/web/src/hooks/useClickOutside.ts\",\"packages/web/src/hooks/useConversationStream.test.ts\",\"packages/web/src/hooks/useConversationStream.ts\",\"packages/web/src/hooks/useDashboardSSE.ts\",\"packages/web/src/hooks/useDocumentDrawer.ts\",\"packages/web/src/hooks/useEvaluationSSE.ts\",\"packages/web/src/hooks/useFileAttachments.ts\",\"packages/web/src/hooks/useKeyboardShortcuts.ts\",\"packages/web/src/hooks/useObservabilitySSE.ts\",\"packages/web/src/hooks/usePollingWhenRunning.test.ts\",\"packages/web/src/hooks/usePollingWhenRunning.ts\",\"packages/web/src/hooks/useProviders.ts\",\"packages/web/src/hooks/useRuntimeTraceSSE.ts\",\"packages/web/src/hooks/useSSE.ts\",\"packages/web/src/hooks/useServerValidation.test.ts\",\"packages/web/src/hooks/useServerValidation.ts\",\"packages/web/src/hooks/useSetupStatus.ts\",\"packages/web/src/hooks/useWorkflowDraftSync.test.ts\",\"packages/web/src/hooks/useWorkflowDraftSync.ts\",\"packages/web/src/hooks/useWorkflowModels.ts\",\"packages/web/src/index.css\",\"packages/web/src/lib/api-availability.test.ts\",\"packages/web/src/lib/api-availability.ts\",\"packages/web/src/lib/api.test.ts\",\"packages/web/src/lib/api.ts\",\"packages/web/src/lib/artifact-grouping.test.ts\",\"packages/web/src/lib/artifact-grouping.ts\",\"packages/web/src/lib/breakpoint-retry.test.ts\",\"packages/web/src/lib/breakpoint-retry.ts\",\"packages/web/src/lib/chat-message-reducer.test.ts\",\"packages/web/src/lib/chat-message-reducer.ts\",\"packages/web/src/lib/clarify-request.test.ts\",\"packages/web/src/lib/codebase-input.test.ts\",\"packages/web/src/lib/codebase-input.ts\",\"packages/web/src/lib/command-categories.ts\",\"packages/web/src/lib/composer-persistence.test.ts\",\"packages/web/src/lib/composer-persistence.ts\",\"packages/web/src/lib/conversation-grouping.test.ts\",\"packages/web/src/lib/conversation-grouping.ts\",\"packages/web/src/lib/currency.test.ts\",\"packages/web/src/lib/currency.ts\",\"packages/web/src/lib/dag-layout-loop-back.test.ts\",\"packages/web/src/lib/dag-layout.test.ts\",\"packages/web/src/lib/dag-layout.ts\",\"packages/web/src/lib/dashboard-tab-count.ts\",\"packages/web/src/lib/extract-message-artifacts.test.ts\",\"packages/web/src/lib/extract-message-artifacts.ts\",\"packages/web/src/lib/file-attachments.test.ts\",\"packages/web/src/lib/file-attachments.ts\",\"packages/web/src/lib/format.test.ts\",\"packages/web/src/lib/format.ts\",\"packages/web/src/lib/keyboard.ts\",\"packages/web/src/lib/knowledge/api-key.test.ts\",\"packages/web/src/lib/knowledge/api-key.ts\",\"packages/web/src/lib/knowledge/api.graph-inspection.test.ts\",\"packages/web/src/lib/knowledge/api.test.ts\",\"packages/web/src/lib/knowledge/api.ts\",\"packages/web/src/lib/knowledge/arch-constants.tsx\",\"packages/web/src/lib/knowledge/build-status.test.ts\",\"packages/web/src/lib/knowledge/build-status.ts\",\"packages/web/src/lib/knowledge/constants.ts\",\"packages/web/src/lib/knowledge/entity-form.test.ts\",\"packages/web/src/lib/knowledge/entity-form.ts\",\"packages/web/src/lib/knowledge/force-graph.ts\",\"packages/web/src/lib/knowledge/mock-data.ts\",\"packages/web/src/lib/knowledge/relation-target.test.ts\",\"packages/web/src/lib/knowledge/relation-target.ts\",\"packages/web/src/lib/knowledge/source-parser.ts\",\"packages/web/src/lib/knowledge/types.ts\",\"packages/web/src/lib/knowledge/wiki-api.ts\",\"packages/web/src/lib/knowledge/wiki-version-api.ts\",\"packages/web/src/lib/message-cache.test.ts\",\"packages/web/src/lib/message-cache.ts\",\"packages/web/src/lib/message-mapper.test.ts\",\"packages/web/src/lib/message-mapper.ts\",\"packages/web/src/lib/message-turns.test.ts\",\"packages/web/src/lib/message-turns.ts\",\"packages/web/src/lib/observability-query-keys.ts\",\"packages/web/src/lib/observability.test.ts\",\"packages/web/src/lib/observability.ts\",\"packages/web/src/lib/onboarding-nav.test.ts\",\"packages/web/src/lib/onboarding-nav.ts\",\"packages/web/src/lib/overflow-utils.test.ts\",\"packages/web/src/lib/overflow-utils.ts\",\"packages/web/src/lib/project-scope.test.ts\",\"packages/web/src/lib/project-scope.ts\",\"packages/web/src/lib/query-client.ts\",\"packages/web/src/lib/runtime-config.ts\",\"packages/web/src/lib/runtime-trace-insights.test.ts\",\"packages/web/src/lib/runtime-trace-insights.ts\",\"packages/web/src/lib/scheduled-task-polling.test.ts\",\"packages/web/src/lib/scheduled-task-polling.ts\",\"packages/web/src/lib/select-initial-node.test.ts\",\"packages/web/src/lib/select-initial-node.ts\",\"packages/web/src/lib/session-status-colors.test.ts\",\"packages/web/src/lib/session-status-colors.ts\",\"packages/web/src/lib/session-url-validation.test.ts\",\"packages/web/src/lib/session-url-validation.ts\",\"packages/web/src/lib/settings-copy.test.ts\",\"packages/web/src/lib/settings-copy.ts\",\"packages/web/src/lib/sidebar-progress.test.ts\",\"packages/web/src/lib/sidebar-progress.ts\",\"packages/web/src/lib/status-summary-bar-utils.ts\",\"packages/web/src/lib/types.ts\",\"packages/web/src/lib/utils.ts\",\"packages/web/src/lib/workflow-builder-canvas-status.test.ts\",\"packages/web/src/lib/workflow-builder-canvas-status.ts\",\"packages/web/src/lib/workflow-draft-content.test.ts\",\"packages/web/src/lib/workflow-draft-content.ts\",\"packages/web/src/lib/workflow-events.test.ts\",\"packages/web/src/lib/workflow-events.ts\",\"packages/web/src/lib/workflow-history-table-styles.test.ts\",\"packages/web/src/lib/workflow-history-table-styles.ts\",\"packages/web/src/lib/workflow-metadata.test.ts\",\"packages/web/src/lib/workflow-metadata.ts\",\"packages/web/src/lib/workflow-node-type.test.ts\",\"packages/web/src/lib/workflow-node-type.ts\",\"packages/web/src/lib/workflow-run-state.test.ts\",\"packages/web/src/lib/workflow-run-state.ts\",\"packages/web/src/lib/workflow-scope.test.ts\",\"packages/web/src/lib/workflow-scope.ts\",\"packages/web/src/lib/workflow-stage-mapping.ts\",\"packages/web/src/lib/workflow-usage-timing.test.ts\",\"packages/web/src/lib/workflow-usage-timing.ts\",\"packages/web/src/lib/workflow-usage-trace.test.ts\",\"packages/web/src/lib/workflow-usage-trace.ts\",\"packages/web/src/lib/workflow-utils.test.ts\",\"packages/web/src/lib/workflow-utils.ts\",\"packages/web/src/routes/ChatPage.test.tsx\",\"packages/web/src/routes/ChatPage.tsx\",\"packages/web/src/routes/ControlConsolePage.tsx\",\"packages/web/src/routes/DashboardPage.tsx\",\"packages/web/src/routes/EvaluationSlaPage.render.test.tsx\",\"packages/web/src/routes/EvaluationSlaPage.test.ts\",\"packages/web/src/routes/EvaluationSlaPage.theme.test.tsx\",\"packages/web/src/routes/LoginPage.tsx\",\"packages/web/src/routes/PersonnelUsagePage.test.tsx\",\"packages/web/src/routes/PersonnelUsagePage.tsx\",\"packages/web/src/routes/ProductSpacePage.tsx\",\"packages/web/src/routes/RealtimeEvaluationPage.tsx\",\"packages/web/src/routes/SettingsPage.tsx\",\"packages/web/src/routes/SidebarListPage.test.tsx\",\"packages/web/src/routes/SidebarListPage.tsx\",\"packages/web/src/routes/SidebarRunPage.test.tsx\",\"packages/web/src/routes/SidebarRunPage.tsx\",\"packages/web/src/routes/SidebarStartPage.test.tsx\",\"packages/web/src/routes/SidebarStartPage.tsx\",\"packages/web/src/routes/WorkflowBuilderPage.tsx\",\"packages/web/src/routes/WorkflowDetailPage.tsx\",\"packages/web/src/routes/WorkflowExecutionPage.tsx\",\"packages/web/src/routes/WorkflowSpacePage.tsx\",\"packages/web/src/routes/WorkflowUsagePage.tsx\",\"packages/web/src/routes/control-console/debug.tsx\",\"packages/web/src/routes/control-console/governance.tsx\",\"packages/web/src/routes/control-console/overview.render.test.tsx\",\"packages/web/src/routes/control-console/overview.test.ts\",\"packages/web/src/routes/control-console/overview.tsx\",\"packages/web/src/routes/control-console/runForScope.test.ts\",\"packages/web/src/routes/control-console/shared.test.ts\",\"packages/web/src/routes/control-console/shared.tsx\",\"packages/web/src/routes/control-console/topology.test.tsx\",\"packages/web/src/routes/control-console/topology.tsx\",\"packages/web/src/routes/control-console/workflows.raw-download.test.tsx\",\"packages/web/src/routes/control-console/workflows.scroll.test.tsx\",\"packages/web/src/routes/control-console/workflows.select-trace.test.tsx\",\"packages/web/src/routes/control-console/workflows.spacing.test.ts\",\"packages/web/src/routes/control-console/workflows.trace-list.test.ts\",\"packages/web/src/routes/control-console/workflows.tsx\",\"packages/web/src/routes/knowledge/AikuApiKeyDialog.render.test.tsx\",\"packages/web/src/routes/knowledge/AikuApiKeyDialog.state.test.tsx\",\"packages/web/src/routes/knowledge/AikuApiKeyDialog.test.tsx\",\"packages/web/src/routes/knowledge/AikuApiKeyDialog.tsx\",\"packages/web/src/routes/knowledge/DocsSection.tsx\",\"packages/web/src/routes/knowledge/GraphSection.tsx\",\"packages/web/src/routes/knowledge/QualitySection.tsx\",\"packages/web/src/routes/knowledge/audit/AuditSection.test.tsx\",\"packages/web/src/routes/knowledge/audit/AuditSection.tsx\",\"packages/web/src/routes/knowledge/bootstrap/ark-import.tsx\",\"packages/web/src/routes/knowledge/bootstrap/doc-upload-button.test.tsx\",\"packages/web/src/routes/knowledge/bootstrap/doc-upload-button.tsx\",\"packages/web/src/routes/knowledge/bootstrap/index.tsx\",\"packages/web/src/routes/knowledge/bootstrap/smart-fill.test.tsx\",\"packages/web/src/routes/knowledge/bootstrap/smart-fill.tsx\",\"packages/web/src/routes/knowledge/bootstrap/step-testcases.test.tsx\",\"packages/web/src/routes/knowledge/bootstrap/step-testcases.tsx\",\"packages/web/src/routes/knowledge/bootstrap/step1-browse.test.tsx\",\"packages/web/src/routes/knowledge/bootstrap/step1-browse.tsx\",\"packages/web/src/routes/knowledge/bootstrap/step1.test.tsx\",\"packages/web/src/routes/knowledge/bootstrap/step1.tsx\",\"packages/web/src/routes/knowledge/bootstrap/step2.tsx\",\"packages/web/src/routes/knowledge/bootstrap/step3.tsx\",\"packages/web/src/routes/knowledge/bootstrap/ui.test.tsx\",\"packages/web/src/routes/knowledge/bootstrap/ui.tsx\",\"packages/web/src/routes/knowledge/eval/EvalHistorySheet.test.tsx\",\"packages/web/src/routes/knowledge/eval/EvalHistorySheet.tsx\",\"packages/web/src/routes/knowledge/eval/EvalQuestionCreate.test.tsx\",\"packages/web/src/routes/knowledge/eval/EvalQuestionCreate.tsx\",\"packages/web/src/routes/knowledge/eval/EvalQuestionEdit.test.tsx\",\"packages/web/src/routes/knowledge/eval/EvalQuestionEdit.tsx\",\"packages/web/src/routes/knowledge/eval/EvalSection.test.tsx\",\"packages/web/src/routes/knowledge/eval/EvalSection.tsx\",\"packages/web/src/routes/knowledge/eval/EvalSetDetail.test.tsx\",\"packages/web/src/routes/knowledge/eval/EvalSetDetail.tsx\",\"packages/web/src/routes/knowledge/eval/EvalSetHistorySheet.test.tsx\",\"packages/web/src/routes/knowledge/eval/EvalSetHistorySheet.tsx\",\"packages/web/src/routes/knowledge/eval/EvalSetList.test.tsx\",\"packages/web/src/routes/knowledge/eval/EvalSetList.tsx\",\"packages/web/src/routes/knowledge/eval/FeedbackImportSheet.test.tsx\",\"packages/web/src/routes/knowledge/eval/FeedbackImportSheet.tsx\",\"packages/web/src/routes/knowledge/eval/dimensions.test.ts\",\"packages/web/src/routes/knowledge/eval/dimensions.ts\",\"packages/web/src/routes/knowledge/evaluation/CaseResultDrawer.test.tsx\",\"packages/web/src/routes/knowledge/evaluation/CaseResultDrawer.tsx\",\"packages/web/src/routes/knowledge/evaluation/EvaluationSection.test.tsx\",\"packages/web/src/routes/knowledge/evaluation/EvaluationSection.tsx\",\"packages/web/src/routes/knowledge/evaluation/LatestRunSummary.test.tsx\",\"packages/web/src/routes/knowledge/evaluation/LatestRunSummary.tsx\",\"packages/web/src/routes/knowledge/evaluation/RunDetail.test.tsx\",\"packages/web/src/routes/knowledge/evaluation/RunDetail.tsx\",\"packages/web/src/routes/knowledge/evaluation/RunList.test.tsx\",\"packages/web/src/routes/knowledge/evaluation/RunList.tsx\",\"packages/web/src/routes/knowledge/evaluation/RunReport.test.tsx\",\"packages/web/src/routes/knowledge/evaluation/RunReport.tsx\",\"packages/web/src/routes/knowledge/evaluation/TriggerRunDialog.test.tsx\",\"packages/web/src/routes/knowledge/evaluation/TriggerRunDialog.tsx\",\"packages/web/src/routes/knowledge/evaluation/api-hooks.ts\",\"packages/web/src/routes/knowledge/evaluation/index.ts\",\"packages/web/src/routes/knowledge/evaluation/shared.test.tsx\",\"packages/web/src/routes/knowledge/evaluation/shared.tsx\",\"packages/web/src/routes/knowledge/governance/CandidateDetailDialog.test.tsx\",\"packages/web/src/routes/knowledge/governance/CandidateDetailDialog.tsx\",\"packages/web/src/routes/knowledge/governance/CandidateReviewPanel.test.tsx\",\"packages/web/src/routes/knowledge/governance/CandidateReviewPanel.tsx\",\"packages/web/src/routes/knowledge/governance/GovernanceSection.test.tsx\",\"packages/web/src/routes/knowledge/governance/GovernanceSection.tsx\",\"packages/web/src/routes/knowledge/governance/InspectionReportDetail.test.tsx\",\"packages/web/src/routes/knowledge/governance/InspectionReportDetail.tsx\",\"packages/web/src/routes/knowledge/governance/helpers.test.tsx\",\"packages/web/src/routes/knowledge/governance/helpers.tsx\",\"packages/web/src/routes/knowledge/graph/ArchitectureViewPage.test.tsx\",\"packages/web/src/routes/knowledge/graph/ArchitectureViewPage.tsx\",\"packages/web/src/routes/knowledge/graph/EntityBrowserPage.test.tsx\",\"packages/web/src/routes/knowledge/graph/EntityBrowserPage.tsx\",\"packages/web/src/routes/knowledge/graph/GraphPage.test.tsx\",\"packages/web/src/routes/knowledge/graph/GraphPage.tsx\",\"packages/web/src/routes/knowledge/integrity/IntegritySection.render.test.tsx\",\"packages/web/src/routes/knowledge/integrity/IntegritySection.test.tsx\",\"packages/web/src/routes/knowledge/integrity/IntegritySection.tsx\",\"packages/web/src/routes/knowledge/shared.test.ts\",\"packages/web/src/routes/knowledge/shared.tsx\",\"packages/web/src/routes/knowledge/usage/UsageStatsSection.test.tsx\",\"packages/web/src/routes/knowledge/usage/UsageStatsSection.tsx\",\"packages/web/src/routes/knowledge/useKnowledgeBuildStatus.ts\",\"packages/web/src/routes/knowledge/wiki/WikiChangeBanner.tsx\",\"packages/web/src/routes/knowledge/wiki/WikiComposePane.test.tsx\",\"packages/web/src/routes/knowledge/wiki/WikiComposePane.tsx\",\"packages/web/src/routes/knowledge/wiki/WikiDiffView.tsx\",\"packages/web/src/routes/knowledge/wiki/WikiDocPane.test.tsx\",\"packages/web/src/routes/knowledge/wiki/WikiDocPane.tsx\",\"packages/web/src/routes/knowledge/wiki/WikiHistoryDialog.tsx\",\"packages/web/src/routes/knowledge/wiki/WikiPendingPane.test.tsx\",\"packages/web/src/routes/knowledge/wiki/WikiPendingPane.tsx\",\"packages/web/src/routes/knowledge/wiki/WikiSection.test.tsx\",\"packages/web/src/routes/knowledge/wiki/WikiSection.tsx\",\"packages/web/src/routes/knowledge/wiki/WikiTree.test.tsx\",\"packages/web/src/routes/knowledge/wiki/WikiTree.tsx\",\"packages/web/src/routes/realtime-evaluation/RealtimeEvaluationChrome.tsx\",\"packages/web/src/routes/realtime-evaluation/RealtimeEvaluationContent.tsx\",\"packages/web/src/routes/realtime-evaluation/WorkflowUsageSection.tsx\",\"packages/web/src/routes/realtime-evaluation/evaluation-view-model.test.ts\",\"packages/web/src/routes/realtime-evaluation/evaluation-view-model.ts\",\"packages/web/src/routes/realtime-evaluation/shared.test.ts\",\"packages/web/src/routes/realtime-evaluation/shared.tsx\",\"packages/web/src/routes/realtime-evaluation/useRealtimeEvaluationPageState.test.tsx\",\"packages/web/src/routes/realtime-evaluation/useRealtimeEvaluationPageState.ts\",\"packages/web/src/routes/realtime-evaluation/workflow-usage-metrics.test.ts\",\"packages/web/src/routes/sidebar-common.tsx\",\"packages/web/src/routes/ui-replay/UiReplayCenterPage.tsx\",\"packages/web/src/routes/ui-replay/browserReplay.ts\",\"packages/web/src/routes/ui-replay/codegen.ts\",\"packages/web/src/routes/ui-replay/components.tsx\",\"packages/web/src/routes/ui-replay/constants.ts\",\"packages/web/src/routes/ui-replay/format.ts\",\"packages/web/src/routes/ui-replay/types.ts\",\"packages/web/src/routes/ui-replay/useIframeRecorder.ts\",\"packages/web/src/stores/auth-store.test.ts\",\"packages/web/src/stores/product-space-store.test.ts\",\"packages/web/src/stores/product-space-store.ts\",\"packages/web/src/stores/sidebar-store.ts\",\"packages/web/src/stores/workflow-space-store.test.ts\",\"packages/web/src/stores/workflow-space-store.ts\",\"packages/web/src/stores/workflow-store-loop-back-hydrate.test.ts\",\"packages/web/src/stores/workflow-store-loop-back.test.ts\",\"packages/web/src/stores/workflow-store.test.ts\",\"packages/web/src/stores/workflow-store.ts\",\"packages/web/tsconfig.json\",\"packages/web/vite.config.ts\"],\"Other \u2014 workflows\":[\"packages/workflows/package.json\",\"packages/workflows/src/artifact-publisher.test.ts\",\"packages/workflows/src/artifact-publisher.ts\",\"packages/workflows/src/combo-codebases.test.ts\",\"packages/workflows/src/combo-codebases.ts\",\"packages/workflows/src/command-discovery.test.ts\",\"packages/workflows/src/command-discovery.ts\",\"packages/workflows/src/command-validation.test.ts\",\"packages/workflows/src/command-validation.ts\",\"packages/workflows/src/condition-evaluator.test.ts\",\"packages/workflows/src/condition-evaluator.ts\",\"packages/workflows/src/dag-executor-loop-back-resume.test.ts\",\"packages/workflows/src/dag-executor-loop-back-review.test.ts\",\"packages/workflows/src/dag-executor-loop-back.test.ts\",\"packages/workflows/src/dag-executor.test.ts\",\"packages/workflows/src/dag-executor.ts\",\"packages/workflows/src/defaults/bundled-defaults.test.ts\",\"packages/workflows/src/defaults/bundled-defaults.ts\",\"packages/workflows/src/deps.ts\",\"packages/workflows/src/event-emitter.test.ts\",\"packages/workflows/src/event-emitter.ts\",\"packages/workflows/src/executor-preamble.test.ts\",\"packages/workflows/src/executor-shared.test.ts\",\"packages/workflows/src/executor-shared.ts\",\"packages/workflows/src/executor.model-resolution.test.ts\",\"packages/workflows/src/executor.test.ts\",\"packages/workflows/src/executor.ts\",\"packages/workflows/src/extract-input-request.test.ts\",\"packages/workflows/src/hooks.test.ts\",\"packages/workflows/src/knowledge-governor.test.ts\",\"packages/workflows/src/knowledge-governor.ts\",\"packages/workflows/src/knowledge-mode.test.ts\",\"packages/workflows/src/knowledge-mode.ts\",\"packages/workflows/src/knowledge-observability.test.ts\",\"packages/workflows/src/knowledge-observability.ts\",\"packages/workflows/src/load-command-prompt.test.ts\",\"packages/workflows/src/loader-loop-back.test.ts\",\"packages/workflows/src/loader.test.ts\",\"packages/workflows/src/loader.ts\",\"packages/workflows/src/logger.test.ts\",\"packages/workflows/src/logger.ts\",\"packages/workflows/src/loop-back-e2e.test.ts\",\"packages/workflows/src/loop-back-interval.test.ts\",\"packages/workflows/src/loop-back-interval.ts\",\"packages/workflows/src/router.test.ts\",\"packages/workflows/src/router.ts\",\"packages/workflows/src/runtime-check.test.ts\",\"packages/workflows/src/schemas.test.ts\",\"packages/workflows/src/schemas/dag-node.ts\",\"packages/workflows/src/schemas/hooks.ts\",\"packages/workflows/src/schemas/index.ts\",\"packages/workflows/src/schemas/input-request.test.ts\",\"packages/workflows/src/schemas/input-request.ts\",\"packages/workflows/src/schemas/loop-back.test.ts\",\"packages/workflows/src/schemas/loop-back.ts\",\"packages/workflows/src/schemas/loop-metrics.ts\",\"packages/workflows/src/schemas/loop.ts\",\"packages/workflows/src/schemas/retry.ts\",\"packages/workflows/src/schemas/workflow-run-loop-back.test.ts\",\"packages/workflows/src/schemas/workflow-run.ts\",\"packages/workflows/src/schemas/workflow.test.ts\",\"packages/workflows/src/schemas/workflow.ts\",\"packages/workflows/src/script-discovery.test.ts\",\"packages/workflows/src/script-discovery.ts\",\"packages/workflows/src/script-node-deps.test.ts\",\"packages/workflows/src/skill-installer.test.ts\",\"packages/workflows/src/skill-installer.ts\",\"packages/workflows/src/store.ts\",\"packages/workflows/src/test-utils.ts\",\"packages/workflows/src/utils/duration.test.ts\",\"packages/workflows/src/utils/duration.ts\",\"packages/workflows/src/utils/idle-timeout.test.ts\",\"packages/workflows/src/utils/idle-timeout.ts\",\"packages/workflows/src/utils/tool-formatter.test.ts\",\"packages/workflows/src/utils/tool-formatter.ts\",\"packages/workflows/src/utils/variable-substitution.test.ts\",\"packages/workflows/src/utils/variable-substitution.ts\",\"packages/workflows/src/validation-parser.test.ts\",\"packages/workflows/src/validation-parser.ts\",\"packages/workflows/src/validator.test.ts\",\"packages/workflows/src/validator.ts\",\"packages/workflows/src/version-snapshot.test.ts\",\"packages/workflows/src/version-snapshot.ts\",\"packages/workflows/src/workflow-discovery.ts\",\"packages/workflows/tsconfig.json\"],\"Other \u2014 scripts\":[\"scripts/build-binaries.sh\",\"scripts/build.sh\",\"scripts/check-aiflow-pytest-scenarios.py\",\"scripts/check-bundled-skill.ts\",\"scripts/check-sla-reliability.sql\",\"scripts/checksums.sh\",\"scripts/clean-dev-branches.sh\",\"scripts/coverage-gate.test.ts\",\"scripts/coverage-gate.ts\",\"scripts/cr-classify.sh\",\"scripts/delete-dev-workflows.sql\",\"scripts/gen-workflow-syntax-doc.test.ts\",\"scripts/gen-workflow-syntax-doc.ts\",\"scripts/generate-api-inventory.test.ts\",\"scripts/generate-api-inventory.ts\",\"scripts/generate-bundled-defaults.ts\",\"scripts/gitnexus-init.sh\",\"scripts/install.ps1\",\"scripts/install.sh\",\"scripts/install_aiflow.sh\",\"scripts/ipipe-cr.sh\",\"scripts/quality-report.ts\",\"scripts/ragas-e2e-stress.ts\",\"scripts/run-aiflow-scenario-cases.sh\",\"scripts/run-coverage.ts\",\"scripts/security-secrets.sh\",\"scripts/select-affected.ts\",\"scripts/sync-versions.sh\",\"scripts/test-sandbox-file-ops.ts\",\"scripts/test-uic-search.ts\",\"scripts/trigger-workflow.sh\",\"scripts/tsconfig.json\",\"scripts/ui-replay-report.ts\",\"scripts/ui-replay-scaffold.ts\",\"scripts/update-homebrew.sh\",\"scripts/upload-aiflow-bos.sh\",\"scripts/validate-setup.sh\",\"scripts/verify-space-commands.ts\"],\"Other \u2014 db-governance\":[\"scripts/db-governance/00_preflight.sql\",\"scripts/db-governance/01_shrink_observability_events.sql\",\"scripts/db-governance/02_shrink_trace_events.sql\",\"scripts/db-governance/03_shrink_workflow_events.sql\",\"scripts/db-governance/04_verify_after_shrink.sql\",\"scripts/db-governance/05_drop_old_tables.sql\",\"scripts/db-governance/10_rolling_cleanup.sql\",\"scripts/db-governance/README.md\"],\"Other \u2014 deepeval-evaluator\":[\"services/deepeval-evaluator/Dockerfile\",\"services/deepeval-evaluator/README.md\",\"services/deepeval-evaluator/requirements.txt\"],\"Other \u2014 ragas-evaluator\":[\"services/ragas-evaluator/Dockerfile\",\"services/ragas-evaluator/README.md\",\"services/ragas-evaluator/requirements.txt\"],\"Other \u2014 todos.md\":[\"todos.md\"],\"Other \u2014 tsconfig.json\":[\"tsconfig.json\"]},\"moduleTree\":[{\"name\":\"Authentication and Identity\",\"slug\":\"authentication-and-identity\",\"files\":[\"packages/server/src/routes/auth.ts\",\"packages/server/src/routes/schemas/auth.schemas.ts\",\"packages/web/src/lib/auth-guard.tsx\",\"packages/web/src/stores/auth-store.ts\",\"auth-service/server.js\"]},{\"name\":\"Chat and Platform Adapters\",\"slug\":\"chat-and-platform-adapters\",\"files\":[\"packages/adapters/src/utils/message-splitting.ts\",\"packages/cli/src/adapters/cli-adapter.ts\",\"packages/server/src/adapters/web.ts\"]},{\"name\":\"CLI and Developer Tools\",\"slug\":\"cli-and-developer-tools\",\"files\":[\"homebrew/archon.rb\"]},{\"name\":\"Workflow Orchestration and Scheduling\",\"slug\":\"workflow-orchestration-and-scheduling\",\"files\":[\"packages/core/src/services/cleanup-service.ts\",\"packages/core/src/services/codebase-restore-service.ts\",\"packages/core/src/services/title-generator.ts\",\"packages/server/src/services/scheduled-task-deps.ts\",\"packages/server/src/services/workflow-run-actions.ts\",\"packages/server/src/services/workflow-run-auto-exporter.ts\",\"packages/server/src/services/workflow-run-exporter.ts\",\"packages/server/src/services/workflow-notification-listener.ts\",\"packages/server/src/workers/sla-infoflow-worker.ts\"]},{\"name\":\"API Server and Integrations\",\"slug\":\"api-server-and-integrations\",\"files\":[\"packages/server/src/index.ts\",\"packages/server/src/gitcase-client.ts\",\"packages/server/src/bos-client.ts\",\"packages/server/src/runtime-config.ts\",\"packages/server/src/services/infoflow-sender.ts\",\"packages/server/src/services/infoflow-webhook.ts\",\"packages/server/src/services/workflow-run-knowledge-sync-dispatcher.ts\",\"packages/server/src/services/sla-infoflow-notifier.ts\",\"packages/server/src/sync-bundled-commands.ts\",\"packages/server/src/sync-bundled-workflows.ts\",\"packages/server/src/sync-project-workflows.ts\",\"packages/server/src/sync-user-workflows.ts\"]},{\"name\":\"Observability, Runtime Tracing, and Evaluation\",\"slug\":\"observability-runtime-tracing-and-evaluation\",\"files\":[],\"children\":[{\"name\":\"Observability, Runtime Tracing, and Evaluation \u2014 core\",\"slug\":\"observability-runtime-tracing-and-evaluation-core\",\"files\":[\"packages/core/src/services/evolution-service.ts\",\"packages/core/src/services/failure-attribution-service.ts\",\"packages/core/src/services/golden-sample-candidate-service.ts\",\"packages/core/src/services/quality-gate-service.ts\",\"packages/core/src/services/runtime-intelligence.ts\"]},{\"name\":\"Observability, Runtime Tracing, and Evaluation \u2014 server\",\"slug\":\"observability-runtime-tracing-and-evaluation-server\",\"files\":[\"packages/server/src/services/evolution-replay.ts\",\"packages/server/src/services/workflow-access.ts\",\"packages/server/src/routes/api/evaluations.ts\",\"packages/server/src/routes/api/evolution.ts\",\"packages/server/src/routes/api/observability.ts\",\"packages/server/src/routes/api/runtime-traces.ts\",\"packages/server/src/routes/api/personnel-usage.ts\"]},{\"name\":\"Observability, Runtime Tracing, and Evaluation \u2014 web\",\"slug\":\"observability-runtime-tracing-and-evaluation-web\",\"files\":[\"packages/web/src/routes/EvaluationSlaPage.tsx\",\"packages/web/src/routes/DiagnosticsPage.tsx\"]},{\"name\":\"Observability, Runtime Tracing, and Evaluation \u2014 deepeval-evaluator\",\"slug\":\"observability-runtime-tracing-and-evaluation-deepeval-evalua\",\"files\":[\"services/deepeval-evaluator/app.py\"]},{\"name\":\"Observability, Runtime Tracing, and Evaluation \u2014 ragas-evaluator\",\"slug\":\"observability-runtime-tracing-and-evaluation-ragas-evaluator\",\"files\":[\"services/ragas-evaluator/app.py\"]}]},{\"name\":\"Knowledge Management\",\"slug\":\"knowledge-management\",\"files\":[\"packages/core/src/services/evaluation-knowledge-artifact-service.ts\",\"packages/server/src/routes/knowledge-router.ts\",\"packages/web/src/routes/KnowledgePage.tsx\"]},{\"name\":\"Web Application UI\",\"slug\":\"web-application-ui\",\"files\":[\"packages/web/src/App.tsx\",\"packages/web/src/main.tsx\"]},{\"name\":\"Developer Documentation and Operational Scripts\",\"slug\":\"developer-documentation-and-operational-scripts\",\"files\":[\"assets/ducc-skills/get-ugate-token/getUgateToken.py\",\"docs/parallel-study/analyze_parallelism.py\"]},{\"name\":\"Other\",\"slug\":\"other\",\"files\":[],\"children\":[{\"name\":\"Other \u2014 AGENTS.md\",\"slug\":\"other-agents-md\",\"files\":[\"AGENTS.md\"]},{\"name\":\"Other \u2014 CLAUDE.md\",\"slug\":\"other-claude-md\",\"files\":[\"CLAUDE.md\"]},{\"name\":\"Other \u2014 Caddyfile.example\",\"slug\":\"other-caddyfile-example\",\"files\":[\"Caddyfile.example\"]},{\"name\":\"Other \u2014 DESIGN.md\",\"slug\":\"other-design-md\",\"files\":[\"DESIGN.md\"]},{\"name\":\"Other \u2014 Dockerfile\",\"slug\":\"other-dockerfile\",\"files\":[\"Dockerfile\"]},{\"name\":\"Other \u2014 Dockerfile.base\",\"slug\":\"other-dockerfile-base\",\"files\":[\"Dockerfile.base\"]},{\"name\":\"Other \u2014 Dockerfile.ci\",\"slug\":\"other-dockerfile-ci\",\"files\":[\"Dockerfile.ci\"]},{\"name\":\"Other \u2014 Dockerfile.user.example\",\"slug\":\"other-dockerfile-user-example\",\"files\":[\"Dockerfile.user.example\"]},{\"name\":\"Other \u2014 Makefile\",\"slug\":\"other-makefile\",\"files\":[\"Makefile\"]},{\"name\":\"Other \u2014 README.md\",\"slug\":\"other-readme-md\",\"files\":[\"README.md\"]},{\"name\":\"Other \u2014 ducc-skills\",\"slug\":\"other-ducc-skills\",\"files\":[\"assets/ducc-skills/cnap/SKILL.md\",\"assets/ducc-skills/cnap/references/baidu-internal-network.md\",\"assets/ducc-skills/cnap/references/cases.md\",\"assets/ducc-skills/cnap/references/cnap-accounts.md\",\"assets/ducc-skills/cnap/references/cnap-applications.md\",\"assets/ducc-skills/cnap/references/cnap-clusters.md\",\"assets/ducc-skills/cnap/references/cnap-cpu-units.md\",\"assets/ducc-skills/cnap/references/cnap-datadist.md\",\"assets/ducc-skills/cnap/references/cnap-environ-vars.md\",\"assets/ducc-skills/cnap/references/cnap-environments.md\",\"assets/ducc-skills/cnap/references/cnap-log-collection.md\",\"assets/ducc-skills/cnap/references/cnap-permissions.md\",\"assets/ducc-skills/cnap/references/cnap-runtime-config.md\",\"assets/ducc-skills/cnap/references/cnap-service-discovery.md\",\"assets/ducc-skills/cnap/references/deploy-babysitter.md\",\"assets/ducc-skills/cnap/references/deploy-troubleshoot.md\",\"assets/ducc-skills/cnap/references/icode.md\",\"assets/ducc-skills/cnap/references/install.md\",\"assets/ducc-skills/cnap/references/iregistry.md\",\"assets/ducc-skills/cnap/references/kubectl.md\",\"assets/ducc-skills/cnap/references/login.md\",\"assets/ducc-skills/cnap/references/oncall.md\",\"assets/ducc-skills/get-ugate-token/SKILL.md\"]},{\"name\":\"Other \u2014 auth-service\",\"slug\":\"other-auth-service\",\"files\":[\"auth-service/Dockerfile\",\"auth-service/package.json\",\"auth-service/test.js\"]},{\"name\":\"Other \u2014 auto-heal.txt\",\"slug\":\"other-auto-heal-txt\",\"files\":[\"auto-heal.txt\"]},{\"name\":\"Other \u2014 bunfig.coverage.toml\",\"slug\":\"other-bunfig-coverage-toml\",\"files\":[\"bunfig.coverage.toml\"]},{\"name\":\"Other \u2014 bunfig.toml\",\"slug\":\"other-bunfig-toml\",\"files\":[\"bunfig.toml\"]},{\"name\":\"Other \u2014 ci.yml\",\"slug\":\"other-ci-yml\",\"files\":[\"ci.yml\"]},{\"name\":\"Other \u2014 deploy\",\"slug\":\"other-deploy\",\"files\":[\"deploy/Dockerfile.user.example\",\"deploy/cloud-init.yml\",\"deploy/docker-compose.override.example.yml\",\"deploy/docker-compose.yml\"]},{\"name\":\"Other \u2014 docker-compose.override.example.yml\",\"slug\":\"other-docker-compose-override-example-yml\",\"files\":[\"docker-compose.override.example.yml\"]},{\"name\":\"Other \u2014 docker-compose.yml\",\"slug\":\"other-docker-compose-yml\",\"files\":[\"docker-compose.yml\"]},{\"name\":\"Other \u2014 docker-entrypoint.sh\",\"slug\":\"other-docker-entrypoint-sh\",\"files\":[\"docker-entrypoint.sh\"]},{\"name\":\"Other \u2014 e2e-dev\",\"slug\":\"other-e2e-dev\",\"files\":[\"docker/e2e-dev/Dockerfile\",\"docker/e2e-dev/Dockerfile.base\",\"docker/e2e-dev/init-claude-workspace.sh\",\"docker/e2e-dev/start_comate_server.sh\"]},{\"name\":\"Other \u2014 docs\",\"slug\":\"other-docs\",\"files\":[\"docs/ai-workflow-builder-design.md\",\"docs/aiflow-skill-design.md\",\"docs/architecture.md\",\"docs/authoring-commands.md\",\"docs/authoring-workflows.md\",\"docs/bundled-workflow-authoring.md\",\"docs/cli-reference.md\",\"docs/cnap-api.md\",\"docs/cr-env.md\",\"docs/cr-rules-code.md\",\"docs/cr-rules-workflow.md\",\"docs/cr-rules.md\",\"docs/document-drawer-design.md\",\"docs/gitcase.md\",\"docs/infoflow-notification-status.md\",\"docs/infoflow-workflow-notification.md\",\"docs/issues.json\",\"docs/knowledge-injection-design.md\",\"docs/loop-back-practice.md\",\"docs/marketing-flow-code-review-redesign.md\",\"docs/marketing-flow-tech-design-step3.md\",\"docs/online-trace-eval-demo-guide.md\",\"docs/online-trace-eval-migration-plan.md\",\"docs/plan-implement-review-loop-parallel.md\",\"docs/product-space-design.md\",\"docs/remove-bundled-system-workflow.md\",\"docs/scheduled-task-practice.md\",\"docs/sla-infoflow-operations.md\",\"docs/standard-dev-flow-artifact-governance-design.md\",\"docs/standard-dev-flow-diagram.md\",\"docs/test-issues.md\",\"docs/ugate-token-adaptation.md\",\"docs/uic-api.md\",\"docs/user-isolation-design.md\",\"docs/uuap-auth.md\",\"docs/workflow-backend-api-chain-api.md\",\"docs/workflow-backend-api-chain-design.md\",\"docs/workflow-loop-back-design.md\",\"docs/workflow-product-space-design.md\",\"docs/workflow-system-analysis.md\",\"docs/workflow-vs-claude-code-comparison.md\",\"docs/workflow-yaml-storage.md\"]},{\"name\":\"Other \u2014 knowledge\",\"slug\":\"other-knowledge\",\"files\":[\"docs/knowledge/baidu-pipeline-docker-build.md\",\"docs/knowledge/kg-self-seal.json\"]},{\"name\":\"Other \u2014 mock\",\"slug\":\"other-mock\",\"files\":[\"docs/mock/\u5de5\u4f5c\u6d41\u4ea7\u54c1\u7a7a\u95f4\u6807\u7b7e-issue.json\",\"docs/mock/\u5de5\u4f5c\u6d41\u5bf9\u8bdd\u6846\u652f\u6301\u6362\u884c-issue.json\"]},{\"name\":\"Other \u2014 parallel-study\",\"slug\":\"other-parallel-study\",\"files\":[\"docs/parallel-study/sample-01-sidebar-pause/issues.json\",\"docs/parallel-study/sample-02-combo-edit/issues.json\",\"docs/parallel-study/sample-03-command-check/issues.json\"]},{\"name\":\"Other \u2014 schemathesis-reports\",\"slug\":\"other-schemathesis-reports\",\"files\":[\"docs/schemathesis-reports/2026-06-04-20-05.json\",\"docs/schemathesis-reports/2026-06-04-20-05.md\"]},{\"name\":\"Other \u2014 superpowers\",\"slug\":\"other-superpowers\",\"files\":[\"docs/superpowers/plans/2026-05-07-icode-codebase-clone.md\",\"docs/superpowers/plans/2026-05-07-uuap-auth.md\",\"docs/superpowers/plans/2026-05-08-icode-clone-icode-cli.md\",\"docs/superpowers/plans/2026-05-12-config-warning-banner.md\",\"docs/superpowers/plans/2026-05-12-oneapi-token.md\",\"docs/superpowers/plans/2026-05-12-setup-wizard-modal.md\",\"docs/superpowers/plans/2026-05-14-sandbox-session-binding.md\",\"docs/superpowers/plans/2026-05-14-workflow-skill-binding.md\",\"docs/superpowers/plans/2026-05-15-comate-auth-token-user-config.md\",\"docs/superpowers/plans/2026-05-18-bug-fix-flow.md\",\"docs/superpowers/plans/2026-05-19-feature-dev-flow.md\",\"docs/superpowers/plans/2026-05-19-superpowers-full-dev-flow.md\",\"docs/superpowers/plans/2026-05-20-bug-fix-flow-clarify.md\",\"docs/superpowers/plans/2026-05-21-ipipe-ducc-cr.md\",\"docs/superpowers/plans/2026-05-21-sandbox-combo-batch-clone.md\",\"docs/superpowers/plans/2026-05-22-fix-gen-ut-uuid-error.md\",\"docs/superpowers/plans/2026-05-22-sandbox-artifacts-dir-simplify.md\",\"docs/superpowers/plans/2026-05-25-gen-ut-workflow-upgrade.md\",\"docs/superpowers/plans/2026-05-25-smart-cr-classification.md\",\"docs/superpowers/plans/2026-05-25-workflow-bash-node-sandbox.md\",\"docs/superpowers/plans/2026-05-26-dev-loop-unit-test-gate.md\",\"docs/superpowers/plans/2026-05-26-metrics-reporter.md\",\"docs/superpowers/plans/2026-05-26-sandbox-file-upload.md\",\"docs/superpowers/plans/2026-05-27-loop-approval-node-started-event.md\",\"docs/superpowers/plans/2026-05-30-sandbox-auto-renew.md\",\"docs/superpowers/plans/2026-06-02-e2e-flow-enhancement.md\",\"docs/superpowers/plans/2026-06-02-impact-analysis-command.md\",\"docs/superpowers/plans/2026-06-03-e2e-flow-cnap-deploy-refactor.md\",\"docs/superpowers/plans/2026-06-04-sandbox-release-on-cancel-abandon.md\",\"docs/superpowers/plans/2026-06-04-schemathesis-integration.md\",\"docs/superpowers/plans/2026-06-09-subworkflow.md\",\"docs/superpowers/plans/2026-06-10-workflow-user-pause.md\",\"docs/superpowers/plans/2026-06-11-concurrent-pause-context.md\",\"docs/superpowers/plans/2026-06-12-auto-publish-node-artifacts.md\",\"docs/superpowers/plans/2026-06-12-auto-publish-readback-refactor.md\",\"docs/superpowers/plans/2026-06-13-ai-workflow-builder.md\",\"docs/superpowers/plans/2026-06-16-breakpoint-retry-clarify.md\",\"docs/superpowers/plans/2026-06-16-chat-page-deliverables-grouping-optimize-workflow.md\",\"docs/superpowers/plans/2026-06-16-inline-composer-context-controls.md\",\"docs/superpowers/plans/2026-06-17-aiflow-optimize-existing-workflow.md\",\"docs/superpowers/plans/2026-06-18-aiflow-ku-doc-recognition.md\",\"docs/superpowers/plans/2026-06-18-onboarding-run-to-new-chat.md\",\"docs/superpowers/plans/2026-06-18-require-project-on-new-conversation.md\",\"docs/superpowers/plans/2026-06-22-commit-time-metrics-reporting.md\",\"docs/superpowers/plans/2026-06-22-workflow-draft-staging.md\",\"docs/superpowers/plans/2026-06-23-aiflow-skill-integration.md\",\"docs/superpowers/plans/2026-06-24-interactive-loop-structured-input.md\",\"docs/superpowers/plans/2026-06-24-sandbox-heartbeat-renew.md\",\"docs/superpowers/plans/2026-06-25-dag-loop-back.md\",\"docs/superpowers/plans/2026-06-26-all-workflow-infoflow-notification.md\",\"docs/superpowers/plans/2026-06-30-breakpoint-retry-move-to-statusbar.md\",\"docs/superpowers/plans/2026-06-30-marketing-flow-test-loop-back.md\",\"docs/superpowers/plans/2026-06-30-workflow-model-dropdown.md\",\"docs/superpowers/plans/2026-07-01-aiflow-loop-back-authoring.md\",\"docs/superpowers/plans/2026-07-02-builder-dag-node-run-status.md\",\"docs/superpowers/plans/2026-07-02-command-market-and-management.md\",\"docs/superpowers/plans/2026-07-02-marketing-flow-merge-to-dev.md\",\"docs/superpowers/plans/2026-07-03-scheduled-tasks.md\",\"docs/superpowers/plans/2026-07-06-command-discovery-mirror-workflow.md\",\"docs/superpowers/plans/2026-07-06-infoflow-robot-api-and-reply.md\",\"docs/superpowers/plans/2026-07-07-backfill-forked-workflow-commands.md\",\"docs/superpowers/plans/2026-07-07-conversation-workflow-scope-badge.md\",\"docs/superpowers/plans/2026-07-07-scheduled-task-ducc-callback.md\",\"docs/superpowers/plans/2026-07-07-workflow-draft-preview-run.md\",\"docs/superpowers/plans/2026-07-08-workflow-version-updated-at.md\",\"docs/superpowers/plans/2026-07-09-infoflow-reply-session-identifier.md\",\"docs/superpowers/plans/2026-07-09-infoflow-sidebar-part1-bubble-card.md\",\"docs/superpowers/plans/2026-07-09-infoflow-sidebar-part2-oauth.md\",\"docs/superpowers/plans/2026-07-09-infoflow-sidebar-part3-web-page.md\",\"docs/superpowers/plans/2026-07-10-scheduled-tasks-space-scoped.md\",\"docs/superpowers/plans/2026-07-13-aiflow-new-conversation-unpublished-draft-guard.md\",\"docs/superpowers/plans/2026-07-13-session-deliverables-enhancements.md\",\"docs/superpowers/plans/2026-07-14-on-reject-session-resume.md\",\"docs/superpowers/plans/2026-07-14-sidebar-sse-realtime.md\",\"docs/superpowers/plans/2026-07-15-aiflow-cli-skill.md\",\"docs/superpowers/plans/2026-07-15-anthropic-workflow-to-aiflow-convert.md\",\"docs/superpowers/plans/2026-07-15-artifact-drawer-auto-refresh.md\",\"docs/superpowers/plans/2026-07-16-infoflow-bubble-session-entry.md\",\"docs/superpowers/plans/2026-07-16-infoflow-sidebar-artifact-panel.md\",\"docs/superpowers/plans/2026-07-17-workflow-authoring-space-command.md\",\"docs/superpowers/plans/2026-07-18-platform-only-cli.md\",\"docs/superpowers/plans/2026-07-20-command-delete.md\",\"docs/superpowers/plans/2026-07-21-aiflow-skill-platform-cli.md\",\"docs/superpowers/plans/2026-07-21-anthropic-workflow-package-convert.md\",\"docs/superpowers/plans/2026-07-21-infoflow-abandon-workflow-button.md\",\"docs/superpowers/plans/2026-07-22-standard-dev-flow.md\",\"docs/superpowers/plans/2026-07-23-workflow-command-source-from-db.md\",\"docs/superpowers/plans/2026-07-24-downstream-refresh-upstream-artifacts.md\",\"docs/superpowers/plans/2026-07-27-loop-back-human-review.md\",\"docs/superpowers/plans/2026-07-27-online-event-data-governance.md\",\"docs/superpowers/plans/2026-07-27-workflow-custom-sandbox-image.md\",\"docs/superpowers/plans/2026-07-29-combo-multi-codebase-workflow.md\",\"docs/superpowers/plans/2026-07-29-workflow-restart-recovery.md\",\"docs/superpowers/plans/2026-07-30-conversation-turn-collapse.md\",\"docs/superpowers/plans/2026-07-30-session-task-model-switch.md\",\"docs/superpowers/plans/2026-07-31-try-it-list.md\",\"docs/superpowers/specs/2026-05-07-icode-codebase-clone-design.md\",\"docs/superpowers/specs/2026-05-07-uuap-auth-design.md\",\"docs/superpowers/specs/2026-05-12-config-warning-banner-design.md\",\"docs/superpowers/specs/2026-05-12-oneapi-token-design.md\",\"docs/superpowers/specs/2026-05-12-setup-wizard-modal-design.md\",\"docs/superpowers/specs/2026-05-14-sandbox-session-binding-design.md\",\"docs/superpowers/specs/2026-05-14-workflow-skill-binding-design.md\",\"docs/superpowers/specs/2026-05-15-comate-auth-token-user-config-design.md\",\"docs/superpowers/specs/2026-05-18-bug-fix-flow-design.md\",\"docs/superpowers/specs/2026-05-19-feature-dev-flow-design.md\",\"docs/superpowers/specs/2026-05-19-superpowers-full-dev-flow-design.md\",\"docs/superpowers/specs/2026-05-20-bug-fix-flow-clarify-design.md\",\"docs/superpowers/specs/2026-05-21-ipipe-ducc-cr-design.md\",\"docs/superpowers/specs/2026-05-22-sandbox-artifacts-dir-simplify-design.md\",\"docs/superpowers/specs/2026-05-25-gen-ut-workflow-design.md\",\"docs/superpowers/specs/2026-05-25-smart-cr-classification-design.md\",\"docs/superpowers/specs/2026-05-26-bun-in-e2e-dev-image-design.md\",\"docs/superpowers/specs/2026-05-26-dev-loop-unit-test-gate-design.md\",\"docs/superpowers/specs/2026-05-26-metrics-reporter-design.md\",\"docs/superpowers/specs/2026-05-26-sandbox-file-upload-design.md\",\"docs/superpowers/specs/2026-05-30-sandbox-auto-renew-design.md\",\"docs/superpowers/specs/2026-06-02-impact-analysis-command-design.md\",\"docs/superpowers/specs/2026-06-04-sandbox-release-on-cancel-abandon-design.md\",\"docs/superpowers/specs/2026-06-04-schemathesis-integration-design.md\",\"docs/superpowers/specs/2026-06-09-product-space-global-filter-design.md\",\"docs/superpowers/specs/2026-06-09-subworkflow-design.md\",\"docs/superpowers/specs/2026-06-10-workflow-user-pause-design.md\",\"docs/superpowers/specs/2026-06-11-concurrent-pause-context-design.md\",\"docs/superpowers/specs/2026-06-11-workflow-product-space-refactor-design.md\",\"docs/superpowers/specs/2026-06-12-auto-publish-node-artifacts-design.md\",\"docs/superpowers/specs/2026-06-13-ai-workflow-builder-design.md\",\"docs/superpowers/specs/2026-06-16-breakpoint-retry-clarify-ai-nodes-only-design.md\",\"docs/superpowers/specs/2026-06-16-breakpoint-retry-clarify-design.md\",\"docs/superpowers/specs/2026-06-16-chat-page-deliverables-grouping-optimize-workflow-design.md\",\"docs/superpowers/specs/2026-06-16-onboarding-wizard-design.md\",\"docs/superpowers/specs/2026-06-16-workflow-builder-run-flow-design.md\",\"docs/superpowers/specs/2026-06-17-aiflow-optimize-existing-workflow-design.md\",\"docs/superpowers/specs/2026-06-18-aiflow-ku-doc-recognition-design.md\",\"docs/superpowers/specs/2026-06-18-onboarding-run-to-new-chat-design.md\",\"docs/superpowers/specs/2026-06-18-require-project-on-new-conversation-design.md\",\"docs/superpowers/specs/2026-06-22-commit-time-metrics-reporting-design.md\",\"docs/superpowers/specs/2026-06-22-workflow-draft-staging-design.md\",\"docs/superpowers/specs/2026-06-23-aiflow-skill-integration-design.md\",\"docs/superpowers/specs/2026-06-23-interactive-loop-structured-input-design.md\",\"docs/superpowers/specs/2026-06-24-interactive-loop-structured-input-design.md\",\"docs/superpowers/specs/2026-06-24-sandbox-heartbeat-renew-design.md\",\"docs/superpowers/specs/2026-06-25-codebase-branch-list-design.md\",\"docs/superpowers/specs/2026-06-25-dag-loop-back-design.md\",\"docs/superpowers/specs/2026-06-26-all-workflow-infoflow-notification-design.md\",\"docs/superpowers/specs/2026-06-30-breakpoint-retry-move-to-statusbar-design.md\",\"docs/superpowers/specs/2026-06-30-marketing-flow-dynamic-branch-design.md\",\"docs/superpowers/specs/2026-06-30-marketing-flow-test-loop-back-design.md\",\"docs/superpowers/specs/2026-06-30-space-private-command-db-design.md\",\"docs/superpowers/specs/2026-06-30-workflow-model-dropdown-design.md\",\"docs/superpowers/specs/2026-07-01-aiflow-loop-back-authoring-design.md\",\"docs/superpowers/specs/2026-07-02-builder-dag-node-run-status-design.md\",\"docs/superpowers/specs/2026-07-02-command-market-and-management-design.md\",\"docs/superpowers/specs/2026-07-02-marketing-flow-merge-to-dev-design.md\",\"docs/superpowers/specs/2026-07-03-scheduled-tasks-design.md\",\"docs/superpowers/specs/2026-07-06-infoflow-robot-api-and-reply-design.md\",\"docs/superpowers/specs/2026-07-07-backfill-forked-workflow-commands-design.md\",\"docs/superpowers/specs/2026-07-07-conversation-workflow-scope-badge-design.md\",\"docs/superpowers/specs/2026-07-07-scheduled-task-ducc-callback-design.md\",\"docs/superpowers/specs/2026-07-07-workflow-draft-preview-run-design.md\",\"docs/superpowers/specs/2026-07-08-workflow-version-updated-at-design.md\",\"docs/superpowers/specs/2026-07-09-infoflow-reply-session-identifier-design.md\",\"docs/superpowers/specs/2026-07-09-infoflow-sidebar-run-detail-design.md\",\"docs/superpowers/specs/2026-07-10-scheduled-tasks-space-scoped-design.md\",\"docs/superpowers/specs/2026-07-11-marketing-flow-clarify-design.md\",\"docs/superpowers/specs/2026-07-13-aiflow-new-conversation-unpublished-draft-guard-design.md\",\"docs/superpowers/specs/2026-07-13-session-deliverables-enhancements-design.md\",\"docs/superpowers/specs/2026-07-14-on-reject-session-resume-design.md\",\"docs/superpowers/specs/2026-07-14-sidebar-sse-realtime-design.md\",\"docs/superpowers/specs/2026-07-15-aiflow-cli-skill-design.md\",\"docs/superpowers/specs/2026-07-15-anthropic-workflow-to-aiflow-convert-design.md\",\"docs/superpowers/specs/2026-07-15-artifact-drawer-auto-refresh-design.md\",\"docs/superpowers/specs/2026-07-16-infoflow-bubble-session-entry-design.md\",\"docs/superpowers/specs/2026-07-16-infoflow-sidebar-artifact-panel-design.md\",\"docs/superpowers/specs/2026-07-17-workflow-authoring-space-command-design.md\",\"docs/superpowers/specs/2026-07-18-platform-only-cli-design.md\",\"docs/superpowers/specs/2026-07-20-command-delete-design.md\",\"docs/superpowers/specs/2026-07-21-aiflow-skill-platform-cli-design.md\",\"docs/superpowers/specs/2026-07-21-anthropic-workflow-package-convert-design.md\",\"docs/superpowers/specs/2026-07-21-infoflow-abandon-workflow-button-design.md\",\"docs/superpowers/specs/2026-07-22-standard-dev-flow-design.md\",\"docs/superpowers/specs/2026-07-23-workflow-command-source-from-db-design.md\",\"docs/superpowers/specs/2026-07-27-loop-back-human-review-design.md\",\"docs/superpowers/specs/2026-07-27-online-event-data-governance-design.md\",\"docs/superpowers/specs/2026-07-27-workflow-custom-sandbox-image-design.md\",\"docs/superpowers/specs/2026-07-29-combo-multi-codebase-workflow-design.md\",\"docs/superpowers/specs/2026-07-29-workflow-restart-recovery-design.md\",\"docs/superpowers/specs/2026-07-30-conversation-turn-collapse-design.md\",\"docs/superpowers/specs/2026-07-30-session-task-model-switch-design.md\",\"docs/superpowers/specs/2026-07-31-try-it-list-design.md\",\"docs/superpowers/test-plans/2026-06-23-workflow-draft-staging-test-plan.md\",\"docs/superpowers/test-plans/db-inspect-guide.md\"]},{\"name\":\"Other \u2014 testing\",\"slug\":\"other-testing\",\"files\":[\"docs/testing/api-test-gate.md\",\"docs/testing/examples/delete_codebase_by_id_404.json\",\"docs/testing/examples/delete_codebase_env_key_404.json\",\"docs/testing/examples/delete_conversations.json\",\"docs/testing/examples/delete_ugate_token.json\",\"docs/testing/examples/get_alert_rules.json\",\"docs/testing/examples/get_alerts.json\",\"docs/testing/examples/get_alerts_preview.json\",\"docs/testing/examples/get_anomalies.json\",\"docs/testing/examples/get_archives.json\",\"docs/testing/examples/get_auth_me.json\",\"docs/testing/examples/get_codebase_by_id_404.json\",\"docs/testing/examples/get_codebase_env_404.json\",\"docs/testing/examples/get_codebases.json\",\"docs/testing/examples/get_comate_auth_token.json\",\"docs/testing/examples/get_combos.json\",\"docs/testing/examples/get_commands.json\",\"docs/testing/examples/get_config.json\",\"docs/testing/examples/get_conversations.json\",\"docs/testing/examples/get_cost_trends.json\",\"docs/testing/examples/get_evaluation_workflow_run_404.json\",\"docs/testing/examples/get_evaluations_aggregates.json\",\"docs/testing/examples/get_evaluations_workflows.json\",\"docs/testing/examples/get_failure_aggregates.json\",\"docs/testing/examples/get_gitcase_spaces.json\",\"docs/testing/examples/get_golden_samples.json\",\"docs/testing/examples/get_human_feedback.json\",\"docs/testing/examples/get_icafe_space.json\",\"docs/testing/examples/get_intelligence.json\",\"docs/testing/examples/get_product_spaces.json\",\"docs/testing/examples/get_product_spaces_mine.json\",\"docs/testing/examples/get_recording_guide.json\",\"docs/testing/examples/get_reliability.json\",\"docs/testing/examples/get_schema_migrations.json\",\"docs/testing/examples/get_schema_migrations_summary.json\",\"docs/testing/examples/get_settings_me.json\",\"docs/testing/examples/get_slow_node_trends.json\",\"docs/testing/examples/get_stale_runs.json\",\"docs/testing/examples/get_trace_by_id_404.json\",\"docs/testing/examples/get_traces.json\",\"docs/testing/examples/get_traces_health.json\",\"docs/testing/examples/get_ugate_token.json\",\"docs/testing/examples/get_ui_replay_audit_events.json\",\"docs/testing/examples/get_ui_replay_governance.json\",\"docs/testing/examples/get_ui_replay_quality_rules.json\",\"docs/testing/examples/get_ui_replay_recordings.json\",\"docs/testing/examples/get_ui_replay_runs.json\",\"docs/testing/examples/get_update_check.json\",\"docs/testing/examples/get_usage_aggregates.json\",\"docs/testing/examples/get_version_effectiveness.json\",\"docs/testing/examples/get_workflow_aggregates.json\",\"docs/testing/examples/get_workflow_by_name_404.json\",\"docs/testing/examples/get_workflow_run_by_id_404.json\",\"docs/testing/examples/get_workflow_run_by_worker_404.json\",\"docs/testing/examples/get_workflow_v2_by_id_404.json\",\"docs/testing/examples/patch_config_assistants.json\",\"docs/testing/examples/post_conversations.json\",\"docs/testing/examples/put_codebase_env_404.json\",\"docs/testing/specmatic-coverage.sh\",\"docs/testing/specmatic-doarchon-docker-test-guide.md\",\"docs/testing/specmatic-doarchon.yaml\",\"docs/testing/specmatic-integration.md\",\"docs/testing/specmatic-test.sh\",\"docs/testing/ui-replay-quality.md\"]},{\"name\":\"Other \u2014 wiki-drafts\",\"slug\":\"other-wiki-drafts\",\"files\":[\"docs/wiki-drafts/PROMPT.md\",\"docs/wiki-drafts/feature-workflow-authoring.md\",\"docs/wiki-drafts/feature-workflow-isolation.md\"]},{\"name\":\"Other \u2014 eslint.config.mjs\",\"slug\":\"other-eslint-config-mjs\",\"files\":[\"eslint.config.mjs\"]},{\"name\":\"Other \u2014 migrations\",\"slug\":\"other-migrations\",\"files\":[\"migrations/000_combined.sql\",\"migrations/001_initial_schema.sql\",\"migrations/001_user_isolation.sql\",\"migrations/002_command_templates.sql\",\"migrations/002_product_spaces.sql\",\"migrations/003_add_worktree.sql\",\"migrations/004_worktree_sharing.sql\",\"migrations/005_isolation_abstraction.sql\",\"migrations/006_isolation_environments.sql\",\"migrations/007_drop_legacy_columns.sql\",\"migrations/008_workflow_runs.sql\",\"migrations/009_workflow_last_activity.sql\",\"migrations/010_immutable_sessions.sql\",\"migrations/011_partial_unique_constraint.sql\",\"migrations/012_workflow_events.sql\",\"migrations/013_conversation_titles.sql\",\"migrations/014_message_history.sql\",\"migrations/015_background_dispatch.sql\",\"migrations/016_session_ended_reason.sql\",\"migrations/017_drop_command_templates.sql\",\"migrations/018_fix_workflow_status_default.sql\",\"migrations/019_workflow_resume_path.sql\",\"migrations/020_codebase_env_vars.sql\",\"migrations/021_add_allow_env_keys_to_codebases.sql\",\"migrations/022_ugate_tokens.sql\",\"migrations/023_codebase_combos.sql\",\"migrations/023_runtime_trace.sql\",\"migrations/024_runtime_trace_alerts.sql\",\"migrations/024_ugate_token_icafe_space.sql\",\"migrations/025_runtime_trace_schema_migrations.sql\",\"migrations/026_runtime_trace_issue_id.sql\",\"migrations/027_workflow_evaluations.sql\",\"migrations/028_dedupe_workflow_evaluations.sql\",\"migrations/029_workflow_run_history_governance.sql\",\"migrations/030_evaluation_objective_datasets.sql\",\"migrations/031_trace_event_skill_name.sql\",\"migrations/032_runtime_trace_governance_indexes.sql\",\"migrations/032_sandbox.sql\",\"migrations/032_workflows_product_space.sql\",\"migrations/033_runtime_trace_schema_backfill.sql\",\"migrations/034_runtime_trace_query_indexes.sql\",\"migrations/035_space_codebases.sql\",\"migrations/035_workflow_run_access_scope.sql\",\"migrations/036_evolution_candidates.sql\",\"migrations/037_messages_created_at_timestamptz.sql\",\"migrations/038_error_details.sql\",\"migrations/039_message_knowledge_columns.sql\",\"migrations/040_ui_replay_persistence.sql\",\"migrations/041_ui_replay_audit.sql\",\"migrations/042_personal_space.sql\",\"migrations/042_workflow_definition_versions.sql\",\"migrations/043_workflow_project_source.sql\",\"migrations/044_observability_events.sql\",\"migrations/045_observability_user_activity_indexes.sql\",\"migrations/045_workflow_name_unique_per_space.sql\",\"migrations/047_conversations_product_space.sql\",\"migrations/048_observability_sla_performance_indexes.sql\",\"migrations/048_workflow_drafts.sql\",\"migrations/049_observability_sla_bucket_snapshots.sql\",\"migrations/051_conversation_branches.sql\",\"migrations/051_loop_back_state.sql\",\"migrations/052_space_commands.sql\",\"migrations/052_workflow_models.sql\",\"migrations/053_workflow_models_backfill.sql\",\"migrations/054_commands_market.sql\",\"migrations/055_workflow_run_command_scope.sql\",\"migrations/056_command_source_type.sql\",\"migrations/057_scheduled_tasks.sql\",\"migrations/058_workflow_run_trigger_source.sql\",\"migrations/059_scheduled_task_branch.sql\",\"migrations/060_scheduled_task_rename_prompt.sql\",\"migrations/061_workflow_version.sql\",\"migrations/062_scheduled_task_product_required.sql\",\"migrations/062_web_verify_steps.sql\",\"migrations/063_observability_sla_user_operation_metrics.sql\",\"migrations/063_user_department_profiles.sql\",\"migrations/064_sla_notification_deliveries.sql\",\"migrations/064_workflow_run_original_started_at.sql\",\"migrations/065_workflow_usage_index.sql\",\"migrations/066_observability_sla_snapshot_retention.sql\",\"migrations/067_observability_active_probe_history_index.sql\",\"migrations/068_observability_traffic_signal_covering_index.sql\",\"migrations/069_workflow_run_codebase_name.sql\",\"migrations/070_observability_sla_schema_reconciliation.sql\",\"migrations/071_observability_sla_online_indexes.sql\",\"migrations/072_observability_sla_snapshot_environment_signals.sql\",\"migrations/073_observability_sla_coverage_lookup_index.sql\",\"migrations/074_observability_sla_dirty_update_triggers.sql\",\"migrations/075_observability_sla_workflow_dirty_triggers.sql\",\"migrations/076_observability_sla_v5_frontend_noise_rebuild.sql\",\"migrations/077_sla_breach_monitoring.sql\",\"migrations/078_observability_sla_integrity_remediation.sql\",\"migrations/079_observability_sla_snapshot_generation.sql\",\"migrations/080_observability_sla_attribution_epoch_fence.sql\",\"migrations/081_observability_dashboard_facts.sql\",\"migrations/082_observability_sla_workflow_owned_failures.sql\",\"migrations/082_workflow_knowledge_observability.sql\",\"migrations/083_evaluation_effect_evidence.sql\",\"migrations/083_workflow_knowledge_sync_jobs.sql\",\"migrations/084_evaluation_benchmark_suites.sql\",\"migrations/084_workflow_knowledge_context_dedup.sql\",\"migrations/085_evaluation_knowledge_artifact_outbox.sql\",\"migrations/086_workflow_models_refresh.sql\",\"migrations/087_evaluation_jobs_runs.sql\",\"migrations/088_observability_sla_attribution_v8_epoch.sql\"]},{\"name\":\"Other \u2014 package.json\",\"slug\":\"other-package-json\",\"files\":[\"package.json\"]},{\"name\":\"Other \u2014 adapters\",\"slug\":\"other-adapters\",\"files\":[\"packages/adapters/package.json\",\"packages/adapters/src/chat/slack/adapter.test.ts\",\"packages/adapters/src/chat/slack/adapter.ts\",\"packages/adapters/src/chat/slack/auth.test.ts\",\"packages/adapters/src/chat/slack/auth.ts\",\"packages/adapters/src/chat/slack/index.ts\",\"packages/adapters/src/chat/slack/types.ts\",\"packages/adapters/src/chat/telegram/adapter.test.ts\",\"packages/adapters/src/chat/telegram/adapter.ts\",\"packages/adapters/src/chat/telegram/auth.test.ts\",\"packages/adapters/src/chat/telegram/auth.ts\",\"packages/adapters/src/chat/telegram/index.ts\",\"packages/adapters/src/chat/telegram/markdown.test.ts\",\"packages/adapters/src/chat/telegram/markdown.ts\",\"packages/adapters/src/chat/telegram/types.ts\",\"packages/adapters/src/community/chat/README.md\",\"packages/adapters/src/community/chat/discord/adapter.test.ts\",\"packages/adapters/src/community/chat/discord/adapter.ts\",\"packages/adapters/src/community/chat/discord/auth.test.ts\",\"packages/adapters/src/community/chat/discord/auth.ts\",\"packages/adapters/src/community/chat/discord/index.ts\",\"packages/adapters/src/community/chat/discord/types.ts\",\"packages/adapters/src/community/forge/README.md\",\"packages/adapters/src/community/forge/gitea/adapter-internals.test.ts\",\"packages/adapters/src/community/forge/gitea/adapter.test.ts\",\"packages/adapters/src/community/forge/gitea/adapter.ts\",\"packages/adapters/src/community/forge/gitea/auth.test.ts\",\"packages/adapters/src/community/forge/gitea/auth.ts\",\"packages/adapters/src/community/forge/gitea/index.ts\",\"packages/adapters/src/community/forge/gitea/types.ts\",\"packages/adapters/src/community/forge/gitlab/adapter-internals.test.ts\",\"packages/adapters/src/community/forge/gitlab/adapter.test.ts\",\"packages/adapters/src/community/forge/gitlab/adapter.ts\",\"packages/adapters/src/community/forge/gitlab/auth.test.ts\",\"packages/adapters/src/community/forge/gitlab/auth.ts\",\"packages/adapters/src/community/forge/gitlab/index.ts\",\"packages/adapters/src/community/forge/gitlab/types.ts\",\"packages/adapters/src/forge/github/adapter.test.ts\",\"packages/adapters/src/forge/github/adapter.ts\",\"packages/adapters/src/forge/github/auth.test.ts\",\"packages/adapters/src/forge/github/auth.ts\",\"packages/adapters/src/forge/github/context.test.ts\",\"packages/adapters/src/forge/github/index.ts\",\"packages/adapters/src/forge/github/types.ts\",\"packages/adapters/src/index.ts\",\"packages/adapters/src/utils/message-splitting.test.ts\",\"packages/adapters/tsconfig.json\"]},{\"name\":\"Other \u2014 auth\",\"slug\":\"other-auth\",\"files\":[\"packages/auth/package.json\",\"packages/auth/src/db.test.ts\",\"packages/auth/src/db.ts\",\"packages/auth/src/deptmember/client.test.ts\",\"packages/auth/src/deptmember/client.ts\",\"packages/auth/src/index.ts\",\"packages/auth/src/jwt.test.ts\",\"packages/auth/src/jwt.ts\",\"packages/auth/src/middleware.test.ts\",\"packages/auth/src/middleware.ts\",\"packages/auth/src/uic/client.test.ts\",\"packages/auth/src/uic/client.ts\",\"packages/auth/src/uuap/client.test.ts\",\"packages/auth/src/uuap/client.ts\",\"packages/auth/src/uuap/types.ts\",\"packages/auth/tsconfig.json\"]},{\"name\":\"Other \u2014 cli\",\"slug\":\"other-cli\",\"files\":[\"packages/cli/package.json\",\"packages/cli/src/adapters/cli-adapter.test.ts\",\"packages/cli/src/aiflow/auth.test.ts\",\"packages/cli/src/aiflow/auth.ts\",\"packages/cli/src/aiflow/client.test.ts\",\"packages/cli/src/aiflow/client.ts\",\"packages/cli/src/aiflow/commands/codebase.test.ts\",\"packages/cli/src/aiflow/commands/codebase.ts\",\"packages/cli/src/aiflow/commands/combo.test.ts\",\"packages/cli/src/aiflow/commands/combo.ts\",\"packages/cli/src/aiflow/commands/conversation.test.ts\",\"packages/cli/src/aiflow/commands/conversation.ts\",\"packages/cli/src/aiflow/commands/run.test.ts\",\"packages/cli/src/aiflow/commands/run.ts\",\"packages/cli/src/aiflow/commands/space.test.ts\",\"packages/cli/src/aiflow/commands/space.ts\",\"packages/cli/src/aiflow/commands/token.test.ts\",\"packages/cli/src/aiflow/commands/token.ts\",\"packages/cli/src/aiflow/commands/workflow.test.ts\",\"packages/cli/src/aiflow/commands/workflow.ts\",\"packages/cli/src/aiflow/file-upload.ts\",\"packages/cli/src/aiflow/format.test.ts\",\"packages/cli/src/aiflow/format.ts\",\"packages/cli/src/aiflow/platform.test.ts\",\"packages/cli/src/aiflow/platform.ts\",\"packages/cli/src/bundled-skill.ts\",\"packages/cli/src/cli-platform.test.ts\",\"packages/cli/src/cli-platform.ts\",\"packages/cli/src/cli.test.ts\",\"packages/cli/src/cli.ts\",\"packages/cli/src/commands/chat.test.ts\",\"packages/cli/src/commands/chat.ts\",\"packages/cli/src/commands/continue.ts\",\"packages/cli/src/commands/doctor.test.ts\",\"packages/cli/src/commands/doctor.ts\",\"packages/cli/src/commands/icafe-space.test.ts\",\"packages/cli/src/commands/icafe-space.ts\",\"packages/cli/src/commands/isolation.test.ts\",\"packages/cli/src/commands/isolation.ts\",\"packages/cli/src/commands/serve-binary.test.ts\",\"packages/cli/src/commands/serve.test.ts\",\"packages/cli/src/commands/serve.ts\",\"packages/cli/src/commands/setup-flow.test.ts\",\"packages/cli/src/commands/setup.test.ts\",\"packages/cli/src/commands/setup.ts\",\"packages/cli/src/commands/skill.test.ts\",\"packages/cli/src/commands/skill.ts\",\"packages/cli/src/commands/ugate-token.test.ts\",\"packages/cli/src/commands/ugate-token.ts\",\"packages/cli/src/commands/validate.ts\",\"packages/cli/src/commands/version.test.ts\",\"packages/cli/src/commands/version.ts\",\"packages/cli/src/commands/workflow.test.ts\",\"packages/cli/src/commands/workflow.ts\",\"packages/cli/tsconfig.json\"]},{\"name\":\"Other \u2014 core\",\"slug\":\"other-core\",\"files\":[\"packages/core/package.json\",\"packages/core/src/config/config-loader.test.ts\",\"packages/core/src/config/config-loader.ts\",\"packages/core/src/config/config-types.ts\",\"packages/core/src/config/index.ts\",\"packages/core/src/db/adapters/index.ts\",\"packages/core/src/db/adapters/postgres.test.ts\",\"packages/core/src/db/adapters/postgres.ts\",\"packages/core/src/db/adapters/sqlite.test.ts\",\"packages/core/src/db/adapters/sqlite.ts\",\"packages/core/src/db/adapters/types.ts\",\"packages/core/src/db/assistant-override.ts\",\"packages/core/src/db/codebases.test.ts\",\"packages/core/src/db/codebases.ts\",\"packages/core/src/db/combos.test.ts\",\"packages/core/src/db/combos.ts\",\"packages/core/src/db/connection.test.ts\",\"packages/core/src/db/connection.ts\",\"packages/core/src/db/conversations.test.ts\",\"packages/core/src/db/conversations.ts\",\"packages/core/src/db/env-vars.test.ts\",\"packages/core/src/db/env-vars.ts\",\"packages/core/src/db/error-details.test.ts\",\"packages/core/src/db/error-details.ts\",\"packages/core/src/db/evaluation-benchmarks.ts\",\"packages/core/src/db/evaluation-evidence.ts\",\"packages/core/src/db/evaluation-knowledge-artifacts.ts\",\"packages/core/src/db/evaluations.test.ts\",\"packages/core/src/db/evaluations.ts\",\"packages/core/src/db/evolution.test.ts\",\"packages/core/src/db/evolution.ts\",\"packages/core/src/db/index.ts\",\"packages/core/src/db/isolation-environments.test.ts\",\"packages/core/src/db/isolation-environments.ts\",\"packages/core/src/db/knowledge-observations.test.ts\",\"packages/core/src/db/knowledge-observations.ts\",\"packages/core/src/db/knowledge-sync-jobs.test.ts\",\"packages/core/src/db/knowledge-sync-jobs.ts\",\"packages/core/src/db/messages.test.ts\",\"packages/core/src/db/messages.ts\",\"packages/core/src/db/migrate.test.ts\",\"packages/core/src/db/migrate.ts\",\"packages/core/src/db/observability.test.ts\",\"packages/core/src/db/observability.ts\",\"packages/core/src/db/personnel-usage.test.ts\",\"packages/core/src/db/personnel-usage.ts\",\"packages/core/src/db/product-spaces.test.ts\",\"packages/core/src/db/product-spaces.ts\",\"packages/core/src/db/runtime-traces.test.ts\",\"packages/core/src/db/runtime-traces.ts\",\"packages/core/src/db/sandbox-environments.test.ts\",\"packages/core/src/db/sandbox-environments.ts\",\"packages/core/src/db/scheduled-tasks.test.ts\",\"packages/core/src/db/scheduled-tasks.ts\",\"packages/core/src/db/sessions.test.ts\",\"packages/core/src/db/sessions.ts\",\"packages/core/src/db/sla-notification-deliveries.test.ts\",\"packages/core/src/db/sla-notification-deliveries.ts\",\"packages/core/src/db/space-commands.test.ts\",\"packages/core/src/db/space-commands.ts\",\"packages/core/src/db/ugate-tokens.test.ts\",\"packages/core/src/db/ugate-tokens.ts\",\"packages/core/src/db/ui-replay.ts\",\"packages/core/src/db/user-settings.test.ts\",\"packages/core/src/db/user-settings.ts\",\"packages/core/src/db/user-workflows.test.ts\",\"packages/core/src/db/user-workflows.ts\",\"packages/core/src/db/users.test.ts\",\"packages/core/src/db/users.ts\",\"packages/core/src/db/web-verify-steps.ts\",\"packages/core/src/db/workflow-definition-versions.test.ts\",\"packages/core/src/db/workflow-definition-versions.ts\",\"packages/core/src/db/workflow-drafts.test.ts\",\"packages/core/src/db/workflow-drafts.ts\",\"packages/core/src/db/workflow-events-loop-back.test.ts\",\"packages/core/src/db/workflow-events.test.ts\",\"packages/core/src/db/workflow-events.ts\",\"packages/core/src/db/workflow-loop-metrics.test.ts\",\"packages/core/src/db/workflow-loop-metrics.ts\",\"packages/core/src/db/workflow-models.test.ts\",\"packages/core/src/db/workflow-models.ts\",\"packages/core/src/db/workflow-run-trigger-source.test.ts\",\"packages/core/src/db/workflows-loop-back.test.ts\",\"packages/core/src/db/workflows-v2.test.ts\",\"packages/core/src/db/workflows-v2.ts\",\"packages/core/src/db/workflows.test.ts\",\"packages/core/src/db/workflows.ts\",\"packages/core/src/evaluation/event-bus.ts\",\"packages/core/src/handlers/clone.test.ts\",\"packages/core/src/handlers/clone.ts\",\"packages/core/src/handlers/command-handler.test.ts\",\"packages/core/src/handlers/command-handler.ts\",\"packages/core/src/handlers/command-handler.workflow-run.test.ts\",\"packages/core/src/handlers/icode-clone.test.ts\",\"packages/core/src/handlers/icode-clone.ts\",\"packages/core/src/index.ts\",\"packages/core/src/knowledge/product-resolver.test.ts\",\"packages/core/src/knowledge/product-resolver.ts\",\"packages/core/src/notifications/infoflow-client.oauth.test.ts\",\"packages/core/src/notifications/infoflow-client.test.ts\",\"packages/core/src/notifications/infoflow-client.ts\",\"packages/core/src/notifications/infoflow-sidebar-link.test.ts\",\"packages/core/src/notifications/infoflow-sidebar-link.ts\",\"packages/core/src/notifications/infoflow.test.ts\",\"packages/core/src/notifications/infoflow.ts\",\"packages/core/src/operations/index.ts\",\"packages/core/src/operations/isolation-operations.test.ts\",\"packages/core/src/operations/isolation-operations.ts\",\"packages/core/src/operations/workflow-operations.test.ts\",\"packages/core/src/operations/workflow-operations.ts\",\"packages/core/src/orchestrator/dispatchBackgroundWorkflow.test.ts\",\"packages/core/src/orchestrator/orchestrator-agent.test.ts\",\"packages/core/src/orchestrator/orchestrator-agent.ts\",\"packages/core/src/orchestrator/orchestrator-isolation.test.ts\",\"packages/core/src/orchestrator/orchestrator.test.ts\",\"packages/core/src/orchestrator/orchestrator.ts\",\"packages/core/src/orchestrator/prompt-builder.test.ts\",\"packages/core/src/orchestrator/prompt-builder.ts\",\"packages/core/src/orchestrator/sandbox-helpers.test.ts\",\"packages/core/src/orchestrator/sandbox-helpers.ts\",\"packages/core/src/orchestrator/workflow-authoring-command-list.test.ts\",\"packages/core/src/orchestrator/workflow-authoring-retry.ts\",\"packages/core/src/orchestrator/workflow-authoring.test.ts\",\"packages/core/src/orchestrator/workflow-authoring.ts\",\"packages/core/src/runtime/alerts.ts\",\"packages/core/src/runtime/cost.test.ts\",\"packages/core/src/runtime/cost.ts\",\"packages/core/src/runtime/emitter.test.ts\",\"packages/core/src/runtime/emitter.ts\",\"packages/core/src/runtime/evaluation-worker.test.ts\",\"packages/core/src/runtime/evaluation-worker.ts\",\"packages/core/src/runtime/ids.test.ts\",\"packages/core/src/runtime/ids.ts\",\"packages/core/src/runtime/index.ts\",\"packages/core/src/runtime/issue-clustering.test.ts\",\"packages/core/src/runtime/issue-clustering.ts\",\"packages/core/src/runtime/observability-bus.test.ts\",\"packages/core/src/runtime/observability-bus.ts\",\"packages/core/src/runtime/policy.test.ts\",\"packages/core/src/runtime/policy.ts\",\"packages/core/src/runtime/redaction.test.ts\",\"packages/core/src/runtime/redaction.ts\",\"packages/core/src/runtime/trace-bus.test.ts\",\"packages/core/src/runtime/trace-bus.ts\",\"packages/core/src/runtime/types.ts\",\"packages/core/src/runtime/workflow-trace-recorder.test.ts\",\"packages/core/src/runtime/workflow-trace-recorder.ts\",\"packages/core/src/scheduling/next-run.test.ts\",\"packages/core/src/scheduling/next-run.ts\",\"packages/core/src/scheduling/sandbox-envs-env.test.ts\",\"packages/core/src/scheduling/sandbox-envs.test.ts\",\"packages/core/src/scheduling/sandbox-envs.ts\",\"packages/core/src/scheduling/scheduled-task-runner.test.ts\",\"packages/core/src/scheduling/scheduled-task-runner.ts\",\"packages/core/src/services/cleanup-service.test.ts\",\"packages/core/src/services/codebase-restore-service.test.ts\",\"packages/core/src/services/evaluation-benchmark-service.test.ts\",\"packages/core/src/services/evaluation-benchmark-service.ts\",\"packages/core/src/services/evaluation-calibration-service.test.ts\",\"packages/core/src/services/evaluation-calibration-service.ts\",\"packages/core/src/services/evaluation-capability-readiness-service.test.ts\",\"packages/core/src/services/evaluation-capability-readiness-service.ts\",\"packages/core/src/services/evaluation-evidence-service.test.ts\",\"packages/core/src/services/evaluation-evidence-service.ts\",\"packages/core/src/services/evaluation-knowledge-artifact-service.test.ts\",\"packages/core/src/services/evaluation-service.test.ts\",\"packages/core/src/services/evaluation-service.ts\",\"packages/core/src/services/evolution-service.test.ts\",\"packages/core/src/services/failure-attribution-service.test.ts\",\"packages/core/src/services/golden-sample-candidate-service.test.ts\",\"packages/core/src/services/quality-gate-service.test.ts\",\"packages/core/src/services/runtime-intelligence.test.ts\",\"packages/core/src/services/title-generator.test.ts\",\"packages/core/src/services/ui-replay-assertions.test.ts\",\"packages/core/src/services/ui-replay-assertions.ts\",\"packages/core/src/state/session-transitions.test.ts\",\"packages/core/src/state/session-transitions.ts\",\"packages/core/src/test/mocks/database.ts\",\"packages/core/src/test/mocks/logger.ts\",\"packages/core/src/test/mocks/platform.ts\",\"packages/core/src/test/setup.ts\",\"packages/core/src/types/index.ts\",\"packages/core/src/utils/commands.test.ts\",\"packages/core/src/utils/commands.ts\",\"packages/core/src/utils/conversation-lock.test.ts\",\"packages/core/src/utils/conversation-lock.ts\",\"packages/core/src/utils/credential-sanitizer.test.ts\",\"packages/core/src/utils/credential-sanitizer.ts\",\"packages/core/src/utils/error-formatter.test.ts\",\"packages/core/src/utils/error-formatter.ts\",\"packages/core/src/utils/error.test.ts\",\"packages/core/src/utils/error.ts\",\"packages/core/src/utils/github-graphql.test.ts\",\"packages/core/src/utils/github-graphql.ts\",\"packages/core/src/utils/path-validation.test.ts\",\"packages/core/src/utils/path-validation.ts\",\"packages/core/src/utils/port-allocation.test.ts\",\"packages/core/src/utils/port-allocation.ts\",\"packages/core/src/utils/worktree-sync.test.ts\",\"packages/core/src/utils/worktree-sync.ts\",\"packages/core/src/workflows/index.ts\",\"packages/core/src/workflows/store-adapter.test.ts\",\"packages/core/src/workflows/store-adapter.ts\",\"packages/core/tsconfig.json\",\"packages/core/tsconfig.tsbuildinfo\"]},{\"name\":\"Other \u2014 docs-web\",\"slug\":\"other-docs-web\",\"files\":[\"packages/docs-web/astro.config.mjs\",\"packages/docs-web/package.json\",\"packages/docs-web/public/CNAME\",\"packages/docs-web/public/install\",\"packages/docs-web/public/install.ps1\",\"packages/docs-web/src/content.config.ts\",\"packages/docs-web/src/content/docs/adapters/community/discord.md\",\"packages/docs-web/src/content/docs/adapters/community/gitea.md\",\"packages/docs-web/src/content/docs/adapters/community/gitlab.md\",\"packages/docs-web/src/content/docs/adapters/github.md\",\"packages/docs-web/src/content/docs/adapters/index.md\",\"packages/docs-web/src/content/docs/adapters/slack.md\",\"packages/docs-web/src/content/docs/adapters/telegram.md\",\"packages/docs-web/src/content/docs/adapters/web.md\",\"packages/docs-web/src/content/docs/book/dag-workflows.md\",\"packages/docs-web/src/content/docs/book/essential-workflows.md\",\"packages/docs-web/src/content/docs/book/first-command.md\",\"packages/docs-web/src/content/docs/book/first-five-minutes.md\",\"packages/docs-web/src/content/docs/book/first-workflow.md\",\"packages/docs-web/src/content/docs/book/hooks-and-quality.md\",\"packages/docs-web/src/content/docs/book/how-it-works.md\",\"packages/docs-web/src/content/docs/book/index.md\",\"packages/docs-web/src/content/docs/book/isolation.md\",\"packages/docs-web/src/content/docs/book/quick-reference.md\",\"packages/docs-web/src/content/docs/book/what-is-archon.md\",\"packages/docs-web/src/content/docs/contributing/adding-a-community-provider.md\",\"packages/docs-web/src/content/docs/contributing/cli-internals.md\",\"packages/docs-web/src/content/docs/contributing/dx-quirks.md\",\"packages/docs-web/src/content/docs/contributing/index.md\",\"packages/docs-web/src/content/docs/contributing/new-developer-guide.md\",\"packages/docs-web/src/content/docs/contributing/releasing.md\",\"packages/docs-web/src/content/docs/deployment/cloud.md\",\"packages/docs-web/src/content/docs/deployment/docker.md\",\"packages/docs-web/src/content/docs/deployment/e2e-testing-wsl.md\",\"packages/docs-web/src/content/docs/deployment/e2e-testing.md\",\"packages/docs-web/src/content/docs/deployment/index.md\",\"packages/docs-web/src/content/docs/deployment/local.md\",\"packages/docs-web/src/content/docs/deployment/windows.md\",\"packages/docs-web/src/content/docs/getting-started/ai-assistants.md\",\"packages/docs-web/src/content/docs/getting-started/concepts.md\",\"packages/docs-web/src/content/docs/getting-started/configuration.md\",\"packages/docs-web/src/content/docs/getting-started/installation.md\",\"packages/docs-web/src/content/docs/getting-started/overview.md\",\"packages/docs-web/src/content/docs/getting-started/quick-start.md\",\"packages/docs-web/src/content/docs/guides/approval-nodes.md\",\"packages/docs-web/src/content/docs/guides/authoring-commands.md\",\"packages/docs-web/src/content/docs/guides/authoring-workflows.md\",\"packages/docs-web/src/content/docs/guides/global-workflows.md\",\"packages/docs-web/src/content/docs/guides/hooks.md\",\"packages/docs-web/src/content/docs/guides/index.md\",\"packages/docs-web/src/content/docs/guides/loop-nodes.md\",\"packages/docs-web/src/content/docs/guides/mcp-servers.md\",\"packages/docs-web/src/content/docs/guides/remotion-workflow.md\",\"packages/docs-web/src/content/docs/guides/script-nodes.md\",\"packages/docs-web/src/content/docs/guides/skills.md\",\"packages/docs-web/src/content/docs/index.mdx\",\"packages/docs-web/src/content/docs/reference/api.md\",\"packages/docs-web/src/content/docs/reference/architecture.md\",\"packages/docs-web/src/content/docs/reference/archon-directories.md\",\"packages/docs-web/src/content/docs/reference/cli.md\",\"packages/docs-web/src/content/docs/reference/commands.md\",\"packages/docs-web/src/content/docs/reference/configuration.md\",\"packages/docs-web/src/content/docs/reference/database.md\",\"packages/docs-web/src/content/docs/reference/index.md\",\"packages/docs-web/src/content/docs/reference/security.md\",\"packages/docs-web/src/content/docs/reference/troubleshooting.md\",\"packages/docs-web/src/content/docs/reference/variables.md\",\"packages/docs-web/src/styles/custom.css\",\"packages/docs-web/tsconfig.json\"]},{\"name\":\"Other \u2014 git\",\"slug\":\"other-git\",\"files\":[\"packages/git/package.json\",\"packages/git/src/branch.ts\",\"packages/git/src/exec.test.ts\",\"packages/git/src/exec.ts\",\"packages/git/src/git.test.ts\",\"packages/git/src/index.ts\",\"packages/git/src/keyed-mutex.test.ts\",\"packages/git/src/keyed-mutex.ts\",\"packages/git/src/repo.ts\",\"packages/git/src/types.ts\",\"packages/git/src/worktree.ts\",\"packages/git/tsconfig.json\"]},{\"name\":\"Other \u2014 isolation\",\"slug\":\"other-isolation\",\"files\":[\"packages/isolation/package.json\",\"packages/isolation/src/errors.test.ts\",\"packages/isolation/src/errors.ts\",\"packages/isolation/src/factory.test.ts\",\"packages/isolation/src/factory.ts\",\"packages/isolation/src/index.ts\",\"packages/isolation/src/pr-state.test.ts\",\"packages/isolation/src/pr-state.ts\",\"packages/isolation/src/providers/worktree.test.ts\",\"packages/isolation/src/providers/worktree.ts\",\"packages/isolation/src/resolver.test.ts\",\"packages/isolation/src/resolver.ts\",\"packages/isolation/src/store.ts\",\"packages/isolation/src/types.ts\",\"packages/isolation/src/worktree-copy.test.ts\",\"packages/isolation/src/worktree-copy.ts\",\"packages/isolation/tsconfig.json\"]},{\"name\":\"Other \u2014 paths\",\"slug\":\"other-paths\",\"files\":[\"packages/paths/package.json\",\"packages/paths/src/archon-paths.test.ts\",\"packages/paths/src/archon-paths.ts\",\"packages/paths/src/bundled-build.test.ts\",\"packages/paths/src/bundled-build.ts\",\"packages/paths/src/env-integration.test.ts\",\"packages/paths/src/env-loader.test.ts\",\"packages/paths/src/env-loader.ts\",\"packages/paths/src/index.ts\",\"packages/paths/src/logger.test.ts\",\"packages/paths/src/logger.ts\",\"packages/paths/src/mcp-init.test.ts\",\"packages/paths/src/mcp-init.ts\",\"packages/paths/src/strip-cwd-env-boot.ts\",\"packages/paths/src/strip-cwd-env.test.ts\",\"packages/paths/src/strip-cwd-env.ts\",\"packages/paths/src/telemetry.test.ts\",\"packages/paths/src/telemetry.ts\",\"packages/paths/src/update-check.test.ts\",\"packages/paths/src/update-check.ts\",\"packages/paths/tsconfig.json\"]},{\"name\":\"Other \u2014 providers\",\"slug\":\"other-providers\",\"files\":[\"packages/providers/package.json\",\"packages/providers/src/claude/binary-resolver-dev.test.ts\",\"packages/providers/src/claude/binary-resolver.test.ts\",\"packages/providers/src/claude/binary-resolver.ts\",\"packages/providers/src/claude/capabilities.ts\",\"packages/providers/src/claude/config.test.ts\",\"packages/providers/src/claude/config.ts\",\"packages/providers/src/claude/index.ts\",\"packages/providers/src/claude/provider.test.ts\",\"packages/providers/src/claude/provider.ts\",\"packages/providers/src/codex/binary-guard.test.ts\",\"packages/providers/src/codex/binary-resolver-dev.test.ts\",\"packages/providers/src/codex/binary-resolver.test.ts\",\"packages/providers/src/codex/binary-resolver.ts\",\"packages/providers/src/codex/capabilities.ts\",\"packages/providers/src/codex/config.test.ts\",\"packages/providers/src/codex/config.ts\",\"packages/providers/src/codex/index.ts\",\"packages/providers/src/codex/provider.test.ts\",\"packages/providers/src/codex/provider.ts\",\"packages/providers/src/community/pi/capabilities.ts\",\"packages/providers/src/community/pi/config.test.ts\",\"packages/providers/src/community/pi/config.ts\",\"packages/providers/src/community/pi/event-bridge.test.ts\",\"packages/providers/src/community/pi/event-bridge.ts\",\"packages/providers/src/community/pi/index.ts\",\"packages/providers/src/community/pi/model-ref.test.ts\",\"packages/providers/src/community/pi/model-ref.ts\",\"packages/providers/src/community/pi/options-translator.test.ts\",\"packages/providers/src/community/pi/options-translator.ts\",\"packages/providers/src/community/pi/provider-lazy-load.test.ts\",\"packages/providers/src/community/pi/provider.test.ts\",\"packages/providers/src/community/pi/provider.ts\",\"packages/providers/src/community/pi/registration.ts\",\"packages/providers/src/community/pi/resource-loader.ts\",\"packages/providers/src/community/pi/session-resolver.test.ts\",\"packages/providers/src/community/pi/session-resolver.ts\",\"packages/providers/src/community/pi/ui-context-stub.test.ts\",\"packages/providers/src/community/pi/ui-context-stub.ts\",\"packages/providers/src/errors.ts\",\"packages/providers/src/index.ts\",\"packages/providers/src/registry.test.ts\",\"packages/providers/src/registry.ts\",\"packages/providers/src/test/mocks/logger.ts\",\"packages/providers/src/types.ts\",\"packages/providers/src/workflow-models.test.ts\",\"packages/providers/src/workflow-models.ts\",\"packages/providers/tsconfig.json\"]},{\"name\":\"Other \u2014 sandbox\",\"slug\":\"other-sandbox\",\"files\":[\"packages/sandbox/package.json\",\"packages/sandbox/src/file-helpers.test.ts\",\"packages/sandbox/src/file-helpers.ts\",\"packages/sandbox/src/index.ts\",\"packages/sandbox/src/manager.test.ts\",\"packages/sandbox/src/manager.ts\",\"packages/sandbox/src/provider.test.ts\",\"packages/sandbox/src/provider.ts\",\"packages/sandbox/src/semaphore.test.ts\",\"packages/sandbox/src/semaphore.ts\",\"packages/sandbox/src/stream-parser.test.ts\",\"packages/sandbox/src/stream-parser.ts\",\"packages/sandbox/src/types.ts\",\"packages/sandbox/tsconfig.json\"]},{\"name\":\"Other \u2014 server\",\"slug\":\"other-server\",\"files\":[\"packages/server/package.json\",\"packages/server/src/adapters/web/persistence.test.ts\",\"packages/server/src/adapters/web/persistence.ts\",\"packages/server/src/adapters/web/transport.test.ts\",\"packages/server/src/adapters/web/transport.ts\",\"packages/server/src/adapters/web/workflow-bridge-loop-back.test.ts\",\"packages/server/src/adapters/web/workflow-bridge.test.ts\",\"packages/server/src/adapters/web/workflow-bridge.ts\",\"packages/server/src/api-tests/brand-text-regression.test.ts\",\"packages/server/src/api-tests/contract.test.ts\",\"packages/server/src/api-tests/scenario.test.ts\",\"packages/server/src/api-tests/scheduled-tasks.test.ts\",\"packages/server/src/api-tests/workflow-run-product-scope.test.ts\",\"packages/server/src/api-tests/workflow-run-scheduled-gates.test.ts\",\"packages/server/src/api-tests/workflow-run-upload.test.ts\",\"packages/server/src/bos-client.test.ts\",\"packages/server/src/gitcase-client.test.ts\",\"packages/server/src/routes/api.bos.test.ts\",\"packages/server/src/routes/api.case-info.test.ts\",\"packages/server/src/routes/api.codebases.test.ts\",\"packages/server/src/routes/api.combos.test.ts\",\"packages/server/src/routes/api.commands-v2.test.ts\",\"packages/server/src/routes/api.commands-v2.ts\",\"packages/server/src/routes/api.conversations.test.ts\",\"packages/server/src/routes/api.debug-session.test.ts\",\"packages/server/src/routes/api.evaluations.test.ts\",\"packages/server/src/routes/api.gitcase.test.ts\",\"packages/server/src/routes/api.health.test.ts\",\"packages/server/src/routes/api.helpers.test.ts\",\"packages/server/src/routes/api.infoflow-webhook.test.ts\",\"packages/server/src/routes/api.infoflow.test.ts\",\"packages/server/src/routes/api.knowledge-chat-proxy.ts\",\"packages/server/src/routes/api.knowledge-chat.ts\",\"packages/server/src/routes/api.knowledge-proxy.test.ts\",\"packages/server/src/routes/api.knowledge-proxy.ts\",\"packages/server/src/routes/api.knowledge-sync-callback.test.ts\",\"packages/server/src/routes/api.knowledge.test.ts\",\"packages/server/src/routes/api.knowledge.ts\",\"packages/server/src/routes/api.messages.test.ts\",\"packages/server/src/routes/api.observability.test.ts\",\"packages/server/src/routes/api.personnel-usage.test.ts\",\"packages/server/src/routes/api.product-spaces.test.ts\",\"packages/server/src/routes/api.product-spaces.ts\",\"packages/server/src/routes/api.providers.test.ts\",\"packages/server/src/routes/api.runtime-traces.test.ts\",\"packages/server/src/routes/api.sandbox-file.test.ts\",\"packages/server/src/routes/api.ts\",\"packages/server/src/routes/api.ui-replay.test.ts\",\"packages/server/src/routes/api.web-verify-steps.test.ts\",\"packages/server/src/routes/api.webhooks.test.ts\",\"packages/server/src/routes/api.workflow-runs.test.ts\",\"packages/server/src/routes/api.workflows-v2.test.ts\",\"packages/server/src/routes/api.workflows-v2.ts\",\"packages/server/src/routes/api.workflows.test.ts\",\"packages/server/src/routes/api/bos-download.ts\",\"packages/server/src/routes/api/bos-preview.ts\",\"packages/server/src/routes/api/bos-upload.ts\",\"packages/server/src/routes/api/case-info.ts\",\"packages/server/src/routes/api/codebases.ts\",\"packages/server/src/routes/api/combos.ts\",\"packages/server/src/routes/api/conversations.ts\",\"packages/server/src/routes/api/debug-session.ts\",\"packages/server/src/routes/api/gitcase.ts\",\"packages/server/src/routes/api/helpers.ts\",\"packages/server/src/routes/api/infoflow-crypto.test.ts\",\"packages/server/src/routes/api/infoflow-crypto.ts\",\"packages/server/src/routes/api/infoflow-oauth.test.ts\",\"packages/server/src/routes/api/infoflow-oauth.ts\",\"packages/server/src/routes/api/infoflow-reply-routing.test.ts\",\"packages/server/src/routes/api/infoflow-reply-routing.ts\",\"packages/server/src/routes/api/infoflow-webhook.ts\",\"packages/server/src/routes/api/infoflow.ts\",\"packages/server/src/routes/api/knowledge-sync-callback.ts\",\"packages/server/src/routes/api/product-access.ts\",\"packages/server/src/routes/api/sandbox-file.ts\",\"packages/server/src/routes/api/scheduled-tasks.ts\",\"packages/server/src/routes/api/system.ts\",\"packages/server/src/routes/api/ui-replay.ts\",\"packages/server/src/routes/api/web-verify-steps.ts\",\"packages/server/src/routes/api/workflow-runs.ts\",\"packages/server/src/routes/api/workflows.ts\",\"packages/server/src/routes/api/zip-decompress.test.ts\",\"packages/server/src/routes/api/zip-decompress.ts\",\"packages/server/src/routes/auth.test.ts\",\"packages/server/src/routes/command-frontmatter.test.ts\",\"packages/server/src/routes/command-frontmatter.ts\",\"packages/server/src/routes/command-references.test.ts\",\"packages/server/src/routes/command-references.ts\",\"packages/server/src/routes/health.test.ts\",\"packages/server/src/routes/health.ts\",\"packages/server/src/routes/openapi-defaults.ts\",\"packages/server/src/routes/schemas/case-info.schemas.ts\",\"packages/server/src/routes/schemas/codebase.schemas.ts\",\"packages/server/src/routes/schemas/combo.schemas.ts\",\"packages/server/src/routes/schemas/command-v2.schemas.ts\",\"packages/server/src/routes/schemas/common.schemas.ts\",\"packages/server/src/routes/schemas/config.schemas.ts\",\"packages/server/src/routes/schemas/conversation.schemas.ts\",\"packages/server/src/routes/schemas/evaluation.schemas.ts\",\"packages/server/src/routes/schemas/evolution.schemas.ts\",\"packages/server/src/routes/schemas/gitcase.schemas.ts\",\"packages/server/src/routes/schemas/observability.schemas.ts\",\"packages/server/src/routes/schemas/personnel-usage.schemas.ts\",\"packages/server/src/routes/schemas/product-space.schemas.ts\",\"packages/server/src/routes/schemas/provider.schemas.ts\",\"packages/server/src/routes/schemas/runtime.schemas.ts\",\"packages/server/src/routes/schemas/scheduled-tasks.schemas.ts\",\"packages/server/src/routes/schemas/settings.schemas.ts\",\"packages/server/src/routes/schemas/system.schemas.ts\",\"packages/server/src/routes/schemas/ui-replay.schemas.ts\",\"packages/server/src/routes/schemas/web-verify.schemas.ts\",\"packages/server/src/routes/schemas/workflow.schemas.test.ts\",\"packages/server/src/routes/schemas/workflow.schemas.ts\",\"packages/server/src/routes/webhooks.ts\",\"packages/server/src/runtime-config.test.ts\",\"packages/server/src/scripts/backfill-forked-workflow-commands.ts\",\"packages/server/src/scripts/backfill-product-commands.ts\",\"packages/server/src/scripts/backfill-sla-classifications.ts\",\"packages/server/src/scripts/migrate-space-commands.ts\",\"packages/server/src/scripts/setup-auth.ts\",\"packages/server/src/services/callback-block.test.ts\",\"packages/server/src/services/infoflow-sender.test.ts\",\"packages/server/src/services/infoflow-webhook.test.ts\",\"packages/server/src/services/sla-infoflow-notifier.test.ts\",\"packages/server/src/services/workflow-access.test.ts\",\"packages/server/src/services/workflow-notification-listener.test.ts\",\"packages/server/src/services/workflow-restart-recovery.integration.test.ts\",\"packages/server/src/services/workflow-restart-recovery.test.ts\",\"packages/server/src/services/workflow-restart-recovery.ts\",\"packages/server/src/services/workflow-run-actions.test.ts\",\"packages/server/src/services/workflow-run-exporter.test.ts\",\"packages/server/src/services/workflow-run-knowledge-sync-dispatcher.test.ts\",\"packages/server/src/sync-bundled-commands.test.ts\",\"packages/server/src/sync-bundled-workflows.test.ts\",\"packages/server/src/sync-project-workflows.test.ts\",\"packages/server/src/sync-user-workflows.test.ts\",\"packages/server/src/test/workflow-mock-factories.ts\",\"packages/server/src/workers/sla-infoflow-worker.test.ts\",\"packages/server/tsconfig.json\",\"packages/server/tsconfig.tsbuildinfo\"]},{\"name\":\"Other \u2014 web\",\"slug\":\"other-web\",\"files\":[\"packages/web/components.json\",\"packages/web/e2e/chat-primary-flow.spec.ts\",\"packages/web/e2e/console-flow.spec.ts\",\"packages/web/e2e/dashboard-paused-delete-flow.spec.ts\",\"packages/web/e2e/dashboard-review-flow.spec.ts\",\"packages/web/e2e/diagnostics-flow.spec.ts\",\"packages/web/e2e/evaluation-center-flow.spec.ts\",\"packages/web/e2e/fixtures.ts\",\"packages/web/e2e/governance-smoke.spec.ts\",\"packages/web/e2e/knowledge-eval-real.spec.ts\",\"packages/web/e2e/knowledge-flow.spec.ts\",\"packages/web/e2e/mock-helpers.ts\",\"packages/web/e2e/settings-flow.spec.ts\",\"packages/web/e2e/space-admin-flow.spec.ts\",\"packages/web/e2e/traces-redirect-flow.spec.ts\",\"packages/web/e2e/ui-replay-center-flow.spec.ts\",\"packages/web/e2e/ui-replay-smoke.spec.ts\",\"packages/web/e2e/workflow-run-flow.spec.ts\",\"packages/web/index.html\",\"packages/web/package.json\",\"packages/web/playwright.config.ts\",\"packages/web/postcss.config.mjs\",\"packages/web/src/App.sidebar-routes.test.ts\",\"packages/web/src/components/chat/ArtifactRail.tsx\",\"packages/web/src/components/chat/BreakpointRetry.tsx\",\"packages/web/src/components/chat/ChatInterface.tsx\",\"packages/web/src/components/chat/ComposerContextControls.test.tsx\",\"packages/web/src/components/chat/ComposerContextControls.tsx\",\"packages/web/src/components/chat/ErrorCard.tsx\",\"packages/web/src/components/chat/FileAttachmentChips.tsx\",\"packages/web/src/components/chat/InputRequestForm.test.tsx\",\"packages/web/src/components/chat/InputRequestForm.tsx\",\"packages/web/src/components/chat/LockIndicator.tsx\",\"packages/web/src/components/chat/MessageBubble.strip.test.ts\",\"packages/web/src/components/chat/MessageBubble.tsx\",\"packages/web/src/components/chat/MessageInput.test.tsx\",\"packages/web/src/components/chat/MessageInput.tsx\",\"packages/web/src/components/chat/MessageList.tsx\",\"packages/web/src/components/chat/ToolCallCard.tsx\",\"packages/web/src/components/chat/TryItList.test.ts\",\"packages/web/src/components/chat/TryItList.tsx\",\"packages/web/src/components/chat/WorkflowApprovalBar.tsx\",\"packages/web/src/components/chat/WorkflowProgressCard.tsx\",\"packages/web/src/components/chat/WorkflowSelector.test.tsx\",\"packages/web/src/components/chat/WorkflowSelector.tsx\",\"packages/web/src/components/chat/WorkflowStatusBar.tsx\",\"packages/web/src/components/chat/markdownLink.tsx\",\"packages/web/src/components/chat/strip-input-request.ts\",\"packages/web/src/components/chat/workflow-groups.test.ts\",\"packages/web/src/components/chat/workflow-groups.ts\",\"packages/web/src/components/commands/CommandCard.tsx\",\"packages/web/src/components/commands/CommandDetailDialog.tsx\",\"packages/web/src/components/commands/CommandEditorDialog.theme.test.ts\",\"packages/web/src/components/commands/CommandEditorDialog.tsx\",\"packages/web/src/components/commands/CommandList.tsx\",\"packages/web/src/components/commands/DeleteCommandDialog.tsx\",\"packages/web/src/components/commands/ForkCommandDialog.tsx\",\"packages/web/src/components/conversations/ConversationItem.tsx\",\"packages/web/src/components/dashboard/ConfirmRunActionDialog.tsx\",\"packages/web/src/components/dashboard/DashboardFilters.tsx\",\"packages/web/src/components/dashboard/DashboardTabCount.test.tsx\",\"packages/web/src/components/dashboard/SettingsConcurrencySection.test.ts\",\"packages/web/src/components/dashboard/StatusBoard.tsx\",\"packages/web/src/components/dashboard/StatusSummaryBar.test.tsx\",\"packages/web/src/components/dashboard/WorkflowHistoryTable.tsx\",\"packages/web/src/components/dashboard/WorkflowRunCard.test.ts\",\"packages/web/src/components/dashboard/WorkflowRunCard.tsx\",\"packages/web/src/components/dashboard/WorkflowRunGroup.tsx\",\"packages/web/src/components/document-drawer/DocumentDrawer.tsx\",\"packages/web/src/components/document-drawer/DocumentDrawerContent.tsx\",\"packages/web/src/components/document-drawer/LogDrawer.tsx\",\"packages/web/src/components/document-drawer/MindMapViewer.tsx\",\"packages/web/src/components/document-drawer/SyncGitCaseDialog.tsx\",\"packages/web/src/components/document-drawer/transformCaseJson.ts\",\"packages/web/src/components/knowledge/graph/ArchView.tsx\",\"packages/web/src/components/knowledge/graph/EntityCreateDialog.tsx\",\"packages/web/src/components/knowledge/graph/EntityDetailLegend.tsx\",\"packages/web/src/components/knowledge/graph/EntityDetailSheet.tsx\",\"packages/web/src/components/knowledge/graph/EntityListTable.tsx\",\"packages/web/src/components/knowledge/graph/GraphCanvas.tsx\",\"packages/web/src/components/knowledge/graph/GraphToolbar.tsx\",\"packages/web/src/components/knowledge/graph/RelationEditDialog.tsx\",\"packages/web/src/components/layout/AppSidebar.test.tsx\",\"packages/web/src/components/layout/AppSidebar.tsx\",\"packages/web/src/components/layout/BackendStatusBanner.tsx\",\"packages/web/src/components/layout/Header.tsx\",\"packages/web/src/components/layout/Layout.tsx\",\"packages/web/src/components/layout/OnboardingWizardModal.tsx\",\"packages/web/src/components/layout/OneApiTokenDialog.tsx\",\"packages/web/src/components/layout/SetupWizardModal.render.test.tsx\",\"packages/web/src/components/layout/SetupWizardModal.test.ts\",\"packages/web/src/components/layout/SetupWizardModal.tsx\",\"packages/web/src/components/layout/Sidebar.test.tsx\",\"packages/web/src/components/layout/brand-constants.ts\",\"packages/web/src/components/layout/topnav-utils.ts\",\"packages/web/src/components/observability/ObservabilityProvider.tsx\",\"packages/web/src/components/product-space/AddGroupDialog.tsx\",\"packages/web/src/components/product-space/AddMemberDialog.tsx\",\"packages/web/src/components/product-space/GroupTable.tsx\",\"packages/web/src/components/product-space/MemberTable.tsx\",\"packages/web/src/components/product-space/ProductSpaceForm.tsx\",\"packages/web/src/components/product-space/ProductSpaceSelector.tsx\",\"packages/web/src/components/product-space/SpaceComboSection.tsx\",\"packages/web/src/components/product-space/SpaceProjectsSection.delete-confirm.test.ts\",\"packages/web/src/components/product-space/SpaceProjectsSection.tsx\",\"packages/web/src/components/product-space/SpaceScheduledTasksSection.tsx\",\"packages/web/src/components/settings/TokenSections.mutation.test.tsx\",\"packages/web/src/components/settings/TokenSections.test.tsx\",\"packages/web/src/components/settings/TokenSections.tsx\",\"packages/web/src/components/sidebar/AllConversationsView.tsx\",\"packages/web/src/components/sidebar/ProjectDetail.tsx\",\"packages/web/src/components/sidebar/ProjectSelector.tsx\",\"packages/web/src/components/sidebar/SearchBar.test.tsx\",\"packages/web/src/components/sidebar/SearchBar.tsx\",\"packages/web/src/components/sidebar/SidebarAbandonBar.test.tsx\",\"packages/web/src/components/sidebar/SidebarAbandonBar.tsx\",\"packages/web/src/components/sidebar/SidebarArtifactList.test.tsx\",\"packages/web/src/components/sidebar/SidebarArtifactList.tsx\",\"packages/web/src/components/sidebar/SidebarArtifactPanel.test.tsx\",\"packages/web/src/components/sidebar/SidebarArtifactPanel.tsx\",\"packages/web/src/components/sidebar/SidebarArtifactView.test.tsx\",\"packages/web/src/components/sidebar/SidebarArtifactView.tsx\",\"packages/web/src/components/sidebar/SidebarComposer.test.tsx\",\"packages/web/src/components/sidebar/SidebarComposer.tsx\",\"packages/web/src/components/sidebar/SidebarConfirmDialog.test.tsx\",\"packages/web/src/components/sidebar/SidebarConfirmDialog.tsx\",\"packages/web/src/components/sidebar/SidebarDetailHeader.test.tsx\",\"packages/web/src/components/sidebar/SidebarDetailHeader.tsx\",\"packages/web/src/components/sidebar/SidebarRunDetail.test.tsx\",\"packages/web/src/components/sidebar/SidebarRunDetail.tsx\",\"packages/web/src/components/sidebar/WorkflowInvoker.test.tsx\",\"packages/web/src/components/sidebar/WorkflowInvoker.tsx\",\"packages/web/src/components/sidebar/open-external.ts\",\"packages/web/src/components/sidebar/sidebar-artifact-css.test.ts\",\"packages/web/src/components/sidebar/sidebar-artifacts.test.ts\",\"packages/web/src/components/sidebar/sidebar-artifacts.ts\",\"packages/web/src/components/sidebar/sidebar-auth.test.ts\",\"packages/web/src/components/sidebar/sidebar-auth.ts\",\"packages/web/src/components/sidebar/sidebar-download.test.ts\",\"packages/web/src/components/sidebar/sidebar-download.ts\",\"packages/web/src/components/sidebar/sidebar-turn-css.test.ts\",\"packages/web/src/components/sidebar/sidebar.css\",\"packages/web/src/components/sidebar/useSidebarAuthGuard.test.ts\",\"packages/web/src/components/sidebar/useSidebarAuthGuard.ts\",\"packages/web/src/components/sidebar/useSidebarRun.ts\",\"packages/web/src/components/ui/adapters.test.tsx\",\"packages/web/src/components/ui/alert-dialog.tsx\",\"packages/web/src/components/ui/badge.tsx\",\"packages/web/src/components/ui/button.tsx\",\"packages/web/src/components/ui/card.tsx\",\"packages/web/src/components/ui/collapsible.tsx\",\"packages/web/src/components/ui/combobox.tsx\",\"packages/web/src/components/ui/dialog.tsx\",\"packages/web/src/components/ui/dropdown-menu.tsx\",\"packages/web/src/components/ui/input.tsx\",\"packages/web/src/components/ui/popover.tsx\",\"packages/web/src/components/ui/primitives.test.tsx\",\"packages/web/src/components/ui/resizable.tsx\",\"packages/web/src/components/ui/scroll-area.tsx\",\"packages/web/src/components/ui/select.tsx\",\"packages/web/src/components/ui/separator.tsx\",\"packages/web/src/components/ui/sheet.tsx\",\"packages/web/src/components/ui/switch.tsx\",\"packages/web/src/components/ui/tabs.tsx\",\"packages/web/src/components/ui/textarea.tsx\",\"packages/web/src/components/ui/tooltip.tsx\",\"packages/web/src/components/ui/two-level-menu.tsx\",\"packages/web/src/components/workflows/AiBuilderPanel.autofix.test.ts\",\"packages/web/src/components/workflows/AiBuilderPanel.convert.test.tsx\",\"packages/web/src/components/workflows/AiBuilderPanel.tsx\",\"packages/web/src/components/workflows/ArtifactSummary.tsx\",\"packages/web/src/components/workflows/ArtifactViewerModal.tsx\",\"packages/web/src/components/workflows/AuthoringModelSelect.tsx\",\"packages/web/src/components/workflows/BuilderToolbar.tsx\",\"packages/web/src/components/workflows/CommandPicker.tsx\",\"packages/web/src/components/workflows/DagNodeComponent.test.ts\",\"packages/web/src/components/workflows/DagNodeComponent.tsx\",\"packages/web/src/components/workflows/DagNodeProgress.tsx\",\"packages/web/src/components/workflows/ExecutionDagNode.tsx\",\"packages/web/src/components/workflows/ForkWorkflowDialog.tsx\",\"packages/web/src/components/workflows/ImportAnthropicWorkflowDialog.test.ts\",\"packages/web/src/components/workflows/ImportAnthropicWorkflowDialog.tsx\",\"packages/web/src/components/workflows/LoopBackEdge.render.test.tsx\",\"packages/web/src/components/workflows/LoopBackEdge.test.tsx\",\"packages/web/src/components/workflows/LoopBackEdge.tsx\",\"packages/web/src/components/workflows/NodeInspector.tsx\",\"packages/web/src/components/workflows/NodeLibrary.tsx\",\"packages/web/src/components/workflows/NodePalette.tsx\",\"packages/web/src/components/workflows/PopularWorkflows.tsx\",\"packages/web/src/components/workflows/QuickAddPicker.tsx\",\"packages/web/src/components/workflows/StatusBar.tsx\",\"packages/web/src/components/workflows/StatusIcon.tsx\",\"packages/web/src/components/workflows/StepLogs.tsx\",\"packages/web/src/components/workflows/ValidationPanel.tsx\",\"packages/web/src/components/workflows/WorkflowBuilder.theme.test.ts\",\"packages/web/src/components/workflows/WorkflowBuilder.toolbar.test.ts\",\"packages/web/src/components/workflows/WorkflowBuilder.tsx\",\"packages/web/src/components/workflows/WorkflowCanvas.nodeLabel.test.ts\",\"packages/web/src/components/workflows/WorkflowCanvas.test.ts\",\"packages/web/src/components/workflows/WorkflowCanvas.tsx\",\"packages/web/src/components/workflows/WorkflowCard.test.ts\",\"packages/web/src/components/workflows/WorkflowCard.tsx\",\"packages/web/src/components/workflows/WorkflowDagViewer.tsx\",\"packages/web/src/components/workflows/WorkflowDetail.tsx\",\"packages/web/src/components/workflows/WorkflowExecution.tsx\",\"packages/web/src/components/workflows/WorkflowList.delete-confirm.test.ts\",\"packages/web/src/components/workflows/WorkflowList.sidebar-filter.test.ts\",\"packages/web/src/components/workflows/WorkflowList.tsx\",\"packages/web/src/components/workflows/WorkflowLogs.tsx\",\"packages/web/src/components/workflows/WorkflowModelSelect.tsx\",\"packages/web/src/components/workflows/WorkflowScopeBadge.tsx\",\"packages/web/src/components/workflows/WorkflowSourceBadge.test.ts\",\"packages/web/src/components/workflows/WorkflowSourceBadge.tsx\",\"packages/web/src/components/workflows/WorkflowSpaceSelector.tsx\",\"packages/web/src/components/workflows/YamlCodeView.test.ts\",\"packages/web/src/components/workflows/YamlCodeView.tsx\",\"packages/web/src/components/workflows/use-popular-workflows.test.ts\",\"packages/web/src/components/workflows/use-popular-workflows.ts\",\"packages/web/src/contexts/OnboardingContext.tsx\",\"packages/web/src/contexts/ProjectContext.model-memory.test.ts\",\"packages/web/src/contexts/ProjectContext.tsx\",\"packages/web/src/contexts/ThemeContext.tsx\",\"packages/web/src/contexts/TokenValidationContext.test.tsx\",\"packages/web/src/contexts/TokenValidationContext.tsx\",\"packages/web/src/contexts/model-memory.ts\",\"packages/web/src/hooks/stream-hooks.test.ts\",\"packages/web/src/hooks/useApiAvailability.test.ts\",\"packages/web/src/hooks/useApiAvailability.ts\",\"packages/web/src/hooks/useAutoScroll.ts\",\"packages/web/src/hooks/useBuilderKeyboard.test.ts\",\"packages/web/src/hooks/useBuilderKeyboard.ts\",\"packages/web/src/hooks/useBuilderUndo.ts\",\"packages/web/src/hooks/useBuilderValidation.ts\",\"packages/web/src/hooks/useClickOutside.ts\",\"packages/web/src/hooks/useConversationStream.test.ts\",\"packages/web/src/hooks/useConversationStream.ts\",\"packages/web/src/hooks/useDashboardSSE.ts\",\"packages/web/src/hooks/useDocumentDrawer.ts\",\"packages/web/src/hooks/useEvaluationSSE.ts\",\"packages/web/src/hooks/useFileAttachments.ts\",\"packages/web/src/hooks/useKeyboardShortcuts.ts\",\"packages/web/src/hooks/useObservabilitySSE.ts\",\"packages/web/src/hooks/usePollingWhenRunning.test.ts\",\"packages/web/src/hooks/usePollingWhenRunning.ts\",\"packages/web/src/hooks/useProviders.ts\",\"packages/web/src/hooks/useRuntimeTraceSSE.ts\",\"packages/web/src/hooks/useSSE.ts\",\"packages/web/src/hooks/useServerValidation.test.ts\",\"packages/web/src/hooks/useServerValidation.ts\",\"packages/web/src/hooks/useSetupStatus.ts\",\"packages/web/src/hooks/useWorkflowDraftSync.test.ts\",\"packages/web/src/hooks/useWorkflowDraftSync.ts\",\"packages/web/src/hooks/useWorkflowModels.ts\",\"packages/web/src/index.css\",\"packages/web/src/lib/api-availability.test.ts\",\"packages/web/src/lib/api-availability.ts\",\"packages/web/src/lib/api.test.ts\",\"packages/web/src/lib/api.ts\",\"packages/web/src/lib/artifact-grouping.test.ts\",\"packages/web/src/lib/artifact-grouping.ts\",\"packages/web/src/lib/breakpoint-retry.test.ts\",\"packages/web/src/lib/breakpoint-retry.ts\",\"packages/web/src/lib/chat-message-reducer.test.ts\",\"packages/web/src/lib/chat-message-reducer.ts\",\"packages/web/src/lib/clarify-request.test.ts\",\"packages/web/src/lib/codebase-input.test.ts\",\"packages/web/src/lib/codebase-input.ts\",\"packages/web/src/lib/command-categories.ts\",\"packages/web/src/lib/composer-persistence.test.ts\",\"packages/web/src/lib/composer-persistence.ts\",\"packages/web/src/lib/conversation-grouping.test.ts\",\"packages/web/src/lib/conversation-grouping.ts\",\"packages/web/src/lib/currency.test.ts\",\"packages/web/src/lib/currency.ts\",\"packages/web/src/lib/dag-layout-loop-back.test.ts\",\"packages/web/src/lib/dag-layout.test.ts\",\"packages/web/src/lib/dag-layout.ts\",\"packages/web/src/lib/dashboard-tab-count.ts\",\"packages/web/src/lib/extract-message-artifacts.test.ts\",\"packages/web/src/lib/extract-message-artifacts.ts\",\"packages/web/src/lib/file-attachments.test.ts\",\"packages/web/src/lib/file-attachments.ts\",\"packages/web/src/lib/format.test.ts\",\"packages/web/src/lib/format.ts\",\"packages/web/src/lib/keyboard.ts\",\"packages/web/src/lib/knowledge/api-key.test.ts\",\"packages/web/src/lib/knowledge/api-key.ts\",\"packages/web/src/lib/knowledge/api.graph-inspection.test.ts\",\"packages/web/src/lib/knowledge/api.test.ts\",\"packages/web/src/lib/knowledge/api.ts\",\"packages/web/src/lib/knowledge/arch-constants.tsx\",\"packages/web/src/lib/knowledge/build-status.test.ts\",\"packages/web/src/lib/knowledge/build-status.ts\",\"packages/web/src/lib/knowledge/constants.ts\",\"packages/web/src/lib/knowledge/entity-form.test.ts\",\"packages/web/src/lib/knowledge/entity-form.ts\",\"packages/web/src/lib/knowledge/force-graph.ts\",\"packages/web/src/lib/knowledge/mock-data.ts\",\"packages/web/src/lib/knowledge/relation-target.test.ts\",\"packages/web/src/lib/knowledge/relation-target.ts\",\"packages/web/src/lib/knowledge/source-parser.ts\",\"packages/web/src/lib/knowledge/types.ts\",\"packages/web/src/lib/knowledge/wiki-api.ts\",\"packages/web/src/lib/knowledge/wiki-version-api.ts\",\"packages/web/src/lib/message-cache.test.ts\",\"packages/web/src/lib/message-cache.ts\",\"packages/web/src/lib/message-mapper.test.ts\",\"packages/web/src/lib/message-mapper.ts\",\"packages/web/src/lib/message-turns.test.ts\",\"packages/web/src/lib/message-turns.ts\",\"packages/web/src/lib/observability-query-keys.ts\",\"packages/web/src/lib/observability.test.ts\",\"packages/web/src/lib/observability.ts\",\"packages/web/src/lib/onboarding-nav.test.ts\",\"packages/web/src/lib/onboarding-nav.ts\",\"packages/web/src/lib/overflow-utils.test.ts\",\"packages/web/src/lib/overflow-utils.ts\",\"packages/web/src/lib/project-scope.test.ts\",\"packages/web/src/lib/project-scope.ts\",\"packages/web/src/lib/query-client.ts\",\"packages/web/src/lib/runtime-config.ts\",\"packages/web/src/lib/runtime-trace-insights.test.ts\",\"packages/web/src/lib/runtime-trace-insights.ts\",\"packages/web/src/lib/scheduled-task-polling.test.ts\",\"packages/web/src/lib/scheduled-task-polling.ts\",\"packages/web/src/lib/select-initial-node.test.ts\",\"packages/web/src/lib/select-initial-node.ts\",\"packages/web/src/lib/session-status-colors.test.ts\",\"packages/web/src/lib/session-status-colors.ts\",\"packages/web/src/lib/session-url-validation.test.ts\",\"packages/web/src/lib/session-url-validation.ts\",\"packages/web/src/lib/settings-copy.test.ts\",\"packages/web/src/lib/settings-copy.ts\",\"packages/web/src/lib/sidebar-progress.test.ts\",\"packages/web/src/lib/sidebar-progress.ts\",\"packages/web/src/lib/status-summary-bar-utils.ts\",\"packages/web/src/lib/types.ts\",\"packages/web/src/lib/utils.ts\",\"packages/web/src/lib/workflow-builder-canvas-status.test.ts\",\"packages/web/src/lib/workflow-builder-canvas-status.ts\",\"packages/web/src/lib/workflow-draft-content.test.ts\",\"packages/web/src/lib/workflow-draft-content.ts\",\"packages/web/src/lib/workflow-events.test.ts\",\"packages/web/src/lib/workflow-events.ts\",\"packages/web/src/lib/workflow-history-table-styles.test.ts\",\"packages/web/src/lib/workflow-history-table-styles.ts\",\"packages/web/src/lib/workflow-metadata.test.ts\",\"packages/web/src/lib/workflow-metadata.ts\",\"packages/web/src/lib/workflow-node-type.test.ts\",\"packages/web/src/lib/workflow-node-type.ts\",\"packages/web/src/lib/workflow-run-state.test.ts\",\"packages/web/src/lib/workflow-run-state.ts\",\"packages/web/src/lib/workflow-scope.test.ts\",\"packages/web/src/lib/workflow-scope.ts\",\"packages/web/src/lib/workflow-stage-mapping.ts\",\"packages/web/src/lib/workflow-usage-timing.test.ts\",\"packages/web/src/lib/workflow-usage-timing.ts\",\"packages/web/src/lib/workflow-usage-trace.test.ts\",\"packages/web/src/lib/workflow-usage-trace.ts\",\"packages/web/src/lib/workflow-utils.test.ts\",\"packages/web/src/lib/workflow-utils.ts\",\"packages/web/src/routes/ChatPage.test.tsx\",\"packages/web/src/routes/ChatPage.tsx\",\"packages/web/src/routes/ControlConsolePage.tsx\",\"packages/web/src/routes/DashboardPage.tsx\",\"packages/web/src/routes/EvaluationSlaPage.render.test.tsx\",\"packages/web/src/routes/EvaluationSlaPage.test.ts\",\"packages/web/src/routes/EvaluationSlaPage.theme.test.tsx\",\"packages/web/src/routes/LoginPage.tsx\",\"packages/web/src/routes/PersonnelUsagePage.test.tsx\",\"packages/web/src/routes/PersonnelUsagePage.tsx\",\"packages/web/src/routes/ProductSpacePage.tsx\",\"packages/web/src/routes/RealtimeEvaluationPage.tsx\",\"packages/web/src/routes/SettingsPage.tsx\",\"packages/web/src/routes/SidebarListPage.test.tsx\",\"packages/web/src/routes/SidebarListPage.tsx\",\"packages/web/src/routes/SidebarRunPage.test.tsx\",\"packages/web/src/routes/SidebarRunPage.tsx\",\"packages/web/src/routes/SidebarStartPage.test.tsx\",\"packages/web/src/routes/SidebarStartPage.tsx\",\"packages/web/src/routes/WorkflowBuilderPage.tsx\",\"packages/web/src/routes/WorkflowDetailPage.tsx\",\"packages/web/src/routes/WorkflowExecutionPage.tsx\",\"packages/web/src/routes/WorkflowSpacePage.tsx\",\"packages/web/src/routes/WorkflowUsagePage.tsx\",\"packages/web/src/routes/control-console/debug.tsx\",\"packages/web/src/routes/control-console/governance.tsx\",\"packages/web/src/routes/control-console/overview.render.test.tsx\",\"packages/web/src/routes/control-console/overview.test.ts\",\"packages/web/src/routes/control-console/overview.tsx\",\"packages/web/src/routes/control-console/runForScope.test.ts\",\"packages/web/src/routes/control-console/shared.test.ts\",\"packages/web/src/routes/control-console/shared.tsx\",\"packages/web/src/routes/control-console/topology.test.tsx\",\"packages/web/src/routes/control-console/topology.tsx\",\"packages/web/src/routes/control-console/workflows.raw-download.test.tsx\",\"packages/web/src/routes/control-console/workflows.scroll.test.tsx\",\"packages/web/src/routes/control-console/workflows.select-trace.test.tsx\",\"packages/web/src/routes/control-console/workflows.spacing.test.ts\",\"packages/web/src/routes/control-console/workflows.trace-list.test.ts\",\"packages/web/src/routes/control-console/workflows.tsx\",\"packages/web/src/routes/knowledge/AikuApiKeyDialog.render.test.tsx\",\"packages/web/src/routes/knowledge/AikuApiKeyDialog.state.test.tsx\",\"packages/web/src/routes/knowledge/AikuApiKeyDialog.test.tsx\",\"packages/web/src/routes/knowledge/AikuApiKeyDialog.tsx\",\"packages/web/src/routes/knowledge/DocsSection.tsx\",\"packages/web/src/routes/knowledge/GraphSection.tsx\",\"packages/web/src/routes/knowledge/QualitySection.tsx\",\"packages/web/src/routes/knowledge/audit/AuditSection.test.tsx\",\"packages/web/src/routes/knowledge/audit/AuditSection.tsx\",\"packages/web/src/routes/knowledge/bootstrap/ark-import.tsx\",\"packages/web/src/routes/knowledge/bootstrap/doc-upload-button.test.tsx\",\"packages/web/src/routes/knowledge/bootstrap/doc-upload-button.tsx\",\"packages/web/src/routes/knowledge/bootstrap/index.tsx\",\"packages/web/src/routes/knowledge/bootstrap/smart-fill.test.tsx\",\"packages/web/src/routes/knowledge/bootstrap/smart-fill.tsx\",\"packages/web/src/routes/knowledge/bootstrap/step-testcases.test.tsx\",\"packages/web/src/routes/knowledge/bootstrap/step-testcases.tsx\",\"packages/web/src/routes/knowledge/bootstrap/step1-browse.test.tsx\",\"packages/web/src/routes/knowledge/bootstrap/step1-browse.tsx\",\"packages/web/src/routes/knowledge/bootstrap/step1.test.tsx\",\"packages/web/src/routes/knowledge/bootstrap/step1.tsx\",\"packages/web/src/routes/knowledge/bootstrap/step2.tsx\",\"packages/web/src/routes/knowledge/bootstrap/step3.tsx\",\"packages/web/src/routes/knowledge/bootstrap/ui.test.tsx\",\"packages/web/src/routes/knowledge/bootstrap/ui.tsx\",\"packages/web/src/routes/knowledge/eval/EvalHistorySheet.test.tsx\",\"packages/web/src/routes/knowledge/eval/EvalHistorySheet.tsx\",\"packages/web/src/routes/knowledge/eval/EvalQuestionCreate.test.tsx\",\"packages/web/src/routes/knowledge/eval/EvalQuestionCreate.tsx\",\"packages/web/src/routes/knowledge/eval/EvalQuestionEdit.test.tsx\",\"packages/web/src/routes/knowledge/eval/EvalQuestionEdit.tsx\",\"packages/web/src/routes/knowledge/eval/EvalSection.test.tsx\",\"packages/web/src/routes/knowledge/eval/EvalSection.tsx\",\"packages/web/src/routes/knowledge/eval/EvalSetDetail.test.tsx\",\"packages/web/src/routes/knowledge/eval/EvalSetDetail.tsx\",\"packages/web/src/routes/knowledge/eval/EvalSetHistorySheet.test.tsx\",\"packages/web/src/routes/knowledge/eval/EvalSetHistorySheet.tsx\",\"packages/web/src/routes/knowledge/eval/EvalSetList.test.tsx\",\"packages/web/src/routes/knowledge/eval/EvalSetList.tsx\",\"packages/web/src/routes/knowledge/eval/FeedbackImportSheet.test.tsx\",\"packages/web/src/routes/knowledge/eval/FeedbackImportSheet.tsx\",\"packages/web/src/routes/knowledge/eval/dimensions.test.ts\",\"packages/web/src/routes/knowledge/eval/dimensions.ts\",\"packages/web/src/routes/knowledge/evaluation/CaseResultDrawer.test.tsx\",\"packages/web/src/routes/knowledge/evaluation/CaseResultDrawer.tsx\",\"packages/web/src/routes/knowledge/evaluation/EvaluationSection.test.tsx\",\"packages/web/src/routes/knowledge/evaluation/EvaluationSection.tsx\",\"packages/web/src/routes/knowledge/evaluation/LatestRunSummary.test.tsx\",\"packages/web/src/routes/knowledge/evaluation/LatestRunSummary.tsx\",\"packages/web/src/routes/knowledge/evaluation/RunDetail.test.tsx\",\"packages/web/src/routes/knowledge/evaluation/RunDetail.tsx\",\"packages/web/src/routes/knowledge/evaluation/RunList.test.tsx\",\"packages/web/src/routes/knowledge/evaluation/RunList.tsx\",\"packages/web/src/routes/knowledge/evaluation/RunReport.test.tsx\",\"packages/web/src/routes/knowledge/evaluation/RunReport.tsx\",\"packages/web/src/routes/knowledge/evaluation/TriggerRunDialog.test.tsx\",\"packages/web/src/routes/knowledge/evaluation/TriggerRunDialog.tsx\",\"packages/web/src/routes/knowledge/evaluation/api-hooks.ts\",\"packages/web/src/routes/knowledge/evaluation/index.ts\",\"packages/web/src/routes/knowledge/evaluation/shared.test.tsx\",\"packages/web/src/routes/knowledge/evaluation/shared.tsx\",\"packages/web/src/routes/knowledge/governance/CandidateDetailDialog.test.tsx\",\"packages/web/src/routes/knowledge/governance/CandidateDetailDialog.tsx\",\"packages/web/src/routes/knowledge/governance/CandidateReviewPanel.test.tsx\",\"packages/web/src/routes/knowledge/governance/CandidateReviewPanel.tsx\",\"packages/web/src/routes/knowledge/governance/GovernanceSection.test.tsx\",\"packages/web/src/routes/knowledge/governance/GovernanceSection.tsx\",\"packages/web/src/routes/knowledge/governance/InspectionReportDetail.test.tsx\",\"packages/web/src/routes/knowledge/governance/InspectionReportDetail.tsx\",\"packages/web/src/routes/knowledge/governance/helpers.test.tsx\",\"packages/web/src/routes/knowledge/governance/helpers.tsx\",\"packages/web/src/routes/knowledge/graph/ArchitectureViewPage.test.tsx\",\"packages/web/src/routes/knowledge/graph/ArchitectureViewPage.tsx\",\"packages/web/src/routes/knowledge/graph/EntityBrowserPage.test.tsx\",\"packages/web/src/routes/knowledge/graph/EntityBrowserPage.tsx\",\"packages/web/src/routes/knowledge/graph/GraphPage.test.tsx\",\"packages/web/src/routes/knowledge/graph/GraphPage.tsx\",\"packages/web/src/routes/knowledge/integrity/IntegritySection.render.test.tsx\",\"packages/web/src/routes/knowledge/integrity/IntegritySection.test.tsx\",\"packages/web/src/routes/knowledge/integrity/IntegritySection.tsx\",\"packages/web/src/routes/knowledge/shared.test.ts\",\"packages/web/src/routes/knowledge/shared.tsx\",\"packages/web/src/routes/knowledge/usage/UsageStatsSection.test.tsx\",\"packages/web/src/routes/knowledge/usage/UsageStatsSection.tsx\",\"packages/web/src/routes/knowledge/useKnowledgeBuildStatus.ts\",\"packages/web/src/routes/knowledge/wiki/WikiChangeBanner.tsx\",\"packages/web/src/routes/knowledge/wiki/WikiComposePane.test.tsx\",\"packages/web/src/routes/knowledge/wiki/WikiComposePane.tsx\",\"packages/web/src/routes/knowledge/wiki/WikiDiffView.tsx\",\"packages/web/src/routes/knowledge/wiki/WikiDocPane.test.tsx\",\"packages/web/src/routes/knowledge/wiki/WikiDocPane.tsx\",\"packages/web/src/routes/knowledge/wiki/WikiHistoryDialog.tsx\",\"packages/web/src/routes/knowledge/wiki/WikiPendingPane.test.tsx\",\"packages/web/src/routes/knowledge/wiki/WikiPendingPane.tsx\",\"packages/web/src/routes/knowledge/wiki/WikiSection.test.tsx\",\"packages/web/src/routes/knowledge/wiki/WikiSection.tsx\",\"packages/web/src/routes/knowledge/wiki/WikiTree.test.tsx\",\"packages/web/src/routes/knowledge/wiki/WikiTree.tsx\",\"packages/web/src/routes/realtime-evaluation/RealtimeEvaluationChrome.tsx\",\"packages/web/src/routes/realtime-evaluation/RealtimeEvaluationContent.tsx\",\"packages/web/src/routes/realtime-evaluation/WorkflowUsageSection.tsx\",\"packages/web/src/routes/realtime-evaluation/evaluation-view-model.test.ts\",\"packages/web/src/routes/realtime-evaluation/evaluation-view-model.ts\",\"packages/web/src/routes/realtime-evaluation/shared.test.ts\",\"packages/web/src/routes/realtime-evaluation/shared.tsx\",\"packages/web/src/routes/realtime-evaluation/useRealtimeEvaluationPageState.test.tsx\",\"packages/web/src/routes/realtime-evaluation/useRealtimeEvaluationPageState.ts\",\"packages/web/src/routes/realtime-evaluation/workflow-usage-metrics.test.ts\",\"packages/web/src/routes/sidebar-common.tsx\",\"packages/web/src/routes/ui-replay/UiReplayCenterPage.tsx\",\"packages/web/src/routes/ui-replay/browserReplay.ts\",\"packages/web/src/routes/ui-replay/codegen.ts\",\"packages/web/src/routes/ui-replay/components.tsx\",\"packages/web/src/routes/ui-replay/constants.ts\",\"packages/web/src/routes/ui-replay/format.ts\",\"packages/web/src/routes/ui-replay/types.ts\",\"packages/web/src/routes/ui-replay/useIframeRecorder.ts\",\"packages/web/src/stores/auth-store.test.ts\",\"packages/web/src/stores/product-space-store.test.ts\",\"packages/web/src/stores/product-space-store.ts\",\"packages/web/src/stores/sidebar-store.ts\",\"packages/web/src/stores/workflow-space-store.test.ts\",\"packages/web/src/stores/workflow-space-store.ts\",\"packages/web/src/stores/workflow-store-loop-back-hydrate.test.ts\",\"packages/web/src/stores/workflow-store-loop-back.test.ts\",\"packages/web/src/stores/workflow-store.test.ts\",\"packages/web/src/stores/workflow-store.ts\",\"packages/web/tsconfig.json\",\"packages/web/vite.config.ts\"]},{\"name\":\"Other \u2014 workflows\",\"slug\":\"other-workflows\",\"files\":[\"packages/workflows/package.json\",\"packages/workflows/src/artifact-publisher.test.ts\",\"packages/workflows/src/artifact-publisher.ts\",\"packages/workflows/src/combo-codebases.test.ts\",\"packages/workflows/src/combo-codebases.ts\",\"packages/workflows/src/command-discovery.test.ts\",\"packages/workflows/src/command-discovery.ts\",\"packages/workflows/src/command-validation.test.ts\",\"packages/workflows/src/command-validation.ts\",\"packages/workflows/src/condition-evaluator.test.ts\",\"packages/workflows/src/condition-evaluator.ts\",\"packages/workflows/src/dag-executor-loop-back-resume.test.ts\",\"packages/workflows/src/dag-executor-loop-back-review.test.ts\",\"packages/workflows/src/dag-executor-loop-back.test.ts\",\"packages/workflows/src/dag-executor.test.ts\",\"packages/workflows/src/dag-executor.ts\",\"packages/workflows/src/defaults/bundled-defaults.test.ts\",\"packages/workflows/src/defaults/bundled-defaults.ts\",\"packages/workflows/src/deps.ts\",\"packages/workflows/src/event-emitter.test.ts\",\"packages/workflows/src/event-emitter.ts\",\"packages/workflows/src/executor-preamble.test.ts\",\"packages/workflows/src/executor-shared.test.ts\",\"packages/workflows/src/executor-shared.ts\",\"packages/workflows/src/executor.model-resolution.test.ts\",\"packages/workflows/src/executor.test.ts\",\"packages/workflows/src/executor.ts\",\"packages/workflows/src/extract-input-request.test.ts\",\"packages/workflows/src/hooks.test.ts\",\"packages/workflows/src/knowledge-governor.test.ts\",\"packages/workflows/src/knowledge-governor.ts\",\"packages/workflows/src/knowledge-mode.test.ts\",\"packages/workflows/src/knowledge-mode.ts\",\"packages/workflows/src/knowledge-observability.test.ts\",\"packages/workflows/src/knowledge-observability.ts\",\"packages/workflows/src/load-command-prompt.test.ts\",\"packages/workflows/src/loader-loop-back.test.ts\",\"packages/workflows/src/loader.test.ts\",\"packages/workflows/src/loader.ts\",\"packages/workflows/src/logger.test.ts\",\"packages/workflows/src/logger.ts\",\"packages/workflows/src/loop-back-e2e.test.ts\",\"packages/workflows/src/loop-back-interval.test.ts\",\"packages/workflows/src/loop-back-interval.ts\",\"packages/workflows/src/router.test.ts\",\"packages/workflows/src/router.ts\",\"packages/workflows/src/runtime-check.test.ts\",\"packages/workflows/src/schemas.test.ts\",\"packages/workflows/src/schemas/dag-node.ts\",\"packages/workflows/src/schemas/hooks.ts\",\"packages/workflows/src/schemas/index.ts\",\"packages/workflows/src/schemas/input-request.test.ts\",\"packages/workflows/src/schemas/input-request.ts\",\"packages/workflows/src/schemas/loop-back.test.ts\",\"packages/workflows/src/schemas/loop-back.ts\",\"packages/workflows/src/schemas/loop-metrics.ts\",\"packages/workflows/src/schemas/loop.ts\",\"packages/workflows/src/schemas/retry.ts\",\"packages/workflows/src/schemas/workflow-run-loop-back.test.ts\",\"packages/workflows/src/schemas/workflow-run.ts\",\"packages/workflows/src/schemas/workflow.test.ts\",\"packages/workflows/src/schemas/workflow.ts\",\"packages/workflows/src/script-discovery.test.ts\",\"packages/workflows/src/script-discovery.ts\",\"packages/workflows/src/script-node-deps.test.ts\",\"packages/workflows/src/skill-installer.test.ts\",\"packages/workflows/src/skill-installer.ts\",\"packages/workflows/src/store.ts\",\"packages/workflows/src/test-utils.ts\",\"packages/workflows/src/utils/duration.test.ts\",\"packages/workflows/src/utils/duration.ts\",\"packages/workflows/src/utils/idle-timeout.test.ts\",\"packages/workflows/src/utils/idle-timeout.ts\",\"packages/workflows/src/utils/tool-formatter.test.ts\",\"packages/workflows/src/utils/tool-formatter.ts\",\"packages/workflows/src/utils/variable-substitution.test.ts\",\"packages/workflows/src/utils/variable-substitution.ts\",\"packages/workflows/src/validation-parser.test.ts\",\"packages/workflows/src/validation-parser.ts\",\"packages/workflows/src/validator.test.ts\",\"packages/workflows/src/validator.ts\",\"packages/workflows/src/version-snapshot.test.ts\",\"packages/workflows/src/version-snapshot.ts\",\"packages/workflows/src/workflow-discovery.ts\",\"packages/workflows/tsconfig.json\"]},{\"name\":\"Other \u2014 scripts\",\"slug\":\"other-scripts\",\"files\":[\"scripts/build-binaries.sh\",\"scripts/build.sh\",\"scripts/check-aiflow-pytest-scenarios.py\",\"scripts/check-bundled-skill.ts\",\"scripts/check-sla-reliability.sql\",\"scripts/checksums.sh\",\"scripts/clean-dev-branches.sh\",\"scripts/coverage-gate.test.ts\",\"scripts/coverage-gate.ts\",\"scripts/cr-classify.sh\",\"scripts/delete-dev-workflows.sql\",\"scripts/gen-workflow-syntax-doc.test.ts\",\"scripts/gen-workflow-syntax-doc.ts\",\"scripts/generate-api-inventory.test.ts\",\"scripts/generate-api-inventory.ts\",\"scripts/generate-bundled-defaults.ts\",\"scripts/gitnexus-init.sh\",\"scripts/install.ps1\",\"scripts/install.sh\",\"scripts/install_aiflow.sh\",\"scripts/ipipe-cr.sh\",\"scripts/quality-report.ts\",\"scripts/ragas-e2e-stress.ts\",\"scripts/run-aiflow-scenario-cases.sh\",\"scripts/run-coverage.ts\",\"scripts/security-secrets.sh\",\"scripts/select-affected.ts\",\"scripts/sync-versions.sh\",\"scripts/test-sandbox-file-ops.ts\",\"scripts/test-uic-search.ts\",\"scripts/trigger-workflow.sh\",\"scripts/tsconfig.json\",\"scripts/ui-replay-report.ts\",\"scripts/ui-replay-scaffold.ts\",\"scripts/update-homebrew.sh\",\"scripts/upload-aiflow-bos.sh\",\"scripts/validate-setup.sh\",\"scripts/verify-space-commands.ts\"]},{\"name\":\"Other \u2014 db-governance\",\"slug\":\"other-db-governance\",\"files\":[\"scripts/db-governance/00_preflight.sql\",\"scripts/db-governance/01_shrink_observability_events.sql\",\"scripts/db-governance/02_shrink_trace_events.sql\",\"scripts/db-governance/03_shrink_workflow_events.sql\",\"scripts/db-governance/04_verify_after_shrink.sql\",\"scripts/db-governance/05_drop_old_tables.sql\",\"scripts/db-governance/10_rolling_cleanup.sql\",\"scripts/db-governance/README.md\"]},{\"name\":\"Other \u2014 deepeval-evaluator\",\"slug\":\"other-deepeval-evaluator\",\"files\":[\"services/deepeval-evaluator/Dockerfile\",\"services/deepeval-evaluator/README.md\",\"services/deepeval-evaluator/requirements.txt\"]},{\"name\":\"Other \u2014 ragas-evaluator\",\"slug\":\"other-ragas-evaluator\",\"files\":[\"services/ragas-evaluator/Dockerfile\",\"services/ragas-evaluator/README.md\",\"services/ragas-evaluator/requirements.txt\"]},{\"name\":\"Other \u2014 todos.md\",\"slug\":\"other-todos-md\",\"files\":[\"todos.md\"]},{\"name\":\"Other \u2014 tsconfig.json\",\"slug\":\"other-tsconfig-json\",\"files\":[\"tsconfig.json\"]}]}]};\n\n(function() {\n  var activePage = 'overview';\n\n  document.addEventListener('DOMContentLoaded', function() {\n    mermaid.initialize({ startOnLoad: false, theme: 'neutral', securityLevel: 'loose' });\n    renderMeta();\n    renderNav();\n    document.getElementById('menu-toggle').addEventListener('click', function() {\n      document.getElementById('sidebar').classList.toggle('open');\n    });\n    if (location.hash &amp;&amp; location.hash.length &gt; 1) {\n      activePage = decodeURIComponent(location.hash.slice(1));\n    }\n    navigateTo(activePage);\n  });\n\n  function renderMeta() {\n    if (!META) return;\n    var el = document.getElementById('meta-info');\n    var parts = [];\n    if (META.generatedAt) {\n      parts.push(new Date(META.generatedAt).toLocaleDateString());\n    }\n    if (META.model) parts.push(META.model);\n    if (META.fromCommit) parts.push(META.fromCommit.slice(0, 8));\n    el.textContent = parts.join(' \\u00b7 ');\n  }\n\n  function renderNav() {\n    var container = document.getElementById('nav-tree');\n    var html = '\n';\n    html += 'Overview';\n    html += '';\n    if (TREE.length &gt; 0) {\n      html += '\nModules';\n      html += buildNavTree(TREE);\n    }\n    container.innerHTML = html;\n    container.addEventListener('click', function(e) {\n      var target = e.target;\n      while (target &amp;&amp; !target.dataset.page) { target = target.parentElement; }\n      if (target &amp;&amp; target.dataset.page) {\n        e.preventDefault();\n        navigateTo(target.dataset.page);\n      }\n    });\n  }\n\n  function buildNavTree(nodes) {\n    var html = '';\n    for (var i = 0; i &lt; nodes.length; i++) {\n      var node = nodes[i];\n      html += '\n';\n      html += '' + escH(node.name) + '';\n      if (node.children &amp;&amp; node.children.length &gt; 0) {\n        html += '\n' + buildNavTree(node.children) + '';\n      }\n      html += '';\n    }\n    return html;\n  }\n\n  function escH(s) {\n    var d = document.createElement('div');\n    d.textContent = s;\n    return d.innerHTML;\n  }\n\n  function navigateTo(page) {\n    activePage = page;\n    location.hash = encodeURIComponent(page);\n\n    var items = document.querySelectorAll('.nav-item');\n    for (var i = 0; i &lt; items.length; i++) {\n      if (items[i].dataset.page === page) {\n        items[i].classList.add('active');\n      } else {\n        items[i].classList.remove('active');\n      }\n    }\n\n    var contentEl = document.getElementById('content');\n    var md = PAGES[page];\n\n    if (!md) {\n      contentEl.innerHTML = '\n\nPage not found\n' + escH(page) + '.md does not exist.';\n      return;\n    }\n\n    contentEl.innerHTML = marked.parse(md);\n\n    // Rewrite .md links to hash navigation\n    var links = contentEl.querySelectorAll('a[href]');\n    for (var i = 0; i &lt; links.length; i++) {\n      var href = links[i].getAttribute('href');\n      if (href &amp;&amp; href.endsWith('.md') &amp;&amp; href.indexOf('://') === -1) {\n        var slug = href.replace(/\\.md$/, '');\n        links[i].setAttribute('href', '#' + encodeURIComponent(slug));\n        (function(s) {\n          links[i].addEventListener('click', function(e) {\n            e.preventDefault();\n            navigateTo(s);\n          });\n        })(slug);\n      }\n    }\n\n    // Convert mermaid code blocks into mermaid divs\n    var mermaidBlocks = contentEl.querySelectorAll('pre code.language-mermaid');\n    for (var i = 0; i &lt; mermaidBlocks.length; i++) {\n      var pre = mermaidBlocks[i].parentElement;\n      var div = document.createElement('div');\n      div.className = 'mermaid';\n      div.textContent = mermaidBlocks[i].textContent;\n      pre.parentNode.replaceChild(div, pre);\n    }\n    try { mermaid.run({ querySelector: '.mermaid' }); } catch(e) {}\n\n    window.scrollTo(0, 0);\n    document.getElementById('sidebar').classList.remove('open');\n  }\n})();\n\n\n\n", "creation_timestamp": "2026-08-04T08:51:40.257285Z"}