@ordewell/core 0.5.6 → 0.6.1

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 (47) hide show
  1. package/dist/{IFileSystem-C0l-4MGT.d.ts → IFileSystem-DuEiG_kA.d.ts} +1 -1
  2. package/dist/{IFileSystem-BkPX7mLD.d.mts → IFileSystem-d_SV7jAH.d.mts} +1 -1
  3. package/dist/{ModeResolver-CjpG5Wli.d.ts → ModeResolver-DIReYAOq.d.mts} +6 -2
  4. package/dist/{ModeResolver--16lh7dS.d.mts → ModeResolver-DXxV4n_V.d.ts} +6 -2
  5. package/dist/{Task-Dyxp67s2.d.mts → Task-ib_U0YP7.d.mts} +102 -16
  6. package/dist/{Task-Dyxp67s2.d.ts → Task-ib_U0YP7.d.ts} +102 -16
  7. package/dist/{chunk-ROVYWEBI.mjs → chunk-I6U3PVHL.mjs} +41 -17
  8. package/dist/chunk-I6U3PVHL.mjs.map +1 -0
  9. package/dist/{chunk-EDGUFCIR.mjs → chunk-JRZPSNRO.mjs} +7 -3
  10. package/dist/chunk-JRZPSNRO.mjs.map +1 -0
  11. package/dist/{chunk-JBEFAJ2W.mjs → chunk-M4KXBEFJ.mjs} +23 -3
  12. package/dist/chunk-M4KXBEFJ.mjs.map +1 -0
  13. package/dist/{chunk-C44UWIAD.mjs → chunk-N66ZHFGN.mjs} +2 -2
  14. package/dist/chunk-N66ZHFGN.mjs.map +1 -0
  15. package/dist/index.d.mts +325 -67
  16. package/dist/index.d.ts +325 -67
  17. package/dist/index.js +5741 -4489
  18. package/dist/index.js.map +1 -1
  19. package/dist/index.mjs +5368 -4163
  20. package/dist/index.mjs.map +1 -1
  21. package/dist/order-labels.d.mts +1 -1
  22. package/dist/order-labels.d.ts +1 -1
  23. package/dist/{parsing-EcmCsF1y.d.ts → parsing-C8Z22twN.d.ts} +2 -2
  24. package/dist/{parsing-DPEpAszP.d.mts → parsing-DjRJJX-y.d.mts} +2 -2
  25. package/dist/parsing.d.mts +3 -3
  26. package/dist/parsing.d.ts +3 -3
  27. package/dist/parsing.js +5 -2
  28. package/dist/parsing.js.map +1 -1
  29. package/dist/parsing.mjs +2 -2
  30. package/dist/{plan-utils-BAvW3hvl.d.mts → plan-utils-D4ioaM8q.d.mts} +25 -4
  31. package/dist/{plan-utils-BMyEiDKv.d.ts → plan-utils-DvHPzAfV.d.ts} +25 -4
  32. package/dist/plan-utils.d.mts +3 -3
  33. package/dist/plan-utils.d.ts +3 -3
  34. package/dist/plan-utils.js +2 -1
  35. package/dist/plan-utils.js.map +1 -1
  36. package/dist/plan-utils.mjs +2 -2
  37. package/dist/testing.d.mts +14 -5
  38. package/dist/testing.d.ts +14 -5
  39. package/dist/testing.js +30 -3
  40. package/dist/testing.js.map +1 -1
  41. package/dist/testing.mjs +30 -3
  42. package/dist/testing.mjs.map +1 -1
  43. package/package.json +1 -1
  44. package/dist/chunk-C44UWIAD.mjs.map +0 -1
  45. package/dist/chunk-EDGUFCIR.mjs.map +0 -1
  46. package/dist/chunk-JBEFAJ2W.mjs.map +0 -1
  47. package/dist/chunk-ROVYWEBI.mjs.map +0 -1
