@overdeck/desktop 0.44.0 → 0.45.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (19) hide show
  1. package/package.json +1 -1
  2. package/server/public/assets/{chunk-BO2N2NFS-DurskaRQ.js → chunk-BO2N2NFS-CaAvtgHW.js} +4 -4
  3. package/server/public/assets/{diagram-OG6HWLK6-Dk7-KYG7.js → diagram-OG6HWLK6-C4flU2X9.js} +1 -1
  4. package/server/public/assets/{dist-Dm4--nOM.js → dist-DXAnG2e9.js} +1 -1
  5. package/server/public/assets/{dist-CaEw8nYm.js → dist-DygIHsen.js} +3 -3
  6. package/server/public/assets/{ganttDiagram-6RSMTGT7-CFh4T1Yl.js → ganttDiagram-6RSMTGT7-BJY25etK.js} +1 -1
  7. package/server/public/assets/{highlighted-body-OFNGDK62--ggf-1jf.js → highlighted-body-OFNGDK62-DIEQLSG_.js} +1 -1
  8. package/server/public/assets/index-BsKNi2y5.js +796 -0
  9. package/server/public/assets/{linear-B_aOIp4o.js → linear-CRa2o9KP.js} +1 -1
  10. package/server/public/assets/mermaid-GHXKKRXX-uIkd-n0c.js +1 -0
  11. package/server/public/assets/{pieDiagram-4H26LBE5-_QEBgJ8d.js → pieDiagram-4H26LBE5-Cb6OrK_c.js} +1 -1
  12. package/server/public/assets/{prod-oCB7Fr_u.js → prod-DWpuiL-y.js} +4 -4
  13. package/server/public/assets/{quadrantDiagram-W4KKPZXB-CAbpwVBa.js → quadrantDiagram-W4KKPZXB-DhZzzcAO.js} +1 -1
  14. package/server/public/assets/{sankeyDiagram-5OEKKPKP-mPlHirkS.js → sankeyDiagram-5OEKKPKP-CVe6lE5A.js} +1 -1
  15. package/server/public/assets/{xychartDiagram-2RQKCTM6-m6Efea7b.js → xychartDiagram-2RQKCTM6-zukUz5pI.js} +1 -1
  16. package/server/public/index.html +1 -1
  17. package/server/server.js +546 -482
  18. package/server/public/assets/index-CuIG3f59.js +0 -796
  19. package/server/public/assets/mermaid-GHXKKRXX-DvZawyn9.js +0 -1
package/server/server.js CHANGED
@@ -1,101 +1,101 @@
1
1
  import { a as __toCommonJS, i as __require, o as __toESM, t as __commonJSMin } from "./rolldown-runtime-DNCzzKnI.js";
2
- import { $ as getModelEffortLevelsSync, D as init_harness_policy, Dn as resolveProjectFromIssue, Dr as SYNC_SOURCES, Dt as init_record, Fr as packageRoot, G as DEFAULT_ROLES, Gn as init_auto_commit, I as getProviderForModelSync, In as extractPrefixSync, Ir as resolveOhmypiExtensionPath, K as DEFAULT_WORKHORSES, L as init_providers, Ln as init_issue_id, Lr as sessionFilePath, Mn as setProjectAutoMergeDefaultSync, Mr as getOverdeckHome, N as getBuiltInDefaultHarness, Nr as init_paths, On as resolveProjectFromIssueSync, P as getKimiAnthropicBaseUrl, Pr as isDevMode, R as piProviderForModel, S as resolveTieredExecutionEnabled, T as canUseHarnessSync, Tn as registerProjectSync, Tt as getIssueWorkspacePath, U as defaultBackgroundAiFeatures, Un as flushAllPendingAutoCommits, Vn as require_dist$1, W as init_registry, Wn as flushAutoCommits, X as MODEL_CAPABILITIES, Y as resolveModel, Z as MODEL_DEPRECATIONS, _ as mergeTtsDaemonConfigs, an as findProjectByTeamSync, b as TieredExecutionConfigError, bn as listProjectsSync, br as OVERDECK_HOME, cr as TrackerError, ct as PARENT_MODEL_REF, d as loadConfigSync, dr as AGENTS_DIR, er as FsError, et as hasModelCapabilitySync, f as updateConversationsConfig, g as getDefaultTtsDaemonConfig, gn as init_projects, gr as CLAUDE_DIR, h as mergeConfigs, i as getConversationsConfig, j as UnknownModelError, jr as getLegacyHome, kr as encodeClaudeProjectDir, l as isTldrEnabledSync, lt as ROLE_EFFORTS, m as jsYaml, n as clearConfigCache, nr as GitHubApiError, nt as modelSupportsImagesSync, o as getGlobalConfigPath, or as ProcessSpawnError, p as init_js_yaml, q as computeModelOrigin, r as getConversationSearchConfigSync, rt as resolveModelIdSync, s as isClaudeCodeChannelsEnabled, sn as getIssuePrefix, st as COMPLIANCE_MODES, t as init_config_yaml, tn as extractTeamPrefix, tt as init_model_capabilities, u as loadConfigNoMigration, un as getProjectSync, ur as init_errors, w as validateTieredExecutionConfig, x as init_tier_table, yn as listProjects, yr as LOGS_DIR, zn as parseIssueIdSync } from "./config-yaml-D0t3y9AC.js";
3
- import { _ as getDashboardIdentity, c as startUatTrainReconciler, d as openFlywheelRunReportForDashboard, f as pauseFlywheelRunForDashboard, g as runDashboardDbJob, h as startFlywheelRunForDashboard, l as stopUatTrainReconciler, m as resumeFlywheelRunForDashboard, p as readCurrentFlywheelStatusForDashboard, u as abortFlywheelRunForDashboard, v as readHostDashboardApiPort, y as shouldRefuseHostDashboardPort } from "./uat-train-CpEtMAyD.js";
4
- import { A as jsonResponse, D as validateOriginHeaders, E as validateOrigin$1, O as checkCodexAuthStatus, S as getHeaderFromMap, _ as resolveAgentHarness, a as agentsRouteLayer, b as resolveJsonlPath, c as evaluateSpawnGuardrails, d as isSmeeConfiguredSync, f as startSmeeProcessSync, g as readLauncherPinnedSessionId, j as jsonStringResponse, k as httpHandler, l as invalidateAgentsCache, m as resolveConversationGitInfo, o as saveAgentStateAndEmitEvent, p as resolveAgentGitInfo, s as saveAgentStateAndEmitEventProgram, t as specialistsRouteLayer, u as getSystemHealthSnapshot, v as resolveClaudeSessionId, w as isTrustedOriginForHost, x as resolvePiSessionPath, y as resolveCodexRolloutPath } from "./specialists-CWh4WUGp.js";
2
+ import { $n as init_issue_id, Br as init_paths, C as resolveTieredExecutionEnabled, Cn as getIssuePrefix, Cr as CLAUDE_DIR, Dr as OVERDECK_HOME, E as canUseHarnessSync, En as getProjectSync, Er as LOGS_DIR, Et as getIssueWorkspacePath, F as getKimiAnthropicBaseUrl, Fn as listProjects, G as init_registry, Hr as packageRoot, In as listProjectsSync, Ir as encodeClaudeProjectDir, J as computeModelOrigin, Jn as setProjectAutoMergeDefaultSync, K as DEFAULT_ROLES, L as getProviderForModelSync, M as UnknownModelError, Mn as init_projects, O as init_harness_policy, Ot as init_record, P as getBuiltInDefaultHarness, Pr as SYNC_SOURCES, Q as MODEL_DEPRECATIONS, Qn as extractPrefixSync, R as init_providers, Rr as getLegacyHome, S as init_tier_table, T as validateTieredExecutionConfig, Un as resolveProjectFromIssue, Ur as resolveOhmypiExtensionPath, Vn as registerProjectSync, Vr as isDevMode, W as defaultBackgroundAiFeatures, Wn as resolveProjectFromIssueSync, Wr as sessionFilePath, X as resolveModel, Z as MODEL_CAPABILITIES, _ as getDefaultTtsDaemonConfig, _n as extractTeamPrefix, _r as init_errors, c as isClaudeCodeChannelsEnabled, ct as COMPLIANCE_MODES, d as loadConfigNoMigration, et as getModelEffortLevelsSync, f as loadConfigSync, g as mergeConfigs, h as jsYaml, hr as TrackerError, i as getConversationsConfig, it as resolveModelIdSync, lr as GitHubApiError, lt as PARENT_MODEL_REF, m as init_js_yaml, n as clearConfigCache, nn as flushAutoCommits, nt as init_model_capabilities, o as getGlobalConfigPath, p as updateConversationsConfig, pr as ProcessSpawnError, q as DEFAULT_WORKHORSES, r as getConversationSearchConfigSync, rn as init_auto_commit, rr as require_dist$1, rt as modelSupportsImagesSync, sr as FsError, t as init_config_yaml, tn as flushAllPendingAutoCommits, tr as parseIssueIdSync, tt as hasModelCapabilitySync, u as isTldrEnabledSync, ut as ROLE_EFFORTS, v as mergeTtsDaemonConfigs, vr as AGENTS_DIR, x as TieredExecutionConfigError, xn as findProjectByTeamSync, yn as findProjectByPathSync, z as piProviderForModel, zr as getOverdeckHome } from "./config-yaml-CFi3m2pp.js";
3
+ import { _ as getDashboardIdentity, c as startUatTrainReconciler, d as openFlywheelRunReportForDashboard, f as pauseFlywheelRunForDashboard, g as runDashboardDbJob, h as startFlywheelRunForDashboard, l as stopUatTrainReconciler, m as resumeFlywheelRunForDashboard, p as readCurrentFlywheelStatusForDashboard, u as abortFlywheelRunForDashboard, v as readHostDashboardApiPort, y as shouldRefuseHostDashboardPort } from "./uat-train-BK1II1Ug.js";
4
+ import { C as validateOrigin$1, D as jsonResponse, E as httpHandler, O as jsonStringResponse, T as checkCodexAuthStatus, _ as resolveJsonlPath, a as agentsRouteLayer, c as evaluateSpawnGuardrails, d as resolveConversationGitInfo, g as resolveCodexRolloutPath, h as resolveClaudeSessionId, l as invalidateAgentsCache, m as resolveAgentHarness, o as saveAgentStateAndEmitEvent, p as readLauncherPinnedSessionId, s as saveAgentStateAndEmitEventProgram, t as specialistsRouteLayer, u as resolveAgentGitInfo, v as resolvePiSessionPath, w as validateOriginHeaders, x as isTrustedOriginForHost, y as getHeaderFromMap } from "./specialists-IIjyUvYM.js";
5
5
  import { a as init_activity_logger, i as emitDashboardLifecycleSync, n as emitActivityEntrySync, r as emitActivityTtsSync } from "./activity-logger-Dm95Ua07.js";
6
- import { A as init_paths$1, O as OVERDECK_MIGRATION_PATH, d as getOverdeckDatabaseSync, f as init_infra, i as DbLive, k as getOverdeckDatabasePath, u as TmuxLive } from "./infra-D6hW7oZO.js";
6
+ import { A as init_paths$1, O as OVERDECK_MIGRATION_PATH, d as getOverdeckDatabaseSync, f as init_infra, i as DbLive, k as getOverdeckDatabasePath, u as TmuxLive } from "./infra-NrG-t1jj.js";
7
7
  import { n as openDatabase, t as init_driver } from "./driver-D-HBOQa_.js";
