Skip to content

fix: preserve subdirectory in generated pipeline_path and source_path#114

Merged
jamesadevine merged 4 commits intomainfrom
copilot/fix-source-path-issue
Apr 2, 2026
Merged

fix: preserve subdirectory in generated pipeline_path and source_path#114
jamesadevine merged 4 commits intomainfrom
copilot/fix-source-path-issue

Conversation

Copy link
Copy Markdown
Contributor

Copilot AI commented Apr 1, 2026

When compiling an agent from a subdirectory (e.g. ado-aw compile agents/ctf.md), the embedded runtime paths dropped the directory component — $(Build.SourcesDirectory)/ctf.yml instead of $(Build.SourcesDirectory)/agents/ctf.yml — causing the integrity check to fail with "Failed to read pipeline file".

Changes

  • generate_pipeline_path — was using .file_name() only, stripping the directory. Now uses the full relative output path.
  • generate_source_path — was using .file_name() with a hardcoded agents/ prefix. Now uses the actual input path, so it works for agents outside agents/ too.
  • normalize_relative_path (new private helper) — shared logic for both functions: normalises backslashes, strips leading ./, returns None for absolute paths (which fall back to filename-only to avoid embedding machine-local paths).
# Before
ado-aw compile agents/ctf.md
→ pipeline_path: $(Build.SourcesDirectory)/ctf.yml        ❌
→ source_path:   $(Build.SourcesDirectory)/agents/ctf.md  (coincidentally correct)

# After
→ pipeline_path: $(Build.SourcesDirectory)/agents/ctf.yml ✅
→ source_path:   $(Build.SourcesDirectory)/agents/ctf.md  ✅

Warning

Firewall rules blocked me from connecting to one or more addresses (expand for details)