package/dist/index.d.ts CHANGED
@@ -1,14 +1,14 @@
1
- import { aG as RunnerId, ag as PlanStatus, a6 as LegacyPlanState, I as IApproval, k as ApprovalDecision, p as ApprovalRequest, j as ApprovalAnswer, L as ITerminalRunner, J as IConfig, h as AiProvider, as as ProviderModelLists, m as ApprovalMode, X as IsolationMergeResult, T as IsolationLandedTask, N as IWorktreeIsolation, a2 as IsolationTaskStatus, ad as PlanIsolation, aL as RunnerTransport, az as RepoGroupLayout, M as ITerminalSession, w as DiscoveredModel, aU as Task, f as AgentProcessDeps, c as AgentAdapter, aB as ResearchProgress, aA as ResearchLogEntry, u as ConversationMessage, b9 as UsageRecord, b1 as TaskSnapshot, r as AwaitingReason, Q as IsolationHandoff, $ as IsolationRun, a0 as IsolationTaskRecord, aV as TaskIsolation, a3 as IsolationView, Y as IsolationOutcome, ay as RepairEvidence, bg as Verdict, aJ as RunnerRegistry, ax as QueuedTaskMessage, aw as QueuedMessage, b as ActiveTaskSession, ac as OrchestratorOption, aY as TaskModeAgentAdapter, g as AgentStartOptions, e as AgentEvent, aE as ResearchToolType, ai as PlannerUsage, n as ApprovalPolicy, af as PlanState, aH as RunnerInvocation, A as AbstractRunner, a as AbstractTerminalSession, aQ as StructuredSessionCapability, b2 as TaskStartOptions, aR as StructuredTurnEnd, aP as StructuredEvent, aK as RunnerSpawnOptions, K as IPluginStore, aI as RunnerPluginManifest, aF as ResolveContext } from './Task-Dyxp67s2.js';
2
- export { d as AgentAdapterFactory, i as AllProviderModels, l as ApprovalKind, o as ApprovalPolicyOptions, q as ApprovalSource, B as BlockingPrompt, C as CMD_EXE_MAX_COMMAND_LINE, s as CatalogModel, t as CommandLineTooLongError, D as DENY_ALL, v as DiscoveredMode, x as DiscoveryCommand, E as EmbeddedNewlineError, y as ExecutableNotFoundError, F as FetchAllProviderModelsOptions, H as HeadlessRunner, z as HeadlessRunnerDeps, G as HeadlessSession, O as IntegrationDisposal, P as IsolationAvailability, R as IsolationHandoffRepo, S as IsolationInactiveReason, U as IsolationLanding, V as IsolationMergeBlock, W as IsolationMergeBlockReason, Z as IsolationPruneResult, _ as IsolationRepo, a1 as IsolationTaskRepo, a4 as LaunchDeps, a5 as LaunchPlan, a7 as LineBuffer, a8 as Message, a9 as ModelCatalog, aa as ModelShortcut, ab as ORCHESTRATOR_SHORTCUTS, ae as PlanModificationWarnings, ah as PlannerStartOptions, aj as PluginCloneFn, ak as PluginEntry, al as PluginFeatures, am as PluginMode, an as PluginModelDiscovery, ao as PluginRunnerDef, ap as PreparedLaunch, aq as PreparedTask, ar as ProviderCredentialSource, at as ProviderModelsResult, au as PtySize, av as PtyWrapOptions, aC as ResearchStep, aD as ResearchStepOutcome, aM as StreamEvent, aN as StreamStepEvent, aO as StreamThinkingEvent, aS as SubagentLogEntry, aT as SubagentOutcome, aW as TaskIsolationState, aX as TaskMode, aZ as TaskModeUnsupportedError, a_ as TaskModelAssignment, a$ as TaskOutputSummary, b0 as TaskRunnerFlags, b3 as TaskStatus, b4 as TaskTransport, b5 as TaskType, b6 as TaskWithParent, b7 as ThinkingBlock, b8 as UsageLine, ba as UsageTotals, bb as UserPromptEntry, bc as UserStep, bd as ValidationCheck, be as ValidationContext, bf as ValidationResult, bh as VerificationCheck, bi as WINDOWS_MAX_COMMAND_LINE, bj as addPlannerUsage, bk as addTaskToPlan, bl as addUsage, bm as buildShellInvocation, bn as collectProviderCredentials, bo as createEmptyPlan, bp as createTask, bq as emptyWarnings, br as enabledRunners, bs as fetchAllProviderModels, bt as flattenTasks, bu as flattenTasksWithParents, bv as isAwaitingReason, bw as isExecutableResolved, bx as isGranted, by as isMeasured, bz as isReservedRunnerName, bA as isRunnerApproval, bB as isRunnerTransport, bC as isStructuredSession, bD as keepExecutionState, bE as knownModelId, bF as migrateLegacyPlan, bG as migratePlanState, bH as migrateTask, bI as partedPromptUsage, bJ as planDirectLaunch, bK as planShellLaunch, bL as plannerContextFill, bM as posixShellQuote, bN as removeTaskFromPlan, bO as renumberTasks, bP as resolveModelShortcut, bQ as resolveProvider, bR as stripAnsi, bS as toApprovalDecision, bT as toOrchestratorOptions, bU as updateTaskInPlan, bV as usageLine, bW as validateModifiedPlan, bX as warningsText, bY as windowsCommandLine, bZ as wrapWithPty } from './Task-Dyxp67s2.js';
3
- import { t as TaskOp, l as SessionBroadcaster, A as ApplyTaskOpsResult, m as SessionMessage, n as SessionNotice, r as TaskLogEvent } from './plan-utils-BMyEiDKv.js';
4
- export { a as ApprovalBlock, b as ApprovalStatus, C as CHECKPOINT_TRUNCATE_LENGTH, c as ConversationInput, d as ConversationView, D as DisplayBlock, E as EMPTY_CONVERSATION, e as EMPTY_HOLD, f as EMPTY_TASK_LOG, G as GatedConversation, L as LocalEntry, M as MessageBlock, g as MessageRole, N as NO_TURN, O as OutputPreview, P as PlanBlock, h as PlanMarkerStatus, i as PromptHold, S as SerializedPlan, j as SerializedTask, k as SerializedTaskStatus, o as SubagentBlock, p as SubagentChild, q as SubagentStatus, T as TakenPrompt, s as TaskLogView, u as TaskRef, v as ThinkingDisplayBlock, w as ToolBlock, x as ToolHeadline, y as ToolStatus, z as TurnGate, U as UsageBlock, B as aheadOfDraft, F as applyTaskOps, H as canMergeTasks, I as canSetDependencies, J as canSplitTask, K as capConflictFiles, Q as classifyOutcome, R as coalesceTaskLog, V as dependencyCandidates, W as dependentsOf, X as drainNext, Y as executionSummary, Z as followTurn, _ as fromTranscript, $ as hasHiddenDetail, a0 as holdPrompt, a1 as outputLines, a2 as outputPreview, a3 as parseTaskOpsJson, a4 as reduceConversation, a5 as reduceTaskLog, a6 as replayTaskLog, a7 as runnerToolSubject, a8 as serializePlan, a9 as serializeTask, aa as serializeTaskStatus, ab as stopTurn, ac as summarizeToolCall, ad as taskStartedNotice, ae as textHasTaskOps, af as toTaskLogEvent, ag as toolHeadline, ah as trimToolOutput, ai as truncateCheckpointSummary, aj as unsendAll, ak as unsendLatest } from './plan-utils-BMyEiDKv.js';
5
- import { I as IFileSystem, R as ReadFileOpts, T as ToolOutcome, b as GrepOptions, a as GlobOptions, F as FindSymbolOptions } from './IFileSystem-C0l-4MGT.js';
6
- export { G as GREP_DEFAULT_HEAD_LIMIT, c as GrepOutputMode, S as SEARCH_EXCLUSIONS } from './IFileSystem-C0l-4MGT.js';
7
- import { R as RunnerModeInfo } from './ModeResolver-CjpG5Wli.js';
8
- export { M as ManifestLookup, b as buildModeGuide, f as filteredBuildModes, r as resolveDefaultMode, a as resolveTaskMode, c as runnerModesFrom } from './ModeResolver-CjpG5Wli.js';
1
+ import { aG as RunnerId, ag as PlanStatus, a6 as LegacyPlanState, I as IApproval, k as ApprovalDecision, p as ApprovalRequest, j as ApprovalAnswer, L as ITerminalRunner, J as IConfig, h as AiProvider, as as ProviderModelLists, m as ApprovalMode, X as IsolationMergeResult, T as IsolationLandedTask, N as IWorktreeIsolation, a2 as IsolationTaskStatus, ad as PlanIsolation, aL as RunnerTransport, az as RepoGroupLayout, M as ITerminalSession, w as DiscoveredModel, aU as Task, f as AgentProcessDeps, c as AgentAdapter, aB as ResearchProgress, aA as ResearchLogEntry, u as ConversationMessage, ba as UsageRecord, b1 as TaskSnapshot, r as AwaitingReason, Q as IsolationHandoff, $ as IsolationRun, a0 as IsolationTaskRecord, aV as TaskIsolation, a3 as IsolationView, Y as IsolationOutcome, ay as RepairEvidence, b8 as TreeSnapshot, bh as Verdict, aJ as RunnerRegistry, ax as QueuedTaskMessage, aw as QueuedMessage, b as ActiveTaskSession, ac as OrchestratorOption, aY as TaskModeAgentAdapter, g as AgentStartOptions, e as AgentEvent, aE as ResearchToolType, ai as PlannerUsage, n as ApprovalPolicy, af as PlanState, aH as RunnerInvocation, A as AbstractRunner, a as AbstractTerminalSession, aQ as StructuredSessionCapability, b2 as TaskStartOptions, aR as StructuredTurnEnd, aP as StructuredEvent, aK as RunnerSpawnOptions, K as IPluginStore, aI as RunnerPluginManifest, aF as ResolveContext, b0 as TaskRunnerFlags } from './Task-ib_U0YP7.js';
2
+ export { d as AgentAdapterFactory, i as AllProviderModels, l as ApprovalKind, o as ApprovalPolicyOptions, q as ApprovalSource, B as BlockingPrompt, C as CMD_EXE_MAX_COMMAND_LINE, s as CatalogModel, t as CommandLineTooLongError, D as DENY_ALL, v as DiscoveredMode, x as DiscoveryCommand, E as EmbeddedNewlineError, y as ExecutableNotFoundError, F as FetchAllProviderModelsOptions, H as HeadlessRunner, z as HeadlessRunnerDeps, G as HeadlessSession, O as IntegrationDisposal, P as IsolationAvailability, R as IsolationHandoffRepo, S as IsolationInactiveReason, U as IsolationLanding, V as IsolationMergeBlock, W as IsolationMergeBlockReason, Z as IsolationPruneResult, _ as IsolationRepo, a1 as IsolationTaskRepo, a4 as LaunchDeps, a5 as LaunchPlan, a7 as LineBuffer, a8 as Message, a9 as ModelCatalog, aa as ModelShortcut, ab as ORCHESTRATOR_SHORTCUTS, ae as PlanModificationWarnings, ah as PlannerStartOptions, aj as PluginCloneFn, ak as PluginEntry, al as PluginFeatures, am as PluginMode, an as PluginModelDiscovery, ao as PluginRunnerDef, ap as PreparedLaunch, aq as PreparedTask, ar as ProviderCredentialSource, at as ProviderModelsResult, au as PtySize, av as PtyWrapOptions, aC as ResearchStep, aD as ResearchStepOutcome, aM as StreamEvent, aN as StreamStepEvent, aO as StreamThinkingEvent, aS as SubagentLogEntry, aT as SubagentOutcome, aW as TaskIsolationState, aX as TaskMode, aZ as TaskModeUnsupportedError, a_ as TaskModelAssignment, a$ as TaskOutputSummary, b3 as TaskStatus, b4 as TaskTransport, b5 as TaskType, b6 as TaskWithParent, b7 as ThinkingBlock, b9 as UsageLine, bb as UsageTotals, bc as UserPromptEntry, bd as UserStep, be as ValidationCheck, bf as ValidationContext, bg as ValidationResult, bi as VerificationCheck, bj as WINDOWS_MAX_COMMAND_LINE, bk as addPlannerUsage, bl as addTaskToPlan, bm as addUsage, bn as approvalScopes, bo as buildShellInvocation, bp as collectProviderCredentials, bq as createEmptyPlan, br as createTask, bs as emptyWarnings, bt as enabledRunners, bu as fetchAllProviderModels, bv as flattenTasks, bw as flattenTasksWithParents, bx as isAwaitingReason, by as isExecutableResolved, bz as isGranted, bA as isMeasured, bB as isReservedRunnerName, bC as isRunnerApproval, bD as isRunnerTransport, bE as isStructuredSession, bF as keepExecutionState, bG as knownModelId, bH as migrateLegacyPlan, bI as migratePlanState, bJ as migrateTask, bK as partedPromptUsage, bL as planDirectLaunch, bM as planShellLaunch, bN as plannerContextFill, bO as posixShellQuote, bP as removeTaskFromPlan, bQ as renumberTasks, bR as resolveModelShortcut, bS as resolveProvider, bT as stripAnsi, bU as toApprovalDecision, bV as toOrchestratorOptions, bW as updateTaskInPlan, bX as usageLine, bY as validateModifiedPlan, bZ as warningsText, b_ as windowsCommandLine, b$ as wrapWithPty } from './Task-ib_U0YP7.js';
3
+ import { u as TaskOp, M as MergeGateView, m as SessionBroadcaster, A as ApplyTaskOpsResult, n as SessionMessage, o as SessionNotice, s as TaskLogEvent } from './plan-utils-DvHPzAfV.js';
4
+ export { a as ApprovalBlock, b as ApprovalStatus, C as CHECKPOINT_TRUNCATE_LENGTH, c as ConversationInput, d as ConversationView, D as DisplayBlock, E as EMPTY_CONVERSATION, e as EMPTY_HOLD, f as EMPTY_TASK_LOG, G as GatedConversation, L as LocalEntry, g as MessageBlock, h as MessageRole, N as NO_TURN, O as OutputPreview, P as PlanBlock, i as PlanMarkerStatus, j as PromptHold, S as SerializedPlan, k as SerializedTask, l as SerializedTaskStatus, p as SubagentBlock, q as SubagentChild, r as SubagentStatus, T as TakenPrompt, t as TaskLogView, v as TaskRef, w as ThinkingDisplayBlock, x as ToolBlock, y as ToolHeadline, z as ToolStatus, B as TurnGate, U as UsageBlock, F as aheadOfDraft, H as applyTaskOps, I as canMergeTasks, J as canSetDependencies, K as canSplitTask, Q as capConflictFiles, R as classifyOutcome, V as coalesceTaskLog, W as dependencyCandidates, X as dependentsOf, Y as drainNext, Z as executionSummary, _ as followTurn, $ as fromTranscript, a0 as hasHiddenDetail, a1 as holdPrompt, a2 as outputLines, a3 as outputPreview, a4 as parseTaskOpsJson, a5 as reduceConversation, a6 as reduceTaskLog, a7 as replayTaskLog, a8 as runnerToolSubject, a9 as serializePlan, aa as serializeTask, ab as serializeTaskStatus, ac as stopTurn, ad as summarizeToolCall, ae as taskStartedNotice, af as textHasTaskOps, ag as toTaskLogEvent, ah as toolHeadline, ai as trimToolOutput, aj as truncateCheckpointSummary, ak as unsendAll, al as unsendLatest } from './plan-utils-DvHPzAfV.js';
5
+ import { I as IFileSystem, R as ReadFileOpts, T as ToolOutcome, b as GrepOptions, a as GlobOptions, F as FindSymbolOptions } from './IFileSystem-DuEiG_kA.js';
6
+ export { G as GREP_DEFAULT_HEAD_LIMIT, c as GrepOutputMode, S as SEARCH_EXCLUSIONS } from './IFileSystem-DuEiG_kA.js';
7
+ import { R as RunnerModeInfo } from './ModeResolver-DXxV4n_V.js';
8
+ export { M as ManifestLookup, a as autonomyLevelLabel, b as buildModeGuide, f as filteredBuildModes, p as parseAutonomyLevel, r as resolveDefaultMode, c as resolveTaskMode, d as runnerModesFrom } from './ModeResolver-DXxV4n_V.js';
9
9
  import { ChildProcess } from 'child_process';
