1import { assert, it } from "@effect/vitest";
2import {
3 CommandId,
4 type OrchestrationV2ProviderCapabilities,
5 type OrchestrationV2ThreadProjection,
6 ProviderInstanceId,
7 ProviderSessionId,
8 ProviderThreadId,
9 RunId,
10 ThreadId,
11} from "@t3tools/contracts";
12import * as Effect from "effect/Effect";
13
14import { CodexProviderCapabilitiesV2 } from "./Adapters/CodexAdapterV2.ts";
15import { CursorProviderCapabilitiesV2 } from "@t3tools/provider-cursor/testing";
16import { GrokProviderCapabilitiesV2 } from "@t3tools/provider-grok/testing";
17import * as CommandPolicy from "./CommandPolicy.ts";
18
19const commandId = CommandId.make("command-policy-test");
20const threadId = ThreadId.make("command-policy-thread");
21const activeRunId = RunId.make("command-policy-active-run");
22
23const baseCapabilities: OrchestrationV2ProviderCapabilities = CodexProviderCapabilitiesV2;
24
25function capabilities(
26 override: (current: OrchestrationV2ProviderCapabilities) => OrchestrationV2ProviderCapabilities,
27): OrchestrationV2ProviderCapabilities {
28 return override(baseCapabilities);
29}
30
31function dispatchProjection(
32 sessionCapabilities?: OrchestrationV2ProviderCapabilities,
33): OrchestrationV2ThreadProjection {
34 const providerThreadId = ProviderThreadId.make("command-policy-provider-thread");
35 const providerSessionId = ProviderSessionId.make("command-policy-provider-session");
36 return {
37 runs:
38 sessionCapabilities === undefined
39 ? []
40 : [{ id: activeRunId, status: "running", providerThreadId }],
41 providerThreads:
42 sessionCapabilities === undefined ? [] : [{ id: providerThreadId, providerSessionId }],
43 providerSessions:
44 sessionCapabilities === undefined
45 ? []
46 : [{ id: providerSessionId, capabilities: sessionCapabilities }],
47 } as unknown as OrchestrationV2ThreadProjection;
48}
49
50it("resolves automatic message delivery from authoritative provider capabilities", () => {
51 assert.deepEqual(
52 CommandPolicy.resolveMessageDispatchIntent(
53 dispatchProjection(),
54 { type: "start_immediately" },
55 "auto",
56 ),
57 { type: "start_immediately" },
58 );
59 assert.deepEqual(
60 CommandPolicy.resolveMessageDispatchIntent(
61 dispatchProjection(baseCapabilities),
62 { type: "start_immediately" },
63 "auto",
64 ),
65 { type: "steer_active", targetRunId: activeRunId },
66 );
67 assert.deepEqual(
68 CommandPolicy.resolveMessageDispatchIntent(
69 dispatchProjection(
70 capabilities((current) => ({
71 ...current,
72 turns: {
73 ...current.turns,
74 supportsActiveSteering: false,
75 supportsQueuedMessages: true,
76 supportsSteeringByInterruptRestart: true,
77 },
78 })),
79 ),
80 { type: "start_immediately" },
81 "auto",
82 ),
83 { type: "queue_after_active" },
84 );
85 assert.deepEqual(
86 CommandPolicy.resolveMessageDispatchIntent(
87 dispatchProjection(
88 capabilities((current) => ({
89 ...current,
90 turns: {
91 ...current.turns,
92 supportsActiveSteering: false,
93 supportsQueuedMessages: false,
94 supportsSteeringByInterruptRestart: true,
95 },
96 })),
97 ),
98 { type: "start_immediately" },
99 "auto",
100 ),
101 { type: "restart_active", targetRunId: activeRunId },
102 );
103});
104
105it.each(["preparing", "starting"] as const)(
106 "queues an automatic message while the handoff run is %s",
107 (status) => {
108 const projection = dispatchProjection(baseCapabilities);
109 assert.deepEqual(
110 CommandPolicy.resolveMessageDispatchIntent(
111 { ...projection, runs: projection.runs.map((run) => ({ ...run, status })) },
112 { type: "start_immediately" },
113 "auto",
114 ),
115 { type: "queue_after_active" },
116 );
117 },
118);
119
120it("targets the latest active run for explicit steer and restart intent", () => {
121 const projection = dispatchProjection(baseCapabilities);
122 assert.deepEqual(
123 CommandPolicy.resolveMessageDispatchIntent(projection, { type: "start_immediately" }, "steer"),
124 { type: "steer_active", targetRunId: activeRunId },
125 );
126 assert.deepEqual(
127 CommandPolicy.resolveMessageDispatchIntent(
128 projection,
129 { type: "start_immediately" },
130 "restart",
131 ),
132 { type: "restart_active", targetRunId: activeRunId },
133 );
134 assert.deepEqual(
135 CommandPolicy.resolveMessageDispatchIntent(
136 dispatchProjection(),
137 { type: "start_immediately" },
138 "steer",
139 ),
140 { type: "start_immediately" },
141 );
142});
143
144const layer = it.layer(CommandPolicy.layer);
145
146layer("CommandPolicyV2", (it) => {
147 it.effect("prefers direct active steering when the provider supports it", () =>
148 Effect.gen(function* () {
149 const policy = yield* CommandPolicy.CommandPolicyV2;
150
151 const result = yield* policy.decideSteeringExecution({
152 commandId,
153 threadId,
154 providerInstanceId: ProviderInstanceId.make("codex"),
155 capabilities: baseCapabilities,
156 });
157
158 assert.equal(result, "active_steering");
159 }),
160 );
161
162 it.effect("uses interrupt-and-restart steering when direct steering is unavailable", () =>
163 Effect.gen(function* () {
164 const policy = yield* CommandPolicy.CommandPolicyV2;
165
166 const result = yield* policy.decideSteeringExecution({
167 commandId,
168 threadId,
169 providerInstanceId: ProviderInstanceId.make("codex"),
170 capabilities: capabilities((current) => ({
171 ...current,
172 turns: {
173 ...current.turns,
174 supportsActiveSteering: false,
175 supportsInterrupt: true,
176 supportsSteeringByInterruptRestart: true,
177 },
178 })),
179 });
180
181 assert.equal(result, "interrupt_restart");
182 }),
183 );
184
185 it.effect("uses interrupt-and-restart steering for Grok ACP", () =>
186 Effect.gen(function* () {
187 const policy = yield* CommandPolicy.CommandPolicyV2;
188
189 const result = yield* policy.decideSteeringExecution({
190 commandId,
191 threadId,
192 providerInstanceId: ProviderInstanceId.make("grok"),
193 capabilities: GrokProviderCapabilitiesV2,
194 });
195
196 assert.equal(result, "interrupt_restart");
197 }),
198 );
199
200 it.effect("honors an explicit interrupt-and-restart request", () =>
201 Effect.gen(function* () {
202 const policy = yield* CommandPolicy.CommandPolicyV2;
203
204 const result = yield* policy.decideSteeringExecution({
205 commandId,
206 threadId,
207 providerInstanceId: ProviderInstanceId.make("codex"),
208 capabilities: CodexProviderCapabilitiesV2,
209 forceRestart: true,
210 });
211
212 assert.equal(result, "interrupt_restart");
213 }),
214 );
215
216 it.effect("reports the actually missing capability across the steering matrix", () =>
217 Effect.gen(function* () {
218 const policy = yield* CommandPolicy.CommandPolicyV2;
219 const providerInstanceId = ProviderInstanceId.make("codex");
220 const fallbackDetail =
221 "providerInstanceId cannot steer active turns directly or by interrupt-and-restart";
222 const forcedRestartDetail =
223 "providerInstanceId cannot satisfy a required interrupt-and-restart";
224
225 const cases: ReadonlyArray<{
226 readonly forceRestart: boolean;
227 readonly supportsActiveSteering: boolean;
228 readonly supportsInterrupt: boolean;
229 readonly supportsSteeringByInterruptRestart: boolean;
230 readonly expected:
231 | { readonly type: "policy"; readonly value: CommandPolicy.SteeringExecutionPolicyV2 }
232 | {
233 readonly type: "error";
234 readonly capability: CommandPolicy.CommandPolicyCapability;
235 readonly detail: string;
236 };
237 }> = [
238 // Ordinary steering prefers direct active steering whenever available.
239 {
240 forceRestart: false,
241 supportsActiveSteering: true,
242 supportsInterrupt: false,
243 supportsSteeringByInterruptRestart: false,
244 expected: { type: "policy", value: "active_steering" },
245 },
246 {
247 forceRestart: false,
248 supportsActiveSteering: true,
249 supportsInterrupt: false,
250 supportsSteeringByInterruptRestart: true,
251 expected: { type: "policy", value: "active_steering" },
252 },
253 {
254 forceRestart: false,
255 supportsActiveSteering: true,
256 supportsInterrupt: true,
257 supportsSteeringByInterruptRestart: false,
258 expected: { type: "policy", value: "active_steering" },
259 },
260 {
261 forceRestart: false,
262 supportsActiveSteering: true,
263 supportsInterrupt: true,
264 supportsSteeringByInterruptRestart: true,
265 expected: { type: "policy", value: "active_steering" },
266 },
267 // Ordinary steering falls back to interrupt-and-restart, then to a
268 // typed error naming the capability that is actually missing.
269 {
270 forceRestart: false,
271 supportsActiveSteering: false,
272 supportsInterrupt: true,
273 supportsSteeringByInterruptRestart: true,
274 expected: { type: "policy", value: "interrupt_restart" },
275 },
276 {
277 forceRestart: false,
278 supportsActiveSteering: false,
279 supportsInterrupt: true,
280 supportsSteeringByInterruptRestart: false,
281 expected: {
282 type: "error",
283 capability: "interrupt_restart_steering",
284 detail: fallbackDetail,
285 },
286 },
287 {
288 forceRestart: false,
289 supportsActiveSteering: false,
290 supportsInterrupt: false,
291 supportsSteeringByInterruptRestart: true,
292 expected: { type: "error", capability: "active_steering", detail: fallbackDetail },
293 },
294 {
295 forceRestart: false,
296 supportsActiveSteering: false,
297 supportsInterrupt: false,
298 supportsSteeringByInterruptRestart: false,
299 expected: { type: "error", capability: "active_steering", detail: fallbackDetail },
300 },
301 // A forced restart skips direct steering and only succeeds via
302 // interrupt-and-restart; every other combination must report that
303 // capability instead of claiming live steering is unsupported.
304 {
305 forceRestart: true,
306 supportsActiveSteering: true,
307 supportsInterrupt: true,
308 supportsSteeringByInterruptRestart: true,
309 expected: { type: "policy", value: "interrupt_restart" },
310 },
311 {
312 forceRestart: true,
313 supportsActiveSteering: false,
314 supportsInterrupt: true,
315 supportsSteeringByInterruptRestart: true,
316 expected: { type: "policy", value: "interrupt_restart" },
317 },
318 {
319 forceRestart: true,
320 supportsActiveSteering: true,
321 supportsInterrupt: true,
322 supportsSteeringByInterruptRestart: false,
323 expected: {
324 type: "error",
325 capability: "interrupt_restart_steering",
326 detail: forcedRestartDetail,
327 },
328 },
329 {
330 forceRestart: true,
331 supportsActiveSteering: false,
332 supportsInterrupt: true,
333 supportsSteeringByInterruptRestart: false,
334 expected: {
335 type: "error",
336 capability: "interrupt_restart_steering",
337 detail: forcedRestartDetail,
338 },
339 },
340 {
341 forceRestart: true,
342 supportsActiveSteering: true,
343 supportsInterrupt: false,
344 supportsSteeringByInterruptRestart: true,
345 expected: {
346 type: "error",
347 capability: "interrupt_restart_steering",
348 detail: forcedRestartDetail,
349 },
350 },
351 {
352 forceRestart: true,
353 supportsActiveSteering: false,
354 supportsInterrupt: false,
355 supportsSteeringByInterruptRestart: true,
356 expected: {
357 type: "error",
358 capability: "interrupt_restart_steering",
359 detail: forcedRestartDetail,
360 },
361 },
362 {
363 forceRestart: true,
364 supportsActiveSteering: true,
365 supportsInterrupt: false,
366 supportsSteeringByInterruptRestart: false,
367 expected: {
368 type: "error",
369 capability: "interrupt_restart_steering",
370 detail: forcedRestartDetail,
371 },
372 },
373 {
374 forceRestart: true,
375 supportsActiveSteering: false,
376 supportsInterrupt: false,
377 supportsSteeringByInterruptRestart: false,
378 expected: {
379 type: "error",
380 capability: "interrupt_restart_steering",
381 detail: forcedRestartDetail,
382 },
383 },
384 ];
385
386 for (const entry of cases) {
387 const decision = policy.decideSteeringExecution({
388 commandId,
389 threadId,
390 providerInstanceId,
391 forceRestart: entry.forceRestart,
392 capabilities: capabilities((current) => ({
393 ...current,
394 turns: {
395 ...current.turns,
396 supportsActiveSteering: entry.supportsActiveSteering,
397 supportsInterrupt: entry.supportsInterrupt,
398 supportsSteeringByInterruptRestart: entry.supportsSteeringByInterruptRestart,
399 },
400 })),
401 });
402
403 if (entry.expected.type === "policy") {
404 assert.equal(yield* decision, entry.expected.value);
405 continue;
406 }
407
408 const error = yield* decision.pipe(Effect.flip);
409 assert.instanceOf(error, CommandPolicy.CommandPolicyCapabilityUnsupportedError);
410 assert.equal(error.commandId, commandId);
411 assert.equal(error.threadId, threadId);
412 assert.equal(error.providerInstanceId, providerInstanceId);
413 assert.equal(error.capability, entry.expected.capability);
414 assert.equal(error.detail, entry.expected.detail);
415 }
416 }),
417 );
418
419 it.effect("returns typed capability errors for unsupported active steering", () =>
420 Effect.gen(function* () {
421 const policy = yield* CommandPolicy.CommandPolicyV2;
422
423 const error = yield* policy
424 .decideSteeringExecution({
425 commandId,
426 threadId,
427 providerInstanceId: ProviderInstanceId.make("codex"),
428 capabilities: capabilities((current) => ({
429 ...current,
430 turns: {
431 ...current.turns,
432 supportsActiveSteering: false,
433 supportsInterrupt: false,
434 supportsSteeringByInterruptRestart: false,
435 },
436 })),
437 })
438 .pipe(Effect.flip);
439
440 assert.instanceOf(error, CommandPolicy.CommandPolicyCapabilityUnsupportedError);
441 assert.equal(error.capability, "active_steering");
442 }),
443 );
444
445 it.effect("guards native fork behind fork and identity capabilities", () =>
446 Effect.gen(function* () {
447 const policy = yield* CommandPolicy.CommandPolicyV2;
448
449 const error = yield* policy
450 .ensureNativeFork({
451 commandId,
452 threadId,
453 providerInstanceId: ProviderInstanceId.make("codex"),
454 fromSpecificTurn: true,
455 capabilities: capabilities((current) => ({
456 ...current,
457 identity: {
458 ...current.identity,
459 nativeThreadIds: "weak",
460 },
461 })),
462 })
463 .pipe(Effect.flip);
464
465 assert.instanceOf(error, CommandPolicy.CommandPolicyCapabilityUnsupportedError);
466 assert.equal(error.capability, "native_fork");
467 }),
468 );
469
470 it.effect("uses a native fork when the provider supports the requested source point", () =>
471 Effect.gen(function* () {
472 const policy = yield* CommandPolicy.CommandPolicyV2;
473
474 const result = yield* policy.decideForkExecution({
475 commandId,
476 threadId,
477 providerInstanceId: ProviderInstanceId.make("codex"),
478 capabilities: CodexProviderCapabilitiesV2,
479 sameProvider: true,
480 hasStrongNativeSource: true,
481 sourceRunStatus: "completed",
482 fromSpecificTurn: true,
483 });
484
485 assert.equal(result, "native_fork");
486 }),
487 );
488
489 it.effect("falls back to portable context when Cursor cannot fork natively", () =>
490 Effect.gen(function* () {
491 const policy = yield* CommandPolicy.CommandPolicyV2;
492
493 const result = yield* policy.decideForkExecution({
494 commandId,
495 threadId,
496 providerInstanceId: ProviderInstanceId.make("cursor"),
497 capabilities: CursorProviderCapabilitiesV2,
498 sameProvider: true,
499 hasStrongNativeSource: true,
500 sourceRunStatus: "completed",
501 fromSpecificTurn: true,
502 });
503
504 assert.equal(result, "portable_context");
505 }),
506 );
507
508 it.effect("falls back to portable context when Grok ACP cannot fork natively", () =>
509 Effect.gen(function* () {
510 const policy = yield* CommandPolicy.CommandPolicyV2;
511
512 const result = yield* policy.decideForkExecution({
513 commandId,
514 threadId,
515 providerInstanceId: ProviderInstanceId.make("grok"),
516 capabilities: GrokProviderCapabilitiesV2,
517 sameProvider: true,
518 hasStrongNativeSource: true,
519 sourceRunStatus: "completed",
520 fromSpecificTurn: true,
521 });
522
523 assert.equal(result, "portable_context");
524 }),
525 );
526
527 it.effect("returns a typed error when neither native nor portable fork is available", () =>
528 Effect.gen(function* () {
529 const policy = yield* CommandPolicy.CommandPolicyV2;
530
531 const error = yield* policy
532 .decideForkExecution({
533 commandId,
534 threadId,
535 providerInstanceId: ProviderInstanceId.make("cursor"),
536 capabilities: capabilities((current) => ({
537 ...current,
538 threads: {
539 ...current.threads,
540 canForkThread: false,
541 },
542 context: {
543 ...current.context,
544 canConsumeHandoffSummaries: false,
545 },
546 })),
547 sameProvider: true,
548 hasStrongNativeSource: true,
549 sourceRunStatus: "completed",
550 fromSpecificTurn: true,
551 })
552 .pipe(Effect.flip);
553
554 assert.instanceOf(error, CommandPolicy.CommandPolicyCapabilityUnsupportedError);
555 assert.equal(error.capability, "context_handoff");
556 }),
557 );
558
559 it.effect("guards rollback behind provider rollback snapshot support", () =>
560 Effect.gen(function* () {
561 const policy = yield* CommandPolicy.CommandPolicyV2;
562
563 const error = yield* policy
564 .ensureRollback({
565 commandId,
566 threadId,
567 providerInstanceId: ProviderInstanceId.make("codex"),
568 capabilities: capabilities((current) => ({
569 ...current,
570 checkpointing: {
571 ...current.checkpointing,
572 providerRollbackReturnsSnapshot: false,
573 },
574 })),
575 })
576 .pipe(Effect.flip);
577
578 assert.instanceOf(error, CommandPolicy.CommandPolicyCapabilityUnsupportedError);
579 assert.equal(error.capability, "rollback_snapshot");
580 }),
581 );
582
583 it.effect("guards fork-delta handoff behind context handoff capabilities", () =>
584 Effect.gen(function* () {
585 const policy = yield* CommandPolicy.CommandPolicyV2;
586
587 const error = yield* policy
588 .ensureContextHandoff({
589 commandId,
590 threadId,
591 providerInstanceId: ProviderInstanceId.make("codex"),
592 strategy: "fork_delta_context",
593 capabilities: capabilities((current) => ({
594 ...current,
595 context: {
596 ...current.context,
597 supportsDeltaHandoff: false,
598 },
599 })),
600 })
601 .pipe(Effect.flip);
602
603 assert.instanceOf(error, CommandPolicy.CommandPolicyCapabilityUnsupportedError);
604 assert.equal(error.capability, "context_handoff");
605 }),
606 );
607
608 it.effect("guards queued turns behind queued-message support", () =>
609 Effect.gen(function* () {
610 const policy = yield* CommandPolicy.CommandPolicyV2;
611
612 const error = yield* policy
613 .ensureQueuedMessages({
614 commandId,
615 threadId,
616 providerInstanceId: ProviderInstanceId.make("codex"),
617 capabilities: capabilities((current) => ({
618 ...current,
619 turns: {
620 ...current.turns,
621 supportsQueuedMessages: false,
622 },
623 })),
624 })
625 .pipe(Effect.flip);
626
627 assert.instanceOf(error, CommandPolicy.CommandPolicyCapabilityUnsupportedError);
628 assert.equal(error.capability, "queued_messages");
629 }),
630 );
631});