I tried to connect to the following addresses, but was blocked by firewall rules:

  • api.github.com (HTTP Only)
    • Triggering command: /home/REDACTED/work/ado-aw/ado-aw/target/debug/ado-aw /home/REDACTED/work/ado-aw/ado-aw/target/debug/ado-aw proxy --allow api.github.com /home/REDACTED/work/ado-aw/ado-aw/target/debug/deps/ado_aw-901177e61cbb1b68.0kwa8t2hznvu270qhmfsm79sc.1vu0gm9.rcgu.o /home/REDACTED/work/ado-aw/ado-aw/target/debug/deps/ado_aw-901177e61cbb1b68.0pcekopkbnpys1da1ris3pqs9.1vu0gm9.rcgu.o /home/REDACTED/work/ado-aw/ado-aw/target/debug/deps/ado_aw-901177e61cbb1b68.0qtd9xllgeex2wkq0oj23zggp.1vu0gm9.rcgu.o /home/REDACTED/work/ado-aw/ado-aw/target/debug/deps/ado_aw-901177e61cbb1b68.0qxager6yhnw54gls4uzbnw6t.1vu0gm9.rcgu.o /home/REDACTED/work/ado-aw/ado-aw/target/debug/deps/ado_aw-901177e61cbb1b68.0v1xlveprg2v11211pb4hk1b7.1vu0gm9.rcgu.o /home/REDACTED/work/ado-aw/ado-aw/target/debug/deps/ado_aw-901177e61cbb1b68.0w9re9zebc�� /home/REDACTED/work/ado-aw/ado-aw/target/debug/deps/ado_aw-901177e61cbb1b68.0wsvezv21pidn3xtp63wsarpo.1vu0gm9.rcgu.o /home/REDACTED/work/ado-aw/ado-aw/target/debug/deps/ado_aw-901177e61cbb1b68.11a3unh6kxm1239lfz7wptc9c.1vu0gm9.rcgu.o pl-0�� pl-04ebe6c200f92/home/REDACTED/work/ado-aw/ado-aw/target/debug/deps/clap_derive-6c481cafea220ba5.cbash eta.o bin/rustc s/zerovec_derivecc s/zerovec_derive-m64 e-99b09bf0514b3f/home/REDACTED/work/ado-aw/ado-aw/target/debug/deps/rustclqpbQw/symbols.o bin/rustc (packet block)
  • dev.azure.com
    • Triggering command: /home/REDACTED/work/ado-aw/ado-aw/target/debug/deps/ado_aw-120b6e3ae6d990e4 /home/REDACTED/work/ado-aw/ado-aw/target/debug/deps/ado_aw-120b6e3ae6d990e4 /home/REDACTED/work/ado-aw/ado-aw/target/debug/deps/proxy_tests-e918d4672bff9d0a.0ki8be9331fq7b5k43ln63ipe.1bvyay3.rcgu.o /home/REDACTED/work/ado-aw/ado-aw/target/debug/deps/proxy_tests-e918d4672bff9d0a.182866il28js2phhhtx4xusj3.1bvyay3.rcgu.o /home/REDACTED/work/ado-aw/ado-aw/target/debug/deps/proxy_tests-e918d4672bff9d0a.18enw4avdh5wrulx72d9mk2rk.1bvyay3.rcgu.o /home/REDACTED/work/ado-aw/ado-aw/target/debug/deps/proxy_tests-e918d4672bff9d0a.19gy1530lm15039vn08bet7jo.1bvyay3.rcgu.o /home/REDACTED/work/ado-aw/ado-aw/target/debug/deps/proxy_tests-e918d4672bff9d0a.1dro5yol2gis0xxpfric5tutz.1bvyay3.rcgu.o d2d7vvkscal1uwtx3do.1vu0gm9.rcgu.o kerwtsy7jj7met9x0up.1vu0gm9.rcgu.o al8es9e80eizaijemvp.1vu0gm9.rcgu.o 9in3ps4ugqtyrvv5elz.1vu0gm9.rcgu.o shhtycaix58ykco0tsn.1vu0gm9.rcgu.o ffkx0882tm6ia19bbfu.1vu0gm9.rcgu.o hm8gh96bbxozz4u8pid.1vu0gm9.rcgu.o rq5bv4m0vfsgocg94ig.1vu0gm9.rcgu.o rh0oumk11a7z9txwx6p.1vu0gm9.rcgu.o 2hznvu270qhmfsm79sc.1vu0gm9.rcgu.o pkbnpys1da1ris3pqs9.1vu0gm9.rcgu.o llgeex2wkq0oj23zggp.1vu0gm9.rcgu.o r6yhnw54gls4uzbnw6t.1vu0gm9.rcgu.o eprg2v11211pb4hk1b7.1vu0gm9.rcgu.o (dns block)
    • Triggering command: /home/REDACTED/work/ado-aw/ado-aw/target/debug/ado-aw /home/REDACTED/work/ado-aw/ado-aw/target/debug/ado-aw proxy --allow api.github.com --allow dev.azure.com --allow *.visualstudio.com /home/REDACTED/work/ado-aw/ado-aw/target/debug/deps/ado_aw-901177e61cbb1b68.0v1xlveprg2v11211pb4hk1b7.1vu0gm9.rcgu.o /home/REDACTED/work/ado-aw/ado-aw/target/debug/deps/ado_aw-901177e61cbb1b68.0w9re9zebc�� /home/REDACTED/work/ado-aw/ado-aw/target/debug/deps/ado_aw-901177e61cbb1b68.0wsvezv21pidn3xtp63wsarpo.1vu0gm9.rcgu.o /home/REDACTED/work/ado-aw/ado-aw/target/debug/deps/ado_aw-901177e61cbb1b68.11a3unh6kxm1239lfz7wptc9c.1vu0gm9.rcgu.o pl-0�� pl-04ebe6c200f92/home/REDACTED/work/ado-aw/ado-aw/target/debug/deps/clap_derive-6c481cafea220ba5.cbash eta.o bin/rustc s/zerovec_derivecc s/zerovec_derive-m64 e-99b09bf0514b3f/home/REDACTED/work/ado-aw/ado-aw/target/debug/deps/rustclqpbQw/symbols.o bin/rustc (dns block)
  • msazuresphere.visualstudio.com
    • Triggering command: /home/REDACTED/work/ado-aw/ado-aw/target/debug/ado-aw /home/REDACTED/work/ado-aw/ado-aw/target/debug/ado-aw proxy --allow api.github.com --allow dev.azure.com --allow *.visualstudio.com /home/REDACTED/work/ado-aw/ado-aw/target/debug/deps/ado_aw-901177e61cbb1b68.0v1xlveprg2v11211pb4hk1b7.1vu0gm9.rcgu.o /home/REDACTED/work/ado-aw/ado-aw/target/debug/deps/ado_aw-901177e61cbb1b68.0w9re9zebc�� /home/REDACTED/work/ado-aw/ado-aw/target/debug/deps/ado_aw-901177e61cbb1b68.0wsvezv21pidn3xtp63wsarpo.1vu0gm9.rcgu.o /home/REDACTED/work/ado-aw/ado-aw/target/debug/deps/ado_aw-901177e61cbb1b68.11a3unh6kxm1239lfz7wptc9c.1vu0gm9.rcgu.o pl-0�� pl-04ebe6c200f92/home/REDACTED/work/ado-aw/ado-aw/target/debug/deps/clap_derive-6c481cafea220ba5.cbash eta.o bin/rustc s/zerovec_derivecc s/zerovec_derive-m64 e-99b09bf0514b3f/home/REDACTED/work/ado-aw/ado-aw/target/debug/deps/rustclqpbQw/symbols.o bin/rustc (dns block)
  • raw.github.com
    • Triggering command: /home/REDACTED/work/ado-aw/ado-aw/target/debug/ado-aw /home/REDACTED/work/ado-aw/ado-aw/target/debug/ado-aw proxy --allow *.github.com /lib64/ld-linux-x86-64.so.2 -pie -z now -z relro -o /home/REDACTED/work/ado-aw/ado-aw/target/debug/deps/compiler_tests-77e0c86b279020fb g/de�� known-linux-gnu/--build-id known-linux-gnu/--eh-frame-hdr bin/rustc e-486665cf5f9386/home/REDACTED/.rustup/toolchains/stable-x86_64-REDACTED-linux-gnu/bin/rustc e-486665cf5f9386--crate-name e-486665cf5f9386ado_aw bin/rustc (dns block)

