@ordewell/core 0.6.4 → 0.7.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 (54) hide show
  1. package/README.md +1 -1
  2. package/dist/{IFileSystem-Qj2MWHn_.d.mts → IFileSystem-BnLh-_SK.d.mts} +1 -1
  3. package/dist/{IFileSystem-DQEKyC6H.d.ts → IFileSystem-DofiRcCo.d.ts} +1 -1
  4. package/dist/{ModeResolver-rqaY_4Ex.d.mts → ModeResolver-DZzJSdIU.d.mts} +3 -3
  5. package/dist/{ModeResolver-ByNpC0EP.d.ts → ModeResolver-DkMYf4uS.d.ts} +3 -3
  6. package/dist/{Task-xqdxugt2.d.mts → Task-BnLxkVQF.d.mts} +414 -22
  7. package/dist/{Task-xqdxugt2.d.ts → Task-BnLxkVQF.d.ts} +414 -22
  8. package/dist/{chunk-JRZPSNRO.mjs → chunk-LGQNXPBX.mjs} +10 -2
  9. package/dist/chunk-LGQNXPBX.mjs.map +1 -0
  10. package/dist/{chunk-N66ZHFGN.mjs → chunk-OYUSADFM.mjs} +11 -1
  11. package/dist/chunk-OYUSADFM.mjs.map +1 -0
  12. package/dist/{chunk-HPNUFBIT.mjs → chunk-V3JHS7AX.mjs} +9 -1
  13. package/dist/chunk-V3JHS7AX.mjs.map +1 -0
  14. package/dist/{chunk-I6U3PVHL.mjs → chunk-Y36NIASW.mjs} +255 -32
  15. package/dist/chunk-Y36NIASW.mjs.map +1 -0
  16. package/dist/{chunk-M4KXBEFJ.mjs → chunk-ZV5LDNCO.mjs} +44 -43
  17. package/dist/chunk-ZV5LDNCO.mjs.map +1 -0
  18. package/dist/index.d.mts +518 -238
  19. package/dist/index.d.ts +518 -238
  20. package/dist/index.js +3925 -1568
  21. package/dist/index.js.map +1 -1
  22. package/dist/index.mjs +3525 -1393
  23. package/dist/index.mjs.map +1 -1
  24. package/dist/order-labels.d.mts +16 -2
  25. package/dist/order-labels.d.ts +16 -2
  26. package/dist/order-labels.js +12 -2
  27. package/dist/order-labels.js.map +1 -1
  28. package/dist/order-labels.mjs +7 -3
  29. package/dist/{parsing-DDZ1rUYa.d.mts → parsing-B6ctfF80.d.mts} +24 -3
  30. package/dist/{parsing-COPG8-Ep.d.ts → parsing-ddZXZFP4.d.ts} +24 -3
  31. package/dist/parsing.d.mts +4 -3
  32. package/dist/parsing.d.ts +4 -3
  33. package/dist/parsing.js +42 -41
  34. package/dist/parsing.js.map +1 -1
  35. package/dist/parsing.mjs +3 -3
  36. package/dist/{plan-utils-Br8UAoiu.d.ts → plan-utils--kQRzSE-.d.ts} +251 -7
  37. package/dist/{plan-utils-DMgajMvd.d.mts → plan-utils-CKgNtDwQ.d.mts} +251 -7
  38. package/dist/plan-utils.d.mts +5 -3
  39. package/dist/plan-utils.d.ts +5 -3
  40. package/dist/plan-utils.js +313 -61
  41. package/dist/plan-utils.js.map +1 -1
  42. package/dist/plan-utils.mjs +46 -3
  43. package/dist/testing.d.mts +26 -5
  44. package/dist/testing.d.ts +26 -5
  45. package/dist/testing.js +62 -2
  46. package/dist/testing.js.map +1 -1
  47. package/dist/testing.mjs +62 -4
  48. package/dist/testing.mjs.map +1 -1
  49. package/package.json +4 -2
  50. package/dist/chunk-HPNUFBIT.mjs.map +0 -1
  51. package/dist/chunk-I6U3PVHL.mjs.map +0 -1
  52. package/dist/chunk-JRZPSNRO.mjs.map +0 -1
  53. package/dist/chunk-M4KXBEFJ.mjs.map +0 -1
  54. package/dist/chunk-N66ZHFGN.mjs.map +0 -1
@@ -1,5 +1,6 @@
1
1
  import { ChildProcess } from 'child_process';
2
2
  import { EventEmitter } from 'events';
3
+ import { z } from 'zod/v4';
3
4
 
4
5
  /**
5
6
  * Why isolated execution is unavailable for a workspace. The orchestrator needs
@@ -300,18 +301,49 @@ interface PreparedTask {
300
301
  * stay in the task, so the user is told.
301
302
  */
302
303
  copied: string[];
304
+ /** What the attempt this one replaces left unlanded, kept on a branch before its worktree went; absent when nothing was. */
305
+ preserved?: PreservedWork[];
306
+ }
307
+ /** A task as a removal names it. */
308
+ type IsolationTaskRef = Pick<IsolationTaskRecord, 'taskId' | 'order' | 'title'>;
309
+ /**
310
+ * Work a removal found that had not landed — edits never committed, or
311
+ * commits only the task's branch carried — committed and kept on `branch`,
312
+ * a branch of its own under `ordewell-preserved/`, before the worktree went.
313
+ */
314
+ interface PreservedWork {
315
+ /** Absent for a leftover directory no task record owned. */
316
+ task?: IsolationTaskRef;
317
+ repo: string;
318
+ branch: string;
319
+ /** The commit `branch` points at. */
320
+ commit: string;
321
+ }
322
+ /** A worktree a removal left in place, because the work in it could not be kept any other way. */
323
+ interface RefusedRemoval {
324
+ /** Absent for a leftover directory no task record owned. */
325
+ task?: IsolationTaskRef;
326
+ worktree: string;
327
+ /** What stopped git keeping it, in words a surface can repeat. */
328
+ reason: string;
329
+ }
330
+ /**
331
+ * What removing task worktrees did in place of deleting work. A removal never
332
+ * deletes work that has not landed: it keeps it on a branch first
333
+ * (`preserved`), and where it cannot, it leaves that worktree alone
334
+ * (`refused`) — so the record of a refused task stays too.
335
+ */
336
+ interface IsolationRemoval {
337
+ preserved: PreservedWork[];
338
+ refused: RefusedRemoval[];
303
339
  }