8
- import { E as listPaneValues, F as sendKeysAsync, G as buildChildEnvSync, H as init_ui_theme, I as sendRawKeystroke, K as buildChildEnvWithoutTmuxSync, L as sessionExists, M as resizeWindow, O as listSessionNames, P as sendKeys, S as isHarnessProcessAlive, U as setUiTheme, W as BLANKED_PROVIDER_ENV, b as getWindowDimensions, c as ensureManagedTmuxContextOnce, d as exactPaneTarget, i as capturePane, k as listSessions, n as buildTmuxArgs, o as createSession, p as findManagedServerPidSync, q as init_child_env, w as killSession, x as init_tmux, z as setOption } from "./tmux-Cuf3Wudb.js";
9
- import { a as init_event_store, i as initEventStore, n as getEventStore, r as getSharedDb } from "./event-store-B35NfIvv.js";
10
- import { _ as FlywheelRunId, a as getHarnessBehavior, b as DomainEvent, c as FlywheelStats, g as WS_METHODS, h as PanRpcGroup, m as PanRpcError, o as ContextLayerSaveRequest, s as ContextPreviewRequest, t as init_src, v as FlywheelStatus, x as MemoryObservation, y as EDITORS } from "./src-CgBTaItZ.js";
11
- import { a as fixStuckReadyForMerge, c as init_review_status, i as fixStuckCommentedReviews, l as loadReadyForMergeFlags, n as clearReviewStatus, o as getReviewStatus, r as clearStuckMergeStatuses, s as getReviewStatusSync, u as loadReviewStatuses, v as setReviewStatus, y as setReviewStatusSync } from "./review-status-BRzbY-uJ.js";
12
- import { a as EventStoreService, c as ReadModelService, d as init_read_model, f as toAgentResolution, i as init_issue_lifecycle, l as ReadModelServiceLive, m as toRole, n as IssueLifecycleLive, o as EventStoreServiceLive, p as toAgentStatus, s as init_domain_services, t as IssueLifecycle } from "./issue-lifecycle-BrYCFw67.js";
13
- import { d as init_agents, i as recordBriefingSessionStart, n as ensureSessionContextBriefingFile, p as listAllAgentsSync, r as init_briefing_freshness, s as AgentsResolverLive, t as appendFreshBriefingUpdate } from "./briefing-freshness-CKbYolyA.js";
14
- import { i as init_paths$2, l as resolveObservationsFile, r as ensureParentDir, s as resolveIssueMemoryRoot, t as assertMemorySafeSegment } from "./paths-gB-AoCbP.js";
15
- import { n as listFeatureRegistryEntries, t as init_feature_registry_storage } from "./feature-registry-storage-DzHcsyeM.js";
16
- import { a as diffAgainstMainFiles, c as diffFilesAgainstHead, d as findCommitAtTime, i as diffAgainstMain, l as diffPatchFilesAgainstHead, m as listCheckpoints, o as diffCheckpointFiles, p as init_checkpoint_manager, s as diffCheckpoints, t as captureCheckpoint, u as diffPatchSinceCommit } from "./checkpoint-manager-DCSBbepE.js";
17
- import { $n as clearReadySignal, $t as getClaudeAuthStatus, Bt as getAgentRuntimeBaseCommand, Cn as getAgentDir, Ct as init_transcript_landing, Dn as getAgentStateSync, En as getAgentStateFilePath, Et as writeBridgeTokenSync, J as listAgentStates, Kt as injectPiConversationMemory, M as init_operator_interventions, N as operatorInterventionEvent, Qn as writePtyToken, Qt as ohmypiFifoPaths, St as captureTranscriptUserRecordSnapshot, Tn as getAgentState, Tt as init_bridge_token, Ut as getProviderAuthMode, Vn as saveAgentStateSync, X as listRunningAgentsSync, Xn as readAgentHarnessModelRecordSync, Xt as piFifoPaths, Y as listRunningAgents, Yn as init_agent_record_sync, Yt as init_pi_fifo, Zn as init_pty_token, Zt as init_ohmypi_fifo, _t as deliverAgentMessage, an as getProviderExportsForModel, ar as getAgentRuntimeState, c as init_tier_supervisor, en as init_claude_auth, f as supervisorAgentId, ft as init_config, gt as shouldAutoStart, hn as writeChannelsBridgeMcpConfig, ht as saveCloisterConfigSync, in as getProviderEnvForModel, ir as waitForReadySignal, j as messageAgent, ln as getOpenAIAuthStatus, mn as dismissDevChannelsDialog, mt as loadCloisterConfigSync, or as getAgentRuntimeStateSync, pt as loadCloisterConfig, rt as init_concurrency, s as deliverCommitForReview, t as init_agents$1, tr as normalizeAgentId, tt as emergencyBrake, un as init_openai_auth, wt as probeTranscriptSince } from "./agents-BODDwjMW.js";
18
- import { t as init_behavior } from "./behavior-DqR8vtRW.js";
19
- import { a as getCostForIssueAggregateSync, c as getDailyTrendsSync, d as init_cost_sync, l as getModelRollupSync, n as getBackgroundCostBySourceSync, p as queryCostEventsSync, r as getCavemanExperimentDataSync, s as getCostsByIssueSync, u as getTodayCostSync } from "./cost-sync-COCS9jfM.js";
20
- import { c as getAgentsNeedingAttention, d as CostResolverLive, f as CostWriter, l as CostDoorLive, n as readCloisterStateFile, o as generateHealthSummary, s as getAgentHealth, t as getCloisterService, u as CostResolver } from "./service-yJX2ZDTb.js";
21
- import { n as AgentStateServiceLive } from "./agent-state-service-BDYwkuao.js";
22
- import { a as init_tracker_config, i as initTrackerConfigCache, n as getLinearApiKey, r as getRallyConfig, t as getGitHubConfig } from "./tracker-config-Bp-m78D_.js";
23
- import { d as init_typed_errors, l as WorkspaceCreateError, n as AgentStartError, r as BeadsNotInitialized, s as TrackerApiError, t as AgentAlreadyRunning, u as WorkspaceNotFound } from "./typed-errors-BRDFMoss.js";
24
- import { i as init_linear_client, r as LinearClientOptionalLive, t as LinearClient } from "./linear-client-BbxK-2hQ.js";
25
- import { i as init_github_client, r as GitHubClientOptionalLive, t as GitHubClient } from "./github-client-ClT-9ZHn.js";
26
- import { i as init_rally_client, r as RallyClientOptionalLive, t as RallyClient } from "./rally-client-DoecXLs_.js";
27
- import { a as resolveTrackerTypeSync, i as resolveGitHubIssueSync, n as init_tracker_utils } from "./tracker-utils-BGlCcZn1.js";
28
- import { a as CacheService, i as startSharedIssueService, n as init_issue_service_singleton, o as init_cache_service, r as issue_service_singleton_exports, s as parseIntegerHeader, t as getSharedIssueService } from "./issue-service-singleton-Driy3b99.js";
29
- import { i as ensureInternalTokenSync, o as getInternalTokenSync, s as init_internal_token, t as INTERNAL_TOKEN_HEADER } from "./internal-token-DR2busqD.js";
30
- import { a as setPipelineHandlerSync, t as init_pipeline_notifier } from "./pipeline-notifier-DpikL6KI.js";
31
- import { c as init_review_status_sync, i as getMergeBlockerReconcileCandidates } from "./review-status-sync-TCRUOOb0.js";
32
- import { C as transitionToMerging, _ as markFailed, c as isFlywheelGloballyPaused, d as listDuePendingAutoMerges, f as listProblemAutoMerges, g as markBlocked, n as getActionableAutoMerge, o as init_merge_sync, t as cancelPending, u as listActiveAutoMerges, v as markMerged, x as scheduleAutoMergeWithResult, y as requeueToPending } from "./merge-sync-CNvpnmSV.js";
33
- import { B as asPanSpecDocument, C as findSpecByIssue, F as PAN_CONTINUE_FILENAME, I as PAN_DIRNAME, O as writeSpec, T as init_specs, V as init_types$1, a as findWorkspaceDraftPlan, b as init_types, k as writeSpecForIssue, m as readWorkspacePlanSync, o as init_io, p as readWorkspacePlan, r as findPlan, s as isPlanningComplete, u as readPlan, x as subItemsOf } from "./io-DyjLqqzR.js";
34
- import { C as restartCliproxy, S as readPidFile, T as stopCliproxy, b as isCliproxyInstalled, d as getCliproxyAuthDir, o as bridgeCodexAuthToCliproxy, v as init_cliproxy, w as startCliproxy, x as isCliproxyRunning, y as installCliproxy } from "./cliproxy-BRAY5Min.js";
35
- import { f as init_config$1, m as loadConfigSync$1, s as getDashboardApiUrlSync } from "./config-C83PzLrX.js";
36
- import { n as require_auth_errors, r as require_token_error, t as require_token_util } from "./token-util-DEP-WK8V.js";
37
- import { $ as updateConversationTitle, A as listArchivedConversationsWithEnrichment, C as getConversationLedgerCosts, D as incrementForkRetryCount, E as importLegacyConversation, F as markConversationRunning, G as setConversationModel, H as setConversationClaudeSessionId, J as setImportedConversationLinks, K as setFavorite, M as listFavoritedIds, N as markConversationActive, O as init_conversations, P as markConversationEnded, Q as updateConversationForkFallbackReason, R as recordConversationHandoff, S as getConversationByTmuxSession, T as hasOtherActiveConversationOnTmuxSession, U as setConversationEffort, V as setClearedToConvId, W as setConversationHarness, X as updateConversationCost, Y as unarchiveConversation, Z as updateConversationDeliveryMethod, _ as canReplaceTitle, b as getConversationById, et as updateForkStatus, g as backfillConversationModel, h as archiveConversation, ht as getDiscoveredSessionBySessionId, j as listConversations, k as isAgentConversationName, nt as updateSpawnError, q as setForkRequest, tt as updateLastAttached, v as createConversation, vt as init_discovered_sessions, w as getStuckForks, x as getConversationByName, y as getConversationByClaudeSessionId, z as removeFavorite } from "./conversations-DqMw7hzO.js";
38
- import { _ as init_codex_conversation_parser, a as contextUsageFromParseResult, c as parseEntireConversation, d as init_pi_conversation_parser, f as isPiSessionFile, g as parseOhmypiConversationMessages, h as isOhmypiSessionFile, i as computeContextUsage, l as parseFromLastCompactBoundary, m as init_ohmypi_conversation_parser, n as gateSnapshotEmission, o as summarizeConversationActivity, p as parsePiConversationMessages, r as watchConversation, s as parseConversationMessages, t as init_conversation_service, v as parseCodexConversationMessages } from "./conversation-service-DMXhLnSO.js";
39
- import { n as isBackgroundFeatureEnabled, t as init_features } from "./features-DwF4LaSW.js";
40
- import { i as init_settings, r as getMemoryWorkerConcurrency, t as areMemoryObservationsEnabled } from "./settings-DWLiz0Nr.js";
41
- import { i as updateMemoryHealth, n as extractWithProviderPolicy, r as init_health, t as init_providers$1 } from "./providers-cLWAz3kQ.js";
42
- import { n as init_launcher_generator, t as generateLauncherScriptSync } from "./launcher-generator-sMFvWgWt.js";
43
- import { a as init_claude_permissions, o as resolvePermissionModeSync, r as getClaudePermissionFlagsStringSync, t as BYPASS_PERMISSION_MODE } from "./claude-permissions-C0EMsI4l.js";
44
- import { a as globalContextFile$1, d as workspaceContextFile, l as projectContextFile, n as codexGlobalContextFile, o as init_layers, r as ensureProjectLayer, s as piGlobalContextFile } from "./layers-DoUs5i4O.js";
45
- import { l as init_codex, s as findRolloutPath } from "./codex-DlkETOc-.js";
46
- import { C as setMergeTrainEnabled, S as setFlywheelRequireUatBeforeMerge, b as setFlywheelAutoPickupBacklog, c as isCloisterSpawnsPausedSync, d as isFlywheelAutoPickupBacklog, f as isFlywheelGloballyPaused$1, g as setCloisterSpawnsPausedSync, h as setBootReconciliationDecision, m as isMergeTrainEnabled, o as getSetting, p as isFlywheelRequireUatBeforeMerge, r as getBootReconciliationState, s as init_control_settings, u as isDeaconGloballyPausedSync, v as setDeaconGloballyPausedSync, w as setSetting } from "./control-settings-BTPRGd5d.js";
47
- import { c as init_docker_stats } from "./stack-health-C_JMDfQa.js";
48
- import { n as resolveHarness, t as init_harness_resolve } from "./harness-resolve-CYFbeWOz.js";
49
- import { i as checkPrdGateSync, t as init_pan_dir } from "./pan-dir-DB2mqeFg.js";
50
- import { a as init_lifecycle_io, t as appendContinueSessionEntryForIssue } from "./lifecycle-io-CKyWyVWt.js";
51
- import { r as init_swarm_readiness, t as analyzeSwarmReadiness } from "./swarm-readiness-lyw-buM5.js";
52
- import { B as createInFlightGuard, Dt as countPendingAskUserQuestionsForAgent, Et as computeAgentEnrichment, F as setAgentStatusChangedNotifier, I as setAgentStoppedNotifier, It as parseCodexApprovalPrompt, J as startBootReconciliation, K as isBootReconciliationCandidate, L as setMergeReadyNotifier, Mt as scanPendingInputsPromise, Nt as detectAwaitingInputForAgent, O as loadConfig, Ot as getAgentJsonlMtime, Pt as detectAwaitingInputFromPaneSync, Tt as getRuntimeForAgent, at as withConcurrencyLimit, k as loadState, n as assessDeaconPatrolFreshness, q as listBootReconciliationCandidates, t as applyBootReconciliationDecision, x as getDeaconLogs } from "./deacon-Cx7hYXMe.js";
53
- import { i as CostThresholdError, l as embed, s as parseRelativeTime } from "./scanner-bjduWTuH.js";
54
- import { n as deduplicateEventsSync, o as readEventsSync, s as tailEventsSync } from "./events-CiEGnZ53.js";
55
- import { n as recordBackgroundAiCost, t as init_cost } from "./cost-DHjgeEgA.js";
56
- import { S as writeLatestFlywheelStatus, _ as readCurrentLatestFlywheelStatus, b as subscribeLatestFlywheelStatus, f as getFlywheelRunDetail, h as listFlywheelRuns, l as buildClassifyLookups, m as isFlywheelRunId, y as resolveLiveFlywheelRunId } from "./flywheel-CkiZj2Rx.js";
57
- import { C as rejectUnauthorizedDashboardRequest, E as getWorkspacePathForIssue, S as hasDashboardInternalToken, T as rejectUnsafeDashboardMutationRequest, _ as processPendingFeedbackDeliveries, b as dashboardCsrfToken, c as resumeQueuedMerges, d as reconcilePiTranscripts, f as reclassifyUnknownCostEventsSync, g as syncCacheSync, h as rebuildCacheSync, l as syncWalFromAllProjects, m as getCostsForIssueSync, p as migrateAllSessionsSync, t as workspacesRouteLayer, u as reconcile, v as getCachedRunningAgents, w as rejectUnauthorizedDashboardSessionMintRequest, x as dashboardSessionCookieHeader, y as resolveIssueHeadlineCost } from "./workspaces-DjApnCJp.js";
58
- import { l as detectPlatform, u as init_platform } from "./workspace-manager-DV4u07t9.js";
59
- import { O as init_specialists, b as getReviewerSessionName } from "./specialists-DW-1CAK5.js";
60
- import { t as withBdMutex } from "./bd-mutex-Bqr8TTH0.js";
61
- import { n as findPrdAtStatusSync, r as init_prd_locations } from "./prd-locations-BDN-xDNK.js";
62
- import { a as getShadowState, s as init_shadow_state } from "./shadow-state-a0THplpo.js";
63
- import { T as verifyAppCanMerge, d as getPullRequestState, f as init_github_app, l as getMergeBackendStatus, p as isGitHubAppConfigured } from "./github-app-Soz3tZh_.js";
64
- import { t as clearIssueClosedCache } from "./issue-closed-7IHQ8IJf.js";
65
- import { a as writeFeedbackFile, i as init_feedback_writer } from "./feedback-writer-DQqQJkgs.js";
66
- import { a as init_boot_gates, i as formatBootGateState, o as resolveBootGates } from "./no-resume-mode-Hd08C18Q.js";
67
- import { n as parseSequenceMd, r as writeSequenceMd, t as init_sequence_io } from "./sequence-io-MtiwR4U7.js";
68
- import { C as selectNeedsPlanning, S as normalizeGate, _ as computeCohort, b as computeStats, d as OBJECTION_LABEL, f as PARKED_LABEL, g as classifyIssue, h as VETOED_LABEL, m as RELEASED_LABEL, p as READY_LABEL, u as BLOCKS_MAIN_LABEL, v as computeEpicGroups, x as computeWaves, y as computeLanes } from "./flywheel-merge-order-B-03AdML.js";
69
- import { a as loadWorkspaceMetadataSync } from "./workspace-metadata-DYF0ScVu.js";
70
- import { i as resolveAutoSpawnOnFinalize, o as spawnPlanningSession } from "./spawn-planning-session-Dgxpkfaj.js";
71
- import { _ as sendToRemoteAgent, a as getRemoteAgentOutput, n as checkRemoteSpendCap, o as init_remote_agents, p as loadRemoteAgentState, u as killRemoteAgent, v as spawnRemoteAgent } from "./remote-agents-DeiRtncQ.js";
72
- import { r as spawnInspectAgent } from "./inspect-agent-CmBmiWSp.js";
73
- import { n as init_github_pr_lookup, r as lookupPullRequestNumberForBranch, t as githubPrLookupSource } from "./github-pr-lookup-C-YqEBQA.js";
74
- import { a as init_pull_requests, c as getIssuePrTabCacheGeneration, i as fetchIssuePullRequestDiff, l as init_pr_tab_cache, n as fetchIssuePullRequest, o as bumpIssuePrTabCacheGeneration, r as fetchIssuePullRequestDetails, s as getCachedIssuePrTabResponse, t as fetchIssueCheckRuns, u as setCachedIssuePrTabResponse } from "./pull-requests-V9zbOnM7.js";
75
- import { t as enrichReviewStatus } from "./review-status-enrichment-BK-Peqqa.js";
76
- import { i as runMemoryFtsTransaction, n as init_fts_db, r as runMemoryFtsStatement, t as closeMemoryFtsDatabases } from "./fts-db-Bk_iUuHK.js";
77
- import { c as init_pending, l as maybeTriggerStatusRollup, o as readRecentObservations, r as init_rollup, u as writePendingTurn } from "./rollup-BlVsp5Zh.js";
78
- import { n as getTldrDaemonServiceSync, r as init_tldr_daemon } from "./tldr-daemon-Ddo1RYXH.js";
79
- import { C as init_git_activity, w as listGitOperationsSync } from "./merge-agent-DcC21G-0.js";
80
- import { t as getAgentCommandSync } from "./settings-DqPuXxT5.js";
81
- import { n as init_review_agent, r as isExtendedReviewEnabled } from "./review-agent-CzUNH73m.js";
82
- import { r as isRemoteAvailable, t as createFlyProviderFromConfig } from "./remote-DRwGjxzx.js";
83
- import { n as init_claude_settings_overlay, t as detectProviderEnvConflicts } from "./claude-settings-overlay-rU83JjnR.js";
84
- import { a as init_query_expansion, i as clearQueryExpansionCache, n as init_injection, o as buildMatchQuery, r as injectPromptTimeMemory, s as init_search } from "./injection-9zl1FzOq.js";
85
- import { _ as init_transcript_adapter, a as generateFallbackSummary, c as handoffPreconditionFallbackReason, d as prependFallbackFocus, f as requestHandoffFromAgent, g as getTranscriptAdapter, i as copySessionFromCompactBoundary, l as init_summary_fork, o as generateSummaryForFork, p as reserveSummaryForkSession, r as authorHandoffExternal, s as handoffFailureReason, u as logHandoffFallback } from "./summary-fork-D8tUkORq.js";
86
- import { a as init_conversation_compaction, c as shouldInterceptManualCompact, n as compactConversationNative, o as isCompacting } from "./conversation-compaction-NboSkcz4.js";
87
- import { a as init_render, d as validateTemplate, i as hasManagedRegion, l as init_harness, o as userContentOutsideRegion, t as init_context_layers, u as renderForHarness } from "./context-layers-BpZBKYnw.js";
88
- import { r as parseArtifactRef } from "./forge-Ca3Vecel.js";
89
- import { t as getMergeBlockersPayload } from "./merge-blockers-B7ey3CkR.js";
90
- import { a as spawnSequencerAgent, i as init_sequencer_agent, n as clearFinishedSequencerRun, r as getSequencerRunStatus, t as SEQUENCER_AGENT_ID } from "./sequencer-agent-C7AhB-75.js";
91
- import "./supervisor-C0I_2Noz.js";
92
- import { i as listTranscriptCheckpoints, r as getTranscriptCheckpoint$1 } from "./checkpoints-haUPQHnM.js";
8
+ import { E as listPaneValues, F as sendKeysAsync, G as buildChildEnvSync, H as init_ui_theme, I as sendRawKeystroke, K as buildChildEnvWithoutTmuxSync, L as sessionExists, M as resizeWindow, O as listSessionNames, P as sendKeys, S as isHarnessProcessAlive, U as setUiTheme, W as BLANKED_PROVIDER_ENV, b as getWindowDimensions, c as ensureManagedTmuxContextOnce, d as exactPaneTarget, i as capturePane, k as listSessions, n as buildTmuxArgs, o as createSession, p as findManagedServerPidSync, q as init_child_env, w as killSession, x as init_tmux, z as setOption } from "./tmux-BvabkAC1.js";
9
+ import { a as init_event_store, i as initEventStore, n as getEventStore, r as getSharedDb } from "./event-store-BH0ESJtK.js";
10
+ import { _ as FlywheelRunId, a as getHarnessBehavior, b as DomainEvent, c as FlywheelStats, g as WS_METHODS, h as PanRpcGroup, m as PanRpcError, o as ContextLayerSaveRequest, s as ContextPreviewRequest, t as init_src, v as FlywheelStatus, x as MemoryObservation, y as EDITORS } from "./src-AXK4mjue.js";
11
+ import { a as fixStuckReadyForMerge, c as init_review_status, i as fixStuckCommentedReviews, l as loadReadyForMergeFlags, n as clearReviewStatus, o as getReviewStatus, r as clearStuckMergeStatuses, s as getReviewStatusSync, u as loadReviewStatuses, v as setReviewStatus, y as setReviewStatusSync } from "./review-status-_HZzpCJZ.js";
12
+ import { a as EventStoreService, c as ReadModelService, d as init_read_model, f as toAgentResolution, i as init_issue_lifecycle, l as ReadModelServiceLive, m as toRole, n as IssueLifecycleLive, o as EventStoreServiceLive, p as toAgentStatus, s as init_domain_services, t as IssueLifecycle } from "./issue-lifecycle-Dao_ID2V.js";
13
+ import { d as init_agents, i as recordBriefingSessionStart, n as ensureSessionContextBriefingFile, p as listAllAgentsSync, r as init_briefing_freshness, s as AgentsResolverLive, t as appendFreshBriefingUpdate } from "./briefing-freshness-B34zUtI6.js";
14
+ import { i as init_paths$2, l as resolveObservationsFile, r as ensureParentDir, s as resolveIssueMemoryRoot, t as assertMemorySafeSegment } from "./paths-CRDfPnBn.js";
15
+ import { n as listFeatureRegistryEntries, t as init_feature_registry_storage } from "./feature-registry-storage-C3iyyOnJ.js";
16
+ import { a as diffAgainstMain, c as diffCheckpoints, d as diffPatchSinceCommit, f as findCommitAtTime, h as listCheckpoints, l as diffFilesAgainstHead, m as init_checkpoint_manager, o as diffAgainstMainFiles, s as diffCheckpointFiles, t as captureCheckpoint, u as diffPatchFilesAgainstHead } from "./checkpoint-manager-DT3Lukzr.js";
17
+ import { An as getAgentDir, At as init_bridge_token, Dt as captureTranscriptUserRecordSnapshot, Gt as getAgentRuntimeBaseCommand, Jn as saveAgentStateSync, Jt as getProviderAuthMode, M as init_operator_interventions, Mn as getAgentState, N as operatorInterventionEvent, Nn as getAgentStateFilePath, Ot as init_transcript_landing, Pn as getAgentStateSync, Q as listRunningAgentsSync, St as deliverAgentMessage, X as listAgentStates, Z as listRunningAgents, Zt as injectPiConversationMemory, _t as init_config, an as init_claude_auth, ar as init_pty_token, at as init_concurrency, bn as writeChannelsBridgeMcpConfig, bt as saveCloisterConfigSync, c as init_tier_supervisor, en as init_pi_fifo, f as supervisorAgentId, fr as waitForReadySignal, hn as init_openai_auth, in as getClaudeAuthStatus, ir as readAgentHarnessModelRecordSync, j as messageAgent, jt as writeBridgeTokenSync, kt as probeTranscriptSince, ln as getProviderEnvForModel, lr as normalizeAgentId, mn as getOpenAIAuthStatus, mr as getAgentRuntimeStateSync, nn as init_ohmypi_fifo, or as writePtyToken, pr as getAgentRuntimeState, rn as ohmypiFifoPaths, rr as init_agent_record_sync, rt as emergencyBrake, s as deliverCommitForReview, sr as clearReadySignal, t as init_agents$1, tn as piFifoPaths, un as getProviderExportsForModel, vt as loadCloisterConfig, xt as shouldAutoStart, yn as dismissDevChannelsDialog, yt as loadCloisterConfigSync } from "./agents-hAslBDrt.js";
18
+ import { t as init_behavior } from "./behavior-ogCxWPtu.js";
19
+ import { a as getCostForIssueAggregateSync, c as getDailyTrendsSync, d as init_cost_sync, l as getModelRollupSync, n as getBackgroundCostBySourceSync, p as queryCostEventsSync, r as getCavemanExperimentDataSync, s as getCostsByIssueSync, u as getTodayCostSync } from "./cost-sync-B4NiigGa.js";
20
+ import { c as getAgentsNeedingAttention, d as CostResolverLive, f as CostWriter, l as CostDoorLive, n as readCloisterStateFile, o as generateHealthSummary, s as getAgentHealth, t as getCloisterService, u as CostResolver } from "./service-C1j2GOdD.js";
21
+ import { n as AgentStateServiceLive } from "./agent-state-service-ycEfmxxV.js";
22
+ import { a as init_tracker_config, i as initTrackerConfigCache, n as getLinearApiKey, r as getRallyConfig, t as getGitHubConfig } from "./tracker-config-CYfIfbH8.js";
23
+ import { d as init_typed_errors, l as WorkspaceCreateError, n as AgentStartError, r as BeadsNotInitialized, s as TrackerApiError, t as AgentAlreadyRunning, u as WorkspaceNotFound } from "./typed-errors-BEJhbjJg.js";
24
+ import { i as init_linear_client, r as LinearClientOptionalLive, t as LinearClient } from "./linear-client-CkeRcoyg.js";
25
+ import { i as init_github_client, r as GitHubClientOptionalLive, t as GitHubClient } from "./github-client-kAgT9udA.js";
26
+ import { i as init_rally_client, r as RallyClientOptionalLive, t as RallyClient } from "./rally-client-BgQ_z7av.js";
27
+ import { a as resolveTrackerTypeSync, i as resolveGitHubIssueSync, n as init_tracker_utils } from "./tracker-utils-BRZJC_bL.js";
28
+ import { a as CacheService, i as startSharedIssueService, n as init_issue_service_singleton, o as init_cache_service, r as issue_service_singleton_exports, s as parseIntegerHeader, t as getSharedIssueService } from "./issue-service-singleton-BwE8vBo8.js";
29
+ import { i as ensureInternalTokenSync, o as getInternalTokenSync, s as init_internal_token, t as INTERNAL_TOKEN_HEADER } from "./internal-token-CarQ-d2Z.js";
30
+ import { a as setPipelineHandlerSync, t as init_pipeline_notifier } from "./pipeline-notifier-Bu0V4jGJ.js";
31
+ import { c as init_review_status_sync, i as getMergeBlockerReconcileCandidates } from "./review-status-sync-C23_G71k.js";
32
+ import { a as PAN_DIRNAME, f as asPanSpecDocument, i as PAN_CONTINUE_FILENAME, p as init_types } from "./types-CE1m_daD.js";
33
+ import { C as transitionToMerging, _ as markFailed, c as isFlywheelGloballyPaused, d as listDuePendingAutoMerges, f as listProblemAutoMerges, g as markBlocked, n as getActionableAutoMerge, o as init_merge_sync, t as cancelPending, u as listActiveAutoMerges, v as markMerged, x as scheduleAutoMergeWithResult, y as requeueToPending } from "./merge-sync-Cayz43rC.js";
34
+ import { C as findSpecByIssue, O as writeSpec, T as init_specs, a as findWorkspaceDraftPlan, b as init_types$1, k as writeSpecForIssue, m as readWorkspacePlanSync, o as init_io, p as readWorkspacePlan, r as findPlan, s as isPlanningComplete, u as readPlan, x as subItemsOf } from "./io-CJp_69VI.js";
35
+ import { C as restartCliproxy, S as readPidFile, T as stopCliproxy, b as isCliproxyInstalled, d as getCliproxyAuthDir, o as bridgeCodexAuthToCliproxy, v as init_cliproxy, w as startCliproxy, x as isCliproxyRunning, y as installCliproxy } from "./cliproxy-C-j2CZKA.js";
36
+ import { f as init_config$1, m as loadConfigSync$1, s as getDashboardApiUrlSync } from "./config-D1FRRXcO.js";
37
+ import { n as require_auth_errors, r as require_token_error, t as require_token_util } from "./token-util-CROoF5ic.js";
38
+ import { $ as updateConversationForkFallbackReason, A as isAgentConversationName, B as removeFavorite, C as getConversationByTmuxSession, D as importLegacyConversation, E as hasOtherActiveConversationOnTmuxSession, F as markConversationEnded, G as setConversationHarness, H as setClearedToConvId, I as markConversationRunning, J as setForkRequest, K as setConversationModel, M as listConversations, N as listFavoritedIds, O as incrementForkRetryCount, P as markConversationActive, Q as updateConversationDeliveryMethod, S as getConversationByName, T as getStuckForks, U as setConversationClaudeSessionId, W as setConversationEffort, X as unarchiveConversation, Y as setImportedConversationLinks, Z as updateConversationCost, _ as canRefineTitle, b as getConversationByClaudeSessionId, et as updateConversationTitle, g as backfillConversationModel, gt as getDiscoveredSessionBySessionId, h as archiveConversation, j as listArchivedConversationsWithEnrichment, k as init_conversations, nt as updateLastAttached, q as setFavorite, rt as updateSpawnError, tt as updateForkStatus, v as canReplaceTitle, w as getConversationLedgerCosts, x as getConversationById, y as createConversation, yt as init_discovered_sessions, z as recordConversationHandoff } from "./conversations-Z-E71Ot6.js";
39
+ import { _ as init_codex_conversation_parser, a as contextUsageFromParseResult, c as parseEntireConversation, d as init_pi_conversation_parser, f as isPiSessionFile, g as parseOhmypiConversationMessages, h as isOhmypiSessionFile, i as computeContextUsage, l as parseFromLastCompactBoundary, m as init_ohmypi_conversation_parser, n as gateSnapshotEmission, o as summarizeConversationActivity, p as parsePiConversationMessages, r as watchConversation, s as parseConversationMessages, t as init_conversation_service, v as parseCodexConversationMessages } from "./conversation-service-2pG8K2RQ.js";
40
+ import { n as isBackgroundFeatureEnabled, t as init_features } from "./features-CNGp14JQ.js";
41
+ import { i as init_settings, r as getMemoryWorkerConcurrency, t as areMemoryObservationsEnabled } from "./settings-V22-6LRB.js";
42
+ import { i as updateMemoryHealth, n as extractWithProviderPolicy, r as init_health, t as init_providers$1 } from "./providers-DS0lghjI.js";
43
+ import { a as init_launcher_generator, i as generateLauncherScriptSync, n as init_state_home, r as isStateMigrated } from "./state-home-Ct7Sc6c_.js";
44
+ import { a as init_claude_permissions, o as resolvePermissionModeSync, r as getClaudePermissionFlagsStringSync, t as BYPASS_PERMISSION_MODE } from "./claude-permissions-yKBS-gdK.js";
45
+ import { a as globalContextFile$1, f as resolveProjectContextFile, h as workspaceContextFile, l as piGlobalContextFile, n as codexGlobalContextFile, o as init_layers, p as resolveWorkspaceContextFile, r as ensureProjectLayer } from "./layers-CTx4opMx.js";
46
+ import { l as init_codex, s as findRolloutPath } from "./codex-_9Yhw2cp.js";
47
+ import { C as setMergeTrainEnabled, S as setFlywheelRequireUatBeforeMerge, b as setFlywheelAutoPickupBacklog, c as isCloisterSpawnsPausedSync, d as isFlywheelAutoPickupBacklog, f as isFlywheelGloballyPaused$1, g as setCloisterSpawnsPausedSync, h as setBootReconciliationDecision, m as isMergeTrainEnabled, o as getSetting, p as isFlywheelRequireUatBeforeMerge, r as getBootReconciliationState, s as init_control_settings, u as isDeaconGloballyPausedSync, v as setDeaconGloballyPausedSync, w as setSetting } from "./control-settings-CDPBWsZY.js";
48
+ import { n as resolveHarness, t as init_harness_resolve } from "./harness-resolve-Doo8mVky.js";
49
+ import { i as checkPrdGateSync, t as init_pan_dir } from "./pan-dir-O79s0Szv.js";
50
+ import { a as init_lifecycle_io, t as appendContinueSessionEntryForIssue } from "./lifecycle-io-Bays2Q9M.js";
51
+ import { r as init_swarm_readiness, t as analyzeSwarmReadiness } from "./swarm-readiness-1xj7dEqT.js";
52
+ import { $t as scanPendingInputsPromise, B as applyIssueBlocksMainLabel, Bt as formatUptime, F as setAgentStatusChangedNotifier, G as applyIssueVetoedLabel, Gt as isSmeeConfiguredSync, H as applyIssueParkedLabel, Ht as getCurrentDockerStats, I as setAgentStoppedNotifier, J as removeIssueParkedLabel, Jt as countPendingAskUserQuestionsForAgent, K as removeIssueBlocksMainLabel, Kt as startSmeeProcessSync, L as setMergeReadyNotifier, Lt as getRuntimeForAgent, O as loadConfig, Q as createInFlightGuard, U as applyIssueReadyLabel, V as applyIssueObjectionLabel, Vt as getContainerHistory, W as applyIssueReleasedLabel, Wt as getSystemHealthSnapshot, X as removeIssueReleasedLabel, Y as removeIssueReadyLabel, Yt as getAgentJsonlMtime, Z as removeIssueVetoedLabel, _t as withConcurrencyLimit, at as listBootReconciliationCandidates, en as detectAwaitingInputForAgent, it as isBootReconciliationCandidate, k as loadState, n as assessDeaconPatrolFreshness, ot as startBootReconciliation, q as removeIssueObjectionLabel, qt as computeAgentEnrichment, rn as parseCodexApprovalPrompt, t as applyBootReconciliationDecision, tn as detectAwaitingInputFromPaneSync, x as getDeaconLogs, zt as getResourceStacks } from "./deacon-580FfaDW.js";
53
+ import { i as CostThresholdError, l as embed, s as parseRelativeTime } from "./scanner-Dn9cqdgz.js";
54
+ import { n as deduplicateEventsSync, o as readEventsSync, s as tailEventsSync } from "./events-BILgSB1a.js";
55
+ import { n as recordBackgroundAiCost, t as init_cost } from "./cost-CDDkx0PI.js";
56
+ import { S as writeLatestFlywheelStatus, _ as readCurrentLatestFlywheelStatus, b as subscribeLatestFlywheelStatus, f as getFlywheelRunDetail, h as listFlywheelRuns, l as buildClassifyLookups, m as isFlywheelRunId, y as resolveLiveFlywheelRunId } from "./flywheel-CIiIHzVE.js";
57
+ import { C as hasDashboardInternalToken, D as getWorkspacePathForIssue, E as rejectUnsafeDashboardMutationRequest, S as dashboardSessionCookieHeader, T as rejectUnauthorizedDashboardSessionMintRequest, _ as syncCacheSync, b as resolveIssueHeadlineCost, d as reconcile, f as reconcilePiTranscripts, g as rebuildCacheSync, h as getCostsForIssueSync, l as resumeQueuedMerges, m as migrateAllSessionsSync, p as reclassifyUnknownCostEventsSync, t as workspacesRouteLayer, u as syncWalFromAllProjects, v as processPendingFeedbackDeliveries, w as rejectUnauthorizedDashboardRequest, x as dashboardCsrfToken, y as getCachedRunningAgents } from "./workspaces-CsMMlvt-.js";
58
+ import { l as detectPlatform, u as init_platform } from "./workspace-manager-VHSAXpA7.js";
59
+ import { O as init_specialists, b as getReviewerSessionName } from "./specialists-C1UrzX2F.js";
60
+ import { t as withBdMutex } from "./bd-mutex-CE6P_MlD.js";
61
+ import { c as findPrdAtStatusSync, l as init_prd_locations } from "./archive-planning-Bu8Pxfva.js";
62
+ import { a as getShadowState, s as init_shadow_state } from "./shadow-state-DWFtwdvF.js";
63
+ import { T as verifyAppCanMerge, d as getPullRequestState, f as init_github_app, l as getMergeBackendStatus, p as isGitHubAppConfigured } from "./github-app-D8_gUbWj.js";
64
+ import { n as init_issue_closed, t as clearIssueClosedCache } from "./issue-closed-ClkGWMyj.js";
65
+ import { a as writeFeedbackFile, i as init_feedback_writer } from "./feedback-writer-CUP2avGi.js";
66
+ import { a as init_boot_gates, i as formatBootGateState, o as resolveBootGates } from "./no-resume-mode-CKy2bwZL.js";
67
+ import { c as computeCohort, d as computeStats, f as computeWaves, h as selectNeedsPlanning, l as computeEpicGroups, m as normalizeGate, s as classifyIssue, u as computeLanes } from "./pickup-DRn-XNXS.js";
68
+ import { n as parseSequenceMd, r as writeSequenceMd, t as init_sequence_io } from "./sequence-io-DMwVfR77.js";
69
+ import { a as loadWorkspaceMetadataSync } from "./workspace-metadata-DZSZ2rMu.js";
70
+ import { i as resolveAutoSpawnOnFinalize, o as spawnPlanningSession } from "./spawn-planning-session-DlYnE0aL.js";
71
+ import { d as killRemoteAgent, m as loadRemoteAgentState, o as getRemoteAgentOutput, r as checkRemoteSpendCap, s as init_remote_agents, v as sendToRemoteAgent, y as spawnRemoteAgent } from "./remote-agents-DyK_DtXM.js";
72
+ import { r as spawnInspectAgent } from "./inspect-agent-Cafn8B4M.js";
73
+ import { n as init_github_pr_lookup, r as lookupPullRequestNumberForBranch, t as githubPrLookupSource } from "./github-pr-lookup-B-aLAA0M.js";
74
+ import { a as init_pull_requests, c as getIssuePrTabCacheGeneration, i as fetchIssuePullRequestDiff, l as init_pr_tab_cache, n as fetchIssuePullRequest, o as bumpIssuePrTabCacheGeneration, r as fetchIssuePullRequestDetails, s as getCachedIssuePrTabResponse, t as fetchIssueCheckRuns, u as setCachedIssuePrTabResponse } from "./pull-requests-ZcXF1jwZ.js";
75
+ import { t as enrichReviewStatus } from "./review-status-enrichment-DiEp5P49.js";
76
+ import { i as runMemoryFtsTransaction, n as init_fts_db, r as runMemoryFtsStatement, t as closeMemoryFtsDatabases } from "./fts-db-CM78vdJ_.js";
77
+ import { c as init_pending, l as maybeTriggerStatusRollup, o as readRecentObservations, r as init_rollup, u as writePendingTurn } from "./rollup-DMkz8dIT.js";
78
+ import { n as getTldrDaemonServiceSync, r as init_tldr_daemon } from "./tldr-daemon-C99OUCjN.js";
79
+ import { C as init_git_activity, w as listGitOperationsSync } from "./merge-agent-CI0LXwm9.js";
80
+ import { t as getAgentCommandSync } from "./settings-j3qWqwCi.js";
81
+ import { n as init_review_agent, r as isExtendedReviewEnabled } from "./review-agent-Vg_iFpfd.js";
82
+ import { r as isRemoteAvailable, t as createFlyProviderFromConfig } from "./remote-BuX3q71f.js";
83
+ import { n as init_claude_settings_overlay, t as detectProviderEnvConflicts } from "./claude-settings-overlay-D6NffMmt.js";
84
+ import { a as init_query_expansion, i as clearQueryExpansionCache, n as init_injection, o as buildMatchQuery, r as injectPromptTimeMemory, s as init_search } from "./injection-eW0jWzjG.js";
85
+ import { _ as init_transcript_adapter, a as generateFallbackSummary, c as handoffPreconditionFallbackReason, d as prependFallbackFocus, f as requestHandoffFromAgent, g as getTranscriptAdapter, i as copySessionFromCompactBoundary, l as init_summary_fork, o as generateSummaryForFork, p as reserveSummaryForkSession, r as authorHandoffExternal, s as handoffFailureReason, u as logHandoffFallback } from "./summary-fork-CzPuVQAZ.js";
86
+ import { a as init_conversation_compaction, c as shouldInterceptManualCompact, n as compactConversationNative, o as isCompacting } from "./conversation-compaction-KcA3X6Yy.js";
87
+ import { a as init_render, d as validateTemplate, i as hasManagedRegion, l as init_harness, o as userContentOutsideRegion, t as init_context_layers, u as renderForHarness } from "./context-layers-bWw7hOOG.js";
88
+ import { r as parseArtifactRef } from "./forge-Dj4FMDac.js";
89
+ import { t as getMergeBlockersPayload } from "./merge-blockers-DvMepteF.js";
90
+ import { a as spawnSequencerAgent, i as init_sequencer_agent, n as clearFinishedSequencerRun, r as getSequencerRunStatus, t as SEQUENCER_AGENT_ID } from "./sequencer-agent-BLpcWZlb.js";
91
+ import "./supervisor-C6vsGMQJ.js";
92
+ import { i as listTranscriptCheckpoints, r as getTranscriptCheckpoint$1 } from "./checkpoints-BNs7sSvt.js";
93
93
  import { createRequire } from "node:module";