10
- import { b as PlanParseError } from './parsing-EcmCsF1y.js';
11
- export { P as PLAN_ENVELOPE_KEY, a as PartialPlanTask, T as TASK_OPS_ENVELOPE_KEY, c as TASK_QUERY_ENVELOPE_KEY, d as checkDepsResolve, e as checkImmutableLog, f as checkInProgress, g as checkNoCycles, h as checkUniqueIds, i as escapeControlCharsInStrings, j as extractJsonObject, k as extractObjectWithBalance, l as extractObjectsWithKey, m as looksLikePlanAttempt, o as opensWithJsonObject, p as parsePartialPlan, n as parsePlanJson, s as stripModelNoise, q as stripTrailingCommas, v as validatePlanModification } from './parsing-EcmCsF1y.js';
10
+ import { b as PlanParseError } from './parsing-C8Z22twN.js';
11
+ export { P as PLAN_ENVELOPE_KEY, a as PartialPlanTask, T as TASK_OPS_ENVELOPE_KEY, c as TASK_QUERY_ENVELOPE_KEY, d as checkDepsResolve, e as checkImmutableLog, f as checkInProgress, g as checkNoCycles, h as checkUniqueIds, i as escapeControlCharsInStrings, j as extractJsonObject, k as extractObjectWithBalance, l as extractObjectsWithKey, m as looksLikePlanAttempt, o as opensWithJsonObject, p as parsePartialPlan, n as parsePlanJson, s as stripModelNoise, q as stripTrailingCommas, v as validatePlanModification } from './parsing-C8Z22twN.js';
12
12
  export { resolveOrderLabel, taskOrderLabel } from './order-labels.js';
13
13
  import 'events';
14
14
 
@@ -261,16 +261,19 @@ declare abstract class BaseFileSystem implements IFileSystem {
261
261
  * Path confinement for `bash`: an `auto`-tier binary (`cat`, `find`, `rg`, …)
262
262
  * is only auto because *reading* is read-only — its arguments can still
263
263
  * name a path outside the workspace, which is the exact escape confinement
264
- * closes for `readFile`/`glob`/`grep`. Each escaping path needs its own
265
- * approval (scoped to its containing directory); approving one does not
266
- * approve another, so a single command touching two external dirs prompts
267
- * once per distinct scope rather than carrying the first grant to the rest.
264
+ * closes for `readFile`/`glob`/`grep`. Each escaping path is scoped to its
265
+ * containing directory, one entry per distinct scope.
268
266
  */
269
- private authorizeCommandPaths;
267
+ private outsidePaths;
270
268
  /**
271
269
  * Three tiers (see `commandPolicy.ts`): read-only inspection runs silently,
272
270
  * anything else asks once and is remembered, and writes are refused outright
273
271
  * because a planner that mutates the workspace has stopped being a planner.
272
+ *
273
+ * Everything a command needs — its own approval and every outside directory
274
+ * it touches — is one request, so one command is one prompt. Each scope is
275
+ * still granted separately: approving the pair does not approve another
276
+ * directory the next command names.
274
277
  */
275
278
  bash(command: string, signal?: AbortSignal): Promise<ToolOutcome>;
276
279
  }
@@ -698,8 +701,8 @@ interface UserSettings {
698
701
  */
699
702
  enabledRunners?: string[];
700
703
  /**
701
- * How tasks' runners are driven (ADR-0018). Experimental; a run copies it
702
- * onto its plan when it starts, so a change applies from the next run.
704
+ * How tasks' runners are driven (ADR-0018). A run copies it onto its plan
705
+ * when it starts, so a change applies from the next run.
703
706
  */
704
707
  runnerTransport: RunnerTransport;
705
708
  }