304
340
  /**
305
341
  * What a crash-recovery prune found and left alone: task records that were
306
342
  * `active` yet still held unlanded work, so the prune kept them as `kept`
307
343
  * rather than deleting work no one else has.
308
344
  */
309
- interface IsolationPruneResult {
310
- kept: Array<{
311
- taskId: string;
312
- order: number;
313
- title: string;
314
- }>;
345
+ interface IsolationPruneResult extends IsolationRemoval {
346
+ kept: IsolationTaskRef[];
315
347
  }
316
348
  /**
317
349
  * The tracked changes of a workspace's repos at one moment, against each
@@ -378,7 +410,9 @@ interface IWorktreeIsolation {
378
410
  integrate(task: Task, run: IsolationRun, persist?: () => void): Promise<IsolationOutcome>;
379
411
  /**
380
412
  * `keep: false` removes the task's worktree, branch and record (retry, task
381
- * removal). `keep: true` leaves the worktree and branch exactly as they are
413
+ * removal), keeping whatever had not landed on a branch first; a record
414
+ * whose work cannot be kept stays, off `active`. `keep: true` leaves the
415
+ * worktree and branch exactly as they are
382
416
  * for inspection — a failed verdict, a stop, a cancel — and only moves the task off `active`,
383
417
  * so a crash-recovery prune does not sweep it away; a repair it ends leaves
384
418
  * the task `conflict`, as it was before the repair. Takes the run rather than
@@ -387,7 +421,7 @@ interface IWorktreeIsolation {
387
421
  */
388
422
  release(run: IsolationRun, taskId: string, opts: {
389
423
  keep: boolean;
390
- }): Promise<void>;
424
+ }): Promise<IsolationRemoval>;
391
425
  /** End of run: park the integration branch for review and report what landed. */
392
426
  handoff(run: IsolationRun): Promise<IsolationHandoff>;
393
427
  /**
@@ -397,7 +431,8 @@ interface IWorktreeIsolation {
397
431
  * that still holds unlanded work — commits its branch alone carries, or
398
432
  * edits in its worktree — is not a crash orphan: it may belong to a runner
399
433
  * another host is still driving, so it is kept as `kept` and named in the
400
- * result.
434
+ * result. A leftover directory holding work is kept on a branch before it
435
+ * goes, as {@link release} does.
401
436
  */
402
437
  pruneOrphans(run: IsolationRun): Promise<IsolationPruneResult>;
403
438
  /** Unified diff of each repo's integration branch against its base ref. */
@@ -435,11 +470,12 @@ interface IWorktreeIsolation {
435
470
  /**
436
471
  * Remove every worktree and task branch of the run, and settle each repo's
437
472
  * integration branch as `integration` says. Anything but `keep` also clears
438
- * the run's task records.
473
+ * the run's task records, except those of worktrees it refused to remove.
474
+ * Work that had not landed is kept on a branch first, as {@link release} does.
439
475
  */
440
476
  discard(run: IsolationRun, opts: {
441
477
  integration: IntegrationDisposal;
442
- }): Promise<void>;
478
+ }): Promise<IsolationRemoval>;
443
479
  /**
444
480
  * Clear what other runs left in each repo of `run`'s group: every
445
481
  * `ordewell/<run-id>/…` branch the repo's checked-out HEAD already contains.
@@ -914,6 +950,250 @@ interface IApproval {
914
950
  /** Denies everything. The safe default when a surface wires no approval channel. */
915
951
  declare const DENY_ALL: IApproval;
916
952
 
