Unified · Split
| @@ -1,14 +1,52 @@ | ||
| 1 | 1 | import { assert, describe, expect, it, vi } from "@effect/vitest"; |
| 2 | +import * as DateTime from "effect/DateTime"; | |
| 2 | 3 | import * as Effect from "effect/Effect"; |
| 3 | 4 | import * as Layer from "effect/Layer"; |
| 5 | +import * as Option from "effect/Option"; | |
| 4 | 6 | |
| 5 | 7 | import { GitCommandError, VcsRepositoryDetectionError } from "@t3tools/contracts"; |
| 6 | 8 | |
| 7 | 9 | import * as GitManager from "./GitManager.ts"; |
| 8 | 10 | import * as GitWorkflowService from "./GitWorkflowService.ts"; |
| 9 | 11 | import * as GitVcsDriver from "../vcs/GitVcsDriver.ts"; |
| 12 | +import * as VcsDriver from "../vcs/VcsDriver.ts"; | |
| 10 | 13 | import * as VcsDriverRegistry from "../vcs/VcsDriverRegistry.ts"; |
| 11 | 14 | |
| 15 | +const unusedVcsDriver = VcsDriver.VcsDriver.of({ | |
| 16 | + capabilities: { | |
| 17 | + kind: "git", | |
| 18 | + supportsWorktrees: true, | |
| 19 | + supportsBookmarks: false, | |
| 20 | + supportsAtomicSnapshot: false, | |
| 21 | + supportsPushDefaultRemote: true, | |
| 22 | + ignoreClassifier: "native", | |
| 23 | + }, | |
| 24 | + execute: () => Effect.die("unused VCS driver execute"), | |
| 25 | + detectRepository: () => Effect.die("unused VCS repository detection"), | |
| 26 | + isInsideWorkTree: () => Effect.die("unused VCS worktree lookup"), | |
| 27 | + listWorkspaceFiles: () => Effect.die("unused VCS workspace listing"), | |
| 28 | + listRemotes: () => Effect.die("unused VCS remote listing"), | |
| 29 | + filterIgnoredPaths: () => Effect.die("unused VCS ignore classification"), | |
| 30 | + initRepository: () => Effect.die("unused VCS repository initialization"), | |
| 31 | +}); | |
| 32 | + | |
| 33 | +function gitHandle(cwd: string): VcsDriverRegistry.VcsDriverHandle { | |
| 34 | + return { | |
| 35 | + kind: "git", | |
| 36 | + repository: { | |
| 37 | + kind: "git", | |
| 38 | + rootPath: cwd, | |
| 39 | + metadataPath: `${cwd}/.git`, | |
| 40 | + freshness: { | |
| 41 | + source: "live-local", | |
| 42 | + observedAt: DateTime.makeUnsafe("2026-08-30T00:00:00.000Z"), | |
| 43 | + expiresAt: Option.none(), | |
| 44 | + }, | |
| 45 | + }, | |
| 46 | + driver: unusedVcsDriver, | |
| 47 | + }; | |
| 48 | +} | |
| 49 | + | |
| 12 | 50 | function makeLayer(input: { |
| 13 | 51 | readonly detect: VcsDriverRegistry.VcsDriverRegistry["Service"]["detect"]; |
| 14 | 52 | readonly resolve?: VcsDriverRegistry.VcsDriverRegistry["Service"]["resolve"]; |
| @@ -221,7 +259,7 @@ describe("GitWorkflowService", () => { · 206 unmodified lines | ||
| 221 | 259 | Effect.provide( |
| 222 | 260 | makeLayer({ |
| 223 | 261 | detect: () => Effect.succeed(null), |
| 224 | − resolve: () => Effect.succeed({ kind: "git" } as VcsDriverRegistry.VcsDriverHandle), | |
| 262 | + resolve: ({ cwd }) => Effect.succeed(gitHandle(cwd)), | |
| 225 | 263 | execute: (input) => Effect.fail(input.cwd === "/detached" ? detached : corrupt), |
| 226 | 264 | }), |
| 227 | 265 | ), |
| @@ -202,13 +202,13 @@ function threadLaunchPolicyFailure( · 201 unmodified lines | ||
| 202 | 202 | if (isRuntimeModeCeilingError(cause)) { |
| 203 | 203 | return failure( |
| 204 | 204 | "runtime_mode_escalation_denied", |
| 205 | − `Child runtime mode ${cause.targetMode} is broader than the caller ceiling ${cause.capturedCallerMode}.`, | |
| 205 | + `Child runtime mode ${cause.targetMode} exceeds the caller ceiling (captured ${cause.capturedCallerMode}; current ${cause.currentCallerMode}).`, | |
| 206 | 206 | ); |
| 207 | 207 | } |
| 208 | 208 | if (isInteractionModeCeilingError(cause)) { |
| 209 | 209 | return failure( |
| 210 | 210 | "interaction_mode_escalation_denied", |
| 211 | − `Child interaction mode ${cause.targetMode} is broader than the caller ceiling ${cause.capturedCallerMode}.`, | |
| 211 | + `Child interaction mode ${cause.targetMode} exceeds the caller ceiling (captured ${cause.capturedCallerMode}; current ${cause.currentCallerMode}).`, | |
| 212 | 212 | ); |
| 213 | 213 | } |
| 214 | 214 | return null; |
| @@ -636,12 +636,19 @@ describe("orchestrator MCP toolkit", () => { · 635 unmodified lines | ||
| 636 | 636 | ...actual, |
| 637 | 637 | withProjectCreationAdmission: (input, effect) => |
| 638 | 638 | actual.withProjectCreationAdmission(input, (receipt) => |
| 639 | − input.commandId === deletionRaceCommandId && Option.isNone(receipt) | |
| 640 | − ? Deferred.succeed(creationAdmissionEntered, undefined).pipe( | |
| 641 | − Effect.andThen(Deferred.await(allowCreationAdmission)), | |
| 642 | − Effect.andThen(effect(receipt)), | |
| 643 | − ) | |
| 644 | − : effect(receipt), | |
| 639 | + Effect.gen(function* () { | |
| 640 | + if (input.commandId === deletionRaceCommandId && Option.isNone(receipt)) { | |
| 641 | + yield* Deferred.succeed(creationAdmissionEntered, undefined); | |
| 642 | + yield* Deferred.await(allowCreationAdmission); | |
| 643 | + } | |
| 644 | + const gate = launchReceiptReadGates.get(input.commandId); | |
| 645 | + if (gate !== undefined) { | |
| 646 | + yield* Deferred.succeed(gate.entered, undefined); | |
| 647 | + yield* Deferred.await(gate.release); | |
| 648 | + launchReceiptReadGates.delete(input.commandId); | |
| 649 | + } | |
| 650 | + return yield* effect(receipt); | |
| 651 | + }), | |
| 645 | 652 | ), |
| 646 | 653 | }); |
| 647 | 654 | }), |
| @@ -2287,6 +2294,8 @@ describe("orchestrator MCP toolkit", () => { · 1639 unmodified lines | ||
| 2287 | 2294 | const preCreateCall = yield* Fiber.join(preCreateFiber); |
| 2288 | 2295 | expect(preCreateCall.structuredContent).toMatchObject({ |
| 2289 | 2296 | code: "interaction_mode_escalation_denied", |
| 2297 | + message: | |
| 2298 | + "Child interaction mode default exceeds the caller ceiling (captured default; current plan).", | |
| 2290 | 2299 | }); |
| 2291 | 2300 | const preCreateThreadId = ThreadId.make( |
| 2292 | 2301 | `thread:mcp:mcp-provider-session-parent:${preCreateKey}:0`, |
| @@ -2339,6 +2348,8 @@ describe("orchestrator MCP toolkit", () => { · 46 unmodified lines | ||
| 2339 | 2348 | const betweenCreateAndMessageCall = yield* Fiber.join(betweenCreateAndMessageFiber); |
| 2340 | 2349 | expect(betweenCreateAndMessageCall.structuredContent).toMatchObject({ |
| 2341 | 2350 | code: "runtime_mode_escalation_denied", |
| 2351 | + message: | |
| 2352 | + "Child runtime mode full-access exceeds the caller ceiling (captured full-access; current approval-required).", | |
| 2342 | 2353 | }); |
| 2343 | 2354 | const partialProjection = yield* orchestrator.getThreadProjection( |
| 2344 | 2355 | betweenCreateAndMessageThreadId, |