@@ -718,6 +721,12 @@ declare class SettingsService {
718
721
  private filePath;
719
722
  private cache;
720
723
  private cachedMtimeMs;
724
+ /**
725
+ * Whether the transport on disk (or just set) is the user's own choice.
726
+ * Writing the default back out would turn it into one, and a later change of
727
+ * default would then never reach this user.
728
+ */
729
+ private transportChosen;
721
730
  constructor(filePath?: string);
722
731
  getAll(): UserSettings;
723
732
  private fileMtimeMs;
@@ -1341,6 +1350,8 @@ declare class PlanStore {
1341
1350
  private _planTasks;
1342
1351
  private _allTasks;
1343
1352
  private _taskMap;
1353
+ /** Task id → the top-level task it hangs under, itself for a top-level task. */
1354
+ private _rootMap;
1344
1355
  private _planRunners;
1345
1356
  private _onMutate;
1346
1357
  private _executionLog;
@@ -1356,6 +1367,11 @@ declare class PlanStore {
1356
1367
  isCompleted(id: string): boolean;
1357
1368
  isFailed(id: string): boolean;
1358
1369
  get(taskId: string): Readonly<Task> | undefined;
1370
+ /**
1371
+ * Whether a task runs as an ops task (ADR-0020). Only a top-level AI task
1372
+ * can be one; a subtask runs with the top-level task it hangs under.
1373
+ */
1374
+ isOps(taskId: string): boolean;
1359
1375
  /** A copy of the task tree, detached from the store: later status changes do not reach it. */
1360
1376
  snapshot(): Task[];
1361
1377
  getExecutionLog(): ReadonlyArray<TaskSnapshot>;
@@ -1392,6 +1408,8 @@ declare class PlanStore {
1392
1408
  markAwaitingUser(id: string, reason?: AwaitingReason): void;
1393
1409
  markPending(id: string): void;
1394
1410
  retry(id: string): void;
1411
+ /** Kept on the task: it was force-started past its merge gate, before these dependencies' work was merged (ADR-0020). */
1412
+ setForcedPastGate(id: string, dependencies: string[]): void;
1395
1413
  /** A reason outlives nothing: any status but `awaiting_user` drops it. */
1396
1414
  private setStatus;
1397
1415
  blockDependents(id: string): void;
@@ -1431,6 +1449,7 @@ interface IsolationRunListener {
1431
1449
  /**
1432
1450
  * A run opened — the one moment shared by Execute, a manual task run and
1433
1451
  * a force start, so whatever a run pins for its whole length is read here.
1452
+ * Whether it isolates is decided later, at its first change task.
1434
1453
  */
1435
1454
  opened(): void;
1436
1455
  /** A run did not start: `repos` of the group have tracked changes. */
@@ -1453,12 +1472,13 @@ interface IsolationRunControllerDeps {
1453
1472
  listener: IsolationRunListener;
1454
1473
  }
1455
1474
  /**
1456
- * The lifecycle of a plan's isolation run (ADR-0013, ADR-0014), between the
1457
- * scheduler and the git layer: deciding at a run's start whether it executes
1458
- * in worktrees, a blocked run and how it goes on, each attempt's working
1459
- * directory, releasing worktrees, the handoff when the run closes, and what the
1460
- * user does with it afterwards. The record it keeps outlives one run — a
1461
- * resumed plan continues it.
1475
+ * The lifecycle of a plan's isolation run (ADR-0013, ADR-0014, ADR-0020),
1476
+ * between the scheduler and the git layer: deciding, at a run's first change
1477
+ * task, whether it executes in worktrees, a blocked run and how it goes on,
1478
+ * each attempt's working directory, releasing worktrees, which landed work the
1479
+ * user has merged, the tree check of an ops task, the handoff when the run
1480
+ * closes, and what the user does with it afterwards. The record it keeps
1481
+ * outlives one run — a resumed plan continues it.
1462
1482
  */
1463
1483
  declare class IsolationRunController {
1464
1484
  private readonly isolation;
@@ -1470,9 +1490,9 @@ declare class IsolationRunController {
1470
1490
  /** Copied paths already reported for the current run: every task gets the same copies. */
1471
1491
  private reportedCopies;
1472
1492
  /**
1473
- * How the open run executes; null while no run is open. A run is one
1474
- * Execute-Plan or one manual task run, from its start until it settles or
1475
- * is stopped.
1493
+ * How the open run executes; null while no run is open, `undecided` until
1494
+ * its first change task asks. A run is one Execute-Plan or one manual task
1495
+ * run, from its start until it settles or is stopped.
1476
1496
  */
1477
1497
  private mode;
1478
1498
  /** Resolver task id → the conflicted task it resolves; see {@link linkResolver}. */
@@ -1486,6 +1506,8 @@ declare class IsolationRunController {
1486
1506
  /** The plan's run record, open or not; null when the plan has not isolated. */
1487
1507
  get current(): IsolationRun | null;
1488
1508
  get isOpen(): boolean;
1509
+ /** The open run has decided whether it isolates. */
1510
+ get decided(): boolean;
1489
1511
  /** The open run executes in worktrees. */
1490
1512
  get isolating(): boolean;
1491
1513
  /** A run is waiting on the user to stash or to go on without isolation. */
@@ -1509,12 +1531,15 @@ declare class IsolationRunController {
1509
1531
  * would otherwise write a new session file on every reload.
1510
1532
  */
1511
1533
  adopt(state: PlanIsolation | null): Promise<void>;
1534
+ /** Open a run if none is, leaving whether it isolates to its first change task. */
1535
+ open(): void;
1512
1536
  /**
1513
- * Open a run if none is: decide once, at its start, whether it executes in
1514
- * worktrees. `resume` is what a dirty tree parks until the user chooses how
1515
- * to go on. Resolves false when the run did not start.
1537
+ * Decide once per run, as its first change task starts, whether it executes
1538
+ * in worktrees (ADR-0020): an ops task needs none, so a run of only ops
1539
+ * tasks never asks. `resume` is what a dirty tree parks until the user
1540
+ * chooses how to go on. Resolves false while the run waits on that choice.
1516
1541
  */
1517
- open(resume: () => Promise<void>): Promise<boolean>;
1542
+ decide(resume: () => Promise<void>): Promise<boolean>;
1518
1543
  /**
1519
1544
  * Whether the run in force, or else the next one, gives each task its own
1520
1545
  * worktrees, and of which repo group — what the planner is told, since it
@@ -1541,6 +1566,7 @@ declare class IsolationRunController {
1541
1566
  */
1542
1567
  attemptCwd(task: Task, opts: {
1543
1568
  repair: boolean;
1569
+ ops?: boolean;
1544
1570
  }): Promise<{
1545
1571
  cwd: string;
1546
1572
  worktree: boolean;
@@ -1562,8 +1588,33 @@ declare class IsolationRunController {
1562
1588
  release(taskId: string, opts: {
1563
1589
  keep: boolean;
1564
1590
  }, landing?: Promise<unknown> | null): Promise<void>;
1565
- /** Close the open run. An isolated one hands its integration branch over for review. */
1591
+ /**
1592
+ * Close the open run. An isolated one hands its integration branch over for
1593
+ * review — unless the user merged everything it landed at merge gates
1594
+ * already, which leaves nothing to hand over, so it is cleared up as a Merge
1595
+ * all would have.
1596
+ */
1566
1597
  close(): Promise<void>;
1598
+ /**
1599
+ * Whether a task's landed work still waits to be merged into the user's
1600
+ * branch — what holds an ops or user task at its merge gate (ADR-0020). A
1601
+ * task with no record never landed anything to wait for.
1602
+ */
1603
+ awaitsMerge(taskId: string): boolean;
1604
+ /**
1605
+ * Look again for landed work the user has merged — by Merge all, or by hand
1606
+ * with git. Resolves true when some was found.
1607
+ */
1608
+ refreshInHead(): Promise<boolean>;
1609
+ /**
1610
+ * The tracked state of the workspace as an ops task starts, for
1611
+ * {@link filesChangedSince} (ADR-0020). Null where the check does not run:
1612
+ * a run that shares the workspace root, where every task's edits land in
1613
+ * it, or a workspace git cannot isolate at all.
1614
+ */
1615
+ snapshotWorkspace(): Promise<TreeSnapshot | null>;
1616
+ /** Tracked files changed since `snapshot`; none when the run has since gone on in the workspace root. */
1617
+ filesChangedSince(snapshot: TreeSnapshot | null): Promise<string[]>;
1567
1618
  /**
1568
1619
  * A stop or a plan load: the open run ends without a handoff and a parked
1569
1620
  * start is dropped. `keepOpen` spares a run the scheduler is still driving.
@@ -1582,9 +1633,11 @@ declare class IsolationRunController {
1582
1633
  reviewDiff(): Promise<string>;
1583
1634
  /**
1584
1635
  * "Merge all": the run's integration branches into whatever the user has
1585
- * checked out, in every repo or none. Once everything merged, the run has
1586
- * nothing left to hand over, so it is cleared up and forgotten; a branch
1587
- * the user's HEAD somehow does not contain stays for the next run's sweep.
1636
+ * checked out, in every repo or none. During a run it merges what has
1637
+ * landed so far and the run goes on (ADR-0020): its branches stay for the
1638
+ * tasks still to land. Once a settled run merged everything, it has nothing
1639
+ * left to hand over, so it is cleared up and forgotten; a branch the user's
1640
+ * HEAD somehow does not contain stays for the next run's sweep.
1588
1641
  */
1589
1642
  merge(): Promise<IsolationMergeResult>;
1590
1643
  /** Worktrees and task branches go; the integration branch and the record stay for review and merge. */
@@ -1593,7 +1646,7 @@ declare class IsolationRunController {
1593
1646
  discard(): Promise<void>;
1594
1647
  private clearMerged;
1595
1648
  private forget;
1596
- private decide;
1649
+ private assess;
1597
1650
  private activate;
1598
1651
  private begin;
1599
1652
  /** What earlier runs left merged in the group goes; a failure here is worth a word, never a stopped run. */
@@ -1890,6 +1943,10 @@ declare class TaskOrchestrator {
1890
1943
  * pending and nothing ran until the user also re-ran the whole plan.
1891
1944
  */
1892
1945
  private haltedByFailure;
1946
+ /** A Merge all is under way: no ops task starts until it ends (ADR-0020). */
1947
+ private merging;
1948
+ /** The last "waiting for Merge all" notice, so a run paused at a gate says it once, not on every tick. */
1949
+ private gateNotice;
1893
1950
  /** The workspace's own variables for a task's cwd (ADR-0016); swapped out in tests. */
1894
1951
  private workspaceEnv;
1895
1952
  /** What the workspace env has already warned about, so a run says it once, not per task. */
@@ -1997,8 +2054,26 @@ declare class TaskOrchestrator {
1997
2054
  */
1998
2055
  adoptIsolation(state: PlanIsolation | null): Promise<void>;
1999
2056
  reviewRunDiff(): Promise<string>;
2000
- /** "Merge all"; a run that merged everything is cleared up and forgotten. */
2057
+ /**
2058
+ * "Merge all"; a settled run that merged everything is cleared up and
2059
+ * forgotten. During a run it merges what has landed and the run goes on:
2060
+ * the tasks waiting at a merge gate for that work then start (ADR-0020).
2061
+ * Never while an ops task runs, and no ops task starts until it ends — the
2062
+ * one overlap the plan cannot order, because the merge is the user's.
2063
+ */
2001
2064
  mergeRun(): Promise<IsolationMergeResult>;
2065
+ /**
2066
+ * The run as a surface offers Merge all mid-run (ADR-0020): what has landed
2067
+ * and is not merged, and whether the run is paused at its gates with nothing
2068
+ * else running. Null while no task waits at a gate.
2069
+ */
2070
+ mergeGateView(): MergeGateView | null;
2071
+ /**
2072
+ * The dependencies an ops or user task waits on at its merge gate: those
2073
+ * whose landed work is not in the user's branch yet (ADR-0020). Empty once
2074
+ * the task has started, and for every other task.
2075
+ */
2076
+ getMergeGate(taskId: string): string[];
2002
2077
  /** Worktrees and task branches go; the integration branch and the record stay for review and merge. */
2003
2078
  cleanupRun(): Promise<void>;
2004
2079
  /** The run and everything it made go, and the plan forgets it; the next run starts afresh. */
@@ -2068,6 +2143,14 @@ declare class TaskOrchestrator {
2068
2143
  linkConflictResolver(resolverId: string, conflictedId: string): void;
2069
2144
  private landResolved;
2070
2145
  getReadyTasks(): Task[];
2146
+ private readiness;
2147
+ /**
2148
+ * Open the run a task starts in, and for a change task decide whether it
2149
+ * isolates (ADR-0020): an ops task needs no worktree, so it never waits on
2150
+ * that choice. False while a dirty tree waits on the user; `resume` is what
2151
+ * their choice replays.
2152
+ */
2153
+ private openFor;
2071
2154
  /**
2072
2155
  * Cancel a running (or scheduled) task: kill its session and return it to
2073
2156
  * 'pending' — "not executed". The task is put on hold so the scheduler
@@ -2117,6 +2200,13 @@ declare class TaskOrchestrator {
2117
2200
  * No-op if the task is unknown, not an AI task, or already running.
2118
2201
  */
2119
2202
  forceStartTask(taskId: string): Promise<void>;
2203
+ private refuseOpsDuringMerge;
2204
+ /**
2205
+ * A force start passes a merge gate (ADR-0020), and the surface confirmed it
2206
+ * first; the choice is kept on the task and said, because the work it acts
2207
+ * on is not in the user's branch.
2208
+ */
2209
+ private notePastGate;
2120
2210
  /**
2121
2211
  * Run exactly one task outside full-plan scheduling. The active/starting
2122
2212
  * session still contributes to {@link hasLiveWork} so every surface exposes
@@ -2139,6 +2229,11 @@ declare class TaskOrchestrator {
2139
2229
  parallelGroups: number[][];
2140
2230
  };
2141
2231
  tick(): Promise<void>;
2232
+ /**
2233
+ * A run paused at merge gates says so, as plainly as a task that waits on
2234
+ * the user: which tasks wait, and that Merge all lets them go on (ADR-0020).
2235
+ */
2236
+ private sayGate;
2142
2237
  private startTask;
2143
2238
  /**
2144
2239
  * The fallible half of starting a task: resolving its cwd/worktree and
@@ -2568,6 +2663,8 @@ declare abstract class StdioAgentAdapter implements AgentAdapter {
2568
2663
  private betweenTurns;
2569
2664
  /** Set once a turn has ended: after that, out-of-turn events are stale, not startup. */
2570
2665
  private hadTurn;
2666
+ /** A task's session, which wants what the agent says on its own after a turn closed; a planner registers none and drops it. */
2667
+ private outOfTurnListener;
2571
2668
  private disposed;
2572
2669
  /** Resolves when the process ends, so a handshake can lose the race instead of waiting out its timeout. */
2573
2670
  protected processEnded: Promise<void>;
@@ -2590,6 +2687,7 @@ declare abstract class StdioAgentAdapter implements AgentAdapter {
2590
2687
  protected handshake(_opts: AgentStartOptions): Promise<void>;
2591
2688
  start(opts: AgentStartOptions): Promise<void>;
2592
2689
  send(message: string, onEvent: (event: AgentEvent) => void, signal?: AbortSignal, onActivity?: () => void): Promise<void>;
2690
+ onOutOfTurn(listener: (event: AgentEvent) => void): void;
2593
2691
  nativeSessionId(): string | null;
2594
2692
  onProcessExit(listener: (code: number) => void): void;
2595
2693
  dispose(): void;
@@ -2639,6 +2737,18 @@ declare class ClaudeCodeAdapter extends StdioAgentAdapter implements TaskModeAge
2639
2737
  private readonly openSubagents;
2640
2738
  /** Subagent messages already counted. A message arrives as one line per content block, each repeating its usage. */
2641
2739
  private readonly countedSubagentMessages;
2740
+ /** Background tasks (shells, agents) the CLI reports as still running, as of its last `background_tasks_changed`. */
2741
+ private backgroundTaskCount;
2742
+ /**
2743
+ * A task's turn whose `result` arrived while background work was still open.
2744
+ * The CLI reports that result when the model stops talking, then opens a turn
2745
+ * of its own when the work finishes; a turn ended at the first result would
2746
+ * lose everything said after it, the completion marker included.
2747
+ */
2748
+ private resultHeld;
2749
+ private followOnTimer;
2750
+ /** The mode a task asked for, to hold the CLI to it once its `init` says what it started in. */
2751
+ private requestedMode;
2642
2752
  /** The session `--resume` asked for, until the CLI's `init` shows it was taken up. */
2643
2753
  private pendingResume;
2644
2754
  protected spawnSpec(opts: AgentStartOptions): SpawnSpec;
@@ -2672,8 +2782,18 @@ declare class ClaudeCodeAdapter extends StdioAgentAdapter implements TaskModeAge
2672
2782
  * a grant of Ordewell's making.
2673
2783
  */
2674
2784
  answerPermission(id: string, decision: ApprovalDecision): boolean;
2785
+ dispose(): void;
2786
+ private clearFollowOnTimer;
2675
2787
  protected turnPayload(message: string): string;
2676
2788
  protected handleLine(line: string, emit: (event: AgentEvent) => void): void;
2789
+ /**
2790
+ * `--permission-mode auto` on a model or account without auto mode is not
2791
+ * refused: the CLI says nothing and starts in `default`, then asks about every
2792
+ * write — a request nobody is there to answer. The plan, not the CLI, decides
2793
+ * the mode (ADR-0001), so a different one fails the turn rather than running.
2794
+ */
2795
+ private refuseOtherMode;
2796
+ private awaitFollowOnTurn;
2677
2797
  private startSubagent;
2678
2798
  /**
2679
2799
  * A subagent's messages do not stream, so each line's usage is the snapshot
@@ -2706,8 +2826,10 @@ declare class ClaudeCodeAdapter extends StdioAgentAdapter implements TaskModeAge
2706
2826
  }
2707
2827
 
2708
2828
  /**
2709
- * Codex as a planner, over its `app-server` stdio JSON-RPC transport
2710
- * (ADR-0009).
2829
+ * Codex as a planner (ADR-0009) and as a task's runner (ADR-0018, #54), over
2830
+ * its `app-server` stdio JSON-RPC transport. The start switch decides the
2831
+ * thread's settings and who answers its requests; everything a turn reports
2832
+ * is read the same way for both.
2711
2833
  *
2712
2834
  * Ordewell already speaks a slice of this protocol — `ModelDiscovery` drives
2713
2835
  * `initialize` → `model/list` to build the Codex model catalog — so the
@@ -2719,7 +2841,7 @@ declare class ClaudeCodeAdapter extends StdioAgentAdapter implements TaskModeAge
2719
2841
  * version that renames them will surface as a visible dead turn rather than a
2720
2842
  * hang, because the base class watches the process as well as the protocol.
2721
2843
  */
2722
- declare class CodexAdapter extends StdioAgentAdapter {
2844
+ declare class CodexAdapter extends StdioAgentAdapter implements TaskModeAgentAdapter {
2723
2845
  readonly agentId = "codex";
2724
2846
  private threadId;
2725
2847
  /** The model Codex opened the thread with — usage records name it. */
@@ -2730,6 +2852,28 @@ declare class CodexAdapter extends StdioAgentAdapter {
2730
2852
  private startOpts;
2731
2853
  /** Whether this turn has already emitted prose — see the `agentMessage` case. */
2732
2854
  private turnHasText;
2855
+ /**
2856
+ * The turn in flight. Its id arrives with `turn/started` or the `turn/start`
2857
+ * response, whichever lands first; `turn/interrupt` cannot be sent without it.
2858
+ */
2859
+ private turn;
2860
+ /** The JSON-RPC id of the `turn/start` that opened {@link turn}. */
2861
+ private turnRequestId;
2862
+ /** The last turn this adapter ended — so its second end signal, landing late, ends nothing. */
2863
+ private endedTurnId;
2864
+ /** An interrupt was asked for during this turn, so however it ends, it was cut short. */
2865
+ private interruptRequested;
2866
+ /** An interrupt asked for before Codex named the turn, sent once it does. */
2867
+ private interruptOnStart;
2868
+ /** A task's approval requests still waiting for an answer, by the request id as a string. */
2869
+ private readonly openPermissions;
2870
+ /**
2871
+ * The files each in-flight `fileChange` item touches. Its approval request
2872
+ * names only the item, and a person deciding needs to see the files.
2873
+ */
2874
+ private readonly fileChangePaths;
2875
+ /** Requests this adapter sent and awaits an answer to, by JSON-RPC id. */
2876
+ private readonly pendingRequests;
2733
2877
  private resumeAttempted;
2734
2878
  private resumeFallbackSent;
2735
2879
  private sandbox;
@@ -2739,26 +2883,43 @@ declare class CodexAdapter extends StdioAgentAdapter {
2739
2883
  * one stream; the thread id is what tells them apart (see {@link subagentOf}).
2740
2884
  */
2741
2885
  private readonly subagents;
2742
- /** Codex only plans for now (#54): its tasks stay on the terminal transport. */
2743
- start(opts: AgentStartOptions): Promise<void>;
2744
2886
  protected spawnSpec(opts: AgentStartOptions): SpawnSpec;
2745
2887
  /**
2746
- * `initialize`, then `thread/start`, both before the first user message. The
2747
- * thread is pinned to the read-only sandbox with approvals set to `never` —
2748
- * with nobody watching a planner's prompts, "ask" would mean "hang", which is
2749
- * ADR-0008's absent-is-denial invariant kept by construction.
2888
+ * `initialize`, then `thread/start`, both before the first user message. A
2889
+ * planner's thread is pinned to the read-only sandbox with approvals set to
2890
+ * `never` — with nobody watching a planner's prompts, "ask" would mean
2891
+ * "hang", which is ADR-0008's absent-is-denial invariant kept by
2892
+ * construction. A task's runs as its mode says (see {@link threadParams}).
2750
2893
  */
2751
2894
  protected handshake(opts: AgentStartOptions): Promise<void>;
2752
2895
  /**
2753
- * Open the thread this session plans in. A resume id means the previous
2896
+ * Open this session's thread. A resume id means the previous
2754
2897
  * process died mid-session: `thread/resume` puts the agent back in front of
2755
- * the context it already paid to read. A failed resume is not an error — the
2756
- * response handler falls back to a fresh thread, which is the same
2757
- * degradation `restoreChat` performs on every surface (T4).
2898
+ * the context it already paid to read. A planner's failed resume is not an
2899
+ * error — the response handler falls back to a fresh thread, which is the
2900
+ * same degradation `restoreChat` performs on every surface (T4). A task's
2901
+ * is: Continue (K1) offers the session that did the work, and a fresh thread
2902
+ * in its place would pretend it was resumed.
2758
2903
  */
2759
2904
  private startThread;
2905
+ private threadParams;
2906
+ private effort;
2907
+ /**
2908
+ * `turn/interrupt` names the turn as well as the thread, so an interrupt
2909
+ * asked for before Codex has named the turn waits for it. Codex acknowledges
2910
+ * with an empty result, then ends the turn as `interrupted`.
2911
+ */
2912
+ interrupt(timeoutMs: number): Promise<boolean>;
2913
+ /**
2914
+ * Answer an open approval in its own result schema. Codex's decline carries
2915
+ * no message, so a deny note reaches the agent as input steered into the
2916
+ * running turn.
2917
+ */
2918
+ answerPermission(id: string, decision: ApprovalDecision): boolean;
2760
2919
  protected turnPayload(message: string): string;
2761
2920
  protected handleLine(line: string, emit: (event: AgentEvent) => void): void;
2921
+ private turnStarted;
2922
+ private closeTurn;
2762
2923
  /**
2763
2924
  * The child thread id when `threadId` names a subagent's thread, or undefined
2764
2925
  * for the planner's own. Codex replays both threads on one stream and only
@@ -2779,6 +2940,14 @@ declare class CodexAdapter extends StdioAgentAdapter {
2779
2940
  * not added a second time. Codex reports no price.
2780
2941
  */
2781
2942
  private emitUsage;
2943
+ /**
2944
+ * A task's server→client request. An approval stays open for someone to
2945
+ * answer (ADR-0018, A1); everything else is answered at once, because an
2946
+ * unanswered request stalls the turn forever.
2947
+ */
2948
+ private openTaskRequest;
2949
+ /** The request as a person sees it, led by the field that says what it is about. */
2950
+ private approvalInput;
2782
2951
  /**
2783
2952
  * Refuse one server→client request. Requests whose result schema can express
2784
2953
  * a refusal get that payload; everything else — a permission grant, a
@@ -2804,7 +2973,8 @@ declare class CodexAdapter extends StdioAgentAdapter {
2804
2973
  }
2805
2974
 
2806
2975
  /**
2807
- * OpenCode as a planner, over its headless HTTP server (ADR-0009).
2976
+ * OpenCode as a planner or a task runner, over its headless HTTP server
2977
+ * (ADR-0009, ADR-0018).
2808
2978
  *
2809
2979
  * The odd one out: `opencode serve` is a real server rather than a stdio
2810
2980
  * protocol, so this adapter owns both halves of the boundary — it spawns the
@@ -2812,31 +2982,80 @@ declare class CodexAdapter extends StdioAgentAdapter {
2812
2982
  * talks to it through the injected `fetch`. Both are part of the one seam the
2813
2983
  * tests drive.
2814
2984
  *
2815
- * The turn ends when the message POST resolves, and its response is the
2985
+ * A planner turn ends when the message POST resolves, and its response is the
2816
2986
  * authoritative copy of the reply's last message. Everything else — reply text
2817
2987
  * as it streams, earlier model calls' text and reasoning, per-call usage, the
2818
2988
  * subagents a `task` call runs — arrives only on the server's `/event` channel.
2819
2989
  * An event name that changes between OpenCode versions therefore costs that
2820
- * detail, never the final reply.
2990
+ * detail, never the final reply. A task turn is posted asynchronously and read
2991
+ * entirely from the stream — see {@link sendTask}.
2821
2992
  */
2822
- declare class OpenCodeAdapter implements AgentAdapter {
2993
+ declare class OpenCodeAdapter implements TaskModeAgentAdapter {
2823
2994
  private deps;
2824
2995
  readonly agentId = "opencode";
2825
2996
  private process;
2826
2997
  private baseUrl;
2998
+ /** Sent on every request to a task's server, which a per-task password secures. */
2999
+ private authorization;
2827
3000
  private sessionId;
2828
3001
  private stderrTail;
2829
3002
  private exited;
3003
+ private exitCode;
2830
3004
  private disposed;
2831
- private opts;
3005
+ private markEnded;
3006
+ private readonly processEnded;
3007
+ private planner;
3008
+ private task;
2832
3009
  /** Whether this turn has already emitted reply text — see {@link emitPart}. */
2833
3010
  private turnHasText;
2834
3011
  /** The last assistant message already settled — the baseline {@link recoverReply} measures a new reply against. */
2835
3012
  private lastAssistantId;
3013
+ private taskTurn;
3014
+ /** An abort was posted during the current task turn, so the idle that follows ends it as interrupted. */
3015
+ private interruptRequested;
3016
+ /** A task's requests waiting for an answer, by request id, with the session that asked. */
3017
+ private readonly openPermissions;
2836
3018
  constructor(deps: AgentProcessDeps);
2837
- /** OpenCode only plans for now (#55): its tasks stay on the terminal transport. */
2838
- start(options: AgentStartOptions): Promise<void>;
3019
+ start(opts: AgentStartOptions): Promise<void>;
2839
3020
  send(message: string, onEvent: (event: AgentEvent) => void, signal?: AbortSignal, onActivity?: () => void): Promise<void>;
3021
+ /**
3022
+ * One task turn. `prompt_async` only queues the work, so the turn is over
3023
+ * when the session goes idle — OpenCode's own `run` rules: an idle frame
3024
+ * counts once `/session/status` confirms it, because a late idle can belong
3025
+ * to the turn before, and {@link pollStatus} stands behind the stream,
3026
+ * which can miss a status frame. No request is held open for the turn, so
3027
+ * fetch's 300s header timeout, the planner's reason for
3028
+ * {@link recoverReply}, never applies.
3029
+ */
3030
+ private sendTask;
3031
+ /**
3032
+ * Whatever of the turn's own messages the stream missed. Each part is
3033
+ * emitted once, so a turn the stream saw whole adds nothing here; one that
3034
+ * lost its last text part still reaches the plain-text channel, where the
3035
+ * done marker is looked for.
3036
+ */
3037
+ private readBack;
3038
+ /**
3039
+ * The stream can drop a status frame while still delivering the rest, so a
3040
+ * task turn also reads the status itself. A busy session is this turn's own
3041
+ * work as surely as a frame is.
3042
+ */
3043
+ private pollStatus;
3044
+ /** An idle frame ends the turn only if the server agrees now. When it will not say, the frame is trusted, as upstream trusts it. */
3045
+ private confirmIdle;
3046
+ /** Whether the task's session is working, or null when the server will not say. A session absent from the map is idle. */
3047
+ private sessionBusy;
3048
+ /** What a frame of the task's own session says about the turn's end. */
3049
+ private followTaskTurn;
3050
+ /**
3051
+ * Abort the running turn, keeping the server and its session. OpenCode
3052
+ * acknowledges by going idle, which is also what ends the turn — as
3053
+ * interrupted, because the request is remembered.
3054
+ */
3055
+ interrupt(timeoutMs: number): Promise<boolean>;
3056
+ onProcessExit(listener: (code: number) => void): void;
3057
+ answerPermission(id: string, decision: ApprovalDecision): boolean;
3058
+ private role;
2840
3059
  /**
2841
3060
  * Turn one settled assistant message into events. The settled response is
2842
3061
  * authoritative: it names the assistant message, so its parts are the ones
@@ -2905,6 +3124,27 @@ declare class OpenCodeAdapter implements AgentAdapter {
2905
3124
  * shows the planner reaching for something it may not have.
2906
3125
  */
2907
3126
  private denyPermission;
3127
+ /**
3128
+ * A task's request. Under a mode whose manifest sets `approvals: auto` —
3129
+ * `build`, which the terminal transport runs with `--auto` — it is answered
3130
+ * at once with what `run --auto` answers, so the same plan behaves the same
3131
+ * on both transports (ADR-0001), and announced already decided so the log
3132
+ * still shows it. Any other mode leaves it open for an approval card.
3133
+ */
3134
+ private askPermission;
3135
+ /**
3136
+ * `POST /permission/:id/reply` is the current answer. The per-session path
3137
+ * it replaced is tried only when a server too old to know the new one 404s.
3138
+ */
3139
+ private replyPermission;
3140
+ /**
3141
+ * Open `/event` for one turn and wait until it is connected. The stream
3142
+ * stopped being best-effort the moment permission answers moved onto it: a
3143
+ * request raised before we connect is one nobody answers, and the turn
3144
+ * hangs on it. Waiting is bounded so a server that never opens `/event`
3145
+ * still gets its turn.
3146
+ */
3147
+ private openStream;
2908
3148
  /**
2909
3149
  * Server-sent events from `/event`: the turn's live text, reasoning, tool
2910
3150
  * activity and usage, and the only channel permission requests arrive on —
@@ -2912,6 +3152,8 @@ declare class OpenCodeAdapter implements AgentAdapter {
2912
3152
  */
2913
3153
  private streamEvents;
2914
3154
  private json;
3155
+ private request;
3156
+ private headers;
2915
3157
  nativeSessionId(): string | null;
2916
3158
  dispose(): void;
2917
3159
  private exitMessage;
@@ -3301,7 +3543,7 @@ interface SessionEventRelayDeps {
3301
3543
  /** Where isolation notices go, for a host whose notifications are not seen by the user. */
3302
3544
  onNotice?: (notice: SessionNotice) => void;
3303
3545
  store: Pick<PlanStore, 'allTasks' | 'snapshot'>;
3304
- orchestrator: Pick<TaskOrchestrator, 'getIdleSince' | 'getTaskIsolation' | 'getQueuedTaskMessages'>;
3546
+ orchestrator: Pick<TaskOrchestrator, 'getIdleSince' | 'getTaskIsolation' | 'getQueuedTaskMessages' | 'getMergeGate' | 'mergeGateView'>;
3305
3547
  /** Shared with the Session, which snapshots, restores and clears it. */
3306
3548
  usage: PlannerUsageLedger;
3307
3549
  /** How many of a task's runner requests wait for an answer (ADR-0018, A1). */
@@ -3822,13 +4064,19 @@ declare class Session {
3822
4064
  * session asks here instead.
3823
4065
  */
3824
4066
  isolationView(): IsolationView | null;
4067
+ /** The dependencies a task waits on at its merge gate (ADR-0020); empty when it waits for no Merge all. */
4068
+ mergeGate(taskId: string): string[];
4069
+ /** What Merge all would merge mid-run, while any task waits at a merge gate; null otherwise. */
4070
+ mergeGateView(): MergeGateView | null;
3825
4071
  /** The run's integration branch against its base ref, as a unified diff. */
3826
4072
  reviewRunDiff(): Promise<string>;
3827
4073
  /**
3828
4074
  * "Merge all": each repo's integration branch into whatever the user has
3829
4075
  * checked out there — every repo, or none if any cannot take it. The one
3830
4076
  * irreversible step of isolated execution, so this explicit call is the
3831
- * only way it ever happens.
4077
+ * only way it ever happens. During a run it merges what has landed so far,
4078
+ * which is what opens a merge gate (ADR-0020); it waits for no ops task,
4079
+ * and refuses while one runs.
3832
4080
  */
3833
4081
  mergeRun(): Promise<IsolationMergeResult>;
3834
4082
  /** Remove the run's worktrees and task branches; keep its integration branch to review or merge. */
@@ -4410,6 +4658,8 @@ interface ComposeOptions {
4410
4658
  planMapEnabled?: boolean;
4411
4659
  planMapMaxEntries?: number;
4412
4660
  tddEnabled?: boolean;
4661
+ /** An ops task's last attempt, as its output ended (ADR-0020); absent on a first attempt. */
4662
+ previousAttempt?: string;
4413
4663
  }
4414
4664
  declare function composeAugmentedPrompt(task: Task, allTasks: readonly Task[], opts?: ComposeOptions): string;
4415
4665
  /**
@@ -4418,7 +4668,9 @@ declare function composeAugmentedPrompt(task: Task, allTasks: readonly Task[], o
4418
4668
  * original prompt, so it is not sent again — but it holds the old worktree
4419
4669
  * too, and this attempt's is fresh from the integration branch.
4420
4670
  */
4421
- declare function composeContinuationPrompt(task: Task, message: string): string;
4671
+ declare function composeContinuationPrompt(task: Task, message: string, opts?: {
4672
+ ops?: boolean;
4673
+ }): string;
4422
4674
 
4423
4675
  type ExecFileFn = (command: string, args: string[]) => Promise<{
4424
4676
  stdout: string;
@@ -4625,7 +4877,16 @@ declare class StructuredSession extends AbstractTerminalSession implements Struc
4625
4877
  */
4626
4878
  private restartInterrupted;
4627
4879
  private startAdapter;
4880
+ private openTurn;
4628
4881
  private deliver;
4882
+ private route;
4883
+ /**
4884
+ * The runner spoke with no message of ours in flight. When it is working — a
4885
+ * turn it opened itself once background work finished — that is a turn of the
4886
+ * task like any other: the state says working, a queued message waits, and its
4887
+ * end settles it. A message with no text in `turn_start` marks it as not ours.
4888
+ */
4889
+ private handleOutOfTurn;
4629
4890
  private openPermission;
4630
4891
  private cancelPermission;
4631
4892
  private handleEvent;
@@ -5007,14 +5268,11 @@ declare function resolveArgs(manifest: RunnerPluginManifest, ctx: ResolveContext
5007
5268
  /**
5008
5269
  * The manifest's meaning of a task's mode and effort, for a runner driven over
5009
5270
  * its programmatic protocol rather than a command line built from
5010
- * `argsTemplate` (ADR-0018, C1). Same functions and the same `{{if thinking}}`
5011
- * gate as the template path, so a structured task and a terminal task given
5012
- * the same plan run under the same permission mode and effort.
5271
+ * `argsTemplate` (ADR-0018, C1). The effort stays a raw id behind the same
5272
+ * `{{if thinking}}` gate as the template path: how an effort reaches the
5273
+ * runner is protocol, which each adapter owns.
5013
5274
  */
5014
- declare function resolveTaskRunnerFlags(manifest: RunnerPluginManifest, ctx: Pick<ResolveContext, 'mode' | 'model' | 'thinkingEffort'>): {
5015
- permissionMode: string;
5016
- effortArgs: string[];
5017
- };
5275
+ declare function resolveTaskRunnerFlags(manifest: RunnerPluginManifest, ctx: Pick<ResolveContext, 'mode' | 'model' | 'thinkingEffort'>): TaskRunnerFlags;
5018
5276
 
5019
5277
  declare const CLAUDE_CODE_MANIFEST: RunnerPluginManifest;
5020
5278
 
@@ -5145,4 +5403,4 @@ declare const DEFAULT_MAX_PARALLEL = 3;
5145
5403
  */
5146
5404
  declare function parseMaxParallel(value: unknown): number | null;
5147
5405
 
5148
- export { ALLOWED_PLUGIN_HOSTS, ALL_PROVIDERS, AUTO_COMMANDS, AbstractRunner, AbstractTerminalSession, ActiveTaskSession, type Adr0013IsolationRun, type Adr0013PlanIsolation, type Adr0013TaskRecord, AgentAdapter, AgentEvent, AgentProcessDeps, AgentStartOptions, AiProvider, ApplyTaskOpsResult, ApprovalAnswer, ApprovalDecision, ApprovalMode, ApprovalPolicy, ApprovalRequest, type AskOptions, AwaitingReason, BUILTIN_SKILL_NAMES, BaseAiService, BaseConfig, BaseFileSystem, BufferedTaskOutputSource, CLAUDE_CODE_MANIFEST, CLI_PROVIDERS, CORE_PLANNER_PROMPT, type CappedRows, type CheckpointListener, ClaudeCodeAdapter, CliAgentAiService, type CliAgentAiServiceDeps, CodexAdapter, type CommandClassification, type CommandTier, type ComposeOptions, ConsoleLogger, ContextCollector, type Continuability, ConversationBusyError, type ConversationCompaction, ConversationEditError, type ConversationFork, ConversationMessage, type ConversationRequest, type ConversationRewind, type ConversationTurn, type ConversationVariant, DAEMON_SUBPROTOCOL, DAEMON_TOKEN_SUBPROTOCOL_PREFIX, DEFAULT_MAX_PARALLEL, DiscoveredModel, type EnvAdmission, EnvConfig, type ExecFileFn, type ExecImpl, FindSymbolOptions, FsPluginStore, GIT_READONLY_SUBCOMMANDS, GeminiService, type GitExecFn, GlobOptions, type GrepInvocation, GrepOptions, type HasBinFn, HomeTranscriptReader, type IAiService, IApproval, IConfig, IFileSystem, type ILogger, type INotification, IPluginStore, ITerminalRunner, ITerminalSession, IWorktreeIsolation, IsolationHandoff, IsolationLandedTask, IsolationMergeResult, IsolationOutcome, IsolationRun, IsolationTaskRecord, IsolationTaskStatus, IsolationView, JSON_REPAIR_INSTRUCTION, type KillTreeDeps, LegacyPlanState, type LiveOutputLookup, type LiveTail, type LiveTailOptions, type MappedTool, ModelResolver, type ModelResolverDeps, type ModifyPlanRequest, type NotificationAction, OPENCODE_MANIFEST, ORDEWELL_SETTABLE_ENV, OUTPUT_LINES_DEFAULT, OUTPUT_LINES_MAX, OpenAiService, OpenCodeAdapter, type OrchestratorObserver, OrchestratorOption, PLUGIN_NAME_PATTERN, PROVIDER_CREDENTIAL_ENV, PROVIDER_DETECT_PRIORITY, PROVIDER_LABEL, PROVIDER_PRIORITY, PROVIDER_SHORT_LABEL, type PendingApproval, PendingApprovals, type PendingApprovalsOptions, PlanEditError, PlanIsolation, PlanParseError, type PlanRequest, PlanState, PlanStatus, PlanStore, Planner, type PlannerModelCandidate, type PlannerModelChoice, PlannerModelMemory, type PlannerModelRecall, type PlannerModelStore, type PlannerReplyClassification, type PlannerRuntimeToggles, PlannerUsage, type PluginSource, type PrdBlock, type PriorOutput, type ProbeFn, ProviderModelLists, type ProviderRegistration, QueuedMessage, QueuedTaskMessage, REFUSED_COMMANDS, ReadFileOpts, RepairEvidence, type RepairLoopOpts, type RepairVerdict, RepoGroupLayout, type ResearchChat, ResearchLogEntry, ResearchProgress, type ResearchShell, type ResearchShellDeps, ResearchToolType, type ResearchTurn, ResolveContext, type RewindTarget, RunnerApprovals, type RunnerCatalog, RunnerId, RunnerInstallation, RunnerInvocation, type RunnerMode, RunnerModeInfo, RunnerPluginManifest, RunnerRegistry, RunnerSpawnOptions, RunnerTransport, SETTINGS_ENV_ALLOWLIST, SETTINGS_ENV_REFUSED, STATE_DIR, STOPPED_TOOL_RESULT, SYMBOL_LANGUAGES, type SaveSession, Session, SessionBroadcaster, type SessionData, type SessionDeps, SessionMessage, type SessionMeta, SessionNotice, type SessionPlanner, type SessionRuntimeSettings, SettingsService, type ShellDialect, type SkillInfo, type SkillMetadata, SkillsService, type SpawnSpec, StdioAgentAdapter, StructuredEvent, StructuredRunner, type StructuredRunnerDeps, StructuredSession, StructuredSessionCapability, StructuredTurnEnd, TASK_QUERY_ANSWER_MAX_CHARS, TASK_QUERY_ANSWER_OR_OPS, TASK_QUERY_FIELDS, TASK_QUERY_PROTOCOL, TASK_QUERY_REMINDER, TRUNCATED_PLAN_REPAIR_INSTRUCTION, Task, type TaskAttemptSnapshot, TaskControlError, TaskIsolation, TaskLogEvent, type TaskLogFile, type TaskLogLocation, TaskLogRecorder, type TaskLogRecorderDeps, TaskModeAgentAdapter, TaskOp, TaskOrchestrator, type TaskOrchestratorDeps, type TaskOrchestratorOptions, type TaskOutputAttempt, type TaskOutputSource, type TaskQuery, type TaskQueryCatalog, type TaskQueryField, TaskSnapshot, TaskStartOptions, TmuxRunner, type TmuxRunnerDeps, type TokenCarriers, type ToolCall, ToolOutcome, type ToolResult, type TranscriptQuery, type TranscriptReader, type TransportRoute, TransportRouter, UsageRecord, type UserSettings, Verdict, VerdictEngine, type VerdictListener, type WorkspaceCheckDeps, WorkspaceNotAProjectError, WorkspaceNotFoundError, type WorkspaceProjectCheckDeps, type WorktreeIsolationDeps, admitSettingsEnv, applyHeadLimit, assertInstallablePluginUrl, assertPlainPluginName, assertWorkspaceExists, assertWorkspaceIsProject, augmentPromptWithPriorOutputs, augmentedPath, bearerHeaderValue, buildConflictRepairPrompt, buildConflictResolutionPrompt, buildConversationSystemPrompt, buildFallbackGrepArgs, buildGlobArgs, buildGrepArgs, buildMergePrompt, buildModifyDuringExecutionPrompt, buildModifyPlanPrompt, buildPlanWithResults, buildResearchPrompt, buildResearchToolsPrompt, buildRunnerInvocation, buildSplitPrompt, buildSubagentSystemPrompt, canContinue, clampThinkingEffort, classifyCommand, classifyPlannerReply, classifyPluginSource, clearAugmentedPathCache, clearDaemonToken, clearResearchShellCache, clearState, clipboardCopyCommand, coerceAssignments, collectDirectDependencyOutputs, composeAugmentedPrompt, composeContinuationPrompt, configuredProviders, continuability, createAiService, createSession, createSkillsService, createTaskAdapter, createTaskOrchestrator, createWorktreeIsolation, daemonTokenPath, defaultLogger, definitionPattern, deleteSession, describeMergeResult, discoverGeminiModels, effectiveAllowlist, ensureDir, ensurePrivateDir, ensureStateDirIgnored, executionLogBlock, extractPrdBlock, extractPresentedToken, filterFallbackByAnchoredInclude, filterModelsForPrompt, formatSearchOutput, generatePlanWithRepair, getLatestSession, getProviderMeta, getSettingsPath, getStateDir, globalDataDir, grantScopeFor, hasTmux, idSegment, includeGlobFor, isCliProvider, isOpenAiProvider, isPlainPluginName, isValidManifest, killTree, languageForId, listSessions, listTaskLogAttempts, loadSession, loadSessionPlanState, loadState, mapAgentTool, migrateOldConfigDir, migratePlanIsolation, mintDaemonToken, mintSessionId, modelContextBlock, modifyValidationFeedback, normalizeAgentArgs, normalizeGeminiModel, openTaskLog, parseMaxParallel, parseTaskQueryJson, pendingEditRulesBlock, prefixModelId, providerForRunner, reEmitPlanPrompt, reEmitTaskOpsPrompt, reEmitTaskQueryPrompt, readDaemonToken, readTaskLog, referencePattern, renderPlanMap, renderPriorOutputs, renderTaskQueryAnswer, repairLoop, researchShellWarning, researchToolsPath, resolveArgs, resolvePluginInstallDir, resolveProviderFromPrefix, resolveResearchShell, resolveSkillInvocation, resolveTaskRunnerFlags, resolveWithin, retargetTaskRunner, routeTransport, runnerAssignment, runnerForProvider, sanitizeSlug, savePrdMarkdown, saveSession, saveState, sessionDataDir, sessionRuntimeSettings, stateExists, stripModelPrefix, summarizeOutput, supportsTaskMode, taskOpsRejectedPrompt, taskQuerySignature, textHasTaskQuery, tmuxSessionName, tmuxSocketName, tmuxWindowName, tokenSubprotocols, tokensMatch, truncatedPlanReEmitPrompt, wellKnownBinDirs, withPath, writePrivateFile };
5406
+ export { ALLOWED_PLUGIN_HOSTS, ALL_PROVIDERS, AUTO_COMMANDS, AbstractRunner, AbstractTerminalSession, ActiveTaskSession, type Adr0013IsolationRun, type Adr0013PlanIsolation, type Adr0013TaskRecord, AgentAdapter, AgentEvent, AgentProcessDeps, AgentStartOptions, AiProvider, ApplyTaskOpsResult, ApprovalAnswer, ApprovalDecision, ApprovalMode, ApprovalPolicy, ApprovalRequest, type AskOptions, AwaitingReason, BUILTIN_SKILL_NAMES, BaseAiService, BaseConfig, BaseFileSystem, BufferedTaskOutputSource, CLAUDE_CODE_MANIFEST, CLI_PROVIDERS, CORE_PLANNER_PROMPT, type CappedRows, type CheckpointListener, ClaudeCodeAdapter, CliAgentAiService, type CliAgentAiServiceDeps, CodexAdapter, type CommandClassification, type CommandTier, type ComposeOptions, ConsoleLogger, ContextCollector, type Continuability, ConversationBusyError, type ConversationCompaction, ConversationEditError, type ConversationFork, ConversationMessage, type ConversationRequest, type ConversationRewind, type ConversationTurn, type ConversationVariant, DAEMON_SUBPROTOCOL, DAEMON_TOKEN_SUBPROTOCOL_PREFIX, DEFAULT_MAX_PARALLEL, DiscoveredModel, type EnvAdmission, EnvConfig, type ExecFileFn, type ExecImpl, FindSymbolOptions, FsPluginStore, GIT_READONLY_SUBCOMMANDS, GeminiService, type GitExecFn, GlobOptions, type GrepInvocation, GrepOptions, type HasBinFn, HomeTranscriptReader, type IAiService, IApproval, IConfig, IFileSystem, type ILogger, type INotification, IPluginStore, ITerminalRunner, ITerminalSession, IWorktreeIsolation, IsolationHandoff, IsolationLandedTask, IsolationMergeResult, IsolationOutcome, IsolationRun, IsolationTaskRecord, IsolationTaskStatus, IsolationView, JSON_REPAIR_INSTRUCTION, type KillTreeDeps, LegacyPlanState, type LiveOutputLookup, type LiveTail, type LiveTailOptions, type MappedTool, MergeGateView, ModelResolver, type ModelResolverDeps, type ModifyPlanRequest, type NotificationAction, OPENCODE_MANIFEST, ORDEWELL_SETTABLE_ENV, OUTPUT_LINES_DEFAULT, OUTPUT_LINES_MAX, OpenAiService, OpenCodeAdapter, type OrchestratorObserver, OrchestratorOption, PLUGIN_NAME_PATTERN, PROVIDER_CREDENTIAL_ENV, PROVIDER_DETECT_PRIORITY, PROVIDER_LABEL, PROVIDER_PRIORITY, PROVIDER_SHORT_LABEL, type PendingApproval, PendingApprovals, type PendingApprovalsOptions, PlanEditError, PlanIsolation, PlanParseError, type PlanRequest, PlanState, PlanStatus, PlanStore, Planner, type PlannerModelCandidate, type PlannerModelChoice, PlannerModelMemory, type PlannerModelRecall, type PlannerModelStore, type PlannerReplyClassification, type PlannerRuntimeToggles, PlannerUsage, type PluginSource, type PrdBlock, type PriorOutput, type ProbeFn, ProviderModelLists, type ProviderRegistration, QueuedMessage, QueuedTaskMessage, REFUSED_COMMANDS, ReadFileOpts, RepairEvidence, type RepairLoopOpts, type RepairVerdict, RepoGroupLayout, type ResearchChat, ResearchLogEntry, ResearchProgress, type ResearchShell, type ResearchShellDeps, ResearchToolType, type ResearchTurn, ResolveContext, type RewindTarget, RunnerApprovals, type RunnerCatalog, RunnerId, RunnerInstallation, RunnerInvocation, type RunnerMode, RunnerModeInfo, RunnerPluginManifest, RunnerRegistry, RunnerSpawnOptions, RunnerTransport, SETTINGS_ENV_ALLOWLIST, SETTINGS_ENV_REFUSED, STATE_DIR, STOPPED_TOOL_RESULT, SYMBOL_LANGUAGES, type SaveSession, Session, SessionBroadcaster, type SessionData, type SessionDeps, SessionMessage, type SessionMeta, SessionNotice, type SessionPlanner, type SessionRuntimeSettings, SettingsService, type ShellDialect, type SkillInfo, type SkillMetadata, SkillsService, type SpawnSpec, StdioAgentAdapter, StructuredEvent, StructuredRunner, type StructuredRunnerDeps, StructuredSession, StructuredSessionCapability, StructuredTurnEnd, TASK_QUERY_ANSWER_MAX_CHARS, TASK_QUERY_ANSWER_OR_OPS, TASK_QUERY_FIELDS, TASK_QUERY_PROTOCOL, TASK_QUERY_REMINDER, TRUNCATED_PLAN_REPAIR_INSTRUCTION, Task, type TaskAttemptSnapshot, TaskControlError, TaskIsolation, TaskLogEvent, type TaskLogFile, type TaskLogLocation, TaskLogRecorder, type TaskLogRecorderDeps, TaskModeAgentAdapter, TaskOp, TaskOrchestrator, type TaskOrchestratorDeps, type TaskOrchestratorOptions, type TaskOutputAttempt, type TaskOutputSource, type TaskQuery, type TaskQueryCatalog, type TaskQueryField, TaskRunnerFlags, TaskSnapshot, TaskStartOptions, TmuxRunner, type TmuxRunnerDeps, type TokenCarriers, type ToolCall, ToolOutcome, type ToolResult, type TranscriptQuery, type TranscriptReader, type TransportRoute, TransportRouter, TreeSnapshot, UsageRecord, type UserSettings, Verdict, VerdictEngine, type VerdictListener, type WorkspaceCheckDeps, WorkspaceNotAProjectError, WorkspaceNotFoundError, type WorkspaceProjectCheckDeps, type WorktreeIsolationDeps, admitSettingsEnv, applyHeadLimit, assertInstallablePluginUrl, assertPlainPluginName, assertWorkspaceExists, assertWorkspaceIsProject, augmentPromptWithPriorOutputs, augmentedPath, bearerHeaderValue, buildConflictRepairPrompt, buildConflictResolutionPrompt, buildConversationSystemPrompt, buildFallbackGrepArgs, buildGlobArgs, buildGrepArgs, buildMergePrompt, buildModifyDuringExecutionPrompt, buildModifyPlanPrompt, buildPlanWithResults, buildResearchPrompt, buildResearchToolsPrompt, buildRunnerInvocation, buildSplitPrompt, buildSubagentSystemPrompt, canContinue, clampThinkingEffort, classifyCommand, classifyPlannerReply, classifyPluginSource, clearAugmentedPathCache, clearDaemonToken, clearResearchShellCache, clearState, clipboardCopyCommand, coerceAssignments, collectDirectDependencyOutputs, composeAugmentedPrompt, composeContinuationPrompt, configuredProviders, continuability, createAiService, createSession, createSkillsService, createTaskAdapter, createTaskOrchestrator, createWorktreeIsolation, daemonTokenPath, defaultLogger, definitionPattern, deleteSession, describeMergeResult, discoverGeminiModels, effectiveAllowlist, ensureDir, ensurePrivateDir, ensureStateDirIgnored, executionLogBlock, extractPrdBlock, extractPresentedToken, filterFallbackByAnchoredInclude, filterModelsForPrompt, formatSearchOutput, generatePlanWithRepair, getLatestSession, getProviderMeta, getSettingsPath, getStateDir, globalDataDir, grantScopeFor, hasTmux, idSegment, includeGlobFor, isCliProvider, isOpenAiProvider, isPlainPluginName, isValidManifest, killTree, languageForId, listSessions, listTaskLogAttempts, loadSession, loadSessionPlanState, loadState, mapAgentTool, migrateOldConfigDir, migratePlanIsolation, mintDaemonToken, mintSessionId, modelContextBlock, modifyValidationFeedback, normalizeAgentArgs, normalizeGeminiModel, openTaskLog, parseMaxParallel, parseTaskQueryJson, pendingEditRulesBlock, prefixModelId, providerForRunner, reEmitPlanPrompt, reEmitTaskOpsPrompt, reEmitTaskQueryPrompt, readDaemonToken, readTaskLog, referencePattern, renderPlanMap, renderPriorOutputs, renderTaskQueryAnswer, repairLoop, researchShellWarning, researchToolsPath, resolveArgs, resolvePluginInstallDir, resolveProviderFromPrefix, resolveResearchShell, resolveSkillInvocation, resolveTaskRunnerFlags, resolveWithin, retargetTaskRunner, routeTransport, runnerAssignment, runnerForProvider, sanitizeSlug, savePrdMarkdown, saveSession, saveState, sessionDataDir, sessionRuntimeSettings, stateExists, stripModelPrefix, summarizeOutput, supportsTaskMode, taskOpsRejectedPrompt, taskQuerySignature, textHasTaskQuery, tmuxSessionName, tmuxSocketName, tmuxWindowName, tokenSubprotocols, tokensMatch, truncatedPlanReEmitPrompt, wellKnownBinDirs, withPath, writePrivateFile };