953
+ /**
954
+ * The tools of the Ordewell MCP server, per token role (ADR-0022), and the
955
+ * handler interfaces the session side implements to answer them.
956
+ *
957
+ * Every handler method is optional so each tool can be wired on its own; one
958
+ * left unset answers its call with a "not available" error rather than
959
+ * disappearing from `tools/list`, so the list a runner sees never depends on
960
+ * how far the wiring has got.
961
+ */
962
+ declare const taskCompleteInput: z.ZodObject<{
963
+ status: z.ZodEnum<{
964
+ failed: "failed";
965
+ blocked: "blocked";
966
+ done: "done";
967
+ }>;
968
+ summary: z.ZodString;
969
+ reason: z.ZodOptional<z.ZodString>;
970
+ }, z.core.$strip>;
971
+ declare const checkpointInput: z.ZodObject<{
972
+ question: z.ZodString;
973
+ }, z.core.$strip>;
974
+ declare const listRunnersInput: z.ZodObject<{}, z.core.$strip>;
975
+ declare const listModelsInput: z.ZodObject<{
976
+ runner: z.ZodString;
977
+ }, z.core.$strip>;
978
+ declare const submitPlanInput: z.ZodObject<{
979
+ tasks: z.ZodArray<z.ZodObject<{
980
+ id: z.ZodOptional<z.ZodString>;
981
+ order: z.ZodOptional<z.ZodNumber>;
982
+ title: z.ZodString;
983
+ description: z.ZodOptional<z.ZodString>;
984
+ type: z.ZodOptional<z.ZodEnum<{
985
+ user: "user";
986
+ ai: "ai";
987
+ }>>;
988
+ dependencies: z.ZodOptional<z.ZodArray<z.ZodString>>;
989
+ prompt: z.ZodOptional<z.ZodString>;
990
+ userSteps: z.ZodOptional<z.ZodArray<z.ZodObject<{
991
+ order: z.ZodOptional<z.ZodNumber>;
992
+ instruction: z.ZodString;
993
+ }, z.core.$loose>>>;
994
+ assignedRunner: z.ZodOptional<z.ZodString>;
995
+ assignedModel: z.ZodOptional<z.ZodObject<{
996
+ modelId: z.ZodString;
997
+ modelLabel: z.ZodOptional<z.ZodString>;
998
+ thinkingEffort: z.ZodOptional<z.ZodString>;
999
+ }, z.core.$loose>>;
1000
+ taskMode: z.ZodOptional<z.ZodString>;
1001
+ autonomy: z.ZodOptional<z.ZodEnum<{
1002
+ AFK: "AFK";
1003
+ HITL: "HITL";
1004
+ }>>;
1005
+ sliceType: z.ZodOptional<z.ZodEnum<{
1006
+ AFK: "AFK";
1007
+ HITL: "HITL";
1008
+ }>>;
1009
+ ops: z.ZodOptional<z.ZodBoolean>;
1010
+ userStoriesCovered: z.ZodOptional<z.ZodArray<z.ZodString>>;
1011
+ subtasks: z.ZodOptional<z.ZodArray<z.ZodRecord<z.ZodString, z.ZodUnknown>>>;
1012
+ }, z.core.$loose>>;
1013
+ }, z.core.$strip>;
1014
+ declare const editPlanInput: z.ZodObject<{
1015
+ ops: z.ZodArray<z.ZodDiscriminatedUnion<[z.ZodObject<{
1016
+ op: z.ZodLiteral<"update">;
1017
+ taskId: z.ZodUnion<readonly [z.ZodString, z.ZodNumber]>;
1018
+ changes: z.ZodRecord<z.ZodString, z.ZodUnknown>;
1019
+ }, z.core.$strip>, z.ZodObject<{
1020
+ op: z.ZodLiteral<"add">;
1021
+ task: z.ZodRecord<z.ZodString, z.ZodUnknown>;
1022
+ handle: z.ZodOptional<z.ZodString>;
1023
+ }, z.core.$strip>, z.ZodObject<{
1024
+ op: z.ZodLiteral<"remove">;
1025
+ taskId: z.ZodUnion<readonly [z.ZodString, z.ZodNumber]>;
1026
+ }, z.core.$strip>, z.ZodObject<{
1027
+ op: z.ZodLiteral<"reorder">;
1028
+ taskIds: z.ZodArray<z.ZodUnion<readonly [z.ZodString, z.ZodNumber]>>;
1029
+ }, z.core.$strip>, z.ZodObject<{
1030
+ op: z.ZodLiteral<"merge">;
1031
+ taskIds: z.ZodArray<z.ZodUnion<readonly [z.ZodString, z.ZodNumber]>>;
1032
+ merged: z.ZodRecord<z.ZodString, z.ZodUnknown>;
1033
+ handle: z.ZodOptional<z.ZodString>;
1034
+ }, z.core.$strip>, z.ZodObject<{
1035
+ op: z.ZodLiteral<"split">;
1036
+ taskId: z.ZodUnion<readonly [z.ZodString, z.ZodNumber]>;
1037
+ parts: z.ZodArray<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
1038
+ handle: z.ZodOptional<z.ZodString>;
1039
+ }, z.core.$strip>, z.ZodObject<{
1040
+ op: z.ZodLiteral<"rearm">;
1041
+ taskId: z.ZodUnion<readonly [z.ZodString, z.ZodNumber]>;
1042
+ changes: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
1043
+ }, z.core.$strip>]>>;
1044
+ }, z.core.$strip>;
1045
+ declare const taskQueryInput: z.ZodObject<{
1046
+ tasks: z.ZodOptional<z.ZodArray<z.ZodUnion<readonly [z.ZodString, z.ZodNumber]>>>;
1047
+ fields: z.ZodOptional<z.ZodArray<z.ZodEnum<{
1048
+ description: "description";
1049
+ prompt: "prompt";
1050
+ userSteps: "userSteps";
1051
+ verdict: "verdict";
1052
+ outputSummary: "outputSummary";
1053
+ userStoriesCovered: "userStoriesCovered";
1054
+ }>>>;
1055
+ catalog: z.ZodOptional<z.ZodBoolean>;
1056
+ }, z.core.$strip>;
1057
+ declare const taskOutputInput: z.ZodObject<{
1058
+ task: z.ZodUnion<readonly [z.ZodString, z.ZodNumber]>;
1059
+ lines: z.ZodOptional<z.ZodNumber>;
1060
+ since: z.ZodOptional<z.ZodNumber>;
1061
+ }, z.core.$strip>;
1062
+ type TaskCompleteArgs = z.infer<typeof taskCompleteInput>;
1063
+ type CheckpointArgs = z.infer<typeof checkpointInput>;
1064
+ type ListRunnersArgs = z.infer<typeof listRunnersInput>;
1065
+ type ListModelsArgs = z.infer<typeof listModelsInput>;
1066
+ type SubmitPlanArgs = z.infer<typeof submitPlanInput>;
1067
+ type EditPlanArgs = z.infer<typeof editPlanInput>;
1068
+ type TaskQueryArgs = z.infer<typeof taskQueryInput>;
1069
+ type TaskOutputArgs = z.infer<typeof taskOutputInput>;
1070
+ /** What a handler answers with. `isError` marks a refusal the caller should act on. */
1071
+ interface McpToolReply {
1072
+ text: string;
1073
+ isError?: boolean;
1074
+ }
1075
+ /**
1076
+ * How a checkpoint call ended. `withdrawn` is the attempt going away under it
1077
+ * (verdict, cancel, retry, stop) or the call being refused, not a verdict on
1078
+ * the question.
1079
+ */
1080
+ type CheckpointAnswer = {
1081
+ kind: 'continue';
1082
+ } | {
1083
+ kind: 'rejected';
1084
+ reason: string;
1085
+ } | {
1086
+ kind: 'withdrawn';
1087
+ why: string;
1088
+ };
1089
+ interface McpToolContext {
1090
+ /** Aborts when the token is revoked or the caller cancels — a waiting handler must stop. */
1091
+ signal: AbortSignal;
1092
+ }
1093
+ type Run<A> = (args: A, context: McpToolContext) => Promise<McpToolReply>;
1094
+ interface TaskToolHandler {
1095
+ taskComplete?: Run<TaskCompleteArgs>;
1096
+ checkpoint?: Run<CheckpointArgs>;
1097
+ }
1098
+ interface PlannerToolHandler {
1099
+ listRunners?: Run<ListRunnersArgs>;
1100
+ listModels?: Run<ListModelsArgs>;
1101
+ submitPlan?: Run<SubmitPlanArgs>;
1102
+ editPlan?: Run<EditPlanArgs>;
1103
+ taskQuery?: Run<TaskQueryArgs>;
1104
+ taskOutput?: Run<TaskOutputArgs>;
1105
+ }
1106
+ interface McpTool<H> {
1107
+ name: string;
1108
+ description: string;
1109
+ inputSchema: {
1110
+ type: 'object';
1111
+ [key: string]: unknown;
1112
+ };
1113
+ annotations?: {
1114
+ readOnlyHint: boolean;
1115
+ };
1116
+ /** Validate `args` and hand them to the handler's method for this tool. */
1117
+ call(handler: H, args: unknown, context: McpToolContext): Promise<McpToolReply>;
1118
+ }
1119
+ /** The task tool whose call settles the attempt (ADR-0022, V1). */
1120
+ declare const TASK_COMPLETE_TOOL = "task_complete";
1121
+ declare const TASK_TOOLS: readonly McpTool<TaskToolHandler>[];
1122
+ declare const PLANNER_TOOLS: readonly McpTool<PlannerToolHandler>[];
1123
+
1124
+ /**
1125
+ * The Ordewell MCP server (ADR-0022): one loopback listener per process,
1126
+ * shared by every session in it, where the caller's token alone decides which
1127
+ * tools it sees and which session and task its calls reach.
1128
+ */
1129
+ declare const ORDEWELL_MCP_PATH = "/mcp";
1130
+ interface OrdewellMcpServerOptions {
1131
+ /** How often a call that is still waiting tells its caller so. */
1132
+ heartbeatMs?: number;
1133
+ }
1134
+ interface TaskTokenScope {
1135
+ sessionId: string;
1136
+ taskId: string;
1137
+ /** The attempt generation the token is good for; a later attempt gets a new token. */
1138
+ attempt: number;
1139
+ }
1140
+ interface PlannerTokenScope {
1141
+ sessionId: string;
1142
+ }
1143
+ /** Where a runner reaches the server and what it presents there. Never put either half in a prompt. */
1144
+ interface McpCredential {
1145
+ url: string;
1146
+ token: string;
1147
+ }
1148
+ declare class OrdewellMcpServer {
1149
+ private readonly grants;
1150
+ private http;
1151
+ private listening;
1152
+ private boundUrl;
1153
+ private boundHost;
1154
+ private readonly heartbeatMs;
1155
+ constructor(options?: OrdewellMcpServerOptions);
1156
+ /** The listener's URL, once the first token has started it. */
1157
+ get url(): string | undefined;
1158
+ issueTaskToken(scope: TaskTokenScope, handler?: TaskToolHandler): Promise<McpCredential>;
1159
+ issuePlannerToken(scope: PlannerTokenScope, handler?: PlannerToolHandler): Promise<McpCredential>;
1160
+ /** Refuse every later request carrying `token`, and abort the calls it has in flight. */
1161
+ revoke(token: string): void;
1162
+ dispose(): Promise<void>;
1163
+ private issue;
1164
+ private start;
1165
+ private handle;
1166
+ }
1167
+ /** The process's one server, which the daemon and the extension host hand to every session they build. */
1168
+ declare function sharedMcpServer(): OrdewellMcpServer;
1169
+
1170
+ /** The server's name in every runner's MCP configuration, and so in its tool names (`mcp__ordewell__*`). */
1171
+ declare const ORDEWELL_MCP_SERVER_NAME = "ordewell";
1172
+ interface McpClientConfig {
1173
+ name: typeof ORDEWELL_MCP_SERVER_NAME;
1174
+ url: string;
1175
+ headers: Record<string, string>;
1176
+ }
1177
+ /**
1178
+ * The one shape every runner adapter renders its own MCP configuration from.
1179
+ * The token travels only in `headers`: the adapter writes it to an owner-only
1180
+ * file or an environment variable, never a prompt or a process argument
1181
+ * (ADR-0022, A4/A5).
1182
+ */
1183
+ declare function mcpClientConfig(credential: McpCredential): McpClientConfig;
1184
+ /** A runner's MCP configuration on disk, and the way to take it back off. */
1185
+ interface OwnerOnlyFile {
1186
+ path: string;
1187
+ /** Delete the file. Idempotent. */
1188
+ remove(): void;
1189
+ }
1190
+ /**
1191
+ * Write a configuration that carries a token where only the user can read it,
1192
+ * for a runner that takes its MCP servers from a file (ADR-0022, A5). The
1193
+ * directory is private too, so the name cannot be raced before the mode lands.
1194
+ */
1195
+ declare function ownerOnlyConfigFile(fileName: string, contents: string): OwnerOnlyFile;
1196
+
917
1197
  /**
918
1198
  * The harness-planner transport contract (ADR-0009).
919
1199
  *
@@ -1041,6 +1321,24 @@ type AgentEvent =
1041
1321
  type: 'turn_end';
1042
1322
  interrupted?: boolean;
1043
1323
  }
1324
+ /**
1325
+ * The model has a message handed over by {@link TaskModeAgentAdapter.steer},
1326
+ * by the runner's own account rather than because the write succeeded
1327
+ * (ADR-0023, D3). With no turn open, the runner opened one for it.
1328
+ */
1329
+ | {
1330
+ type: 'message_delivered';
1331
+ id: string;
1332
+ }
1333
+ /**
1334
+ * The runner let go of a message it accepted from `steer` without showing it
1335
+ * to the model — Codex does, for one its turn ended before consuming. It is
1336
+ * Ordewell's to send again (ADR-0023, D4).
1337
+ */
1338
+ | {
1339
+ type: 'message_dropped';
1340
+ id: string;
1341
+ }
1044
1342
  /** The turn failed. Carries the agent's own words — never a Ordewell paraphrase. */