94
94
  import { Cause, Context, Data, Duration, Effect, Exit, Fiber, FileSystem, Layer, Option, Path, Queue, Result, Schedule, Schema, Stream } from "effect";
95
95
  import { createReadStream, createWriteStream, existsSync, fstatSync, mkdirSync, readFileSync, statSync, writeFileSync } from "fs";
96
96
  import { basename, dirname, join, resolve } from "path";
97
97
  import { homedir } from "os";
98
- import { freemem as freemem$1, homedir as homedir$1, loadavg as loadavg$1, totalmem, type } from "node:os";
98
+ import { freemem as freemem$1, homedir as homedir$1, loadavg as loadavg$1, totalmem as totalmem$1, type } from "node:os";
99
99
  import { constants, createReadStream as createReadStream$1, existsSync as existsSync$1, mkdirSync as mkdirSync$1, promises as promises$1, readFileSync as readFileSync$1, readdirSync as readdirSync$1, readlinkSync, realpathSync as realpathSync$1, renameSync as renameSync$1, rmSync as rmSync$1, stat, statSync as statSync$1, symlinkSync as symlinkSync$1, unwatchFile, watch, watchFile, writeFileSync as writeFileSync$1 } from "node:fs";
100
100
  import * as sp from "node:path";
101
101
  import { basename as basename$1, delimiter, dirname as dirname$1, extname as extname$1, isAbsolute as isAbsolute$1, join as join$1, normalize, relative as relative$1, resolve as resolve$1, sep as sep$1 } from "node:path";