If you need me to access, download, or install something from one of these locations, you can either:

When compiling from a directory that contains a subdirectory with the
agent markdown (e.g. `ado-aw compile agents/ctf.md` from the repo root),
the generated pipeline embedded only the filename in pipeline_path and
source_path, dropping the subdirectory prefix.

Root causes:
- generate_pipeline_path used file_name() only → agents/ctf.yml became
  {{ workspace }}/ctf.yml instead of {{ workspace }}/agents/ctf.yml
- generate_source_path used file_name() only and hardcoded the agents/
  prefix → would break for files outside agents/

Fix:
- Both functions now preserve the full relative path via a shared
  normalize_relative_path helper (strips leading ./ and normalizes slashes)
- Absolute paths fall back to filename-only to avoid embedding
  machine-specific paths in the pipeline YAML
- Added 8 unit tests covering the corrected behaviour

Agent-Logs-Url: https://github.com/githubnext/ado-aw/sessions/13f2c5e7-28fe-4ffb-9460-dd868098ce0c

Co-authored-by: jamesadevine <4742697+jamesadevine@users.noreply.github.com>
Copilot AI changed the title [WIP] Fix incorrect source path in generated pipeline fix: preserve subdirectory in generated pipeline_path and source_path Apr 1, 2026
Copilot AI requested a review from jamesadevine April 1, 2026 21:56
@jamesadevine
Copy link
Copy Markdown
Collaborator

/rust-review

@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented Apr 2, 2026

Rust PR Reviewer completed successfully!

@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented Apr 2, 2026

🔍 Rust PR Review

Summary: Correct fix with good tests — one missing edge-case test and a minor nit.

Findings

⚠️ Suggestions

  • src/compile/common.rs — no test for absolute-path fallback
    The None branch of normalize_relative_path (absolute paths fall back to filename-only) is documented but not tested. A test like Path::new("/home/user/agents/ctf.md")\{\{ workspace }}/ctf.md would catch regressions in that branch.

  • src/compile/common.rs:558 — minor: redundant allocation in ./ stripping loop

    while s.starts_with("./") {
        s = s[2..].to_string();   // new String per iteration
    }

    Slightly cleaner:

    while let Some(stripped) = s.strip_prefix("./") {
        s = stripped.to_string();
    }

    Not a bug, just idiomatic Rust.

  • normalize_relative_path.. components are passed through unchanged
    If a user runs ado-aw compile ../../my-agent.md, the generated YAML will embed ../../my-agent.md relative to the workspace, which would point outside the checkout at runtime. This won't affect the normal workflow (agents live in agents/), but worth a note or an assertion in the function docs that relative .. components are the caller's responsibility.

✅ What Looks Good

  • Root cause fix is correct: the old generate_pipeline_path was calling file_name() which silently dropped the directory component, while generate_source_path hardcoded agents/ — so the two were only accidentally consistent. Using the full relative path for both is the right approach.
  • 8 well-named unit tests cover the key cases (nested dirs, ./ stripping, filename-only), and they directly encode the expected values so regressions are caught immediately.
  • is_absolute() guard correctly prevents machine paths leaking into generated YAML.
  • All 29 compiler tests pass.