1045
1343
  | {
1046
1344
  type: 'error';
@@ -1065,6 +1363,8 @@ interface PlannerStartOptions extends AgentStartCommon {
1065
1363
  systemPrompt: string;
1066
1364
  /** Variant / reasoning effort id from that model's `variants` list. */
1067
1365
  effort?: string;
1366
+ /** The Ordewell MCP server to inject, pre-authorized (ADR-0022). Only for an adapter with {@link AgentAdapter.mcpAttached}. */
1367
+ mcp?: McpClientConfig;
1068
1368
  }
1069
1369
  /**
1070
1370
  * What a runner manifest says the task's mode and effort mean (ADR-0001),
@@ -1085,6 +1385,12 @@ interface TaskStartOptions extends AgentStartCommon {
1085
1385
  /** The task's runner mode id, as the plan names it. */
1086
1386
  mode: string;
1087
1387
  flags: TaskRunnerFlags;
1388
+ /**
1389
+ * The Ordewell MCP server and this attempt's token (ADR-0022). An adapter
1390
+ * that can inject it does, with its tools pre-approved; one that cannot
1391
+ * ignores it, and the task completes by its marker.
1392
+ */
1393
+ mcp?: McpClientConfig;
1088
1394
  }
1089
1395
  /**
1090
1396
  * The explicit start switch. Discriminated so that a read-only planner and a
@@ -1120,6 +1426,12 @@ interface AgentAdapter {
1120
1426
  nativeSessionId(): string | null;
1121
1427
  /** Kill the process and release its resources. Idempotent. */
