Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
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
3 changes: 3 additions & 0 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,7 @@ fail-closed and only pauses when the agent actually proposed a reviewed output.
│ │ ├── gitattributes.rs # .gitattributes management for compiled pipelines
│ │ ├── filter_ir.rs # Filter expression IR: Fact/Predicate types, lowering, validation, codegen
│ │ ├── pr_filters.rs # PR trigger filter generation (native ADO + gate steps)
│ │ ├── path_layout_check.rs # Warning-only checkout-aware path validation: $(Build.SourcesDirectory)/<seg> refs in steps, runtime-import targets, deprecated directory markers in the body
│ │ ├── extensions/ # CompilerExtension trait and infrastructure extensions
│ │ │ ├── mod.rs # Trait, Extension enum, collect_extensions(), re-exports
│ │ │ ├── ado_aw_marker.rs # Always-on metadata marker extension (emits # ado-aw-metadata JSON)
Expand All @@ -95,6 +96,8 @@ fail-closed and only pauses when the agent actually proposed a reviewed output.
│ │ │ ├── mod.rs # Codemod struct, CODEMODS registry, runner
│ │ │ ├── 0001_repos_unified.rs # Legacy repositories/checkout → repos codemod
│ │ │ ├── 0002_pool_object_form.rs # Legacy scalar pool → object form codemod
│ │ │ ├── 0003_flatten_work_item_config.rs # Legacy work-item config flatten codemod
│ │ │ ├── 0004_legacy_path_markers.rs # Migrate {{ workspace }}/{{ working_directory }}/{{ trigger_repo_directory }} markers → explicit ADO path exprs (resolved from workspace:/repos:)
│ │ │ └── helpers.rs # take_key, insert_no_overwrite, rename_key, ConflictPolicy
│ │ ├── codemod_integration_test.rs # White-box rewrite-path tests (stub registry injection)
│ │ ├── types.rs # Front matter grammar and types
Expand Down
37 changes: 36 additions & 1 deletion docs/codemods.md
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,9 @@ src/compile/codemods/
├── mod.rs # Framework + CODEMODS registry
├── helpers.rs # take_key, insert_no_overwrite, rename_key, ConflictPolicy
├── 0001_repos_unified.rs # Legacy repositories: + checkout: → repos: codemod
└── 0002_pool_object_form.rs # Legacy scalar pool → explicit object form codemod
├── 0002_pool_object_form.rs # Legacy scalar pool → explicit object form codemod
├── 0003_flatten_work_item_config.rs # Legacy work-item config flatten codemod
└── 0004_legacy_path_markers.rs # {{ workspace }} / {{ working_directory }} / {{ trigger_repo_directory }} → explicit ADO path exprs
```

(New codemods are appended as `<NNNN>_<id>.rs` files.)
Expand Down Expand Up @@ -357,6 +359,39 @@ fn describe(v: &Value) -> &'static str {
identifiers cannot start with digits, but the file name does.
The registry-uniqueness and filename-prefix tests keep passing.

## Legacy directory markers (`0004_legacy_path_markers`)

Before the native-IR migration, the compiler folded a fixed
replacement list across the **entire** generated YAML — including
user-authored `steps:` / `post-steps:` / `setup:` / `teardown:`. That
fold substituted the directory markers:

| Marker | Resolved to |
|--------|-------------|
| `{{ workspace }}`, `{{ working_directory }}` | the resolved working directory (`$(Build.SourcesDirectory)`, `$(Build.SourcesDirectory)/$(Build.Repository.Name)`, or `$(Build.SourcesDirectory)/<alias>`) |
| `{{ trigger_repo_directory }}` | the trigger ("self") repo dir |

After the IR migration these markers flow through verbatim and are no
longer substituted. Rather than restore runtime substitution of a
fixed-path anchor — an antipattern under multi-checkout, where
`$(Build.SourcesDirectory)` is the **shared root** of every checked-out
repo — the `legacy_path_markers` codemod migrates existing sources by
rewriting each marker (interior whitespace ignored, so both
`{{ workspace }}` and `{{workspace}}` are handled) to the explicit ADO
path expression it resolved to, derived from the source's own
`workspace:` / `repos:`. The rewrite walks every string scalar in the
front-matter mapping, so markers in any field (not just custom steps)
are migrated.

The codemod cannot touch the **markdown body** (codemods are
mapping-only). A companion warning-only pass —
`src/compile/path_layout_check.rs` — surfaces deprecated markers left
in the body, plus checkout-aware path mistakes such as a
`$(Build.SourcesDirectory)/<seg>` reference whose `<seg>` is a
declared-but-not-checked-out repo, or the multi-checkout self subfolder
form used under a single checkout. These are advisory and never fail
the compile.

## Tests

The codemod framework is covered by three layers of tests:
Expand Down
25 changes: 25 additions & 0 deletions docs/front-matter.md
Original file line number Diff line number Diff line change
Expand Up @@ -252,6 +252,31 @@ default):
Set `workspace:` explicitly to `root`, `repo` (alias `self`), or a specific
checked-out repository alias to override this behavior.

### Deprecated directory markers

Earlier releases substituted the directory markers `{{ workspace }}`,
`{{ working_directory }}`, and `{{ trigger_repo_directory }}` inside custom
`steps:` / `post-steps:` / `setup:` / `teardown:` blocks. These are
**deprecated** — they encouraged hard-coding a fixed path anchor, which is
incorrect under multi-checkout where `$(Build.SourcesDirectory)` is the shared
root of every checked-out repository.

Reference the explicit ADO path instead:

- `$(Build.SourcesDirectory)` — the checkout root (the trigger repo root when
only `self` is checked out).
- `$(Build.SourcesDirectory)/$(Build.Repository.Name)` — the trigger repo when
one or more additional repositories are checked out.
- `$(Build.SourcesDirectory)/<alias>` — a specific checked-out repository.

The `legacy_path_markers` codemod automatically rewrites any remaining markers
in front matter to the path they resolved to on the next `compile` (see
[`docs/codemods.md`](codemods.md)). Markers left in the **agent body** cannot be
migrated automatically and are reported as a compile warning. The compiler also
emits warning-only advisories when a `$(Build.SourcesDirectory)/<seg>` reference
or a `{{#runtime-import …}}` target points at a path that will not exist under
the resolved checkout layout.

## Repositories (`repos:`)

The `repos:` field provides a compact way to declare additional repository
Expand Down
Loading
Loading