Skip to content

Export WARP_SKILL_DIRS as absolute paths to the agent shell - #15256

Draft
warp-agent-staging[bot] wants to merge 2 commits into
masterfrom
factory/absolute-warp-skill-dirs
Draft

Export WARP_SKILL_DIRS as absolute paths to the agent shell#15256
warp-agent-staging[bot] wants to merge 2 commits into
masterfrom
factory/absolute-warp-skill-dirs

Conversation

@warp-agent-staging

@warp-agent-staging warp-agent-staging Bot commented Aug 17, 2026

Copy link
Copy Markdown
Contributor

Description

WARP_SKILL_DIRS is injected into a Factory agent's environment holding paths relative to the environment working directory (e.g. factory-dev/frank/agents/implementation/skills,factory-dev/frank/skills). The driver's own skill loader already resolves these against working_dir, but the raw relative value also leaks into the agent's shell, where skills read it directly — for example the github skill's sed/cd snippet that parses WARP_SKILL_DIRS to locate the factory's factory.yaml and resolve the factory name/alias.

Agents routinely cd into a product repo. Once they do, the relative entries resolve against the wrong directory, sed reads nothing, and skill resolution silently yields empty strings — producing a bare factory label or a missing footer (SEV2, warpdotdev/warp-server#15372).

The environment working directory is only known absolutely on the client (the server injects a relative value because it cannot know the sandbox mount path). So this fixes it at the authoritative place that can resolve it: AgentDriver::new re-exports an absolute WARP_SKILL_DIRS into the agent's environment, resolved against working_dir. Because this value flows through the terminal driver and the third‑party harness runners, Oz, Claude, and Codex agents all see absolute paths regardless of their current working directory. The server-side relative value and the driver's own loader are left unchanged.

Linked Issue

warpdotdev/warp-server#15372

  • The linked issue is labeled ready-to-spec or ready-to-implement.
  • Where appropriate, screenshots or a short video of the implementation are included below (especially for user-visible or UI changes).

Changes

  • Added a pure absolute_skill_dirs(working_dir, dirs) helper in app/src/ai/agent_sdk/driver.rs that resolves relative entries against working_dir (absolute entries pass through) and re-joins them. absolute_skill_dirs_env is now a thin env-reading wrapper over it.
  • The value is assembled directly as an OsString from each path's raw OsStr bytes — not via to_string_lossy — so a working_dir containing non-UTF-8 bytes (possible on Unix) is preserved verbatim instead of being corrupted with U+FFFD.
  • AgentDriver::new inserts that absolute value into the agent's resolved env vars, overriding the relative value inherited from the environment. Returns None/no-op when WARP_SKILL_DIRS is unset or empty.

Testing

Non-UI change (environment-variable resolution), so no visual proof applies.

Regression tests in app/src/ai/agent_sdk/driver_tests.rs (all drive the pure helper with PathBuf inputs — no global set_var/remove_var, no serial):

  • absolute_skill_dirs_makes_relative_entries_absolute — a relative value like the reported one becomes absolute (joined onto the working dir), which is exactly what makes the shell snippet resolve from any cwd.
  • absolute_skill_dirs_passes_absolute_entries_through — absolute entries are untouched; only relative ones are joined.
  • absolute_skill_dirs_empty_is_none — empty input leaves the variable untouched.
  • absolute_skill_dirs_preserves_non_utf8_working_dir (cfg(unix)) — a non-UTF-8 working dir keeps its raw 0xff byte with no U+FFFD replacement sequence.

Commands run (in warp/):

  • cargo test -p warp --lib absolute_skill_dirs4 passed; 0 failed

  • cargo check -p warp --lib → clean

  • ./script/format and cargo fmt -p warp -- --check → clean

  • cargo clippy -p warp --lib → clean

  • I have manually tested my changes locally with ./script/run

Agent Mode

  • Warp Agent Mode - This PR was created via Warp's AI Agent Mode

This PR was created by Oz (running Codex).

WARP_SKILL_DIRS is injected holding paths relative to the environment
working directory. The driver's own skill loader resolves those against
working_dir, but the raw relative value also leaks into the agent's
shell, where skills read it directly (e.g. the github skill's sed/cd
snippet that locates the factory's factory.yaml). Once an agent cd's
into a product repo, those relative paths resolve to nothing, so skill
resolution silently yields empty and the factory label / footer is lost.

The environment working directory is only known absolutely on the
client, so resolve there: in AgentDriver::new, re-export an absolute
WARP_SKILL_DIRS into the agent's environment, resolved against
working_dir via the existing resolve_skills_dirs helper. This flows
through the terminal driver and third-party harness runners, so Oz,
Claude, and Codex agents all see absolute paths regardless of cwd. The
server-side relative value and the driver's own loader are unchanged.

Fixes warpdotdev/warp-server#15372

Co-Authored-By: Warp <agent@warp.dev>
@cla-bot cla-bot Bot added the cla-signed label Aug 17, 2026
Two adversarial-review findings on the WARP_SKILL_DIRS fix:

1. Correctness: the absolute value was assembled with `to_string_lossy`,
   so a `working_dir` containing non-UTF-8 bytes (possible on Unix) would
   be corrupted with U+FFFD replacement characters, exporting paths that
   no longer name the real skill directories. Assemble the comma-separated
   value directly as an `OsString` from each path's raw `OsStr` bytes.

2. Test isolation: the tests mutated the global `WARP_SKILL_DIRS` via
   unsafe `set_var`/`remove_var` (only loosely coordinated by
   `serial_test`) and unconditionally deleted any inherited value. Split a
   pure `absolute_skill_dirs(working_dir, dirs)` from the thin env-reading
   wrapper and drive the tests through it with `PathBuf` inputs, removing
   all process-env mutation and the serial attribute.

Also adds a `cfg(unix)` regression test that builds a non-UTF-8
working directory and asserts the raw 0xff byte survives with no U+FFFD
replacement sequence.

Fixes warpdotdev/warp-server#15372

Co-Authored-By: Warp <agent@warp.dev>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

0 participants