Skip to content

bug(server): workspace_path sent by harnesscli --workspace and the TUI is silently ignored; tools run in the daemon workspace #1372

Description

@dennisonbertram

[parent] #1369

Work type

Bug / regression

Observed behavior

harnesscli --base-url ... --workspace /tmp/other --prompt "..." with a scripted write where-am-i.txt tool call wrote the file into the daemon's HARNESS_WORKSPACE, not /tmp/other. The CLI (cmd/harnesscli/main.go runCreateRequest.WorkspacePath, default cwd) and the TUI (cmd/harnesscli/tui/api.go:72) both send workspace_path; harness.RunRequest (internal/harness/types.go:444) has no such field and handlePostRun decodes without DisallowUnknownFields, so it is dropped silently. The flag help text says "workspace directory for this run" and docs/ux-paths.md:107 says it is forwarded.

Expected behavior

A run started with workspace_path runs its file and shell tools rooted at that directory (validated absolute, existing), confined by the sandbox to that root, and the conversation record stores it. Invalid values are rejected with 400 like extra_dirs. If the server chooses not to support it, it must reject the field rather than ignore it.

Reproduction

  1. Start harnessd with HARNESS_WORKSPACE=/tmp/a.
  2. From /tmp/b: harnesscli --prompt "write hello.txt" (or --workspace /tmp/b).
    Actual: /tmp/a/hello.txt. Deterministic.

User and operational impact

Every TUI/CLI user working from a directory other than the daemon's startup directory gets agent edits applied to the wrong project, with a success message. #559 proposes the same field as a feature; #567 shows the per-run registry path exists for provisioned workspaces.

Suspected seam and search evidence

internal/harness/runner.go ~1716-1817 already builds a per-run tool registry rooted at a provisioned workspace path (NewDefaultRegistryWithOptions(wsPath, ...), workspace.provisioned event). The fix routes an explicit workspace_path through that same per-run root without provisioning. Validation mirrors ExtraDirs checks in StartRun.

Blast-radius impact map

Callers: CLI, TUI, ACP bridge, MCP start_run (check whether they send it). Config/env: HARNESS_WORKSPACE stays the default. API/wire: new optional workspace_path on RunRequest. Persistence: conversations.workspace should record the effective root (#1303 item 1 mentions it is empty in production). Concurrency: per-run registry already exists. Security: absolute+exists validation; sandbox confinement rooted at the per-run path; extra_dirs unchanged. Docs: harnesscli runbook, ux-paths. Tests: internal/harness runner tests, internal/server handler tests, cmd/harnesscli tests.

Regression test first

internal/harness/runner_test.go TestStartRun_WorkspacePathRootsTools (write tool lands under the requested root) and internal/server TestPostRun_WorkspacePathValidated (relative/nonexistent → 400).
Red: go test ./internal/harness -run TestStartRun_WorkspacePath. Expected failure: file written under the daemon root.

Fix boundaries

In scope: decode, validate, and honor workspace_path via the existing per-run registry; record it on the conversation. Out of scope: provisioning/isolation modes, multi-tenant policy for allowed roots (follow-up if needed), #567 VM path.

Diagnostic and observability evidence

Existing workspace.provisioned event should carry the path for explicit roots too.

Verification plan

Red/green; go test ./internal/harness ./internal/server ./cmd/harnesscli -race; live: CLI from a different cwd writes into its cwd; sandbox scenario still blocks escapes from the new root.

Rollout and rollback

Behavior change only for clients that already send the field; revert PR to roll back.

Documentation and handoff

Engineering log; docs/runbooks/harnesscli-live-testing.md, docs/ux-paths.md, README run-request fields.

Definition of done

  • Red tests preserved; field honored and validated
  • Sandbox confinement proven against the per-run root
  • Race and full regression green; docs updated

Process acknowledgement

  • I will preserve the failing regression test, update the issue if the root cause changes, and record any newly discovered bug as its own issue.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't workingcorrectnessCorrectness bugs and logic errorsworkspaceWorkspace abstraction and implementations

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions