Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
refactor(harness): drop Location.Ref; location is always the mount cwd
Ref.directory let a Location point somewhere other than the mount's cwd,
where tools actually run. Only a test fixture set it, and Location.layerWith
and defaultLayer took a Ref with no callers at all. Remove all three; the
fixture mounts the remote sandbox at the repo instead, as the runner mounts
at the session directory.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
  • Loading branch information
sanchitrk and claude committed Oct 6, 2026
commit 28fdbe8171d6e9d49f9bb16bf00f466748cc8d3c
20 changes: 6 additions & 14 deletions packages/harness/src/location/location.ts
Original file line number Diff line number Diff line change
@@ -1,19 +1,17 @@
import { Effect, Layer } from "effect";
import { Database } from "../db/db.ts";
import { Git } from "../git/git.ts";
import { Project } from "../project/project.ts";
import { Repo } from "../repo/repo.ts";
import { SandboxIO } from "../sandbox/io.ts";
import { Sandbox } from "../sandbox/sandbox.ts";
import { AbsolutePath } from "../schema.ts";
import { Space } from "../space/space.ts";
import { Worktree } from "../worktree/worktree.ts";
import { Info, type Ref, Service } from "@codeworksh/plugin/location";
import { Info, Service } from "@codeworksh/plugin/location";

/**
* Where work happens: a directory inside a space.
*
* The shape (`Ref`, `Info`) and the service tag live in `@codeworksh/plugin`, because a resolved
* The shape (`Info`) and the service tag live in `@codeworksh/plugin`, because a resolved
* `Info` is on every plugin context and `Service` is half of a plugin's `Mount`. Resolving one
* needs Project, Space, Repo, Worktree and Git, so the layers stay here.
*/
Expand All @@ -23,19 +21,18 @@ export {
Info,
type Interface,
NotDirectoryError,
Ref,
Service,
} from "@codeworksh/plugin/location";

// `SandboxIO.Current` in the requirements is what makes "mount first" a
// type-level fact rather than a convention: this Layer cannot be built outside a
// mount, so there is never a Location without one underneath.
export const layer = (ref: Ref = {}) =>
export const layer = () =>
Layer.effect(
Service,
Effect.gen(function* () {
const instance = yield* SandboxIO.Current;
const directory = AbsolutePath.make(ref.directory ?? instance.cwd);
const directory = AbsolutePath.make(instance.cwd);
const project = yield* Project.Service;
const resolved = yield* project.resolveOrCreate(directory);
return Service.of(
Expand All @@ -49,8 +46,8 @@ export const layer = (ref: Ref = {}) =>
* folded in. What remains is exactly the mount and the database — for callers
* that already hold both, such as the runner and `Session.create`.
*/
export const layerMounted = (ref: Ref = {}) =>
layer(ref).pipe(
export const layerMounted = () =>
layer().pipe(
Layer.provide(
Project.layer.pipe(
Layer.provide(Layer.mergeAll(Repo.layer, Worktree.layer, Space.layer)),
Expand All @@ -59,9 +56,4 @@ export const layerMounted = (ref: Ref = {}) =>
),
);

export const layerWith = <E, RIn>(ref: Ref, sandbox: Sandbox.Sandbox<E, RIn>) =>
layerMounted(ref).pipe(Layer.provide(sandbox), Layer.provide(Database.defaultLayer));

export const defaultLayer = (ref: Ref, path: string) => layerWith(ref, Sandbox.defaultLayer(path));

export * as Location from "./location.ts";
7 changes: 2 additions & 5 deletions packages/harness/test/fixtures/remote.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@ import { SandboxIO } from "../../src/sandbox/io.ts";
import { Sandbox } from "../../src/sandbox/sandbox.ts";
import { type ISandboxExe, Shell } from "../../src/sandbox/shell/shell.ts";
import { SandboxStore } from "../../src/sandbox/store.ts";
import { AbsolutePath } from "../../src/schema.ts";
import { Session } from "../../src/session/session.ts";
import { fromSandboxShell, ToolShell, ToolShellTimeout } from "../../src/tool/shell.ts";
import { Hash } from "../../src/util/hash.ts";
Expand Down Expand Up @@ -393,6 +392,7 @@ export const remoteSandboxSpec = (options: RemoteSandboxSpecOptions) => {
driver: options.kind,
id: mappedEnvId,
defaultCwd: options.cwd,
cwd: repo,
}),
),
);
Expand All @@ -410,10 +410,7 @@ export const remoteSandboxSpec = (options: RemoteSandboxSpecOptions) => {
}),
),
).pipe(Layer.provide(database));
const location = Location.layerMounted({ directory: AbsolutePath.make(repo) }).pipe(
Layer.provide(sandbox),
Layer.provide(registered),
);
const location = Location.layerMounted().pipe(Layer.provide(sandbox), Layer.provide(registered));
// provideMerge, not provide: `registered` and the block below
// share the one in-memory database.
const application = Layer.merge(location, Session.layer).pipe(
Expand Down
8 changes: 1 addition & 7 deletions packages/plugin/src/location.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ import { SpaceSchema } from "./space.ts";
* equal to or beneath that root. Sessions sharing a space share the project;
* worktree relationships stay a Project concern beneath it.
*
* **Both halves come from the mount, so `Ref` is overrides and nothing else.**
* **Both halves come from the mount, and nothing overrides them.**
* A Location is a directory *within* a mounted namespace — the mount has to be
* resolved first, the way a volume is mounted before any path on it means
* anything — and once it is, the namespace and the working directory are already
Expand All @@ -26,12 +26,6 @@ import { SpaceSchema } from "./space.ts";
* which belong to the harness; a plugin receives a resolved `Info` on its context and asks for
* {@link Service} when it needs the live one.
*/
export const Ref = Schema.Struct({
/** Defaults to the mount's cwd. Set it to work in a subdirectory of the mount. */
directory: Schema.optional(AbsolutePath),
}).annotate({ identifier: "Location.Ref" });
export type Ref = typeof Ref.Type;

export class Info extends Schema.Class<Info>("Location.Info")({
/** The absolute cwd tools run in; `space.location` is the root it lives under. */
directory: AbsolutePath,
Expand Down