@@ -103,9 +103,9 @@ import { FetchHttpClient, HttpRouter, HttpServer, HttpServerRequest, HttpServerR
103
103
  import { EventEmitter } from "node:events";
104
104
  import { access, appendFile, chmod, lstat, mkdir, open, readFile, readdir, realpath, rename, rm, stat as stat$1, unlink, writeFile } from "node:fs/promises";
105
105
  import { createHash, randomUUID } from "crypto";
106
+ import { chmod as chmod$1, mkdir as mkdir$1, open as open$1, readFile as readFile$1, readdir as readdir$1, rename as rename$1, stat as stat$2, unlink as unlink$1, writeFile as writeFile$1 } from "fs/promises";
106
107
  import { exec, execFile, execFileSync, execSync, fork, spawn } from "node:child_process";
107
108
  import { promisify } from "node:util";
108
- import { chmod as chmod$1, mkdir as mkdir$1, open as open$1, readFile as readFile$1, readdir as readdir$1, rename as rename$1, stat as stat$2, unlink as unlink$1, writeFile as writeFile$1 } from "fs/promises";
109
109
  import { createHmac, randomBytes, randomUUID as randomUUID$1, timingSafeEqual } from "node:crypto";
110
110
  import * as pty from "@homebridge/node-pty-prebuilt-multiarch";
111
111
  import { Buffer as Buffer$1 } from "node:buffer";
@@ -294,6 +294,12 @@ const ServerConfigLayer = Layer.effect(ServerConfig, Effect.sync(() => {
294
294
  const identity = getDashboardIdentity();
295
295
  const hostDashboardApiPort = readHostDashboardApiPort();
296
296
  const overrideAllowed = process.env["OVERDECK_WORKSPACE_DASHBOARD_ALLOW_PRIMARY"] === "1";
297
+ const agentId = process.env["OVERDECK_AGENT_ID"];
298
+ if (overrideAllowed && agentId !== void 0 && !agentId.startsWith("conv-")) {
299
+ const msg = `Refusing OVERDECK_WORKSPACE_DASHBOARD_ALLOW_PRIMARY=1 for pipeline-role identity OVERDECK_AGENT_ID=${agentId}. Work, planning, review, and flywheel agents must never bind the host dashboard port; use the workspace container endpoint instead. Only an operator-supervised conversation (conv-*) or a process with no agent identity may use this emergency override.`;
300
+ console.error(`[overdeck] ${msg}`);
301
+ throw new ServerConfigError("OVERDECK_WORKSPACE_DASHBOARD_ALLOW_PRIMARY", msg);
302
+ }
297
303
  if (shouldRefuseHostDashboardPort({
298
304
  repoRoot: identity.repoRoot,
299
305
  mode: identity.mode,
@@ -323,10 +329,10 @@ const ServerConfigLayer = Layer.effect(ServerConfig, Effect.sync(() => {
323
329
  init_activity_logger();
324
330
  init_paths$1();
325
331
  init_driver();
326
- init_auto_commit();
327
332
  var import_dist = /* @__PURE__ */ __toESM(require_dist$1(), 1);
328
333
  init_issue_id();
329
334
  init_projects();
335
+ init_auto_commit();
330
336
  init_record();
331
337
  init_model_capabilities();
332
338
  init_registry();
@@ -650,7 +656,7 @@ const AgentSpawnerLive = Layer.effect(AgentSpawner, Effect.sync(() => ({
650
656
  const beadsDir = join$1(workspacePath, ".beads");
651
657
  const projectBeadsDir = join$1(workspacePath, "..", "..", ".beads");
652
658
  if (!(existsSync$1(beadsDir) || existsSync$1(projectBeadsDir))) throw new BeadsNotInitialized({ workspace: workspacePath });
653
- const { getAgentState, spawnAgent, normalizeAgentId } = await import("./agents-Ea9gfdKS.js");
659
+ const { getAgentState, spawnAgent, normalizeAgentId } = await import("./agents-2mgtTSeb.js");
654
660
  const normalizedId = normalizeAgentId(issueId);
655
661
  if ((await Effect.runPromise(getAgentState(normalizedId)))?.status === "running") throw new AgentAlreadyRunning({ id: issueId });
656
662
  return {
@@ -681,7 +687,7 @@ const AgentSpawnerLive = Layer.effect(AgentSpawner, Effect.sync(() => ({
681
687
  const { workspacePath, projectPath, issue } = opts;
682
688
  if (!existsSync$1(workspacePath)) throw new WorkspaceNotFound({ id: issueId });
683
689
  const sessionName = opts.sessionName ?? `planning-${issueId.toLowerCase()}`;
684
- const { spawnPlanningSession } = await import("./spawn-planning-session-Dr1yJhqp.js");
690
+ const { spawnPlanningSession } = await import("./spawn-planning-session-Qyw8s1SD.js");
685
691
  const result = await spawnPlanningSession({
686
692
  issue: {
687
693
  id: issue.id,
@@ -714,14 +720,14 @@ const AgentSpawnerLive = Layer.effect(AgentSpawner, Effect.sync(() => ({
714
720
  }),
715
721
  kill: (agentId) => Effect.tryPromise({
716
722
  try: async () => {
717
- const { stopAgent } = await import("./agents-Ea9gfdKS.js");
723
+ const { stopAgent } = await import("./agents-2mgtTSeb.js");
718
724
  await Effect.runPromise(stopAgent(agentId));
719
725
  },
720
726
  catch: () => void 0
721
727
  }).pipe(Effect.ignore),
722
728
  message: (agentId, msg) => Effect.tryPromise({
723
729
  try: async () => {
724
- const { messageAgent } = await import("./agents-Ea9gfdKS.js");
730
+ const { messageAgent } = await import("./agents-2mgtTSeb.js");
725
731
  await messageAgent(agentId, msg);
726
732
  },
727
733
  catch: (err) => new AgentStartError({
@@ -732,8 +738,8 @@ const AgentSpawnerLive = Layer.effect(AgentSpawner, Effect.sync(() => ({
732
738
  }),
733
739
  deepWipe: (issueId, opts) => Effect.tryPromise({
734
740
  try: async () => {
735
- const { deepWipe } = await import("./workflows-C94HmADx.js");
736
- const { resolveProjectFromIssueSync } = await import("./projects-BbMEBykK.js");
741
+ const { deepWipe } = await import("./workflows-xeMCyhJE.js");
742
+ const { resolveProjectFromIssueSync } = await import("./projects-Daw2zpGk.js");
737
743
  const project = resolveProjectFromIssueSync(issueId);
738
744
  const projectPath = project?.projectPath ?? process.cwd();
739
745
  await Effect.runPromise(deepWipe({
@@ -762,7 +768,7 @@ const AgentSpawnerLive = Layer.effect(AgentSpawner, Effect.sync(() => ({
762
768
  * Route handlers and AgentSpawner use this instead of calling workspace-manager directly.
763
769
  */
764
770
  init_typed_errors();
765
- const execAsync$12 = promisify(exec);
771
+ const execAsync$11 = promisify(exec);
766
772
  var WorkspaceService = class extends Context.Service()("overdeck/dashboard/WorkspaceService") {};
767
773
  const WorkspaceServiceLive = Layer.effect(WorkspaceService, Effect.sync(() => {
768
774
  function getWorkspacePath(issueId) {
@@ -789,8 +795,8 @@ const WorkspaceServiceLive = Layer.effect(WorkspaceService, Effect.sync(() => {
789
795
  const { workspacePath, branch } = getWorkspacePath(issueId);
790
796
  const issueLower = issueId.toLowerCase();
791
797
  if (existsSync$1(workspacePath)) return workspacePath;
792
- const { createWorkspace } = await import("./workspace-manager-BE2H8gD5.js");
793
- const { loadProjectsConfigSync } = await import("./projects-BbMEBykK.js");
798
+ const { createWorkspace } = await import("./workspace-manager-uVfFRWJG.js");
799
+ const { loadProjectsConfigSync } = await import("./projects-Daw2zpGk.js");
794
800
  const { projects } = loadProjectsConfigSync();
795
801
  const project = resolveProjectFromIssueSync(issueId);
796
802
  if (!project) throw new WorkspaceCreateError({
@@ -825,7 +831,7 @@ const WorkspaceServiceLive = Layer.effect(WorkspaceService, Effect.sync(() => {
825
831
  const { workspacePath } = getWorkspacePath(issueId);
826
832
  const issueLower = issueId.toLowerCase();
827
833
  if (!existsSync$1(workspacePath)) throw new WorkspaceNotFound({ id: issueId });
828
- const { removeWorkspace } = await import("./workspace-manager-BE2H8gD5.js");
834
+ const { removeWorkspace } = await import("./workspace-manager-uVfFRWJG.js");
829
835
  const project = resolveProjectFromIssueSync(issueId);
830
836
  if (!project) throw new WorkspaceCreateError({
831
837
  id: issueId,
@@ -856,7 +862,7 @@ const WorkspaceServiceLive = Layer.effect(WorkspaceService, Effect.sync(() => {
856
862
  try: async () => {
857
863
  const { workspacePath } = getWorkspacePath(issueId);
858
864
  const issueLower = issueId.toLowerCase();
859
- const { stopWorkspaceDocker } = await import("./workspace-manager-BE2H8gD5.js");
865
+ const { stopWorkspaceDocker } = await import("./workspace-manager-uVfFRWJG.js");
860
866
  await Effect.runPromise(stopWorkspaceDocker(workspacePath, issueLower));
861
867
  },
862
868
  catch: () => void 0
@@ -925,7 +931,7 @@ const WorkspaceServiceLive = Layer.effect(WorkspaceService, Effect.sync(() => {
925
931
  join$1(workspacePath, ".devcontainer", "docker-compose.devcontainer.yml")
926
932
  ];
927
933
  if (!composePaths.find((p) => existsSync$1(p))) {
928
- const { ensureDevcontainerSync } = await import("./ensure-devcontainer-Cy2QNx5O.js");
934
+ const { ensureDevcontainerSync } = await import("./ensure-devcontainer-BSPw9WeO.js");
929
935
  const ensure = ensureDevcontainerSync({
930
936
  workspacePath,
931
937
  issueId
@@ -936,7 +942,7 @@ const WorkspaceServiceLive = Layer.effect(WorkspaceService, Effect.sync(() => {
936
942
  });
937
943
  }
938
944
  const finalComposePath = composePaths.find((p) => existsSync$1(p));
939
- if (finalComposePath) await execAsync$12(`docker compose -f "${finalComposePath}" up -d --build`, {
945
+ if (finalComposePath) await execAsync$11(`docker compose -f "${finalComposePath}" up -d --build`, {
940
946
  cwd: dirname$1(finalComposePath),
941
947
  timeout: 3e5
942
948
  });
@@ -1099,7 +1105,7 @@ function getDefaultCwd() {
1099
1105
  //#endregion
1100
1106
  //#region services/open.ts
1101
1107
  init_src();
1102
- const execAsync$11 = promisify(exec);
1108
+ const execAsync$10 = promisify(exec);
1103
1109
  function getFileManagerCommand() {
1104
1110
  switch (process.platform) {
1105
1111
  case "linux": return "xdg-open";
@@ -1132,7 +1138,7 @@ function launchDetached(launch) {
1132
1138
  }
1133
1139
  async function isCommandAvailable(command) {
1134
1140
  try {
1135
- await execAsync$11(`${process.platform === "win32" ? "where" : "which"} ${command}`);
1141
+ await execAsync$10(`${process.platform === "win32" ? "where" : "which"} ${command}`);
1136
1142
  return true;
1137
1143
  } catch {
1138
1144
  return false;
@@ -15943,7 +15949,7 @@ var require_get_vercel_oidc_token = /* @__PURE__ */ __commonJSMin(((exports, mod
15943
15949
  err = error;
15944
15950
  }
15945
15951
  try {
15946
- const [{ getTokenPayload, isExpired }, { refreshToken }] = await Promise.all([await import("./token-util-CEZZegEl.js").then((m) => /* @__PURE__ */ __toESM(m.default)), await import("./token-Cp6YfYRY.js").then((m) => /* @__PURE__ */ __toESM(m.default))]);
15952
+ const [{ getTokenPayload, isExpired }, { refreshToken }] = await Promise.all([await import("./token-util-xNaV-00f.js").then((m) => /* @__PURE__ */ __toESM(m.default)), await import("./token-CiS3w6Ma.js").then((m) => /* @__PURE__ */ __toESM(m.default))]);
15947
15953
  if (!token || isExpired(getTokenPayload(token), options?.expirationBufferMs)) {
15948
15954
  await refreshToken(options);
15949
15955
  token = getVercelOidcTokenSync();
@@ -28260,7 +28266,7 @@ var GoogleCloudTranscription = class {
28260
28266
  }
28261
28267
  async start(apiKey, model) {
28262
28268
  try {
28263
- const { SpeechClient } = await import("./src-DyS4x3Qs.js").then((m) => /* @__PURE__ */ __toESM(m.default, 1)).then((module) => module.v1p1beta1 ?? module.v1);
28269
+ const { SpeechClient } = await import("./src-CNLON0co.js").then((m) => /* @__PURE__ */ __toESM(m.default, 1)).then((module) => module.v1p1beta1 ?? module.v1);
28264
28270
  if (this.closed) return;
28265
28271
  const stream = new SpeechClient({ apiKey }).streamingRecognize({
28266
28272
  config: {
@@ -30043,7 +30049,7 @@ const websocketRpcRouteLayer = Layer.unwrap(Effect.gen(function* () {
30043
30049
  //#endregion
30044
30050
  //#region ../../lib/vbrief/quality-lint.ts
30045
30051
  init_briefing_freshness();
30046
- init_types$1();
30052
+ init_types();
30047
30053
  init_specs();
30048
30054
  init_io();
30049
30055
  init_pty_token();
@@ -30058,11 +30064,12 @@ init_pi_fifo();
30058
30064
  init_launcher_generator();
30059
30065
  init_bridge_token();
30060
30066
  init_transcript_landing();
30067
+ init_state_home();
30061
30068
  init_operator_interventions();
30062
30069
  init_pan_dir();
30063
30070
  init_agents$1();
30064
30071
  init_remote_agents();
30065
- init_types();
30072
+ init_types$1();
30066
30073
  init_swarm_readiness();
30067
30074
  var PlanQualityLintError = class extends Error {
30068
30075
  constructor(issues) {
@@ -30492,7 +30499,7 @@ function isDiscoverableAgentSession(sessionName) {
30492
30499
  async function loadTrackerIssues() {
30493
30500
  const map = /* @__PURE__ */ new Map();
30494
30501
  try {
30495
- const { getSharedIssueService } = await import("./issue-service-singleton-DFei50PX.js");
30502
+ const { getSharedIssueService } = await import("./issue-service-singleton-Cyfvop7U.js");
30496
30503
  const issues = (await getSharedIssueService()).getIssues();
30497
30504
  for (const issue of issues) if (issue.identifier) map.set(issue.identifier.toUpperCase(), issue);
30498
30505
  } catch {
@@ -30691,7 +30698,7 @@ async function computeResourceAllocatedIssues() {
30691
30698
  if (!issue.resourceDetails.tmuxSessions.includes(sessionName)) issue.resourceDetails.tmuxSessions.push(sessionName);
30692
30699
  }
30693
30700
  try {
30694
- const { listActiveRemoteAgentStates } = await import("./remote-agents-BXKV5iBS.js");
30701
+ const { listActiveRemoteAgentStates } = await import("./remote-agents-YROPFM-n.js");
30695
30702
  for (const remoteState of listActiveRemoteAgentStates()) {
30696
30703
  const issue = ensureIssue(remoteState.issueId);
30697
30704
  if (!issue) continue;
@@ -31212,8 +31219,10 @@ function isGitHubIssue$5(issueId) {
31212
31219
  return { isGitHub: false };
31213
31220
  }
31214
31221
  const completePlanningGuard = createInFlightGuard();
31215
- function beginCompletePlanningLease(issueId) {
31222
+ const completePlanningAutoSpawnIntent = /* @__PURE__ */ new Set();
31223
+ function beginCompletePlanningLease(issueId, autoSpawnRequested = false) {
31216
31224
  const key = issueId.toLowerCase();
31225
+ if (autoSpawnRequested) completePlanningAutoSpawnIntent.add(key);
31217
31226
  let release;
31218
31227
  const lease = new Promise((resolve) => {
31219
31228
  release = resolve;
@@ -31221,7 +31230,11 @@ function beginCompletePlanningLease(issueId) {
31221
31230
  const started = completePlanningGuard.run(key, () => lease);
31222
31231
  return {
31223
31232
  started,
31224
- release: started ? release : () => void 0
31233
+ autoSpawnRequested: () => completePlanningAutoSpawnIntent.has(key),
31234
+ release: started ? () => {
31235
+ completePlanningAutoSpawnIntent.delete(key);
31236
+ release();
31237
+ } : () => void 0
31225
31238
  };
31226
31239
  }
31227
31240
  function emitCompletePlanningPhase(issueId, phase, status, reason, details = {}) {
@@ -31254,7 +31267,7 @@ async function completePlanningArtifacts(options) {
31254
31267
  if (workspaceIssueId && workspaceIssueId.toLowerCase() !== issueLower) throw new Error(`Workspace vBRIEF is for ${workspaceIssueId.toUpperCase()}, not ${upperIssueId}`);
31255
31268
  assertPlanQuality(workspaceDoc);
31256
31269
  const createBeads = options.createBeads ?? (async (path) => {
31257
- const mod = await import("./beads-B4ysfx-Y.js");
31270
+ const mod = await import("./beads-CuXF6X4l.js");
31258
31271
  return await Effect.runPromise(mod.createBeadsFromVBrief(path));
31259
31272
  });
31260
31273
  emitCompletePlanningPhase(upperIssueId, "specWrite", "start", "writing proposed vBRIEF spec", { projectPath });
@@ -31312,15 +31325,16 @@ async function completePlanningArtifacts(options) {
31312
31325
  beadsWarning: null
31313
31326
  };
31314
31327
  }
31315
- function completePlanningFilesToStage(projectPath, proposedFilename) {
31316
- const filesToStage = [`.pan/specs/${proposedFilename}`];
31317
- if (existsSync$1(join$1(projectPath, ".pan", "context", "codebase"))) filesToStage.push(".pan/context/codebase/");
31328
+ function completePlanningFilesToStage(projectPath, proposedFilename, migrated = false) {
31329
+ const filesToStage = migrated ? [] : [`.pan/specs/${proposedFilename}`];
31330
+ if (existsSync$1(join$1(projectPath, ".overdeck", "context", "codebase"))) filesToStage.push(".overdeck/context/codebase/");
31331
+ else if (!migrated && existsSync$1(join$1(projectPath, ".pan", "context", "codebase"))) filesToStage.push(".pan/context/codebase/");
31318
31332
  return filesToStage;
31319
31333
  }
31320
- function completePlanningWorkspaceGitAddCommands(gitRoot) {
31334
+ function completePlanningWorkspaceGitAddCommands(gitRoot, migrated = false) {
31321
31335
  const commands = [];
31322
- if (existsSync$1(join$1(gitRoot, ".pan"))) commands.push(["add", ".pan/"]);
31323
- if (existsSync$1(join$1(gitRoot, ".beads"))) commands.push(["add", ".beads/"]);
31336
+ if (!migrated && existsSync$1(join$1(gitRoot, ".pan"))) commands.push(["add", ".pan/"]);
31337
+ if (!migrated && existsSync$1(join$1(gitRoot, ".beads"))) commands.push(["add", ".beads/"]);
31324
31338
  if (existsSync$1(join$1(gitRoot, ".gitignore"))) commands.push(["add", ".gitignore"]);
31325
31339
  return commands;
31326
31340
  }
@@ -31333,6 +31347,11 @@ function completePlanningWorkspaceGitAddCommands(gitRoot) {
31333
31347
  * tree handed to auto-start is clean.
31334
31348
  */
31335
31349
  async function commitWorkspaceRecordBeforeAutoSpawn(gitRoot, issueId) {
31350
+ const project = findProjectByPathSync(gitRoot);
31351
+ if (project && await isStateMigrated(project)) {
31352
+ await Effect.runPromise(flushAutoCommits(project.path));
31353
+ return;
31354
+ }
31336
31355
  if (!existsSync$1(join$1(gitRoot, ".git"))) return;
31337
31356
  const issueLower = issueId.toLowerCase();
31338
31357
  try {
@@ -31484,7 +31503,7 @@ async function completePlanningForIssue(options) {
31484
31503
  }
31485
31504
  const sessionName = `planning-${id.toLowerCase()}`;
31486
31505
  const issueLower = id.toLowerCase();
31487
- const completePlanningLease = beginCompletePlanningLease(id);
31506
+ const completePlanningLease = beginCompletePlanningLease(id, autoSpawn);
31488
31507
  if (!completePlanningLease.started) {
31489
31508
  console.log(`[complete-planning] ${id} already has an in-flight finalize; returning in-flight status`);
31490
31509
  return jsonResponse({
@@ -31583,8 +31602,12 @@ async function completePlanningForIssue(options) {
31583
31602
  });
31584
31603
  console.log(`[complete-planning] Wrote pan spec to ${proposed.path}`);
31585
31604
  console.log(`[complete-planning] Materialized ${beadCount} beads for ${upperIssueId}`);
31586
- const filesToStage = completePlanningFilesToStage(projectPath, proposed.filename);
31587
- if (!existsSync$1(join$1(projectPath, ".git"))) console.log(`[complete-planning] Project root ${projectPath} is not a git repository (polyrepo) — pan spec updated on disk but not committed`);
31605
+ const project = findProjectByPathSync(projectPath);
31606
+ const migrated = project ? await isStateMigrated(project) : false;
31607
+ const filesToStage = completePlanningFilesToStage(projectPath, proposed.filename, migrated);
31608
+ const projectIsGitRepo = existsSync$1(join$1(projectPath, ".git"));
31609
+ if (migrated) await Effect.runPromise(flushAutoCommits(projectPath));
31610
+ else if (!projectIsGitRepo) console.log(`[complete-planning] Project root ${projectPath} is not a git repository (polyrepo) — pan spec updated on disk but not committed`);
31588
31611
  else {
31589
31612
  const { stdout: branchStdout } = await execFileAsync$12("git", [
31590
31613
  "rev-parse",
@@ -31646,7 +31669,7 @@ async function completePlanningForIssue(options) {
31646
31669
  cwd: gitRoot,
31647
31670
  encoding: "utf-8"
31648
31671
  });
31649
- for (const args of completePlanningWorkspaceGitAddCommands(gitRoot)) await execFileAsync$12("git", args, {
31672
+ for (const args of completePlanningWorkspaceGitAddCommands(gitRoot, migrated)) await execFileAsync$12("git", args, {
31650
31673
  cwd: gitRoot,
31651
31674
  encoding: "utf-8"
31652
31675
  });
@@ -31749,15 +31772,16 @@ async function completePlanningForIssue(options) {
31749
31772
  source: "planning-agent",
31750
31773
  eventType: "planning.complete"
31751
31774
  });
31752
- if (autoSpawn && workspacePath) await commitWorkspaceRecordBeforeAutoSpawn(workspacePath, id);
31775
+ const effectiveAutoSpawn = autoSpawn || completePlanningLease.autoSpawnRequested();
31776
+ if (effectiveAutoSpawn && workspacePath) await commitWorkspaceRecordBeforeAutoSpawn(workspacePath, id);
31753
31777
  const autoSpawnResult = await completePlanningAutoSpawnAndKill({
31754
31778
  issueId: id,
31755
- autoSpawn,
31779
+ autoSpawn: effectiveAutoSpawn,
31756
31780
  skipKill,
31757
31781
  sessionName
31758
31782
  });
31759
31783
  emitCompletePlanningPhase(id, "terminal", "success", autoSpawnResult?.workAgentSpawned ? "planning complete and work agent spawn requested" : autoSpawnResult?.workAgentSkipReason ?? "planning complete", {
31760
- autoSpawn,
31784
+ autoSpawn: effectiveAutoSpawn,
31761
31785
  workAgentSpawned: autoSpawnResult?.workAgentSpawned ?? false,
31762
31786
  workAgentSkipReason: autoSpawnResult?.workAgentSkipReason
31763
31787
  });
@@ -31779,6 +31803,7 @@ async function completePlanningForIssue(options) {
31779
31803
  init_review_status();
31780
31804
  init_projects();
31781
31805
  init_lifecycle_io();
31806
+ init_issue_closed();
31782
31807
  async function reopenWorkspaceStatePromise(issueId, workspacePath, options = {}) {
31783
31808
  const result = {
31784
31809
  specialistStatesReset: false,
@@ -31849,7 +31874,7 @@ init_tracker_utils();
31849
31874
  init_agents$1();
31850
31875
  init_issue_id();
31851
31876
  init_io();
31852
- const execAsync$10 = promisify(exec);
31877
+ const execAsync$9 = promisify(exec);
31853
31878
  const execFileAsync$11 = promisify(execFile);
31854
31879
  function isGitHubIssue$4(issueId) {
31855
31880
  const resolved = resolveGitHubIssueSync(issueId);
@@ -31921,7 +31946,7 @@ async function closeIssuePullRequest(issueId, reason = "Canceled via Overdeck")
31921
31946
  timeout: 15e3
31922
31947
  });
31923
31948
  try {
31924
- const { setReviewStatusSync } = await import("./review-status-Rr4SB2Kj.js");
31949
+ const { setReviewStatusSync } = await import("./review-status-CGjyt4SK.js");
31925
31950
  setReviewStatusSync(issueId.toUpperCase(), { prUrl: void 0 });
31926
31951
  } catch {}
31927
31952
  return [`Closed PR #${prNumber} on ${githubCheck.owner}/${githubCheck.repo}`];
@@ -31975,7 +32000,7 @@ async function runDestructiveIssueLifecycle(id, mode, opts = {}) {
31975
32000
  const { ctx, projectConfig } = buildLifecycleContext(id, getIssueDataService$8().getIssueSource(id) ?? void 0);
31976
32001
  const deleteWorkspace = opts.deleteWorkspace ?? true;
31977
32002
  cleanupLog.push(...await closeIssuePullRequest(id, mode === "cancel" ? "Canceled via Overdeck" : "Reset to Todo via Overdeck"));
31978
- const { resetToTodo, cancelIssueWorkflow } = await import("./lifecycle-Va4AZGRx.js");
32003
+ const { resetToTodo, cancelIssueWorkflow } = await import("./lifecycle-DEkQYaAt.js");
31979
32004
  const workflow = mode === "cancel" ? cancelIssueWorkflow : resetToTodo;
31980
32005
  const result = await Effect.runPromise(workflow(ctx, {
31981
32006
  deleteWorkspace,
@@ -31990,7 +32015,7 @@ async function runDestructiveIssueLifecycle(id, mode, opts = {}) {
31990
32015
  }));
31991
32016
  cleanupLog.push(...result.steps.flatMap((step) => step.details || [step.error].filter(Boolean)));
31992
32017
  if (mode === "cancel") try {
31993
- const { transitionVBriefOnMain } = await import("./lifecycle-io-BHi2NPxK.js");
32018
+ const { transitionVBriefOnMain } = await import("./lifecycle-io-BB-r9Bl_.js");
31994
32019
  const tx = await Effect.runPromise(transitionVBriefOnMain(ctx.projectPath, id, "cancelled", "cancelled", `scope: cancel ${id.toUpperCase()} vBRIEF`));
31995
32020
  if (tx.moved) cleanupLog.push(`vBRIEF moved ${tx.fromDir} → cancelled`);
31996
32021
  if (tx.committed) cleanupLog.push(`Committed vBRIEF cancellation on main`);
@@ -31998,8 +32023,8 @@ async function runDestructiveIssueLifecycle(id, mode, opts = {}) {
31998
32023
  cleanupLog.push(`vBRIEF cancel transition failed (non-fatal): ${err?.message ?? err}`);
31999
32024
  }
32000
32025
  try {
32001
- const { killAllReviewerSessions } = await import("./review-agent-DfN-7KW6.js");
32002
- const { resolveProjectFromIssueSync } = await import("./projects-BbMEBykK.js");
32026
+ const { killAllReviewerSessions } = await import("./review-agent-D0X_E1tF.js");
32027
+ const { resolveProjectFromIssueSync } = await import("./projects-Daw2zpGk.js");
32003
32028
  const projectKey = resolveProjectFromIssueSync(id)?.projectKey;
32004
32029
  if (projectKey) {
32005
32030
  const { killed } = await Effect.runPromise(killAllReviewerSessions(projectKey, id.toUpperCase()));
@@ -32013,7 +32038,7 @@ async function runDestructiveIssueLifecycle(id, mode, opts = {}) {
32013
32038
  cleanupLog.push("Cleared review status");
32014
32039
  } catch {}
32015
32040
  try {
32016
- const { resetPostMergeState } = await import("./merge-agent-DZaRBHQA.js");
32041
+ const { resetPostMergeState } = await import("./merge-agent-DzbCbjqg.js");
32017
32042
  resetPostMergeState(id);
32018
32043
  resetPostMergeState(id.toUpperCase());
32019
32044
  cleanupLog.push("Cleared merge state");
@@ -32033,7 +32058,7 @@ function closeIssueTransition(options) {
32033
32058
  const { issueId, body, eventStore } = options;
32034
32059
  const { reason } = body;
32035
32060
  const projectPath = getProjectPath$3(void 0, extractPrefixSync(issueId) ?? issueId.split("-")[0]);
32036
- const { close: closeWorkflow } = yield* Effect.promise(() => import("./lifecycle-Va4AZGRx.js"));
32061
+ const { close: closeWorkflow } = yield* Effect.promise(() => import("./lifecycle-DEkQYaAt.js"));
32037
32062
  const githubCheck = isGitHubIssue$4(issueId);
32038
32063
  const issueDataService = getIssueDataService$8();
32039
32064
  const issueSource = issueDataService.getIssueSource(issueId);
@@ -32056,7 +32081,7 @@ function closeIssueTransition(options) {
32056
32081
  };
32057
32082
  }
32058
32083
  const result = yield* closeWorkflow(ctx, { reason });
32059
- if (githubCheck.isGitHub) execAsync$10("pan sync", {
32084
+ if (githubCheck.isGitHub) execAsync$9("pan sync", {
32060
32085
  encoding: "utf-8",
32061
32086
  timeout: 3e4
32062
32087
  }).catch(() => {});
@@ -32267,13 +32292,13 @@ function reopenIssueTransition(options) {
32267
32292
  }
32268
32293
  yield* Effect.promise(async () => {
32269
32294
  try {
32270
- const { stdout } = await execAsync$10(`gh pr list --head ${`feature/${id.toLowerCase()}`} --state closed --json number,mergedAt --limit 1`, {
32295
+ const { stdout } = await execAsync$9(`gh pr list --head ${`feature/${id.toLowerCase()}`} --state closed --json number,mergedAt --limit 1`, {
32271
32296
  encoding: "utf-8",
32272
32297
  timeout: 15e3
32273
32298
  });
32274
32299
  const prs = JSON.parse(stdout.trim() || "[]");
32275
32300
  if (prs.length > 0 && !prs[0].mergedAt) {
32276
- await execAsync$10(`gh pr reopen ${prs[0].number}`, {
32301
+ await execAsync$9(`gh pr reopen ${prs[0].number}`, {
32277
32302
  encoding: "utf-8",
32278
32303
  timeout: 15e3
32279
32304
  });
@@ -32300,7 +32325,7 @@ function reopenIssueTransition(options) {
32300
32325
  else clearReviewStatus(id.toUpperCase());
32301
32326
  } catch {}
32302
32327
  try {
32303
- const { resetPostMergeState } = await import("./merge-agent-DZaRBHQA.js");
32328
+ const { resetPostMergeState } = await import("./merge-agent-DzbCbjqg.js");
32304
32329
  resetPostMergeState(id);
32305
32330
  resetPostMergeState(id.toUpperCase());
32306
32331
  } catch {}
@@ -32320,7 +32345,7 @@ function reopenIssueTransition(options) {
32320
32345
  const projectPath = (teamPrefix ? findProjectByTeamSync(teamPrefix) : null)?.path || "";
32321
32346
  if (projectPath) {
32322
32347
  const workspacePath = join$1(projectPath, "workspaces", `feature-${issueLower}`);
32323
- const { createBeadsFromVBrief } = await import("./beads-B4ysfx-Y.js");
32348
+ const { createBeadsFromVBrief } = await import("./beads-CuXF6X4l.js");
32324
32349
  if (existsSync$1(workspacePath) && await Effect.runPromise(findPlan(workspacePath))) try {
32325
32350
  const { stdout: bdCheck } = await Effect.runPromise(withBdMutex(() => Effect.promise(() => execFileAsync$11("bd", [
32326
32351
  "list",
@@ -32397,7 +32422,7 @@ function moveIssueStatus(options) {
32397
32422
  "done"
32398
32423
  ];
32399
32424
  if (!targetStatus || !validStatuses.includes(targetStatus)) return jsonResponse({ error: `Invalid targetStatus. Must be one of: ${validStatuses.join(", ")}` }, { status: 400 });
32400
- const { updateShadowState } = yield* Effect.promise(() => import("./shadow-state-nDkNqpYC.js"));
32425
+ const { updateShadowState } = yield* Effect.promise(() => import("./shadow-state-B5mlwqQI.js"));
32401
32426
  const issueState = {
32402
32427
  backlog: "open",
32403
32428
  todo: "open",
@@ -32460,7 +32485,7 @@ function moveIssueStatus(options) {
32460
32485
  init_issue_service_singleton();
32461
32486
  init_issue_id();
32462
32487
  init_agents$1();
32463
- const execAsync$9 = promisify(exec);
32488
+ const execAsync$8 = promisify(exec);
32464
32489
  function getIssueDataService$7() {
32465
32490
  return getSharedIssueService();
32466
32491
  }
@@ -32485,28 +32510,28 @@ async function cleanupWorkspaceForIssue(rawId, eventStore) {
32485
32510
  if (projectRoot) {
32486
32511
  const workspacePath = join$1(projectRoot, "workspaces", `feature-${issueLower}`);
32487
32512
  try {
32488
- if ((await execAsync$9("git worktree list --porcelain", {
32513
+ if ((await execAsync$8("git worktree list --porcelain", {
32489
32514
  cwd: projectRoot,
32490
32515
  encoding: "utf-8"
32491
32516
  })).stdout.includes(workspacePath)) {
32492
- await execAsync$9(`git worktree remove "${workspacePath}" --force`, {
32517
+ await execAsync$8(`git worktree remove "${workspacePath}" --force`, {
32493
32518
  cwd: projectRoot,
32494
32519
  encoding: "utf-8"
32495
32520
  });
32496
32521
  cleanupLog.push(`Removed git worktree: ${workspacePath}`);
32497
32522
  } else if (existsSync$1(workspacePath)) {
32498
- await execAsync$9(`rm -rf "${workspacePath}"`, { encoding: "utf-8" });
32523
+ await execAsync$8(`rm -rf "${workspacePath}"`, { encoding: "utf-8" });
32499
32524
  cleanupLog.push(`Removed directory: ${workspacePath}`);
32500
32525
  }
32501
32526
  } catch {
32502
32527
  if (existsSync$1(workspacePath)) {
32503
- await execAsync$9(`rm -rf "${workspacePath}"`, { encoding: "utf-8" });
32528
+ await execAsync$8(`rm -rf "${workspacePath}"`, { encoding: "utf-8" });
32504
32529
  cleanupLog.push(`Removed directory: ${workspacePath}`);
32505
32530
  }
32506
32531
  }
32507
32532
  const branchName = `feature/${issueLower}`;
32508
32533
  try {
32509
- await execAsync$9(`git branch -D "${branchName}" 2>/dev/null || true`, {
32534
+ await execAsync$8(`git branch -D "${branchName}" 2>/dev/null || true`, {
32510
32535
  cwd: projectRoot,
32511
32536
  encoding: "utf-8"
32512
32537
  });
@@ -32515,7 +32540,7 @@ async function cleanupWorkspaceForIssue(rawId, eventStore) {
32515
32540
  }
32516
32541
  const agentDir = join$1(homedir$1(), ".overdeck", "agents", `agent-${issueLower}`);
32517
32542
  if (existsSync$1(agentDir)) {
32518
- await execAsync$9(`rm -rf "${agentDir}"`, { encoding: "utf-8" });
32543
+ await execAsync$8(`rm -rf "${agentDir}"`, { encoding: "utf-8" });
32519
32544
  cleanupLog.push(`Removed agent state: ${agentDir}`);
32520
32545
  }
32521
32546
  await Effect.runPromise(eventStore.append({
@@ -32624,7 +32649,7 @@ async function copySettingsToWorkspace(id) {
32624
32649
  success: false,
32625
32650
  error: "Workspace not found"
32626
32651
  }, { status: 404 });
32627
- const { copyOverdeckSettingsToWorkspaceSync } = await import("./workspace-manager-BE2H8gD5.js");
32652
+ const { copyOverdeckSettingsToWorkspaceSync } = await import("./workspace-manager-uVfFRWJG.js");
32628
32653
  const result = copyOverdeckSettingsToWorkspaceSync(workspacePath);
32629
32654
  return jsonResponse({
32630
32655
  success: result.errors.length === 0 || result.copied.length > 0,
@@ -32634,6 +32659,8 @@ async function copySettingsToWorkspace(id) {
32634
32659
  }
32635
32660
  //#endregion
32636
32661
  //#region ../../lib/overdeck/task-generation.ts
32662
+ init_shadow_state();
32663
+ init_github_app();
32637
32664
  init_io();
32638
32665
  function buildChildStoriesFromRally(children) {
32639
32666
  return children.map((c) => ({
@@ -32657,7 +32684,7 @@ function generateTasksForIssue(id) {
32657
32684
  success: false,
32658
32685
  error: `No vBRIEF spec found on main for ${id} — run planning first.`
32659
32686
  }, { status: 409 });
32660
- const { createBeadsFromVBrief } = yield* Effect.promise(() => import("./beads-B4ysfx-Y.js"));
32687
+ const { createBeadsFromVBrief } = yield* Effect.promise(() => import("./beads-CuXF6X4l.js"));
32661
32688
  const result = yield* createBeadsFromVBrief(workspacePath);
32662
32689
  if (!result.success || result.created.length === 0) {
32663
32690
  const errors = result.errors.length > 0 ? result.errors : ["Beads creation produced no tasks"];
@@ -32687,7 +32714,7 @@ init_projects();
32687
32714
  init_tracker_utils();
32688
32715
  init_tmux();
32689
32716
  init_typed_errors();
32690
- const execAsync$8 = promisify(exec);
32717
+ const execAsync$7 = promisify(exec);
32691
32718
  const execFileAsync$10 = promisify(execFile);
32692
32719
  function getIssueDataService$6() {
32693
32720
  return getSharedIssueService();
@@ -33097,10 +33124,10 @@ function restartFromPlan(options) {
33097
33124
  });
33098
33125
  const resetResult = yield* Effect.promise(async () => {
33099
33126
  try {
33100
- const { runGitResetHard } = await import("./dangerous-git-ops-C9iYTZ0M.js");
33127
+ const { runGitResetHard } = await import("./dangerous-git-ops-Pongxg2d.js");
33101
33128
  async function findPlanningCommit(grep, label) {
33102
33129
  try {
33103
- const { stdout } = await execAsync$8(`git log --grep="${grep.replace(/"/g, "\\\"")}" --format=%H -1`, {
33130
+ const { stdout } = await execAsync$7(`git log --grep="${grep.replace(/"/g, "\\\"")}" --format=%H -1`, {
33104
33131
  cwd: workspacePath,
33105
33132
  encoding: "utf-8",
33106
33133
  timeout: 1e4
@@ -33116,7 +33143,7 @@ function restartFromPlan(options) {
33116
33143
  }
33117
33144
  const found = await findPlanningCommit(`Complete planning for ${id}`, "complete-planning message") ?? await findPlanningCommit(`chore: planning artifacts for ${id}`, "agent-start message") ?? await (async () => {
33118
33145
  try {
33119
- const { stdout } = await execAsync$8(`git log --diff-filter=A --format=%H -1 -- .pan/spec.vbrief.json`, {
33146
+ const { stdout } = await execAsync$7(`git log --diff-filter=A --format=%H -1 -- .pan/spec.vbrief.json`, {
33120
33147
  cwd: workspacePath,
33121
33148
  encoding: "utf-8",
33122
33149
  timeout: 1e4
@@ -33244,14 +33271,13 @@ function getPlanningState(id) {
33244
33271
  //#endregion
33245
33272
  //#region ../../lib/overdeck/discussions.ts
33246
33273
  init_cost_sync();
33247
- init_github_app();
33248
33274
  init_pull_requests();
33249
33275
  init_issue_id();
33250
33276
  init_github_pr_lookup();
33251
33277
  init_tracker_utils();
33252
33278
  init_tracker_config();
33253
33279
  init_pr_tab_cache();
33254
- const execAsync$7 = promisify(exec);
33280
+ const execAsync$6 = promisify(exec);
33255
33281
  function isGitHubIssue$2(issueId) {
33256
33282
  const resolved = resolveGitHubIssueSync(issueId);
33257
33283
  if (resolved.isGitHub) return {
@@ -33299,7 +33325,7 @@ async function fetchIssueDiscussions(issueId, deps = {}) {
33299
33325
  if (githubCheck.isGitHub && githubCheck.owner && githubCheck.repo && githubCheck.number) {
33300
33326
  const { owner, repo, number } = githubCheck;
33301
33327
  try {
33302
- const { stdout } = await execAsync$7(`gh api "repos/${owner}/${repo}/issues/${number}/comments?per_page=100"`, {
33328
+ const { stdout } = await execAsync$6(`gh api "repos/${owner}/${repo}/issues/${number}/comments?per_page=100"`, {
33303
33329
  encoding: "utf-8",
33304
33330
  timeout: 15e3,
33305
33331
  maxBuffer: 8 * 1024 * 1024
@@ -33362,7 +33388,7 @@ async function fetchIssueDiscussions(issueId, deps = {}) {
33362
33388
  const collectedItems = [];
33363
33389
  const prConversation = (async () => {
33364
33390
  try {
33365
- const { stdout } = await execAsync$7(`gh api "repos/${prOwner}/${prRepo}/issues/${prNumber}/comments?per_page=100"`, {
33391
+ const { stdout } = await execAsync$6(`gh api "repos/${prOwner}/${prRepo}/issues/${prNumber}/comments?per_page=100"`, {
33366
33392
  encoding: "utf-8",
33367
33393
  timeout: 15e3,
33368
33394
  maxBuffer: 8 * 1024 * 1024
@@ -33383,7 +33409,7 @@ async function fetchIssueDiscussions(issueId, deps = {}) {
33383
33409
  })();
33384
33410
  const prReviews = (async () => {
33385
33411
  try {
33386
- const { stdout } = await execAsync$7(`gh api "repos/${prOwner}/${prRepo}/pulls/${prNumber}/reviews?per_page=100"`, {
33412
+ const { stdout } = await execAsync$6(`gh api "repos/${prOwner}/${prRepo}/pulls/${prNumber}/reviews?per_page=100"`, {
33387
33413
  encoding: "utf-8",
33388
33414
  timeout: 15e3,
33389
33415
  maxBuffer: 8 * 1024 * 1024
@@ -33408,7 +33434,7 @@ async function fetchIssueDiscussions(issueId, deps = {}) {
33408
33434
  })();
33409
33435
  const prInlineComments = (async () => {
33410
33436
  try {
33411
- const { stdout } = await execAsync$7(`gh api "repos/${prOwner}/${prRepo}/pulls/${prNumber}/comments?per_page=100"`, {
33437
+ const { stdout } = await execAsync$6(`gh api "repos/${prOwner}/${prRepo}/pulls/${prNumber}/comments?per_page=100"`, {
33412
33438
  encoding: "utf-8",
33413
33439
  timeout: 15e3,
33414
33440
  maxBuffer: 8 * 1024 * 1024
@@ -33550,7 +33576,7 @@ function closeOutIssue(id) {
33550
33576
  }
33551
33577
  const closeOutResult = yield* Effect.promise(async () => {
33552
33578
  try {
33553
- const { closeOut } = await import("./lifecycle-Va4AZGRx.js");
33579
+ const { closeOut } = await import("./lifecycle-DEkQYaAt.js");
33554
33580
  return {
33555
33581
  ok: true,
33556
33582
  result: await Effect.runPromise(closeOut(ctx))
@@ -33636,7 +33662,7 @@ function bulkCloseOut(body) {
33636
33662
  const invalidIds = issueIds.filter((id) => !isValidIssueId(id));
33637
33663
  if (invalidIds.length > 0) return jsonResponse({ error: `Invalid issue ID format: ${invalidIds.join(", ")}` }, { status: 400 });
33638
33664
  const eventStore = yield* EventStoreService;
33639
- const { closeOut } = yield* Effect.promise(() => import("./lifecycle-Va4AZGRx.js"));
33665
+ const { closeOut } = yield* Effect.promise(() => import("./lifecycle-DEkQYaAt.js"));
33640
33666
  const issueDataService = getIssueDataService$5();
33641
33667
  const tasks = [];
33642
33668
  const agentChecks = yield* withConcurrencyLimit(issueIds.map((id) => Effect.promise(async () => {
@@ -33832,8 +33858,8 @@ const getIssueShipLogRoute = HttpRouter.add("GET", "/api/issues/:id/ship-log", h
33832
33858
  const id = (yield* HttpRouter.params)["id"] ?? "";
33833
33859
  if (!parseIssueIdSync(id)) return jsonResponse({ error: "Invalid issue ID" }, { status: 400 });
33834
33860
  return yield* Effect.promise(async () => {
33835
- const { getShipLog } = await import("./ship-log-EV79hCrN.js");
33836
- const { getReviewStatusSync } = await import("./review-status-Rr4SB2Kj.js");
33861
+ const { getShipLog } = await import("./ship-log-B2EEH__n.js");
33862
+ const { getReviewStatusSync } = await import("./review-status-CGjyt4SK.js");
33837
33863
  const log = getShipLog(id);
33838
33864
  const rs = getReviewStatusSync(id);
33839
33865
  return jsonResponse({
@@ -34785,27 +34811,6 @@ const getCloisterAgentsHealthRoute = HttpRouter.add("GET", "/api/cloister/agents
34785
34811
  })));
34786
34812
  const cloisterRouteLayer = Layer.mergeAll(getCloisterStatusRoute, postCloisterStartRoute, postCloisterStopRoute, postCloisterEmergencyStopRoute, postCloisterBrakeRoute, postCloisterResumeSpawnsRoute, getCloisterSpawnStatusRoute, getCloisterConfigRoute, putCloisterConfigRoute, getCloisterAgentsHealthRoute);
34787
34813
  //#endregion
34788
- //#region routes/resources/shared.ts
34789
- init_docker_stats();
34790
- function getCurrentDockerStats() {
34791
- return [];
34792
- }
34793
- function getContainerHistory(containerId) {
34794
- return {
34795
- timestamps: [],
34796
- cpuPercent: [],
34797
- memoryPercent: []
34798
- };
34799
- }
34800
- function formatUptime(startedAt) {
34801
- const ms = Date.now() - new Date(startedAt).getTime();
34802
- const h = Math.floor(ms / 36e5);
34803
- const m = Math.floor(ms % 36e5 / 6e4);
34804
- if (h >= 24) return `${Math.floor(h / 24)}d ${h % 24}h`;
34805
- if (h > 0) return `${h}h ${m}m`;
34806
- return `${m}m`;
34807
- }
34808
- //#endregion
34809
34814
  //#region routes/resources/agents-stats.ts
34810
34815
  init_agents$1();
34811
34816
  init_cost_sync();
@@ -35405,7 +35410,7 @@ function computeAgentCounts(agents, fleet, nowMs) {
35405
35410
  };
35406
35411
  }
35407
35412
  function getDefaultMemoryVitals() {
35408
- const total = totalmem();
35413
+ const total = totalmem$1();
35409
35414
  const available = freemem$1();
35410
35415
  return {
35411
35416
  usedBytes: Math.max(0, total - available),
@@ -35562,86 +35567,6 @@ function spawnGatePressure(decision) {
35562
35567
  return 12;
35563
35568
  }
35564
35569
  //#endregion
35565
- //#region routes/resources/stacks.ts
35566
- init_review_status();
35567
- let reviewStatusReader = (issueId) => getReviewStatusSync(issueId);
35568
- function getResourceStacks(containers) {
35569
- return buildResourceStacks(containers, reviewStatusesFor(containers));
35570
- }
35571
- function buildResourceStacks(containers, reviewStatuses = {}) {
35572
- const groups = /* @__PURE__ */ new Map();
35573
- for (const container of containers) {
35574
- const key = composeProjectFor(container) ?? "unassigned";
35575
- groups.set(key, [...groups.get(key) ?? [], container]);
35576
- }
35577
- return [...groups.entries()].map(([composeProject, services]) => {
35578
- const issueId = issueIdFor$1(composeProject, services);
35579
- const reviewStatus = issueId ? reviewStatuses[issueId] : void 0;
35580
- return {
35581
- id: issueId ?? composeProject,
35582
- issueId,
35583
- issueTitle: issueId ?? "Unassigned",
35584
- composeProject,
35585
- serviceCount: services.length,
35586
- services,
35587
- aggregates: {
35588
- cpuPercent: roundOne(services.reduce((sum, service) => sum + (service.cpuPercent ?? 0), 0)),
35589
- memoryBytes: services.reduce((sum, service) => sum + (service.memoryUsage ?? 0), 0),
35590
- diskBytes: services.reduce((sum, service) => sum + (service.diskUsage ?? 0), 0)
35591
- },
35592
- phase: phaseFor(reviewStatus)
35593
- };
35594
- }).sort((a, b) => a.id.localeCompare(b.id));
35595
- }
35596
- function reviewStatusesFor(containers) {
35597
- const issueIds = /* @__PURE__ */ new Set();
35598
- const groups = /* @__PURE__ */ new Map();
35599
- for (const container of containers) {
35600
- const key = composeProjectFor(container) ?? "unassigned";
35601
- groups.set(key, [...groups.get(key) ?? [], container]);
35602
- }
35603
- for (const [composeProject, services] of groups.entries()) {
35604
- const issueId = issueIdFor$1(composeProject, services);
35605
- if (issueId) issueIds.add(issueId);
35606
- }
35607
- const statuses = {};
35608
- for (const issueId of issueIds) statuses[issueId] = reviewStatusReader(issueId) ?? void 0;
35609
- return statuses;
35610
- }
35611
- function composeProjectFor(container) {
35612
- const labelProject = container.labels?.["com.docker.compose.project"]?.trim();
35613
- if (labelProject) return labelProject;
35614
- const issueProject = container.name.match(/^(.+?feature[-_](?:pan|min|aur|krux)[-_]?\d+)/i);
35615
- if (issueProject?.[1]) return issueProject[1];
35616
- return container.name.match(/^(.+?)[_-][a-z0-9]+[._-][0-9]+$/i)?.[1] ?? null;
35617
- }
35618
- function issueIdFor$1(composeProject, services) {
35619
- if (composeProject === "unassigned") return null;
35620
- const fromProject = issueIdFromText(composeProject);
35621
- if (fromProject) return fromProject;
35622
- for (const service of services) {
35623
- const fromLabels = issueIdFromText(Object.values(service.labels ?? {}).join(" "));
35624
- if (fromLabels) return fromLabels;
35625
- }
35626
- return null;
35627
- }
35628
- function issueIdFromText(value) {
35629
- const match = value.match(/(?:workspaces[\\/])?feature[-_](pan|min|aur|krux)[-_]?(\d+)/i) ?? value.match(/\b(pan|min|aur|krux)[-_]?(\d+)\b/i);
35630
- if (!match) return null;
35631
- return `${match[1].toUpperCase()}-${match[2]}`;
35632
- }
35633
- function phaseFor(status) {
35634
- if (!status) return "todo";
35635
- if (status.mergeStatus === "merged") return "merged";
35636
- if (status.mergeStatus === "queued" || status.mergeStatus === "merging" || status.mergeStatus === "verifying" || status.mergeStatus === "failed" || status.readyForMerge === true) return "ship";
35637
- if (status.verificationStatus === "running") return "verifying";
35638
- if (status.reviewStatus === "reviewing" || status.reviewStatus === "passed" || status.reviewStatus === "failed" || status.reviewStatus === "blocked" || status.testStatus === "testing" || status.testStatus === "passed" || status.testStatus === "failed" || status.inspectStatus === "inspecting" || status.inspectStatus === "passed" || status.inspectStatus === "failed" || status.inspectStatus === "error") return "review";
35639
- return "todo";
35640
- }
35641
- function roundOne(value) {
35642
- return Math.round(value * 10) / 10;
35643
- }
35644
- //#endregion
35645
35570
  //#region routes/resources/snapshot.ts
35646
35571
  init_agents$1();
35647
35572
  init_tmux();
@@ -36516,7 +36441,8 @@ const ROLE_NAMES = [
36516
36441
  "ship",
36517
36442
  "flywheel",
36518
36443
  "strike",
36519
- "sequencer"
36444
+ "sequencer",
36445
+ "knowledge"
36520
36446
  ];
36521
36447
  const WORKHORSE_SLOTS = [
36522
36448
  "expensive",
@@ -37245,17 +37171,20 @@ function getAvailableModelsApi() {
37245
37171
  }
37246
37172
  }
37247
37173
  const openaiOrder = {
37248
- "gpt-5.5": 0,
37249
- "gpt-5.5-pro": 1,
37250
- "gpt-5.4": 10,
37251
- "gpt-5.4-pro": 11,
37252
- "gpt-5.4-mini": 12,
37253
- "gpt-5.3-codex": 20,
37254
- "gpt-5.2": 30,
37255
- "o3": 40,
37256
- "o4-mini": 41,
37257
- "gpt-4o": 50,
37258
- "gpt-4o-mini": 51
37174
+ "gpt-5.6-sol": 0,
37175
+ "gpt-5.6-terra": 1,
37176
+ "gpt-5.6-luna": 2,
37177
+ "gpt-5.5": 10,
37178
+ "gpt-5.5-pro": 11,
37179
+ "gpt-5.4": 20,
37180
+ "gpt-5.4-pro": 21,
37181
+ "gpt-5.4-mini": 22,
37182
+ "gpt-5.3-codex": 30,
37183
+ "gpt-5.2": 40,
37184
+ "o3": 50,
37185
+ "o4-mini": 51,
37186
+ "gpt-4o": 60,
37187
+ "gpt-4o-mini": 61
37259
37188
  };
37260
37189
  result.openai.sort((a, b) => (openaiOrder[a.id] ?? 99) - (openaiOrder[b.id] ?? 99));
37261
37190
  return result;
@@ -37623,7 +37552,7 @@ init_linear_client();
37623
37552
  init_config_yaml();
37624
37553
  init_issue_service_singleton();
37625
37554
  init_io();
37626
- const execAsync$6 = promisify(exec);
37555
+ const execAsync$5 = promisify(exec);
37627
37556
  const execFileAsync$4 = promisify(execFile);
37628
37557
  function getIssueDataService$3() {
37629
37558
  return getSharedIssueService();
@@ -37724,16 +37653,21 @@ async function fetchActivityDataWithContext(issueId, context = {}) {
37724
37653
  const workspacePath = join$1(projectPath, "workspaces", `feature-${issueLower}`);
37725
37654
  const agentId = `agent-${issueLower}`;
37726
37655
  const planningAgentId = `planning-${issueLower}`;
37656
+ const knowledgeAgentId = `agent-${issueLower}-knowledge`;
37727
37657
  const agentsDir = join$1(homedir$1(), ".overdeck", "agents");
37728
37658
  let hasPlanningSection = false;
37729
- for (const checkId of [planningAgentId, agentId]) {
37659
+ for (const checkId of [
37660
+ planningAgentId,
37661
+ agentId,
37662
+ knowledgeAgentId
37663
+ ]) {
37730
37664
  const agentDir = join$1(agentsDir, checkId);
37731
37665
  if (!await pathExists$4(agentDir)) continue;
37732
37666
  const state = getAgentStateSync(checkId);
37733
37667
  if (!state) continue;
37734
37668
  try {
37735
37669
  const isPlanning = checkId.startsWith("planning-");
37736
- const sectionType = isPlanning ? "planning" : "work";
37670
+ const sectionType = isPlanning ? "planning" : checkId.endsWith("-knowledge") ? "knowledge" : "work";
37737
37671
  if (isPlanning) hasPlanningSection = true;
37738
37672
  let transcript = "";
37739
37673
  let transcriptFromPane = false;
@@ -38161,7 +38095,7 @@ async function fetchPlanningData(issueId, options = {}) {
38161
38095
  const cached = stashCountCache.get(cacheKey);
38162
38096
  if (cached && cached.timestamp > Date.now() - STASH_COUNT_CACHE_TTL_MS) result.stashCount = cached.count;
38163
38097
  else {
38164
- const { stdout: stashList } = await execAsync$6("git stash list", {
38098
+ const { stdout: stashList } = await execAsync$5("git stash list", {
38165
38099
  cwd: workspacePath,
38166
38100
  encoding: "utf-8"
38167
38101
  });
@@ -38249,7 +38183,7 @@ async function generateStatusReview(issueId) {
38249
38183
  };
38250
38184
  const execSafe = async (cmd, opts) => {
38251
38185
  try {
38252
- const { stdout } = await execAsync$6(cmd, {
38186
+ const { stdout } = await execAsync$5(cmd, {
38253
38187
  encoding: "utf-8",
38254
38188
  timeout: 1e4,
38255
38189
  ...opts
@@ -38351,7 +38285,7 @@ Be specific: reference actual file names, function names, requirement text, disc
38351
38285
  const { command: cliCmd, args: cliArgs } = getAgentCommandSync(statusModelId);
38352
38286
  const modelFlag = cliArgs.length > 0 ? ` ${cliArgs.join(" ")}` : "";
38353
38287
  const promptFile = join$1(planningDir, ".status-review-prompt.tmp");
38354
- const { getProviderForModelSync, getProviderEnvSync } = await import("./providers-Djkuu1CD.js");
38288
+ const { getProviderForModelSync, getProviderEnvSync } = await import("./providers-pkuT25pY.js");
38355
38289
  let providerEnvStr = "";
38356
38290
  let providerEnv = {};
38357
38291
  const statusProvider = getProviderForModelSync(statusModelId);
@@ -38368,7 +38302,7 @@ Be specific: reference actual file names, function names, requirement text, disc
38368
38302
  try {
38369
38303
  const env = buildChildEnvSync(process.env, providerEnv);
38370
38304
  const promptContent = await readFile(promptFile, "utf-8");
38371
- const { stdout: aiReview } = await execAsync$6(`${cliCmd} -p${modelFlag} --no-session-persistence`, {
38305
+ const { stdout: aiReview } = await execAsync$5(`${cliCmd} -p${modelFlag} --no-session-persistence`, {
38372
38306
  encoding: "utf-8",
38373
38307
  timeout: 12e4,
38374
38308
  maxBuffer: 1024 * 1024,
@@ -38434,7 +38368,7 @@ const postMissionControlUploadRoute = HttpRouter.add("POST", "/api/command-deck/
38434
38368
  let safeName = filename.replace(/[^a-zA-Z0-9._-]/g, "-");
38435
38369
  let processedContent = content;
38436
38370
  if (safeName.endsWith(".vtt")) {
38437
- const { vttToMarkdown } = yield* Effect.promise(() => import("./vtt-parser-d-QMKZn4.js"));
38371
+ const { vttToMarkdown } = yield* Effect.promise(() => import("./vtt-parser-D-q5-8il.js"));
38438
38372
  processedContent = vttToMarkdown(content);
38439
38373
  safeName = safeName.replace(/\.vtt$/, ".md");
38440
38374
  }
@@ -42919,6 +42853,9 @@ const readJsonBody$10 = Effect.gen(function* () {
42919
42853
  });
42920
42854
  /** Model ID to API model ID mapping */
42921
42855
  const MODEL_API_IDS = {
42856
+ "gpt-5.6-sol": { apiModel: "gpt-5.6-sol" },
42857
+ "gpt-5.6-terra": { apiModel: "gpt-5.6-terra" },
42858
+ "gpt-5.6-luna": { apiModel: "gpt-5.6-luna" },
42922
42859
  "gpt-5.5-pro": { apiModel: "gpt-5.5-pro" },
42923
42860
  "gpt-5.5": { apiModel: "gpt-5.5" },
42924
42861
  "gpt-5.4-pro": { apiModel: "gpt-5.4-pro" },
@@ -44245,7 +44182,7 @@ const postRallyValidateRoute = HttpRouter.add("POST", "/api/rally/validate", Eff
44245
44182
  }, { status: 400 });
44246
44183
  return yield* Effect.promise(async () => {
44247
44184
  try {
44248
- const { RallyRestApi } = await import("./rally-api-DpFjC_KQ.js");
44185
+ const { RallyRestApi } = await import("./rally-api-DE3UOdHw.js");
44249
44186
  const api = new RallyRestApi({
44250
44187
  apiKey,
44251
44188
  server: server || "https://rally1.rallydev.com"
@@ -44541,7 +44478,7 @@ const deaconRouteLayer = Layer.mergeAll(getNoResumeModeRoute, postResumeAllRoute
44541
44478
  //#region routes/misc/planning.ts
44542
44479
  init_config_yaml();
44543
44480
  init_issue_id();
44544
- init_types$1();
44481
+ init_types();
44545
44482
  init_projects();
44546
44483
  init_remote_agents();
44547
44484
  init_tmux();
@@ -44573,7 +44510,7 @@ const getPlanningStatusRoute = HttpRouter.add("GET", "/api/planning/:issueId/sta
44573
44510
  const remoteState = loadRemoteAgentState(sessionName);
44574
44511
  const isRemote = !!remoteState;
44575
44512
  const vmName = remoteState?.vmName ?? "";
44576
- const { getAgentStateSync } = await import("./agents-Ea9gfdKS.js");
44513
+ const { getAgentStateSync } = await import("./agents-2mgtTSeb.js");
44577
44514
  const agentStarting = getAgentStateSync(sessionName)?.status === "starting";
44578
44515
  let tmuxSessionAlive = false;
44579
44516
  if (!isRemote) try {
@@ -44716,7 +44653,7 @@ Continue the PLANNING session. Do NOT implement anything.
44716
44653
  `);
44717
44654
  const agentCwd = workspacePath;
44718
44655
  if (existsSync$1(outputFile)) await rename(outputFile, join$1(planningDir, `output-${Date.now()}.jsonl`));
44719
- const { getAgentCommandSync } = await import("./settings-DXeuoifi.js");
44656
+ const { getAgentCommandSync } = await import("./settings-B27w9z21.js");
44720
44657
  let msgPlanningModel = "claude-sonnet-5";
44721
44658
  try {
44722
44659
  msgPlanningModel = resolveModel("plan", void 0, loadConfigSync().config);
@@ -44837,7 +44774,7 @@ async function getIndexStats(rootPath, isMain) {
44837
44774
  }
44838
44775
  const getTldrStatusRoute = HttpRouter.add("GET", "/api/services/tldr/status", Effect.promise(async () => {
44839
44776
  try {
44840
- const { getTldrDaemonServiceSync } = await import("./tldr-daemon-CwUB_rve.js");
44777
+ const { getTldrDaemonServiceSync } = await import("./tldr-daemon-DkRIsKUT.js");
44841
44778
  const projectRoot = process.cwd();
44842
44779
  const venvPath = join$1(projectRoot, ".venv");
44843
44780
  const results = [];
@@ -44882,7 +44819,7 @@ const getTldrStatusRoute = HttpRouter.add("GET", "/api/services/tldr/status", Ef
44882
44819
  }));
44883
44820
  const postTldrStartRoute = HttpRouter.add("POST", "/api/services/tldr/start", Effect.promise(async () => {
44884
44821
  try {
44885
- const { getTldrDaemonServiceSync } = await import("./tldr-daemon-CwUB_rve.js");
44822
+ const { getTldrDaemonServiceSync } = await import("./tldr-daemon-DkRIsKUT.js");
44886
44823
  const projectRoot = process.cwd();
44887
44824
  const venvPath = join$1(projectRoot, ".venv");
44888
44825
  if (!existsSync$1(venvPath)) return jsonResponse({ error: "No .venv found in project root" }, { status: 404 });
@@ -44899,7 +44836,7 @@ const postTldrStartRoute = HttpRouter.add("POST", "/api/services/tldr/start", Ef
44899
44836
  }));
44900
44837
  const postTldrStopRoute = HttpRouter.add("POST", "/api/services/tldr/stop", Effect.promise(async () => {
44901
44838
  try {
44902
- const { getTldrDaemonServiceSync } = await import("./tldr-daemon-CwUB_rve.js");
44839
+ const { getTldrDaemonServiceSync } = await import("./tldr-daemon-DkRIsKUT.js");
44903
44840
  const projectRoot = process.cwd();
44904
44841
  const venvPath = join$1(projectRoot, ".venv");
44905
44842
  if (!existsSync$1(venvPath)) return jsonResponse({ error: "No .venv found in project root" }, { status: 404 });
@@ -44916,7 +44853,7 @@ const postTldrStopRoute = HttpRouter.add("POST", "/api/services/tldr/stop", Effe
44916
44853
  }));
44917
44854
  const postTldrReloadRoute = HttpRouter.add("POST", "/api/services/tldr/reload", Effect.promise(async () => {
44918
44855
  try {
44919
- const { getTldrDaemonServiceSync } = await import("./tldr-daemon-CwUB_rve.js");
44856
+ const { getTldrDaemonServiceSync } = await import("./tldr-daemon-DkRIsKUT.js");
44920
44857
  const enabled = isTldrEnabledSync();
44921
44858
  const projectRoot = process.cwd();
44922
44859
  const targets = [];
@@ -44968,7 +44905,7 @@ init_tracker_config();
44968
44905
  init_issue_id();
44969
44906
  init_projects();
44970
44907
  init_tmux();
44971
- const execAsync$5 = promisify(exec);
44908
+ const execAsync$4 = promisify(exec);
44972
44909
  function getIssueDataService$1() {
44973
44910
  const { getSharedIssueService } = (init_issue_service_singleton(), __toCommonJS(issue_service_singleton_exports));
44974
44911
  return getSharedIssueService();
@@ -44992,7 +44929,7 @@ const getVersionRoute = HttpRouter.add("GET", "/api/version", Effect.promise(asy
44992
44929
  const version = await getOverdeckVersion();
44993
44930
  let supervisorUrl = null;
44994
44931
  try {
44995
- const { getSupervisorUrlSync } = await import("./supervisor-BY_xA7eS.js");
44932
+ const { getSupervisorUrlSync } = await import("./supervisor-BzxM2EIo.js");
44996
44933
  supervisorUrl = getSupervisorUrlSync();
44997
44934
  } catch {}
44998
44935
  return jsonResponse({
@@ -45156,7 +45093,7 @@ const postShadowMonitorRoute = HttpRouter.add("POST", "/api/shadow/:issueId/moni
45156
45093
  const projectPath = await getProjectPath(issuePrefix);
45157
45094
  const workspacePath = join$1(projectPath, "workspaces", `feature-${issueLower}`);
45158
45095
  if (!existsSync$1(workspacePath)) return jsonResponse({ error: "Workspace not found" }, { status: 404 });
45159
- const { gatherArtifacts, generateBasicInference, updateInferenceDocumentSync } = await import("./shadow-engineering-DMC2pBPa.js");
45096
+ const { gatherArtifacts, generateBasicInference, updateInferenceDocumentSync } = await import("./shadow-engineering-C1DS3IT9.js");
45160
45097
  const config = {
45161
45098
  issueId,
45162
45099
  workspacePath,
@@ -45186,7 +45123,7 @@ const postShadowObserveRoute = HttpRouter.add("POST", "/api/shadow/:issueId/obse
45186
45123
  if (!existsSync$1(workspacePath)) return jsonResponse({ error: "Workspace not found" }, { status: 404 });
45187
45124
  const ghConfig = getGitHubConfig();
45188
45125
  if (!ghConfig) return jsonResponse({ error: "GitHub not configured - Observer requires GitHub" }, { status: 400 });
45189
- const { runObserverCycle } = await import("./shadow-engineering-DMC2pBPa.js");
45126
+ const { runObserverCycle } = await import("./shadow-engineering-C1DS3IT9.js");
45190
45127
  const firstRepo = ghConfig.repos[0];
45191
45128
  const config = {
45192
45129
  issueId,
@@ -45218,7 +45155,7 @@ const postDevRebuildRoute = HttpRouter.add("POST", "/api/dev/rebuild", Effect.ge
45218
45155
  if (!overdeckDevMode || !overdeckProjectRoot) return jsonResponse({ error: "Rebuild only available in dev mode" }, { status: 403 });
45219
45156
  return yield* Effect.promise(async () => {
45220
45157
  try {
45221
- const { stdout, stderr } = await execAsync$5("npm run build", {
45158
+ const { stdout, stderr } = await execAsync$4("npm run build", {
45222
45159
  cwd: overdeckProjectRoot,
45223
45160
  timeout: 12e4
45224
45161
  });
@@ -46251,7 +46188,7 @@ async function cleanupConversationAttachments(name) {
46251
46188
  * sessions that the lifecycle poller missed. */
46252
46189
  async function cleanupOrphanedConversationAttachments() {
46253
46190
  try {
46254
- const { listConversations } = await import("./conversations-DSOZG_Sz.js");
46191
+ const { listConversations } = await import("./conversations-CucKmkR7.js");
46255
46192
  const convNames = new Set(listConversations().map((c) => c.name));
46256
46193
  const root = getConversationAttachmentsRoot();
46257
46194
  await runInBatches((await readdir(root, { withFileTypes: true })).filter((entry) => entry.isDirectory() && !convNames.has(entry.name)).map((entry) => join$1(root, entry.name)), 10, (path) => rm(path, {
@@ -46730,7 +46667,7 @@ init_layers();
46730
46667
  init_briefing_freshness();
46731
46668
  init_paths();
46732
46669
  init_event_store();
46733
- const execAsync$4 = promisify(exec);
46670
+ const execAsync$3 = promisify(exec);
46734
46671
  const execFileAsync$2 = promisify(execFile);
46735
46672
  const PROCESS_CLEANUP_GRACE_MS = 750;
46736
46673
  const PTY_SUPERVISOR_SOCKET_WAIT_MS = 3e4;
@@ -46838,7 +46775,7 @@ async function resolveAllowedHarness(requested, model) {
46838
46775
  }
46839
46776
  async function isInsideGitWorkTree(dir) {
46840
46777
  try {
46841
- const { stdout } = await execAsync$4("git rev-parse --is-inside-work-tree", {
46778
+ const { stdout } = await execAsync$3("git rev-parse --is-inside-work-tree", {
46842
46779
  cwd: dir,
46843
46780
  encoding: "utf-8"
46844
46781
  });
@@ -46871,9 +46808,9 @@ async function waitForClaudeReady(tmuxSession) {
46871
46808
  console.warn(`[conversations] Timed out waiting for Claude Code prompt in ${tmuxSession}`);
46872
46809
  }
46873
46810
  function isPiTuiInputReady(snapshot) {
46874
- return /^\s*[❯›>]\s/m.test(snapshot) || /(?:^|\s)0(?:\.\d+)?%\s+context\s+used\b/i.test(snapshot);
46811
+ return /^\s*[❯›>]\s/m.test(snapshot) || /(?:^|\s)0(?:\.\d+)?%\s+context\s+used\b/i.test(snapshot) || /⬢[^\n]*◕/.test(snapshot);
46875
46812
  }
46876
- async function waitForPiTuiReady(tmuxSession, timeoutMs = 3e4) {
46813
+ async function waitForPiTuiReady(tmuxSession, timeoutMs = 6e4) {
46877
46814
  const deadline = Date.now() + timeoutMs;
46878
46815
  while (Date.now() < deadline) {
46879
46816
  if (isPiTuiInputReady(await Effect.runPromise(capturePane(tmuxSession, 40).pipe(Effect.catch(() => Effect.succeed("")))))) {
@@ -46915,8 +46852,9 @@ function shouldUseSupervisorForConversation(harness) {
46915
46852
  }
46916
46853
  async function waitForConversationRuntimeReady(tmuxSession, harness, mode) {
46917
46854
  const transcriptKind = getHarnessBehavior(harness).transcriptKind;
46918
- if (transcriptKind === "ohmypi-jsonl") await waitForPiTuiReady(tmuxSession);
46919
- else if (transcriptKind !== "codex-rollout-jsonl" && mode === "spawn") {
46855
+ if (transcriptKind === "ohmypi-jsonl") {
46856
+ if (!await waitForPiTuiReady(tmuxSession)) throw new Error(`Pi (ohmypi) did not become interactive in ${tmuxSession} within the startup window — MCP server connections are likely still in progress. Retry once MCP servers finish connecting, or check ~/.claude/mcp.json for a slow/hanging server.`);
46857
+ } else if (transcriptKind !== "codex-rollout-jsonl" && mode === "spawn") {
46920
46858
  await waitForClaudeReady(tmuxSession);
46921
46859
  console.log(`[conversations] Claude ready in ${tmuxSession}`);
46922
46860
  } else if (transcriptKind !== "codex-rollout-jsonl") await waitForReadySignal(tmuxSession, 30);
@@ -47119,7 +47057,7 @@ async function spawnConversationSession(tmuxSession, cwd, claudeSessionId, model
47119
47057
  const codexApprovalPolicy = codexPermMode === "full-access" ? "never" : "on-request";
47120
47058
  const codexSandboxMode = codexPermMode === "full-access" ? "danger-full-access" : codexPermMode === "read-only" ? "read-only" : "workspace-write";
47121
47059
  const codexApprovalsReviewer = codexPermMode === "auto-review" ? "auto_review" : void 0;
47122
- const { initCodexHome, extractThreadIdFromRollout } = await import("./codex-BObh4thD.js");
47060
+ const { initCodexHome, extractThreadIdFromRollout } = await import("./codex-DG2Dyp0K.js");
47123
47061
  initCodexHome(codexHome, {
47124
47062
  trustedDir: cwd,
47125
47063
  approvalPolicy: codexApprovalPolicy,
@@ -47189,7 +47127,7 @@ async function spawnConversationSession(tmuxSession, cwd, claudeSessionId, model
47189
47127
  } catch {}
47190
47128
  console.log(`[claude-invoke] purpose=conversation-session | model=${model || "default"} | source=conversations.ts:spawnConversationSession | session=${tmuxSession} | resume=${resume} | command="${runtimeCommand}"`);
47191
47129
  try {
47192
- const { preTrustDirectory } = await import("./workspace-manager-BE2H8gD5.js");
47130
+ const { preTrustDirectory } = await import("./workspace-manager-uVfFRWJG.js");
47193
47131
  preTrustDirectory(cwd);
47194
47132
  } catch {}
47195
47133
  try {
@@ -47206,7 +47144,7 @@ async function spawnConversationSession(tmuxSession, cwd, claudeSessionId, model
47206
47144
  const codexHomeDir = codexFields.codexHome;
47207
47145
  (async () => {
47208
47146
  try {
47209
- const { waitForCodexRollout, extractThreadIdFromRollout, writeThreadId } = await import("./codex-BObh4thD.js");
47147
+ const { waitForCodexRollout, extractThreadIdFromRollout, writeThreadId } = await import("./codex-DG2Dyp0K.js");
47210
47148
  const rollout = await waitForCodexRollout(codexHomeDir, 12e4);
47211
47149
  if (rollout) {
47212
47150
  const threadId = extractThreadIdFromRollout(rollout);
@@ -47837,9 +47775,21 @@ function sanitizeTitle(raw) {
47837
47775
  */
47838
47776
  function fallbackTranscriptTitle(transcript) {
47839
47777
  const lines = transcript.split(/\r?\n/).map((line) => line.trim()).filter((line) => line && !line.startsWith("[…"));
47840
- const compact = (lines.filter((line) => line.startsWith("User:")).map((line) => line.slice(5).trim()).filter(Boolean).at(-1) ?? lines[0]?.replace(/^(User|Assistant):\s*/i, "").trim() ?? "").replace(/```[\s\S]*?```/g, " ").replace(/`([^`]+)`/g, "$1").replace(/\b(?:please|can you|could you|would you)\b/gi, " ").replace(/\b(?:i need you to|i want you to|help me|let's|lets)\b/gi, " ").replace(/https?:\/\/\S+/gi, " ").replace(/[^\p{L}\p{N}#/_+.-]+/gu, " ").replace(/\s+/g, " ").trim();
47841
- if (!compact) return "";
47842
- return sanitizeTitle(compact.split(/\s+/).slice(0, 8).join(" ").replace(/\s+(?:and|or|to|for|with)$/i, "").replace(/[.,:;!?]+$/g, ""));
47778
+ return derivePromptTitle(lines.filter((line) => line.startsWith("User:")).map((line) => line.slice(5).trim()).filter(Boolean).at(-1) ?? lines[0]?.replace(/^(User|Assistant):\s*/i, "").trim() ?? "");
47779
+ }
47780
+ /**
47781
+ * Generate a deterministic title directly from a raw prompt string.
47782
+ * Zero model calls; returns '' only for empty/whitespace-only input.
47783
+ */
47784
+ function derivePromptTitle(prompt) {
47785
+ const trimmed = prompt.trim();
47786
+ if (!trimmed) return "";
47787
+ const compact = trimmed.replace(/```[\s\S]*?```/g, " ").replace(/`([^`]+)`/g, "$1").replace(/\b(?:please|can you|could you|would you)\b/gi, " ").replace(/\b(?:i need you to|i want you to|help me|let's|lets)\b/gi, " ").replace(/https?:\/\/\S+/gi, " ").replace(/[^\p{L}\p{N}#/_+.-]+/gu, " ").replace(/\s+/g, " ").trim();
47788
+ const MAX_TITLE_LEN = 60;
47789
+ if (!compact) return trimmed.slice(0, MAX_TITLE_LEN) + (trimmed.length > MAX_TITLE_LEN ? "…" : "");
47790
+ const sanitized = sanitizeTitle(compact.split(/\s+/).slice(0, 8).join(" ").replace(/\s+(?:and|or|to|for|with)$/i, "").replace(/[.,:;!?]+$/g, ""));
47791
+ if (sanitized.length <= MAX_TITLE_LEN) return sanitized;
47792
+ return sanitized.slice(0, MAX_TITLE_LEN) + "…";
47843
47793
  }
47844
47794
  /**
47845
47795
  * Keep title-generation prompts small and latency-bounded. The serialized
@@ -48488,86 +48438,6 @@ async function generateAiTitle(conversationName, firstMessage, deps) {
48488
48438
  }
48489
48439
  updateConversationTitle(conversationName, sanitized, "ai");
48490
48440
  console.log(`[claude-invoke] SUCCESS purpose=conversation-title | model=${CONVERSATION_TITLE_MODEL} | conversation=${conversationName} | outputChars=${sanitized.length}`);
48491
- scheduleTitleRefinement(conversationName, deps);
48492
- }
48493
- const refinementScheduled = /* @__PURE__ */ new Set();
48494
- function scheduleTitleRefinement(conversationName, deps) {
48495
- if (!isBackgroundFeatureEnabled("titleRefinement")) return;
48496
- if (refinementScheduled.has(conversationName)) return;
48497
- refinementScheduled.add(conversationName);
48498
- const TIMEOUT_MS = 600 * 1e3;
48499
- const POLL_INTERVAL_MS = 1500;
48500
- const startedAt = Date.now();
48501
- let timer = null;
48502
- let running = false;
48503
- let done = false;
48504
- const stop = () => {
48505
- done = true;
48506
- if (timer) clearTimeout(timer);
48507
- refinementScheduled.delete(conversationName);
48508
- };
48509
- async function tick() {
48510
- if (done) return;
48511
- if (running) {
48512
- timer = setTimeout(tick, POLL_INTERVAL_MS);
48513
- return;
48514
- }
48515
- running = true;
48516
- try {
48517
- if (Date.now() - startedAt > TIMEOUT_MS) {
48518
- console.log(`[title-refine] Timed out waiting for first assistant response in "${conversationName}"`);
48519
- stop();
48520
- return;
48521
- }
48522
- const conv = getConversationByName(conversationName);
48523
- if (!conv) {
48524
- stop();
48525
- return;
48526
- }
48527
- if (conv.titleSource !== "ai") {
48528
- stop();
48529
- return;
48530
- }
48531
- const sessionFile = await deps.resolveSessionFile(conv);
48532
- if (!sessionFile || !existsSync$1(sessionFile)) {
48533
- timer = setTimeout(tick, POLL_INTERVAL_MS);
48534
- return;
48535
- }
48536
- const { messages } = await getCachedMessages(sessionFile, false);
48537
- if (!messages.find((m) => m.role === "assistant" && m.completedAt)) {
48538
- timer = setTimeout(tick, POLL_INTERVAL_MS);
48539
- return;
48540
- }
48541
- const transcript = serializeConversationTranscript(messages);
48542
- if (!transcript.trim()) {
48543
- timer = setTimeout(tick, POLL_INTERVAL_MS);
48544
- return;
48545
- }
48546
- console.log(`[claude-invoke] purpose=conversation-title-refine | model=${CONVERSATION_TITLE_MODEL} | conversation=${conversationName} | transcriptChars=${transcript.length}`);
48547
- const refined = await summarizeTranscriptTitle(transcript, configuredTitleModel());
48548
- if (!refined) {
48549
- console.warn(`[title-refine] Model returned empty refined title for "${conversationName}"`);
48550
- stop();
48551
- return;
48552
- }
48553
- const freshConv = getConversationByName(conversationName);
48554
- if (!freshConv || freshConv.titleSource !== "ai") {
48555
- console.log(`[title-refine] Conversation "${conversationName}" no longer eligible (source=${freshConv?.titleSource ?? "missing"}); skipping`);
48556
- stop();
48557
- return;
48558
- }
48559
- updateConversationTitle(conversationName, refined, "ai-refined");
48560
- console.log(`[claude-invoke] SUCCESS purpose=conversation-title-refine | conversation=${conversationName} | title="${refined}"`);
48561
- stop();
48562
- } catch (err) {
48563
- const msg = err instanceof Error ? err.message : String(err);
48564
- console.error(`[title-refine] failed for "${conversationName}":`, msg);
48565
- stop();
48566
- } finally {
48567
- running = false;
48568
- }
48569
- }
48570
- timer = setTimeout(tick, POLL_INTERVAL_MS);
48571
48441
  }
48572
48442
  const MAX_TITLE_LENGTH = 200;
48573
48443
  function patchConversationTitle(name, body) {
@@ -48619,7 +48489,7 @@ async function retitleConversation(name, deps) {
48619
48489
  console.warn(`[conversations] retitle timed out for "${name}"; using deterministic fallback title "${title}"`);
48620
48490
  }
48621
48491
  if (!title) return result({ error: "Title model returned an empty result" }, 502);
48622
- updateConversationTitle(name, title, "ai");
48492
+ updateConversationTitle(name, title, "ai-explicit");
48623
48493
  console.log(`[claude-invoke] SUCCESS purpose=conversation-retitle | conversation=${name} | title="${title}"`);
48624
48494
  return result({ title });
48625
48495
  } finally {
@@ -49073,10 +48943,14 @@ async function handleConversationMessage(name, body, deps = {
49073
48943
  console.error(`[conversations] eaten-message watcher failed for ${conv.name}: ${msg}`);
49074
48944
  });
49075
48945
  }
49076
- if (conv.titleSource === "default") deps.generateAiTitle(name, message).catch((err) => {
49077
- const msg = err instanceof Error ? err.message : String(err);
49078
- console.error(`[TITLE-GEN-FAILED] AI title generation FAILED for "${name}" — NO RETRY, NO FALLBACK:`, msg);
49079
- });
48946
+ if (conv.titleSource === "default") {
48947
+ const derivedTitle = derivePromptTitle(message);
48948
+ if (derivedTitle) updateConversationTitle(name, derivedTitle, "auto");
48949
+ deps.generateAiTitle(name, message).catch((err) => {
48950
+ const msg = err instanceof Error ? err.message : String(err);
48951
+ console.error(`[TITLE-GEN-FAILED] AI title generation FAILED for "${name}" — NO RETRY, NO FALLBACK:`, msg);
48952
+ });
48953
+ }
49080
48954
  return jsonResponse({
49081
48955
  ok: true,
49082
48956
  ...droppedImageCount > 0 ? { imagesDropped: droppedImageCount } : {}
@@ -50192,7 +50066,6 @@ const eventsRouteLayer = Layer.mergeAll(getEventStreamRoute, getEventVersionRout
50192
50066
  * GET /api/show/:issueId/shadow — shadow state details
50193
50067
  * GET /api/show/:issueId/health — health + heartbeat only
50194
50068
  */
50195
- init_shadow_state();
50196
50069
  const getShowRoute = HttpRouter.add("GET", "/api/show/:issueId", httpHandler(Effect.gen(function* () {
50197
50070
  const issueId = (yield* HttpRouter.params)["issueId"] ?? "";
50198
50071
  const shadowState = yield* getShadowState(issueId);
@@ -50290,7 +50163,7 @@ async function registerProjectFromPath(opts) {
50290
50163
  registerProjectSync(key, projectConfig);
50291
50164
  const seededContextLayer = ensureProjectLayer(fullPath);
50292
50165
  try {
50293
- const { preTrustDirectorySync } = await import("./workspace-manager-BE2H8gD5.js");
50166
+ const { preTrustDirectorySync } = await import("./workspace-manager-uVfFRWJG.js");
50294
50167
  preTrustDirectorySync(fullPath);
50295
50168
  } catch {}
50296
50169
  let hooksInstalled = 0;
@@ -50324,9 +50197,9 @@ init_read_model();
50324
50197
  init_agents$1();
50325
50198
  init_pan_dir();
50326
50199
  init_paths();
50327
- const execAsync$3 = promisify(exec);
50200
+ const execAsync$2 = promisify(exec);
50328
50201
  async function getIssueDataService() {
50329
- const { getSharedIssueService } = await import("./issue-service-singleton-DFei50PX.js");
50202
+ const { getSharedIssueService } = await import("./issue-service-singleton-Cyfvop7U.js");
50330
50203
  return getSharedIssueService();
50331
50204
  }
50332
50205
  /** Returns true if the path exists (any type). */
@@ -50438,13 +50311,15 @@ async function collectSessionTreeNodes(issueId, workspacePath, projectPath, cont
50438
50311
  const agentId = `agent-${issueLower}`;
50439
50312
  const planningAgentId = `planning-${issueLower}`;
50440
50313
  const strikeAgentId = `strike-${issueLower}`;
50314
+ const knowledgeAgentId = `agent-${issueLower}-knowledge`;
50441
50315
  const slotWorkSessionPattern = getSlotWorkSessionPattern(issueLower);
50442
50316
  const sections = [];
50443
50317
  let hasPlanningSection = false;
50444
50318
  const candidateSessionIds = new Set([
50445
50319
  planningAgentId,
50446
50320
  agentId,
50447
- strikeAgentId
50321
+ strikeAgentId,
50322
+ knowledgeAgentId
50448
50323
  ]);
50449
50324
  const agentEntries = await readdir(agentsDir, { withFileTypes: true }).catch(() => []);
50450
50325
  for (const entry of agentEntries) {
@@ -50459,7 +50334,7 @@ async function collectSessionTreeNodes(issueId, workspacePath, projectPath, cont
50459
50334
  try {
50460
50335
  const isPlanning = checkId.startsWith("planning-");
50461
50336
  const isStrike = checkId.startsWith("strike-");
50462
- const sectionType = isPlanning ? "planning" : isStrike ? "strike" : "work";
50337
+ const sectionType = isPlanning ? "planning" : isStrike ? "strike" : state.role === "knowledge" ? "knowledge" : "work";
50463
50338
  if (isPlanning) hasPlanningSection = true;
50464
50339
  const rtState = await Effect.runPromise(getAgentRuntimeState(checkId));
50465
50340
  const presence = await deriveSessionPresence(checkId, rtState, context.tmuxSessionNames);
@@ -50469,7 +50344,7 @@ async function collectSessionTreeNodes(issueId, workspacePath, projectPath, cont
50469
50344
  sections.push({
50470
50345
  type: sectionType,
50471
50346
  sessionId: checkId,
50472
- tmuxSession: sectionType === "work" || sectionType === "planning" || sectionType === "strike" ? checkId : void 0,
50347
+ tmuxSession: sectionType === "work" || sectionType === "planning" || sectionType === "strike" || sectionType === "knowledge" ? checkId : void 0,
50473
50348
  model: state.model || "unknown",
50474
50349
  startedAt: state.startedAt || (/* @__PURE__ */ new Date()).toISOString(),
50475
50350
  endedAt: void 0,
@@ -50823,7 +50698,7 @@ const postProjectsRoute = HttpRouter.add("POST", "/api/projects", httpHandler(Ef
50823
50698
  if ((await readdir(target).catch(() => [])).length > 0) return jsonResponse({ error: `target directory already exists and is non-empty: ${target}` }, { status: 409 });
50824
50699
  }
50825
50700
  await mkdir(target, { recursive: true });
50826
- await execAsync$3("git init", { cwd: target });
50701
+ await execAsync$2("git init", { cwd: target });
50827
50702
  try {
50828
50703
  const result = await registerProjectFromPath({
50829
50704
  path: target,
@@ -51021,7 +50896,7 @@ async function describeSyncTarget(harness, layerKind, projectKey, label, path) {
51021
50896
  async function buildSyncTargets(projects) {
51022
50897
  const targets = [await describeSyncTarget("claude-code", "global", void 0, "Claude Code · global", join$1(CLAUDE_DIR, "CLAUDE.md")), await describeSyncTarget("codex", "global", void 0, "Codex · global (codex-global.md)", codexGlobalContextFile())];
51023
50898
  for (const { key, config } of projects) {
51024
- if (!(await readOptionalFile(projectContextFile(config.path))).exists) continue;
50899
+ if (!(await readOptionalFile(resolveProjectContextFile(config.path))).exists) continue;
51025
50900
  targets.push(await describeSyncTarget("claude-code", "project", key, `${config.name} · CLAUDE.md`, join$1(config.path, "CLAUDE.md")));
51026
50901
  targets.push(await describeSyncTarget("pi", "project", key, `${config.name} · AGENTS.md`, join$1(config.path, "AGENTS.md")));
51027
50902
  }
@@ -51030,11 +50905,11 @@ async function buildSyncTargets(projects) {
51030
50905
  async function buildContextLayerState(projects, overdeckHome = getOverdeckHome()) {
51031
50906
  const catalog = await buildContextCatalog(projects);
51032
50907
  const resolvedLayers = [await layerRecord(globalContextFile(overdeckHome), { kind: "global" })];
51033
- for (const project of catalog.projects) resolvedLayers.push(await layerRecord(projectContextFile(project.config.path), {
50908
+ for (const project of catalog.projects) resolvedLayers.push(await layerRecord(resolveProjectContextFile(project.config.path), {
51034
50909
  kind: "project",
51035
50910
  projectKey: project.key
51036
50911
  }));
51037
- for (const workspace of catalog.workspaces) resolvedLayers.push(await layerRecord(workspaceContextFile(workspace.path), {
50912
+ for (const workspace of catalog.workspaces) resolvedLayers.push(await layerRecord(resolveWorkspaceContextFile(workspace.path), {
51038
50913
  kind: "workspace",
51039
50914
  projectKey: workspace.projectKey,
51040
50915
  workspacePath: workspace.path
@@ -51287,14 +51162,16 @@ const postContextSyncRoute = HttpRouter.add("POST", "/api/context/sync", httpHan
51287
51162
  const contextRouteLayer = Layer.mergeAll(getContextLayersRoute, postContextPreviewRoute, putContextLayerRoute, postContextSyncRoute);
51288
51163
  //#endregion
51289
51164
  //#region routes/admin.ts
51165
+ init_tldr_daemon();
51166
+ init_projects();
51167
+ init_conversations();
51290
51168
  /**
51291
51169
  * Admin route module — plumbing endpoints
51292
51170
  *
51293
51171
  * Implements /api/admin/* endpoints mirroring the `pan admin` CLI namespace:
51294
- * GET /api/admin/tldr/:issueId — TLDR daemon status for a workspace
51172
+ * GET /api/admin/tldr/:issueId — TLDR daemon status for a workspace
51173
+ * POST /api/admin/conversations/backfill-titles — retitle stuck conversations
51295
51174
  */
51296
- init_tldr_daemon();
51297
- init_projects();
51298
51175
  const getAdminTldrRoute = HttpRouter.add("GET", "/api/admin/tldr/:issueId", httpHandler(Effect.gen(function* () {
51299
51176
  const issueId = (yield* HttpRouter.params)["issueId"] ?? "";
51300
51177
  const workspacePath = join$1(resolveProjectFromIssueSync(issueId)?.projectPath ?? process.cwd(), "workspaces", `feature-${issueId.toLowerCase()}`);
@@ -51315,7 +51192,76 @@ const getAdminTldrRoute = HttpRouter.add("GET", "/api/admin/tldr/:issueId", http
51315
51192
  });
51316
51193
  });
51317
51194
  })));
51318
- const adminRouteLayer = Layer.mergeAll(getAdminTldrRoute);
51195
+ async function handleBackfillTitlesBody(body, deps) {
51196
+ const dryRun = body.dryRun === true;
51197
+ const stuck = listConversations().filter((conv) => conv.title === "New conversation" && conv.titleSource === "default");
51198
+ const updated = [];
51199
+ const skipped = [];
51200
+ for (const conv of stuck) try {
51201
+ const sessionFile = await deps.resolveSessionFile(conv);
51202
+ if (!sessionFile) {
51203
+ skipped.push({
51204
+ name: conv.name,
51205
+ reason: "no transcript"
51206
+ });
51207
+ continue;
51208
+ }
51209
+ const { messages } = await deps.getCachedMessages(sessionFile, false);
51210
+ const firstUser = messages.find((m) => m.role === "user" && typeof m.text === "string" && m.text.trim().length > 0);
51211
+ let candidate = "";
51212
+ let reason;
51213
+ if (firstUser) {
51214
+ candidate = derivePromptTitle(firstUser.text);
51215
+ reason = "transcript";
51216
+ }
51217
+ if (!candidate) {
51218
+ candidate = `Untitled — ${new Date(conv.createdAt).toISOString().slice(0, 10)}`;
51219
+ reason = "no transcript";
51220
+ }
51221
+ const fresh = getConversationByName(conv.name);
51222
+ if (!fresh || fresh.title !== "New conversation" || fresh.titleSource !== "default") {
51223
+ skipped.push({
51224
+ name: conv.name,
51225
+ reason: "no longer eligible"
51226
+ });
51227
+ continue;
51228
+ }
51229
+ if (!dryRun) updateConversationTitle(conv.name, candidate, "auto");
51230
+ updated.push({
51231
+ name: conv.name,
51232
+ title: candidate,
51233
+ reason
51234
+ });
51235
+ } catch (err) {
51236
+ const msg = err instanceof Error ? err.message : String(err);
51237
+ skipped.push({
51238
+ name: conv.name,
51239
+ reason: `transcript error: ${msg}`
51240
+ });
51241
+ }
51242
+ return {
51243
+ updated,
51244
+ skipped,
51245
+ dryRun
51246
+ };
51247
+ }
51248
+ const postAdminBackfillTitlesRoute = HttpRouter.add("POST", "/api/admin/conversations/backfill-titles", httpHandler(Effect.gen(function* () {
51249
+ const request = yield* HttpServerRequest.HttpServerRequest;
51250
+ if (!hasDashboardInternalToken(request)) return jsonResponse({ error: "unauthorized" }, { status: 401 });
51251
+ const rawBody = yield* request.text;
51252
+ let body;
51253
+ try {
51254
+ body = JSON.parse(rawBody);
51255
+ } catch {
51256
+ return jsonResponse({ error: "invalid JSON" }, { status: 400 });
51257
+ }
51258
+ const dryRun = body.dryRun === true;
51259
+ return jsonResponse(yield* Effect.promise(() => handleBackfillTitlesBody({ dryRun }, {
51260
+ resolveSessionFile,
51261
+ getCachedMessages
51262
+ })));
51263
+ })));
51264
+ const adminRouteLayer = Layer.mergeAll(getAdminTldrRoute, postAdminBackfillTitlesRoute);
51319
51265
  //#endregion
51320
51266
  //#region ../../lib/prereqs/registry.ts
51321
51267
  /**
@@ -51324,7 +51270,7 @@ const adminRouteLayer = Layer.mergeAll(getAdminTldrRoute);
51324
51270
  * requiring a heavy `pan install` step before first use.
51325
51271
  */
51326
51272
  init_platform();
51327
- const execAsync$2 = promisify(exec);
51273
+ const execAsync$1 = promisify(exec);
51328
51274
  const PREREQ_REGISTRY = {
51329
51275
  addGitHubProject: ["gh"],
51330
51276
  addGitLabProject: ["glab"],
@@ -51384,8 +51330,8 @@ async function installTool(tool) {
51384
51330
  }
51385
51331
  }
51386
51332
  async function installTmux() {
51387
- if (await Effect.runPromise(detectPlatform()) === "darwin") await execAsync$2("brew install tmux", { timeout: 12e4 });
51388
- else await execAsync$2("sudo apt-get update && sudo apt-get install -y tmux", { timeout: 12e4 });
51333
+ if (await Effect.runPromise(detectPlatform()) === "darwin") await execAsync$1("brew install tmux", { timeout: 12e4 });
51334
+ else await execAsync$1("sudo apt-get update && sudo apt-get install -y tmux", { timeout: 12e4 });
51389
51335
  return {
51390
51336
  tool: "tmux",
51391
51337
  success: true,
@@ -51398,14 +51344,14 @@ async function installTtyd() {
51398
51344
  mkdirSync$1(binDir, { recursive: true });
51399
51345
  const ttydPath = join$1(binDir, "ttyd");
51400
51346
  if (plat === "darwin") try {
51401
- await execAsync$2("brew install ttyd", { timeout: 12e4 });
51347
+ await execAsync$1("brew install ttyd", { timeout: 12e4 });
51402
51348
  return {
51403
51349
  tool: "ttyd",
51404
51350
  success: true,
51405
51351
  message: "ttyd installed via Homebrew"
51406
51352
  };
51407
51353
  } catch {}
51408
- await execAsync$2(`curl -sL "https://github.com/tsl0922/ttyd/releases/latest/download/ttyd.x86_64" -o "${ttydPath}" && chmod +x "${ttydPath}"`, { timeout: 6e4 });
51354
+ await execAsync$1(`curl -sL "https://github.com/tsl0922/ttyd/releases/latest/download/ttyd.x86_64" -o "${ttydPath}" && chmod +x "${ttydPath}"`, { timeout: 6e4 });
51409
51355
  return {
51410
51356
  tool: "ttyd",
51411
51357
  success: true,
@@ -51414,8 +51360,8 @@ async function installTtyd() {
51414
51360
  }
51415
51361
  async function installMkcert() {
51416
51362
  if (await Effect.runPromise(detectPlatform()) === "darwin") {
51417
- await execAsync$2("brew install mkcert", { timeout: 12e4 });
51418
- await execAsync$2("mkcert -install", { timeout: 3e4 });
51363
+ await execAsync$1("brew install mkcert", { timeout: 12e4 });
51364
+ await execAsync$1("mkcert -install", { timeout: 3e4 });
51419
51365
  return {
51420
51366
  tool: "mkcert",
51421
51367
  success: true,
@@ -51425,8 +51371,8 @@ async function installMkcert() {
51425
51371
  const binDir = join$1(homedir$1(), ".local", "bin");
51426
51372
  mkdirSync$1(binDir, { recursive: true });
51427
51373
  const mkcertPath = join$1(binDir, "mkcert");
51428
- await execAsync$2(`curl -sL "https://github.com/FiloSottile/mkcert/releases/latest/download/mkcert-v1.4.4-linux-${process.arch === "x64" ? "amd64" : process.arch}" -o "${mkcertPath}" && chmod +x "${mkcertPath}"`, { timeout: 6e4 });
51429
- await execAsync$2("mkcert -install", { timeout: 3e4 });
51374
+ await execAsync$1(`curl -sL "https://github.com/FiloSottile/mkcert/releases/latest/download/mkcert-v1.4.4-linux-${process.arch === "x64" ? "amd64" : process.arch}" -o "${mkcertPath}" && chmod +x "${mkcertPath}"`, { timeout: 6e4 });
51375
+ await execAsync$1("mkcert -install", { timeout: 3e4 });
51430
51376
  return {
51431
51377
  tool: "mkcert",
51432
51378
  success: true,
@@ -51435,14 +51381,14 @@ async function installMkcert() {
51435
51381
  }
51436
51382
  async function installBeads() {
51437
51383
  if (await Effect.runPromise(detectPlatform()) === "darwin") try {
51438
- await execAsync$2("brew install gastownhall/beads/bd", { timeout: 12e4 });
51384
+ await execAsync$1("brew install gastownhall/beads/bd", { timeout: 12e4 });
51439
51385
  return {
51440
51386
  tool: "bd",
51441
51387
  success: true,
51442
51388
  message: "beads installed via Homebrew"
51443
51389
  };
51444
51390
  } catch {}
51445
- await execAsync$2("curl -sSL https://raw.githubusercontent.com/gastownhall/beads/main/scripts/install.sh | bash", { timeout: 12e4 });
51391
+ await execAsync$1("curl -sSL https://raw.githubusercontent.com/gastownhall/beads/main/scripts/install.sh | bash", { timeout: 12e4 });
51446
51392
  return {
51447
51393
  tool: "bd",
51448
51394
  success: true,
@@ -51456,7 +51402,7 @@ async function installOx() {
51456
51402
  const binDir = join$1(homedir$1(), ".local", "bin");
51457
51403
  const oxPath = join$1(binDir, "ox");
51458
51404
  mkdirSync$1(binDir, { recursive: true });
51459
- await execAsync$2(`curl -sL "https://github.com/eltmon/ox/releases/download/latest/ox-${platform}-${arch}" -o "${oxPath}" && chmod +x "${oxPath}"`, { timeout: 6e4 });
51405
+ await execAsync$1(`curl -sL "https://github.com/eltmon/ox/releases/download/latest/ox-${platform}-${arch}" -o "${oxPath}" && chmod +x "${oxPath}"`, { timeout: 6e4 });
51460
51406
  return {
51461
51407
  tool: "ox",
51462
51408
  success: true,
@@ -52253,7 +52199,7 @@ async function refreshMergeStateFromGitHub(issueId, repo, prNumber) {
52253
52199
  let mergeState;
52254
52200
  let isDraft;
52255
52201
  let checksFailed;
52256
- const { isGitHubAppConfigured, getPullRequestState } = await import("./github-app-Dg25z05Z.js");
52202
+ const { isGitHubAppConfigured, getPullRequestState } = await import("./github-app-BFaGREfW.js");
52257
52203
  if (isGitHubAppConfigured()) {
52258
52204
  const prState = await Effect.runPromise(getPullRequestState(owner, repoName, prNumber));
52259
52205
  mergeable = prState.mergeable === null ? "UNKNOWN" : prState.mergeable ? "MERGEABLE" : "CONFLICTING";
@@ -52402,8 +52348,8 @@ async function handlePullRequestPromise(payload) {
52402
52348
  bumpIssuePrTabCacheGeneration(issueId);
52403
52349
  const repo = payload.repository.full_name;
52404
52350
  if (payload.action === "closed" && pr.merged === true) try {
52405
- const { postMergeLifecycle } = await import("./merge-agent-DZaRBHQA.js");
52406
- const { resolveProjectFromIssueSync } = await import("./projects-BbMEBykK.js");
52351
+ const { postMergeLifecycle } = await import("./merge-agent-DzbCbjqg.js");
52352
+ const { resolveProjectFromIssueSync } = await import("./projects-Daw2zpGk.js");
52407
52353
  const project = resolveProjectFromIssueSync(issueId);
52408
52354
  if (project) {
52409
52355
  const branchName = pr.head.ref;
@@ -52820,9 +52766,75 @@ const webhooksRouteLayer = HttpRouter.add("POST", "/api/webhooks/github", httpHa
52820
52766
  return yield* runWebhookHandler(body, headers);
52821
52767
  })));
52822
52768
  //#endregion
52769
+ //#region ../../lib/overdeck/title-refinement.ts
52770
+ init_paths$2();
52771
+ /**
52772
+ * Hook-driven progressive conversation title refinement.
52773
+ *
52774
+ * Replaces the old polling-based refinement scheduler with an event-driven
52775
+ * turn-complete handler. First refinement happens as soon as a completed
52776
+ * assistant message is available; later refinements are debounced by turn count
52777
+ * and wall-clock interval.
52778
+ */
52779
+ init_features();
52780
+ init_conversations();
52781
+ const LATER_REFINE_MIN_TURNS = 5;
52782
+ const LATER_REFINE_MIN_INTERVAL_MS = 600 * 1e3;
52783
+ const cadenceByConversation = /* @__PURE__ */ new Map();
52784
+ const inFlight$1 = /* @__PURE__ */ new Set();
52785
+ async function handleTurnComplete(conv, deps) {
52786
+ if (!(deps.isBackgroundFeatureEnabled ?? isBackgroundFeatureEnabled)("titleRefinement")) return;
52787
+ if (!canRefineTitle(conv)) return;
52788
+ const name = conv.name;
52789
+ let cadence = cadenceByConversation.get(name);
52790
+ if (!cadence) {
52791
+ cadence = {
52792
+ turnsSinceRefine: 0,
52793
+ lastRefinedAtMs: conv.titleSource === "ai-refined" ? Date.now() : 0
52794
+ };
52795
+ cadenceByConversation.set(name, cadence);
52796
+ }
52797
+ cadence.turnsSinceRefine += 1;
52798
+ if (!(conv.titleSource === "default" || conv.titleSource === "auto" || conv.titleSource === "ai")) {
52799
+ if (!(cadence.turnsSinceRefine >= LATER_REFINE_MIN_TURNS && Date.now() - cadence.lastRefinedAtMs >= LATER_REFINE_MIN_INTERVAL_MS)) return;
52800
+ }
52801
+ if (inFlight$1.has(name)) return;
52802
+ inFlight$1.add(name);
52803
+ const getCachedMessages$1 = deps.getCachedMessages ?? getCachedMessages;
52804
+ const configuredTitleModel$1 = deps.configuredTitleModel ?? configuredTitleModel;
52805
+ const summarizeTranscriptTitle$1 = deps.summarizeTranscriptTitle ?? summarizeTranscriptTitle;
52806
+ try {
52807
+ const sessionFile = await deps.resolveSessionFile(conv);
52808
+ if (!sessionFile || !existsSync$1(sessionFile)) return;
52809
+ const { messages } = await getCachedMessages$1(sessionFile, false);
52810
+ if (!messages.find((m) => m.role === "assistant" && m.completedAt)) return;
52811
+ const transcript = serializeConversationTranscript(messages);
52812
+ if (!transcript.trim()) return;
52813
+ console.log(`[claude-invoke] purpose=conversation-title-refine | model=${configuredTitleModel$1()} | conversation=${name} | transcriptChars=${transcript.length}`);
52814
+ const refined = await summarizeTranscriptTitle$1(transcript, configuredTitleModel$1());
52815
+ if (!refined) {
52816
+ console.warn(`[title-refine] Model returned empty refined title for "${name}"`);
52817
+ return;
52818
+ }
52819
+ const freshConv = getConversationByName(name);
52820
+ if (!freshConv || !canRefineTitle(freshConv)) {
52821
+ console.log(`[title-refine] Conversation "${name}" no longer eligible (source=${freshConv?.titleSource ?? "missing"}); skipping`);
52822
+ return;
52823
+ }
52824
+ updateConversationTitle(name, refined, "ai-refined");
52825
+ console.log(`[claude-invoke] SUCCESS purpose=conversation-title-refine | conversation=${name} | title="${refined}"`);
52826
+ cadence.turnsSinceRefine = 0;
52827
+ cadence.lastRefinedAtMs = Date.now();
52828
+ } catch (err) {
52829
+ const msg = err instanceof Error ? err.message : String(err);
52830
+ console.error(`[title-refine] failed for "${name}":`, msg);
52831
+ } finally {
52832
+ inFlight$1.delete(name);
52833
+ }
52834
+ }
52835
+ //#endregion
52823
52836
  //#region ../../lib/compliance/advisory-warning.ts
52824
52837
  init_config_yaml();
52825
- init_paths$2();
52826
52838
  init_rollup();
52827
52839
  const COMPLIANCE_ADVISORY_WARNING = "Last turn included a memory-first trigger but the search wasn't called. Try pan memory search first next time.";
52828
52840
  async function resolveComplianceAdvisoryWarning(input) {
@@ -52902,7 +52914,7 @@ function getCheckpointWorker() {
52902
52914
  return worker;
52903
52915
  }
52904
52916
  async function runInline(operation, payload) {
52905
- const { claimTranscriptRange, commitTranscriptRange, releaseTranscriptRange, getTranscriptCheckpoint, listTranscriptCheckpoints } = await import("./checkpoints-auGbx5b0.js");
52917
+ const { claimTranscriptRange, commitTranscriptRange, releaseTranscriptRange, getTranscriptCheckpoint, listTranscriptCheckpoints } = await import("./checkpoints-DjIvtcNL.js");
52906
52918
  switch (operation) {
52907
52919
  case "claimTranscriptRange": return claimTranscriptRange(payload);
52908
52920
  case "commitTranscriptRange": return commitTranscriptRange(payload);
@@ -54056,7 +54068,7 @@ function buildPendingTurn(input, fromOffset, toOffset, compressed) {
54056
54068
  };
54057
54069
  }
54058
54070
  async function emitMemoryObservationCreated(observation, timestamp) {
54059
- const { initEventStore } = await import("./event-store-D7_dSgP8.js");
54071
+ const { initEventStore } = await import("./event-store-w76YFiCU.js");
54060
54072
  await (await initEventStore()).appendAsync({
54061
54073
  type: "memory.observation_created",
54062
54074
  timestamp,
@@ -54819,7 +54831,65 @@ const postPermissionEventRoute = HttpRouter.add("POST", "/api/hooks/permission-e
54819
54831
  waiting
54820
54832
  });
54821
54833
  })));
54822
- const hooksRouteLayer = Layer.mergeAll(postMemoryInjectRoute, postMemorySessionStartRoute, postMemoryTurnRoute, postPermissionEventRoute);
54834
+ async function handleUserPromptSubmitBody(body, options = {}) {
54835
+ const sessionId = typeof body.session_id === "string" ? body.session_id : null;
54836
+ const prompt = typeof body.prompt === "string" ? body.prompt : "";
54837
+ if (!sessionId) return { ok: true };
54838
+ const conv = getConversationByClaudeSessionId(sessionId);
54839
+ if (!conv) return { ok: true };
54840
+ if (conv.titleSource === "default") {
54841
+ const derivedTitle = derivePromptTitle(prompt);
54842
+ if (derivedTitle) updateConversationTitle(conv.name, derivedTitle, "auto");
54843
+ (options.generateAiTitle ?? generateAiTitle)(conv.name, prompt, { resolveSessionFile: options.resolveSessionFile ?? resolveSessionFile }).catch((err) => {
54844
+ const msg = err instanceof Error ? err.message : String(err);
54845
+ console.error(`[hooks/user-prompt-submit] AI title generation failed for "${conv.name}":`, msg);
54846
+ });
54847
+ }
54848
+ return {
54849
+ ok: true,
54850
+ conversationName: conv.name,
54851
+ updated: conv.titleSource === "default"
54852
+ };
54853
+ }
54854
+ const postUserPromptSubmitRoute = HttpRouter.add("POST", "/api/hooks/user-prompt-submit", httpHandler(Effect.gen(function* () {
54855
+ const request = yield* HttpServerRequest.HttpServerRequest;
54856
+ if (!hasDashboardInternalToken(request)) return jsonResponse({ error: "unauthorized" }, { status: 401 });
54857
+ const rawBody = yield* request.text;
54858
+ let body;
54859
+ try {
54860
+ body = JSON.parse(rawBody);
54861
+ } catch {
54862
+ return jsonResponse({ error: "invalid JSON" }, { status: 400 });
54863
+ }
54864
+ return jsonResponse(yield* Effect.promise(() => handleUserPromptSubmitBody(body)));
54865
+ })));
54866
+ async function handleTurnCompleteBody(body, options = {}) {
54867
+ const sessionId = typeof body.session_id === "string" ? body.session_id : null;
54868
+ if (!sessionId) return { ok: true };
54869
+ const conv = getConversationByClaudeSessionId(sessionId);
54870
+ if (!conv) return { ok: true };
54871
+ (options.handleTurnComplete ?? handleTurnComplete)(conv, { resolveSessionFile }).catch((err) => {
54872
+ const msg = err instanceof Error ? err.message : String(err);
54873
+ console.error(`[hooks/turn-complete] title refinement failed for "${conv.name}":`, msg);
54874
+ });
54875
+ return {
54876
+ ok: true,
54877
+ conversationName: conv.name
54878
+ };
54879
+ }
54880
+ const postTurnCompleteRoute = HttpRouter.add("POST", "/api/hooks/turn-complete", httpHandler(Effect.gen(function* () {
54881
+ const request = yield* HttpServerRequest.HttpServerRequest;
54882
+ if (!hasDashboardInternalToken(request)) return jsonResponse({ error: "unauthorized" }, { status: 401 });
54883
+ const rawBody = yield* request.text;
54884
+ let body;
54885
+ try {
54886
+ body = JSON.parse(rawBody);
54887
+ } catch {
54888
+ return jsonResponse({ error: "invalid JSON" }, { status: 400 });
54889
+ }
54890
+ return jsonResponse(yield* Effect.promise(() => handleTurnCompleteBody(body)));
54891
+ })));
54892
+ const hooksRouteLayer = Layer.mergeAll(postMemoryInjectRoute, postMemorySessionStartRoute, postMemoryTurnRoute, postPermissionEventRoute, postUserPromptSubmitRoute, postTurnCompleteRoute);
54823
54893
  function parseMemoryIdentity(value, sessionId) {
54824
54894
  if (!value || typeof value !== "object" || Array.isArray(value)) return null;
54825
54895
  const identity = value;
@@ -57095,7 +57165,7 @@ async function getFlywheelConversationPayload() {
57095
57165
  };
57096
57166
  }
57097
57167
  async function postFlywheelReportPayload() {
57098
- const { flywheelReportCommand } = await import("./flywheel-CFPOlOUd.js");
57168
+ const { flywheelReportCommand } = await import("./flywheel-DrNtUqWK.js");
57099
57169
  await flywheelReportCommand({ cwd: process.cwd() });
57100
57170
  return {
57101
57171
  status: 200,
@@ -57253,11 +57323,11 @@ const getMergeBlockersRoute = HttpRouter.add("GET", "/api/flywheel/merge-blocker
57253
57323
  async function defaultGetOrderedIssueIds() {
57254
57324
  const status = await readCurrentFlywheelStatusForDashboard();
57255
57325
  if (!status) return [];
57256
- const { computeMergeQueue } = await import("./flywheel-merge-order-FN6zqVXG.js");
57326
+ const { computeMergeQueue } = await import("./flywheel-merge-order-CrZrhwbK.js");
57257
57327
  return (await Effect.runPromise(computeMergeQueue(status.activePipeline, process.cwd()).pipe(Effect.provide(layer)))).map((i) => i.issueId);
57258
57328
  }
57259
57329
  async function defaultMergeOne(issueId) {
57260
- const { triggerMerge } = await import("./merge-ops-DRRd3YBA.js");
57330
+ const { triggerMerge } = await import("./merge-ops-CgzhHkd4.js");
57261
57331
  const r = await triggerMerge(issueId);
57262
57332
  return r.success ? { ok: true } : {
57263
57333
  ok: false,
@@ -57277,7 +57347,7 @@ async function postFlywheelMergeNextPayload(payload, deps = {}) {
57277
57347
  body: { error: "n must be a positive integer" }
57278
57348
  };
57279
57349
  const issueIds = (await (deps.getOrderedIssueIds ?? defaultGetOrderedIssueIds)()).slice(0, n);
57280
- const { shipMergeBatch } = await import("./merge-batch-BbG78hx-.js");
57350
+ const { shipMergeBatch } = await import("./merge-batch-LLp_cXUR.js");
57281
57351
  return {
57282
57352
  status: 200,
57283
57353
  body: { outcomes: await shipMergeBatch(issueIds, { merge: deps.merge ?? defaultMergeOne }) }
@@ -57434,7 +57504,7 @@ const getFlywheelMergeQueueRoute = HttpRouter.add("GET", "/api/flywheel/merge-qu
57434
57504
  return yield* Effect.promise(async () => {
57435
57505
  const status = await readCurrentFlywheelStatusForDashboard();
57436
57506
  if (!status) return jsonResponse([]);
57437
- const { computeMergeQueue, resolveMergeQueuePrUrl } = await import("./flywheel-merge-order-FN6zqVXG.js");
57507
+ const { computeMergeQueue, resolveMergeQueuePrUrl } = await import("./flywheel-merge-order-CrZrhwbK.js");
57438
57508
  return jsonResponse(await Effect.runPromise(computeMergeQueue(status.activePipeline, process.cwd(), { getPrUrl: resolveMergeQueuePrUrl }).pipe(Effect.provide(layer))));
57439
57509
  });
57440
57510
  })));
@@ -57448,18 +57518,18 @@ function uatGenerationNameFromParam(param) {
57448
57518
  return decoded.startsWith("uat/") ? decoded : `uat/${decoded}`;
57449
57519
  }
57450
57520
  const getUatGenerationsRoute = HttpRouter.add("GET", "/api/flywheel/uat-generations", httpHandler(Effect.gen(function* () {
57451
- const { getUatGenerationsPayload } = yield* Effect.promise(() => import("./uat-train-ByN1YyZx.js"));
57521
+ const { getUatGenerationsPayload } = yield* Effect.promise(() => import("./uat-train-fTKeQcdW.js"));
57452
57522
  return jsonResponse(yield* Effect.promise(() => getUatGenerationsPayload()));
57453
57523
  })));
57454
57524
  const getUatCandidateRoute = HttpRouter.add("GET", "/api/flywheel/uat-candidate", httpHandler(Effect.gen(function* () {
57455
- const { getUatCandidatePayload } = yield* Effect.promise(() => import("./uat-train-ByN1YyZx.js"));
57525
+ const { getUatCandidatePayload } = yield* Effect.promise(() => import("./uat-train-fTKeQcdW.js"));
57456
57526
  return jsonResponse(yield* Effect.promise(() => getUatCandidatePayload()));
57457
57527
  })));
57458
57528
  const postUatGenerationStackRoute = HttpRouter.add("POST", "/api/flywheel/uat-generations/:name/stack", httpHandler(Effect.gen(function* () {
57459
57529
  const authError = rejectUnsafeDashboardMutationRequest(yield* HttpServerRequest.HttpServerRequest);
57460
57530
  if (authError) return authError;
57461
57531
  const name = uatGenerationNameFromParam((yield* HttpRouter.params)["name"] ?? "");
57462
- const { postUatGenerationStackPayload } = yield* Effect.promise(() => import("./uat-train-ByN1YyZx.js"));
57532
+ const { postUatGenerationStackPayload } = yield* Effect.promise(() => import("./uat-train-fTKeQcdW.js"));
57463
57533
  const result = yield* Effect.promise(() => postUatGenerationStackPayload(name));
57464
57534
  if (!result.ok) return jsonResponse({ error: result.error }, { status: result.status });
57465
57535
  return jsonResponse({
@@ -57471,8 +57541,8 @@ const postUatGenerationPromoteRoute = HttpRouter.add("POST", "/api/flywheel/uat-
57471
57541
  const authError = rejectUnsafeDashboardMutationRequest(yield* HttpServerRequest.HttpServerRequest);
57472
57542
  if (authError) return authError;
57473
57543
  const name = uatGenerationNameFromParam((yield* HttpRouter.params)["name"] ?? "");
57474
- const { postUatGenerationPromotePayload } = yield* Effect.promise(() => import("./uat-train-ByN1YyZx.js"));
57475
- const { firePostMergeLifecycle } = yield* Effect.promise(() => import("./specialists-B6m2H7J6.js"));
57544
+ const { postUatGenerationPromotePayload } = yield* Effect.promise(() => import("./uat-train-fTKeQcdW.js"));
57545
+ const { firePostMergeLifecycle } = yield* Effect.promise(() => import("./specialists-BWNyQTq6.js"));
57476
57546
  const result = yield* Effect.promise(() => postUatGenerationPromotePayload(name, firePostMergeLifecycle));
57477
57547
  if (!result.success) return jsonResponse(result, { status: result.reason === "not-found" ? 404 : result.reason === "merge-failed" ? 500 : 409 });
57478
57548
  return jsonResponse(result);
@@ -57485,7 +57555,7 @@ const postUatGenerationPromoteRoute = HttpRouter.add("POST", "/api/flywheel/uat-
57485
57555
  const postFlywheelAssembleUatRoute = HttpRouter.add("POST", "/api/flywheel/assemble-uat", httpHandler(Effect.gen(function* () {
57486
57556
  const authError = rejectUnsafeDashboardMutationRequest(yield* HttpServerRequest.HttpServerRequest);
57487
57557
  if (authError) return authError;
57488
- const { runUatTrainReconcile } = yield* Effect.promise(() => import("./uat-train-ByN1YyZx.js"));
57558
+ const { runUatTrainReconcile } = yield* Effect.promise(() => import("./uat-train-fTKeQcdW.js"));
57489
57559
  return jsonResponse(yield* Effect.promise(() => runUatTrainReconcile({ force: true })));
57490
57560
  })));
57491
57561
  const getFlywheelStateRoute = HttpRouter.add("GET", "/api/flywheel/state", httpHandler(Effect.gen(function* () {
@@ -57905,36 +57975,8 @@ const postArtifactUnshareRoute = HttpRouter.add("POST", "/api/artifacts/:slug/un
57905
57975
  })));
57906
57976
  const artifactsRouteLayer = Layer.mergeAll(getRawArtifactRoute, getArtifactDetailRoute, getWorkspaceArtifactsRoute, getArtifactThumbnailRoute, postArtifactUnshareRoute);
57907
57977
  //#endregion
57908
- //#region ../../lib/backlog/label-ops.ts
57909
- init_sequence_io();
57910
- init_tracker_utils();
57911
- const execAsync$1 = promisify(exec);
57912
- /**
57913
- * Add or remove a GitHub label on an issue. Non-GitHub issues are silently
57914
- * skipped; the `|| true` keeps a missing-label / already-applied no-op non-fatal.
57915
- */
57916
- async function editIssueLabel(issueId, op, label) {
57917
- const resolution = resolveGitHubIssueSync(issueId);
57918
- if (!resolution.isGitHub) return;
57919
- const { owner, repo, number } = resolution;
57920
- await execAsync$1(`gh issue edit ${number} --repo ${owner}/${repo} ${op === "add" ? "--add-label" : "--remove-label"} "${label}" 2>/dev/null || true`);
57921
- }
57922
- const addIssueLabel = (issueId, label) => editIssueLabel(issueId, "add", label);
57923
- const removeIssueLabel = (issueId, label) => editIssueLabel(issueId, "remove", label);
57924
- const applyIssueParkedLabel = (id) => addIssueLabel(id, PARKED_LABEL);
57925
- const removeIssueParkedLabel = (id) => removeIssueLabel(id, PARKED_LABEL);
57926
- const applyIssueVetoedLabel = (id) => addIssueLabel(id, VETOED_LABEL);
57927
- const removeIssueVetoedLabel = (id) => removeIssueLabel(id, VETOED_LABEL);
57928
- const applyIssueBlocksMainLabel = (id) => addIssueLabel(id, BLOCKS_MAIN_LABEL);
57929
- const removeIssueBlocksMainLabel = (id) => removeIssueLabel(id, BLOCKS_MAIN_LABEL);
57930
- const applyIssueReadyLabel = (id) => addIssueLabel(id, READY_LABEL);
57931
- const removeIssueReadyLabel = (id) => removeIssueLabel(id, READY_LABEL);
57932
- const applyIssueReleasedLabel = (id) => addIssueLabel(id, RELEASED_LABEL);
57933
- const removeIssueReleasedLabel = (id) => removeIssueLabel(id, RELEASED_LABEL);
57934
- const applyIssueObjectionLabel = (id) => addIssueLabel(id, OBJECTION_LABEL);
57935
- const removeIssueObjectionLabel = (id) => removeIssueLabel(id, OBJECTION_LABEL);
57936
- //#endregion
57937
57978
  //#region ../../lib/database/agent-mappers.ts
57979
+ init_sequence_io();
57938
57980
  function agentStateToDbAgent(state) {
57939
57981
  return {
57940
57982
  id: state.id,
@@ -57960,6 +58002,9 @@ function agentStateToDbAgent(state) {
57960
58002
  paused: state.paused ?? null,
57961
58003
  pausedReason: state.pausedReason ?? null,
57962
58004
  pausedAt: state.pausedAt ?? null,
58005
+ yieldedByScheduler: state.yieldedByScheduler ?? null,
58006
+ yieldedAt: state.yieldedAt ?? null,
58007
+ lastYieldResumeAt: state.lastYieldResumeAt ?? null,
57963
58008
  troubled: state.troubled ?? null,
57964
58009
  troubledAt: state.troubledAt ?? null,
57965
58010
  consecutiveFailures: state.consecutiveFailures ?? null,
@@ -58006,7 +58051,8 @@ const VALID_ROLES = new Set([
58006
58051
  "test",
58007
58052
  "ship",
58008
58053
  "flywheel",
58009
- "strike"
58054
+ "strike",
58055
+ "knowledge"
58010
58056
  ]);
58011
58057
  const COLUMN_MAP = {
58012
58058
  id: "id",
@@ -58032,6 +58078,9 @@ const COLUMN_MAP = {
58032
58078
  paused: "paused",
58033
58079
  pausedReason: "paused_reason",
58034
58080
  pausedAt: "paused_at",
58081
+ yieldedByScheduler: "yielded_by_scheduler",
58082
+ yieldedAt: "yielded_at",
58083
+ lastYieldResumeAt: "last_yield_resume_at",
58035
58084
  troubled: "troubled",
58036
58085
  troubledAt: "troubled_at",
58037
58086
  consecutiveFailures: "consecutive_failures",
@@ -58588,6 +58637,9 @@ function initSchema(db) {
58588
58637
  paused INTEGER,
58589
58638
  paused_reason TEXT,
58590
58639
  paused_at TEXT,
58640
+ yielded_by_scheduler INTEGER,
58641
+ yielded_at TEXT,
58642
+ last_yield_resume_at TEXT,
58591
58643
  troubled INTEGER,
58592
58644
  troubled_at TEXT,
58593
58645
  consecutive_failures INTEGER,
@@ -58877,7 +58929,7 @@ function initSchema(db) {
58877
58929
  CREATE INDEX IF NOT EXISTS idx_backlog_sequence_project_rank
58878
58930
  ON backlog_sequence(project_key, rank);
58879
58931
  `);
58880
- db.pragma(`user_version = 58`);
58932
+ db.pragma(`user_version = 59`);
58881
58933
  }
58882
58934
  /**
58883
58935
  * Run schema migrations if the database version is older than SCHEMA_VERSION.
@@ -58885,7 +58937,7 @@ function initSchema(db) {
58885
58937
  */
58886
58938
  function runMigrations(db, dbPath) {
58887
58939
  const currentVersion = db.pragma("user_version", { simple: true });
58888
- if (currentVersion >= 58) return;
58940
+ if (currentVersion >= 59) return;
58889
58941
  if (currentVersion === 0) {
58890
58942
  initSchema(db);
58891
58943
  return;
@@ -59619,7 +59671,18 @@ function runMigrations(db, dbPath) {
59619
59671
  } catch {}
59620
59672
  db.exec(`UPDATE discovered_sessions SET harness = 'claude-code' WHERE harness IS NULL`);
59621
59673
  }
59622
- db.pragma(`user_version = 58`);
59674
+ if (currentVersion < 59) {
59675
+ try {
59676
+ db.exec(`ALTER TABLE agents ADD COLUMN yielded_by_scheduler INTEGER`);
59677
+ } catch {}
59678
+ try {
59679
+ db.exec(`ALTER TABLE agents ADD COLUMN yielded_at TEXT`);
59680
+ } catch {}
59681
+ try {
59682
+ db.exec(`ALTER TABLE agents ADD COLUMN last_yield_resume_at TEXT`);
59683
+ } catch {}
59684
+ }
59685
+ db.pragma(`user_version = 59`);
59623
59686
  }
59624
59687
  //#endregion
59625
59688
  //#region ../../lib/database/index.ts
@@ -61001,7 +61064,7 @@ async function pollOnce(state) {
61001
61064
  try {
61002
61065
  const remoteState = await readFile(join$1(homedir$1(), ".overdeck", "agents", agentId, "remote-state.json"), "utf-8").then((text) => JSON.parse(text)).catch(() => null);
61003
61066
  if (remoteState?.location === "remote" && remoteState?.vmName) {
61004
- const { getRemoteAgentOutput } = await import("./remote-agents-BXKV5iBS.js");
61067
+ const { getRemoteAgentOutput } = await import("./remote-agents-YROPFM-n.js");
61005
61068
  stdout = await getRemoteAgentOutput(agentId, remoteState.vmName, 50);
61006
61069
  } else stdout = await Effect.runPromise(capturePane(agentId, 50));
61007
61070
  } catch {
@@ -61074,7 +61137,8 @@ const BACKFILL_ROLES = new Set([
61074
61137
  "work",
61075
61138
  "review",
61076
61139
  "test",
61077
- "ship"
61140
+ "ship",
61141
+ "knowledge"
61078
61142
  ]);
61079
61143
  const NON_AGENT_PREFIXES = [
61080
61144
  "conv-",
@@ -62184,7 +62248,7 @@ const RESTART_MARKER = join(homedir(), ".overdeck", "dashboard-restarting.json")
62184
62248
  * loads new content-hashed chunk filenames (no ERR_MODULE_NOT_FOUND after rebuild).
62185
62249
  */
62186
62250
  async function defaultLifecycleRunner(pending) {
62187
- const { postMergeLifecycle, notifyTldrDaemon } = await import("./merge-agent-DZaRBHQA.js");
62251
+ const { postMergeLifecycle, notifyTldrDaemon } = await import("./merge-agent-DzbCbjqg.js");
62188
62252
  await postMergeLifecycle(pending.issueId, pending.projectPath, pending.sourceBranch, { skipDeploy: true });
62189
62253
  if (pending.sourceBranch) await notifyTldrDaemon(pending.projectPath, pending.sourceBranch);
62190
62254
  }
@@ -62505,7 +62569,7 @@ function failureReason(result) {
62505
62569
  return result.error ?? result.message ?? `merge returned status ${result.statusCode ?? "unknown"}`;
62506
62570
  }
62507
62571
  async function defaultMergeIssue(issueId) {
62508
- const { triggerMerge } = await import("./merge-ops-DRRd3YBA.js");
62572
+ const { triggerMerge } = await import("./merge-ops-CgzhHkd4.js");
62509
62573
  return triggerMerge(issueId);
62510
62574
  }
62511
62575
  function defaultAnnounceFailure(issueId, reason) {
@@ -63142,7 +63206,7 @@ reconcileStaleGitHubBlockers().then((n) => {
63142
63206
  }
63143
63207
  }).catch((err) => console.warn(`[overdeck] Startup blocker reconciliation failed: ${err.message}`));
63144
63208
  try {
63145
- const { resetProcessingToQueued } = await import("./merge-sync-D3wPN2-T.js");
63209
+ const { resetProcessingToQueued } = await import("./merge-sync-DD-v3GnC.js");
63146
63210
  const resetCount = resetProcessingToQueued();
63147
63211
  if (resetCount > 0) {
63148
63212
  console.log(`[overdeck] Reset ${resetCount} stuck merge queue entries to queued`);