1122
1428
  dispose(): void;
1429
+ /**
1430
+ * Whether the Ordewell MCP server passed in {@link PlannerStartOptions.mcp}
1431
+ * is connected, as the runner itself reports it (ADR-0022, S4). Absent on an
1432
+ * adapter that cannot inject the server at all.
1433
+ */
1434
+ mcpAttached?(): Promise<boolean>;
1123
1435
  }
1124
1436
  /** What an adapter adds to run a task rather than a planner (ADR-0018). */
1125
1437
  interface TaskModeAgentAdapter extends AgentAdapter {
@@ -1139,6 +1451,16 @@ interface TaskModeAgentAdapter extends AgentAdapter {
1139
1451
  onOutOfTurn?(listener: (event: AgentEvent) => void): void;
1140
1452
  /** Registers a listener for the process ending, for any reason. Fires at most once. */
1141
1453
  onProcessExit(listener: (code: number) => void): void;
1454
+ /**
1455
+ * Hand a message to the running turn, for the runner to show the model at
1456
+ * its next step boundary (ADR-0023, D1–D2). Resolves true once the runner
1457
+ * accepted it: handed over, not yet delivered — the turn's events later
1458
+ * carry `message_delivered` or `message_dropped` for `id`. False when the
1459
+ * runner refused it or no turn is running; the caller keeps it for the
1460
+ * turn's end. Absent on an adapter whose runner cannot take a message
1461
+ * mid-turn.
1462
+ */
1463
+ steer?(id: string, text: string): Promise<boolean>;
1142
1464
  /**
1143
1465
  * Answer an open `permission_request`. False when the id is not open — it
1144
1466
  * was answered, cancelled, or never asked.
@@ -1719,25 +2041,49 @@ type StructuredTurnEnd = 'completed' | 'interrupted' | 'failed';
1719
2041
  * full-fidelity task log, never for verdicts.
1720
2042
  */
1721
2043
  type StructuredEvent = Exclude<AgentEvent, {
1722
- type: 'turn_end';
1723
- } | {
1724
- type: 'permission_cancelled';
2044
+ type: 'turn_end' | 'permission_cancelled' | 'message_delivered' | 'message_dropped';
1725
2045
  }>
1726
- /** `text` is the user message the turn answers; `messageId` is set when it had waited in the queue. */
2046
+ /**
2047
+ * `text` is the user message the turn answers; `messageId` is set when it had
2048
+ * waited in the queue, `forced` when it was force sent (ADR-0023, Q2).
2049
+ */
1727
2050
  | {
1728
2051
  type: 'turn_start';
1729
2052
  text: string;
1730
2053
  messageId?: string;
2054
+ forced?: boolean;
1731
2055
  } | {
1732
2056
  type: 'turn_end';
1733
2057
  reason: StructuredTurnEnd;
1734
- } | {
2058
+ }
2059
+ /**
2060
+ * Waiting in Ordewell's queue — again, for a message the runner was handed
2061
+ * and let go of (ADR-0023, D4). `forced` puts it ahead of the rest, behind
2062
+ * earlier forced ones (F2); a message already listed moves there.
2063
+ */
2064
+ | {
1735
2065
  type: 'message_queued';
1736
2066
  messageId: string;
1737
2067
  text: string;
2068
+ forced?: boolean;
1738
2069
  } | {
1739
2070
  type: 'message_removed';
1740
2071
  messageId: string;
2072
+ } | {
2073
+ type: 'message_undelivered';
2074
+ messageId: string;
2075
+ text: string;
2076
+ }
2077
+ /** The runner accepted the message into its running turn; it can no longer be taken back (ADR-0023, D3). */
2078
+ | {
2079
+ type: 'message_handed_over';
2080
+ messageId: string;
2081
+ }
2082
+ /** The model read the message inside the running turn, at this point of it (ADR-0023, Q2). */
2083
+ | {
2084
+ type: 'message_delivered';
2085
+ messageId: string;
2086
+ text: string;
1741
2087
  }
1742
2088
  /** An open `permission_request` was answered, by whoever answered it (ADR-0018, A1). */
1743
2089
  | {
@@ -1753,6 +2099,10 @@ type StructuredEvent = Exclude<AgentEvent, {
1753
2099
  interface QueuedTaskMessage {
1754
2100
  id: string;
1755
2101
  text: string;
2102
+ /** The runner has it and owes a delivery, so it cannot be taken back (ADR-0023, Q1). */
2103
+ handedOver?: boolean;
2104
+ /** Force sent: it goes out as soon as the running turn is interrupted (ADR-0023, F1). */
2105
+ forced?: boolean;
1756
2106
  }
1757
2107
  /**
1758
2108
  * What a session driven over its runner's protocol can do that a terminal
@@ -1766,13 +2116,23 @@ interface StructuredSessionCapability {
1766
2116
  onTurnEnd(listener: (reason: StructuredTurnEnd) => void): void;
1767
2117
  onEvent(listener: (event: StructuredEvent) => void): void;
1768
2118
  /**
1769
- * Queue a user message, delivered when the current turn ends — or at once
1770
- * when idle. Returns its id, for {@link removeQueued}.
2119
+ * Send a user message: at once when idle; while a turn runs, handed to the
2120
+ * runner for its next step where it can take one, otherwise queued until
2121
+ * the turn ends (ADR-0023). Returns its id, for {@link removeQueued}.
1771
2122
  */
1772
2123
  sendMessage(text: string): string;
1773
- /** Take a message back before it is delivered. False when it already was. */
2124
+ /**
2125
+ * Force send (ADR-0023, F1–F3): interrupt the running turn, as
2126
+ * {@link interrupt} does, and deliver this message as the turn that
2127
+ * replaces it, ahead of anything still queued. The task does not wait for
2128
+ * input in between. With no turn running it is {@link sendMessage}.
2129
+ */
2130
+ forceSend(text: string): string;
2131
+ /** Force send a message still queued, by id. False once it was handed over or delivered. */
2132
+ forceSendQueued(id: string): boolean;
2133
+ /** Take a message back before the runner has it. False once it was handed over or delivered. */
1774
2134
  removeQueued(id: string): boolean;
1775
- /** Messages waiting for the current turn to end, oldest first. */
2135
+ /** Messages not yet delivered, oldest first: queued ones, and ones handed over that the runner owes. */
1776
2136
  queued(): QueuedTaskMessage[];
1777
2137
  /**
1778
2138
  * Stop the running turn, keeping the session: a soft interrupt first, then —
@@ -1787,6 +2147,17 @@ interface StructuredSessionCapability {
1787
2147
  * when it is no longer open — answered, withdrawn, or never asked.
1788
2148
  */
1789
2149
  answerPermission(id: string, decision: ApprovalDecision): boolean;
2150
+ /**
2151
+ * The runner's `task_complete` calls on this attempt's token (ADR-0022):
2152
+ * completion evidence beside the marker, for `VerdictEngine` to weigh.
2153
+ */
2154
+ onTaskComplete(listener: (report: TaskCompleteArgs) => void): void;
2155
+ /**
2156
+ * Answers the runner's `checkpoint` calls (ADR-0022, V5): the call stays
2157
+ * open until the returned promise settles, and its result is the answer.
2158
+ * `signal` aborts when the caller goes away.
2159
+ */
2160
+ onToolCheckpoint(handler: (question: string, signal: AbortSignal) => Promise<CheckpointAnswer>): void;
1790
2161
  }
1791
2162
  declare function isStructuredSession(session: ITerminalSession): session is ITerminalSession & StructuredSessionCapability;
1792
2163
 
@@ -1827,6 +2198,11 @@ interface ITerminalRunner {
1827
2198
  * which is why a continue refuses one.
1828
2199
  */
1829
2200
  resumeSessionId?: string;
2201
+ /**
2202
+ * Which run of the task this is, from 1. A structured runner binds the
2203
+ * attempt's MCP token to it (ADR-0022, A2).
2204
+ */
2205
+ attempt?: number;
1830
2206
  }): Promise<ITerminalSession>;
1831
2207
  stop(sessionId: string): void;
1832
2208
  stopAll(): void;
@@ -1840,7 +2216,7 @@ interface UserStep {
1840
2216
  }
1841
2217
  /** One deterministic signal gathered while verifying a completed task. */
1842
2218
  interface VerificationCheck {
1843
- name: 'exit_code' | 'completion_marker' | 'manual';
2219
+ name: 'exit_code' | 'completion_marker' | 'task_complete' | 'manual';
1844
2220
  passed: boolean;
1845
2221
  /** A check that did not apply. Skipped checks don't affect the verdict. */
1846
2222
  skipped: boolean;
@@ -2159,6 +2535,22 @@ declare function migratePlanState(raw: unknown): PlanState;
2159
2535
  declare function migrateLegacyPlan(legacy: LegacyPlanState): PlanState;
2160
2536
 
2161
2537
  declare function createTask(overrides?: Partial<Task>): Task;
2538
+ /**
2539
+ * The `ops` flag as a task stores it (ADR-0020), however it arrived. Only a
2540
+ * literal `true` on an AI task marks an ops task: the planner's JSON is
2541
+ * untyped, and a quoted "true" read as ops would move a task out of its
2542
+ * worktree. Anything else is a change task, stored absent so saved plans need
2543
+ * no migration. Whether the task may be ops at all — a subtask may not — is
2544
+ * for whoever knows where it sits: parsing drops the flag, an edit refuses it.
2545
+ */
2546
+ declare function opsFlag(value: unknown, type?: Task['type']): true | undefined;
2547
+ /**
2548
+ * The flag of a task a merge or a split makes from others: what the edit
2549
+ * chose, else ops only when every task it came from was. A merge that takes
2550
+ * in a change edits files, so it is a change; a split part runs where its
2551
+ * task did.
2552
+ */
2553
+ declare function inheritedOps(from: readonly Pick<Task, 'ops'>[], chosen?: boolean): boolean;
2162
2554
  declare function createEmptyPlan(): LegacyPlanState;
2163
2555
  declare function flattenTasks(tasks: readonly Task[]): Task[];
2164
2556
  /** A flattened task with the parent it hangs under, null for a top-level task. */
@@ -2199,4 +2591,4 @@ interface ValidationContext {
2199
2591
  type ValidationCheck = (ctx: ValidationContext) => ValidationResult;
2200
2592
  declare function warningsText(w: PlanModificationWarnings): string | null;
2201
2593
 
2202
- export { type IsolationRun as $, AbstractRunner as A, type BlockingPrompt as B, CMD_EXE_MAX_COMMAND_LINE as C, DENY_ALL as D, EmbeddedNewlineError as E, type FetchAllProviderModelsOptions as F, HeadlessSession as G, HeadlessRunner as H, type IApproval as I, type IConfig as J, type IPluginStore as K, type ITerminalRunner as L, type ITerminalSession as M, type IWorktreeIsolation as N, type IntegrationDisposal as O, type IsolationAvailability as P, type IsolationHandoff as Q, type IsolationHandoffRepo as R, type IsolationInactiveReason as S, type IsolationLandedTask as T, type IsolationLanding as U, type IsolationMergeBlock as V, type IsolationMergeBlockReason as W, type IsolationMergeResult as X, type IsolationOutcome as Y, type IsolationPruneResult as Z, type IsolationRepo as _, AbstractTerminalSession as a, type TaskModelAssignment as a$, type IsolationTaskRecord as a0, type IsolationTaskRepo as a1, type IsolationTaskStatus as a2, type IsolationView as a3, type LaunchDeps as a4, type LaunchPlan as a5, type LegacyPlanState as a6, LineBuffer as a7, type Message as a8, ModelCatalog as a9, type ResearchLogEntry as aA, type ResearchProgress as aB, type ResearchStep as aC, type ResearchStepOutcome as aD, type ResearchToolType as aE, type ResolveContext as aF, type RunnerId as aG, type RunnerInvocation as aH, type RunnerPluginManifest as aI, RunnerRegistry as aJ, type RunnerSpawnOptions as aK, type RunnerTransport as aL, type RunnerVersionProbe as aM, type StreamEvent as aN, type StreamStepEvent as aO, type StreamThinkingEvent as aP, type StructuredEvent as aQ, type StructuredSessionCapability as aR, type StructuredTurnEnd as aS, type SubagentLogEntry as aT, type SubagentOutcome as aU, type Task as aV, type TaskIsolation as aW, type TaskIsolationState as aX, type TaskMode as aY, type TaskModeAgentAdapter as aZ, TaskModeUnsupportedError as a_, type ModelShortcut as aa, ORCHESTRATOR_SHORTCUTS as ab, type OrchestratorOption as ac, type PlanIsolation as ad, type PlanModificationWarnings as ae, type PlanState as af, type PlanStatus as ag, type PlannerStartOptions as ah, type PlannerUsage as ai, type PluginCloneFn as aj, type PluginEntry as ak, type PluginFeatures as al, type PluginMode as am, type PluginModelDiscovery as an, type PluginRunnerDef as ao, type PreparedLaunch as ap, type PreparedTask as aq, type ProviderCredentialSource as ar, type ProviderModelLists as as, type ProviderModelsResult as at, type PtySize as au, type PtyWrapOptions as av, type QueuedMessage as aw, type QueuedTaskMessage as ax, type RepairEvidence as ay, type RepoGroupLayout as az, type ActiveTaskSession as b, windowsCommandLine as b$, type TaskOutputSummary as b0, type TaskRunnerFlags as b1, type TaskSnapshot as b2, type TaskStartOptions as b3, type TaskStatus as b4, type TaskTransport as b5, type TaskType as b6, type TaskWithParent as b7, type ThinkingBlock as b8, type TreeSnapshot as b9, isGranted as bA, isMeasured as bB, isReservedRunnerName as bC, isRunnerApproval as bD, isRunnerTransport as bE, isStructuredSession as bF, keepExecutionState as bG, knownModelId as bH, migrateLegacyPlan as bI, migratePlanState as bJ, migrateTask as bK, partedPromptUsage as bL, planDirectLaunch as bM, planShellLaunch as bN, plannerContextFill as bO, posixShellQuote as bP, removeTaskFromPlan as bQ, renumberTasks as bR, resolveModelShortcut as bS, resolveProvider as bT, stripAnsi as bU, toApprovalDecision as bV, toOrchestratorOptions as bW, updateTaskInPlan as bX, usageLine as bY, validateModifiedPlan as bZ, warningsText as b_, type UsageLine as ba, type UsageRecord as bb, type UsageTotals as bc, type UserPromptEntry as bd, type UserStep as be, type ValidationCheck as bf, type ValidationContext as bg, type ValidationResult as bh, type Verdict as bi, type VerificationCheck as bj, WINDOWS_MAX_COMMAND_LINE as bk, addPlannerUsage as bl, addTaskToPlan as bm, addUsage as bn, approvalScopes as bo, buildShellInvocation as bp, collectProviderCredentials as bq, createEmptyPlan as br, createTask as bs, emptyWarnings as bt, enabledRunners as bu, fetchAllProviderModels as bv, flattenTasks as bw, flattenTasksWithParents as bx, isAwaitingReason as by, isExecutableResolved as bz, type AgentAdapter as c, wrapWithPty as c0, type AgentAdapterFactory as d, type AgentEvent as e, type AgentProcessDeps as f, type AgentStartOptions as g, type AiProvider as h, type AllProviderModels as i, type ApprovalAnswer as j, type ApprovalDecision as k, type ApprovalKind as l, type ApprovalMode as m, ApprovalPolicy as n, type ApprovalPolicyOptions as o, type ApprovalRequest as p, type ApprovalSource as q, type AwaitingReason as r, type CatalogModel as s, CommandLineTooLongError as t, type ConversationMessage as u, type DiscoveredMode as v, type DiscoveredModel as w, type DiscoveryCommand as x, ExecutableNotFoundError as y, type HeadlessRunnerDeps as z };
2594
+ export { type IsolationOutcome as $, AbstractRunner as A, type BlockingPrompt as B, CMD_EXE_MAX_COMMAND_LINE as C, DENY_ALL as D, type EditPlanArgs as E, EmbeddedNewlineError as F, ExecutableNotFoundError as G, type FetchAllProviderModelsOptions as H, HeadlessRunner as I, type HeadlessRunnerDeps as J, HeadlessSession as K, type IApproval as L, type IConfig as M, type IPluginStore as N, type ITerminalRunner as O, type ITerminalSession as P, type IWorktreeIsolation as Q, type IntegrationDisposal as R, type IsolationAvailability as S, type IsolationHandoff as T, type IsolationHandoffRepo as U, type IsolationInactiveReason as V, type IsolationLandedTask as W, type IsolationLanding as X, type IsolationMergeBlock as Y, type IsolationMergeBlockReason as Z, type IsolationMergeResult as _, AbstractTerminalSession as a, type RunnerId as a$, type IsolationPruneResult as a0, type IsolationRemoval as a1, type IsolationRepo as a2, type IsolationRun as a3, type IsolationTaskRecord as a4, type IsolationTaskRef as a5, type IsolationTaskRepo as a6, type IsolationTaskStatus as a7, type IsolationView as a8, type LaunchDeps as a9, type PlannerToolHandler as aA, type PlannerUsage as aB, type PluginCloneFn as aC, type PluginEntry as aD, type PluginFeatures as aE, type PluginMode as aF, type PluginModelDiscovery as aG, type PluginRunnerDef as aH, type PreparedLaunch as aI, type PreparedTask as aJ, type PreservedWork as aK, type ProviderCredentialSource as aL, type ProviderModelLists as aM, type ProviderModelsResult as aN, type PtySize as aO, type PtyWrapOptions as aP, type QueuedMessage as aQ, type QueuedTaskMessage as aR, type RefusedRemoval as aS, type RepairEvidence as aT, type RepoGroupLayout as aU, type ResearchLogEntry as aV, type ResearchProgress as aW, type ResearchStep as aX, type ResearchStepOutcome as aY, type ResearchToolType as aZ, type ResolveContext as a_, type LaunchPlan as aa, type LegacyPlanState as ab, LineBuffer as ac, type ListModelsArgs as ad, type ListRunnersArgs as ae, type McpClientConfig as af, type McpCredential as ag, type McpTool as ah, type McpToolContext as ai, type McpToolReply as aj, type Message as ak, ModelCatalog as al, type ModelShortcut as am, ORCHESTRATOR_SHORTCUTS as an, ORDEWELL_MCP_PATH as ao, ORDEWELL_MCP_SERVER_NAME as ap, type OrchestratorOption as aq, OrdewellMcpServer as ar, type OwnerOnlyFile as as, PLANNER_TOOLS as at, type PlanIsolation as au, type PlanModificationWarnings as av, type PlanState as aw, type PlanStatus as ax, type PlannerStartOptions as ay, type PlannerTokenScope as az, type ActiveTaskSession as b, inheritedOps as b$, type RunnerInvocation as b0, type RunnerPluginManifest as b1, RunnerRegistry as b2, type RunnerSpawnOptions as b3, type RunnerTransport as b4, type RunnerVersionProbe as b5, type StreamEvent as b6, type StreamStepEvent as b7, type StreamThinkingEvent as b8, type StructuredEvent as b9, type TaskWithParent as bA, type ThinkingBlock as bB, type TreeSnapshot as bC, type UsageLine as bD, type UsageRecord as bE, type UsageTotals as bF, type UserPromptEntry as bG, type UserStep as bH, type ValidationCheck as bI, type ValidationContext as bJ, type ValidationResult as bK, type Verdict as bL, type VerificationCheck as bM, WINDOWS_MAX_COMMAND_LINE as bN, addPlannerUsage as bO, addTaskToPlan as bP, addUsage as bQ, approvalScopes as bR, buildShellInvocation as bS, collectProviderCredentials as bT, createEmptyPlan as bU, createTask as bV, emptyWarnings as bW, enabledRunners as bX, fetchAllProviderModels as bY, flattenTasks as bZ, flattenTasksWithParents as b_, type StructuredSessionCapability as ba, type StructuredTurnEnd as bb, type SubagentLogEntry as bc, type SubagentOutcome as bd, type SubmitPlanArgs as be, TASK_COMPLETE_TOOL as bf, TASK_TOOLS as bg, type Task as bh, type TaskCompleteArgs as bi, type TaskIsolation as bj, type TaskIsolationState as bk, type TaskMode as bl, type TaskModeAgentAdapter as bm, TaskModeUnsupportedError as bn, type TaskModelAssignment as bo, type TaskOutputArgs as bp, type TaskOutputSummary as bq, type TaskQueryArgs as br, type TaskRunnerFlags as bs, type TaskSnapshot as bt, type TaskStartOptions as bu, type TaskStatus as bv, type TaskTokenScope as bw, type TaskToolHandler as bx, type TaskTransport as by, type TaskType as bz, type AgentAdapter as c, isAwaitingReason as c0, isExecutableResolved as c1, isGranted as c2, isMeasured as c3, isReservedRunnerName as c4, isRunnerApproval as c5, isRunnerTransport as c6, isStructuredSession as c7, keepExecutionState as c8, knownModelId as c9, mcpClientConfig as ca, migrateLegacyPlan as cb, migratePlanState as cc, migrateTask as cd, opsFlag as ce, ownerOnlyConfigFile as cf, partedPromptUsage as cg, planDirectLaunch as ch, planShellLaunch as ci, plannerContextFill as cj, posixShellQuote as ck, removeTaskFromPlan as cl, renumberTasks as cm, resolveModelShortcut as cn, resolveProvider as co, sharedMcpServer as cp, stripAnsi as cq, toApprovalDecision as cr, toOrchestratorOptions as cs, updateTaskInPlan as ct, usageLine as cu, validateModifiedPlan as cv, warningsText as cw, windowsCommandLine as cx, wrapWithPty as cy, type AgentAdapterFactory as d, type AgentEvent as e, type AgentProcessDeps as f, type AgentStartOptions as g, type AiProvider as h, type AllProviderModels as i, type ApprovalAnswer as j, type ApprovalDecision as k, type ApprovalKind as l, type ApprovalMode as m, ApprovalPolicy as n, type ApprovalPolicyOptions as o, type ApprovalRequest as p, type ApprovalSource as q, type AwaitingReason as r, type CatalogModel as s, type CheckpointAnswer as t, type CheckpointArgs as u, CommandLineTooLongError as v, type ConversationMessage as w, type DiscoveredMode as x, type DiscoveredModel as y, type DiscoveryCommand as z };
@@ -150,9 +150,15 @@ function createTask(overrides = {}) {
150
150
  autonomy: overrides.autonomy,
151
151
  sliceType: overrides.sliceType,
152
152
  userStoriesCovered: overrides.userStoriesCovered,
153
- ...overrides.ops === true && (overrides.type ?? "ai") === "ai" ? { ops: true } : {}
153
+ ...opsFlag(overrides.ops, overrides.type) ? { ops: true } : {}
154
154
  };
155
155
  }
156
+ function opsFlag(value, type = "ai") {
157
+ return value === true && type === "ai" ? true : void 0;
158
+ }
159
+ function inheritedOps(from, chosen) {
160
+ return chosen ?? from.every((t) => opsFlag(t.ops) === true);
161
+ }
156
162
  function createEmptyPlan() {
157
163
  return {
158
164
  tasks: [],
@@ -493,6 +499,8 @@ export {
493
499
  migratePlanState,
494
500
  migrateLegacyPlan,
495
501
  createTask,
502
+ opsFlag,
503
+ inheritedOps,
496
504
  createEmptyPlan,
497
505
  flattenTasks,
498
506
  flattenTasksWithParents,
@@ -516,4 +524,4 @@ export {
516
524
  stripTrailingCommas,
517
525
  escapeControlCharsInStrings
518
526
  };
519
- //# sourceMappingURL=chunk-JRZPSNRO.mjs.map
527
+ //# sourceMappingURL=chunk-LGQNXPBX.mjs.map