Generated by Rust PR Reviewer for issue #114 ·

Warning

⚠️ Firewall blocked 1 domain

The following domain was blocked by the firewall during workflow execution:

  • dev.azure.com

To allow these domains, add them to the network.allowed list in your workflow frontmatter:

network:
  allowed:
    - defaults
    - "dev.azure.com"

See Network Configuration for more information.

@jamesadevine
Copy link
Copy Markdown
Collaborator

@copilot

src/compile/common.rs — no test for absolute-path fallback
The None branch of normalize_relative_path (absolute paths fall back to filename-only) is documented but not tested. A test like Path::new("/home/user/agents/ctf.md") → {{ workspace }}/ctf.md would catch regressions in that branch.

src/compile/common.rs:558 — minor: redundant allocation in ./ stripping loop

while s.starts_with("./") {
s = s[2..].to_string(); // new String per iteration
}
Slightly cleaner:

while let Some(stripped) = s.strip_prefix("./") {
s = stripped.to_string();
}
Not a bug, just idiomatic Rust.

normalize_relative_path — .. components are passed through unchanged
If a user runs ado-aw compile ../../my-agent.md, the generated YAML will embed ../../my-agent.md relative to the workspace, which would point outside the checkout at runtime. This won't affect the normal workflow (agents live in agents/), but worth a note or an assertion in the function docs that relative .. components are the caller's responsibility.

- Use strip_prefix idiom instead of manual index slicing in ./ loop
- Add doc note that .. components are the caller's responsibility
- Add absolute-path fallback tests for both generate_source_path and
  generate_pipeline_path

Agent-Logs-Url: https://github.com/githubnext/ado-aw/sessions/a8c9ad7f-e06e-40d8-98bf-25160a4183d8

Co-authored-by: jamesadevine <4742697+jamesadevine@users.noreply.github.com>
Copy link
Copy Markdown
Contributor Author

Copilot AI commented Apr 2, 2026

@copilot

src/compile/common.rs — no test for absolute-path fallback
...

Addressed in f67a9ca:

  • ./ stripping loop — switched to strip_prefix idiom (no per-iteration allocation).
  • .. components — added a doc note that relative .. components are passed through unchanged and are the caller's responsibility.
  • Absolute-path fallback tests — added test_generate_source_path_absolute_falls_back_to_filename and test_generate_pipeline_path_absolute_falls_back_to_filename covering the None branch.

Comment thread src/compile/common.rs
/// runtime path (`$(Build.SourcesDirectory)/agents/ctf.md`) rather than a path
/// that drops the directory component.
///
/// Absolute paths fall back to using only the filename to avoid embedding
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@copilot does this mean if an absolute path is provided the error will reoccur? If so, we should instead detect an absolute path and extract the common root directory where the .git folder lies and compute the relative path.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes — with the previous code, an absolute path would lose the directory and the bug would reoccur. Fixed in bfe3530.

Added find_git_root which walks up the directory tree looking for a .git entry (works with both .git directories and worktree .git files). normalize_relative_path now uses it for absolute paths: /home/user/repo/agents/ctf.mdagents/ctf.md (relative to the git root). Only falls back to filename-only when no git root is found.

@jamesadevine jamesadevine marked this pull request as ready for review April 2, 2026 09:29
When an absolute path is passed (e.g. ado-aw compile /home/user/repo/agents/ctf.md),
the previous code fell back to filename-only, losing the directory component and
causing the integrity check to fail.

- Add find_git_root() to walk up the directory tree looking for a .git entry
- Update normalize_relative_path() to use it for absolute paths, computing a
  path relative to the git repo root instead of falling back to filename-only
- Fall back to filename-only only when no git root is found
- Add tests covering the git-root happy path (using tempfile::TempDir for
  safe cleanup) and the no-git-root fallback for both functions

Agent-Logs-Url: https://github.com/githubnext/ado-aw/sessions/75c10525-fed4-4c3f-a784-ede99d43f058

Co-authored-by: jamesadevine <4742697+jamesadevine@users.noreply.github.com>
@jamesadevine jamesadevine merged commit 32137fe into main Apr 2, 2026
Copilot stopped work on behalf of jamesadevine due to an error April 2, 2026 09:34
Copilot AI requested a review from jamesadevine April 2, 2026 09:34
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Source path is incorrect when generated from different directory.

2 participants