Fix workspace context review findings

This commit is contained in:
Yichen Jiang
2026-07-13 16:31:03 +08:00
parent adf6b8a1ab
commit aa62b5109a
40 changed files with 708 additions and 252 deletions
+1 -1
View File
@@ -34,7 +34,7 @@ Field names are snake_case to match Claude Code and existing harness tool schema
## The tool is the executor; policy is an event gate
The tools do **not** inject a policy service or inspect any cache. Each tool resolves the path via `ctx.fs.resolve(path, { cwd })` — passing the calling agent's session cwd (`exec.agent.session.header.cwd`) so a relative path resolves against the session's workspace, matching `dsh-tool-bash` (see [the per-session cwd RFC](../../../docs/rfc/implemented/architecture/2026-07-02-fs-per-session-cwd.md)) — then:
The tools do **not** inject a policy service or inspect any cache. Each tool resolves the path via `ctx.fs.resolve(path, { cwd, signal })` — passing the calling agent's session cwd (`exec.agent.session.header.cwd`) so a relative path resolves against the session's workspace, matching `dsh-tool-bash`, and forwarding tool cancellation through resolution (see [the per-session cwd RFC](../../../docs/rfc/implemented/architecture/2026-07-02-fs-per-session-cwd.md)) — then:
- **read** — one `ctx.fs.stat` (type + size routing + version), then `readText`/`streamText`, then builds the line window, then emits `fs/observed` with a plain `ctx.emit`. (1 stat.)
- **write** — `ctx.waterfall('fs/write-intent', target, exec, () => undefined)` for the optional guard, then `ctx.fs.writeText(target, content, intent)`, then `fs/observed`. (0 stat.)
+4 -1
View File
@@ -83,7 +83,10 @@ export function applyEditTool(ctx: Context): void {
async execute(args, exec): Promise<{ content: ContentBlock[]; meta?: FsDiffMeta }> {
const input = parseEditArgs(args)
const cwd = sessionCwd(exec)
const target = await ctx.fs.resolve(input.filePath, cwd !== undefined ? { cwd } : undefined)
const target = await ctx.fs.resolve(input.filePath, {
...cwd !== undefined ? { cwd } : {},
...exec.signal !== undefined ? { signal: exec.signal } : {},
})
// Single-slot decision: the policy plugin returns { version: vObserved } or
// throws FS_NOT_OBSERVED; the bare default is undefined (unconditional edit).
// No stat — the bare default never manufactures a version basis.
+4 -1
View File
@@ -95,7 +95,10 @@ export function applyReadTool(ctx: Context, caps: ReadToolCaps): void {
async execute(args, exec): Promise<ContentBlock[]> {
const input = parseReadArgs(args, caps.limit)
const cwd = sessionCwd(exec)
const target = await ctx.fs.resolve(input.filePath, cwd !== undefined ? { cwd } : undefined)
const target = await ctx.fs.resolve(input.filePath, {
...cwd !== undefined ? { cwd } : {},
...exec.signal !== undefined ? { signal: exec.signal } : {},
})
// One stat: type check + size routing + the version recorded as observed.
// A writer racing between this stat and the read can at worst make a LATER
+4 -1
View File
@@ -68,7 +68,10 @@ export function applyWriteTool(ctx: Context): void {
async execute(args, exec): Promise<{ content: ContentBlock[]; meta?: FsDiffMeta }> {
const input = parseWriteArgs(args)
const cwd = sessionCwd(exec)
const target = await ctx.fs.resolve(input.filePath, cwd !== undefined ? { cwd } : undefined)
const target = await ctx.fs.resolve(input.filePath, {
...cwd !== undefined ? { cwd } : {},
...exec.signal !== undefined ? { signal: exec.signal } : {},
})
// Single-slot decision: the policy plugin produces createIfAbsent/
// replaceIfVersion; the bare default is undefined (unconditional). No stat.
const intent = await ctx.waterfall('fs/write-intent', target, exec, () => undefined)