Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
39 commits
Select commit Hold shift + click to select a range
4e1fdcf
feat(compile): add PR trigger filters with pre-activation gate
jamesadevine Apr 28, 2026
5434bc6
refactor(compile): extract PR filters to dedicated module
jamesadevine Apr 28, 2026
e48a03e
feat(compile): add Tier 3 PR filters (time-window, change-count, buil…
jamesadevine Apr 28, 2026
3088e8a
feat(compile)!: unify schedule and triggers under on: key
jamesadevine Apr 28, 2026
35f08e6
feat(compile): add commit-message filter and on: deserialization tests
jamesadevine Apr 28, 2026
ceb32cd
feat(compile): formalize trigger filter IR with compile-time validation
jamesadevine Apr 30, 2026
90491eb
refactor(compile): replace bash codegen with data-driven Python evalu…
jamesadevine Apr 30, 2026
1b0335a
feat(compile): add TriggerFiltersExtension for gate evaluator delivery
jamesadevine Apr 30, 2026
144a4e0
docs: update filter-ir spec and extending docs for extension model
jamesadevine Apr 30, 2026
e3bc9f0
refactor(compile): pass CompileContext to setup_steps, remove inline …
jamesadevine Apr 30, 2026
de20d2d
fix(compile): collect setup_steps from all extensions, not just trigg…
jamesadevine Apr 30, 2026
251d09a
test(compile): add integration tests, evaluator tests, and JSON schema
jamesadevine Apr 30, 2026
bd9858d
Merge remote-tracking branch 'origin/main' into feat/pr-trigger-filters
jamesadevine Apr 30, 2026
d20dea3
fix: update new common.rs tests from main merge for setup_job/depends…
jamesadevine Apr 30, 2026
22f5e51
refactor(compile): use env block instead of bash exports for gate step
jamesadevine Apr 30, 2026
d03c5c5
fix(compile): remove duplicate ADO_SYSTEM_ACCESS_TOKEN env var
jamesadevine Apr 30, 2026
fdbb475
feat(compile)!: switch filter patterns from regex to glob syntax
jamesadevine Apr 30, 2026
8b63174
fix(compile): three bug fixes — dependency, validation, and shell inj…
jamesadevine Apr 30, 2026
4dddf9a
fix(compile): address six review findings
jamesadevine May 1, 2026
b5c3862
fix(compile): evaluator null handling, fail_closed skip, and inline i…
jamesadevine May 1, 2026
2f0f360
refactor(compile): remove inline bash codegen, unify to Python evaluator
jamesadevine May 1, 2026
b8497bf
fix(compile): fid NameError, dual gate condition, time format validation
jamesadevine May 1, 2026
72c4d93
fix(compile): file_glob_match false positive, fail_closed semantics, …
jamesadevine May 1, 2026
0807f62
fix(compile): glob doc comments, proper topo-sort, empty files warning
jamesadevine May 1, 2026
eda5cbb
docs: document time-window half-open interval and changed-files empty…
jamesadevine May 1, 2026
0ca6747
fix(compile): six review findings — dead code, exclude-only glob, ass…
jamesadevine May 1, 2026
f8a5013
fix(compile): FailOpen short-circuit, Result propagation, glob consis…
jamesadevine May 1, 2026
162f5ad
fix(compile): docs syntax, ADO expression injection, refs/heads strip…
jamesadevine May 1, 2026
6d8ae8a
fix(compile): fail_open propagation, policy validation, dead binding
jamesadevine May 1, 2026
20cc2eb
fix(compile): extension steps nested correctly in Setup job via repla…
jamesadevine May 1, 2026
6d68191
refactor(compile): setup_steps returns Result, remove dead code
jamesadevine May 1, 2026
f84f3e0
fix(compile): unified glob semantics, assert→raise, token docs, dedup
jamesadevine May 1, 2026
2a6c8d5
fix(compile): empty filters guard, branch-only ref strip, expression …
jamesadevine May 1, 2026
4f9b0e1
fix(compile): empty filters:{} no longer generates dangling dependsOn
jamesadevine May 1, 2026
8fcee82
fix(compile): test docs, glob DOTALL, token requirements, empty pr: g…
jamesadevine May 2, 2026
aed57bb
fix(compile): newline injection in expression, has_gate lowering, gat…
jamesadevine May 2, 2026
815faa1
fix(compile): gate variable selector uses lowered check presence, rem…
jamesadevine May 2, 2026
15ed7f1
fix(compile): add reject_pipeline_injection for on.pr branch/path values
Copilot May 2, 2026
48b8439
fix(compile): include entry value in pr branch/path injection error m…
Copilot May 2, 2026
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
11 changes: 10 additions & 1 deletion .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -56,13 +56,20 @@ jobs:
cd target/release
cp ado-aw ado-aw-linux-x64

- name: Package scripts bundle
run: |
set -euo pipefail
cd scripts
zip -r ../scripts.zip .

- name: Upload release assets
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
TAG="${{ needs.release-please.outputs.tag_name || github.event.inputs.tag_name }}"
gh release upload "$TAG" \
target/release/ado-aw-linux-x64 \
scripts.zip \
--clobber

build-windows:
Expand Down Expand Up @@ -152,11 +159,13 @@ jobs:
TAG="${{ needs.release-please.outputs.tag_name || github.event.inputs.tag_name }}"
gh release download "$TAG" \
--pattern "ado-aw-*" \
--pattern "scripts.zip" \
--repo "${{ github.repository }}"
test -f ado-aw-linux-x64 || { echo "Missing ado-aw-linux-x64"; exit 1; }
test -f ado-aw-windows-x64.exe || { echo "Missing ado-aw-windows-x64.exe"; exit 1; }
test -f ado-aw-darwin-arm64 || { echo "Missing ado-aw-darwin-arm64"; exit 1; }
sha256sum ado-aw-linux-x64 ado-aw-windows-x64.exe ado-aw-darwin-arm64 > checksums.txt
test -f scripts.zip || { echo "Missing scripts.zip"; exit 1; }
sha256sum ado-aw-linux-x64 ado-aw-windows-x64.exe ado-aw-darwin-arm64 scripts.zip > checksums.txt

- name: Upload checksums
env:
Expand Down
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,2 +1,4 @@
target
examples/sample-agent.yml
*.pyc
__pycache__/
9 changes: 9 additions & 0 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -53,10 +53,13 @@ Every compiled pipeline runs as three sequential jobs:
│ │ ├── standalone.rs # Standalone pipeline compiler
│ │ ├── onees.rs # 1ES Pipeline Template compiler
│ │ ├── 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)
│ │ ├── extensions/ # CompilerExtension trait and infrastructure extensions
│ │ │ ├── mod.rs # Trait, Extension enum, collect_extensions(), re-exports
│ │ │ ├── github.rs # Always-on GitHub MCP extension
│ │ │ ├── safe_outputs.rs # Always-on SafeOutputs MCP extension
│ │ │ ├── trigger_filters.rs # Trigger filter extension (gate evaluator delivery)
│ │ │ └── tests.rs # Extension integration tests
│ │ └── types.rs # Front matter grammar and types
│ ├── init.rs # Repository initialization for AI-first authoring
Expand Down Expand Up @@ -116,6 +119,9 @@ Every compiled pipeline runs as three sequential jobs:
│ └── execute.rs # Stage 3 runtime (validate/copy)
├── ado-aw-derive/ # Proc-macro crate: #[derive(SanitizeConfig)], #[derive(SanitizeContent)]
├── examples/ # Example agent definitions
├── scripts/ # Supporting scripts shipped as release artifacts
│ ├── gate-eval.py # Python gate evaluator (data-driven filter evaluation)
│ └── gate-spec.schema.json # JSON Schema for gate spec (generated from Rust types)
├── tests/ # Integration tests and fixtures
├── docs/ # Per-concept reference documentation (see index below)
├── Cargo.toml # Rust dependencies
Expand Down Expand Up @@ -174,6 +180,9 @@ index to jump to the right page.
- [`docs/extending.md`](docs/extending.md) — adding new CLI commands, compile
targets, front-matter fields, template markers, safe-output tools,
first-class tools, and runtimes; the `CompilerExtension` trait.
- [`docs/filter-ir.md`](docs/filter-ir.md) — filter expression IR
specification: `Fact`/`Predicate` types, three-pass compilation (lower →
validate → codegen), gate step generation, adding new filter types.
- [`docs/local-development.md`](docs/local-development.md) — local development
setup notes.

Expand Down
2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ dirs = "6"
serde = { version = "1.0.228", features = ["derive"] }
serde_yaml = "0.9.34"
serde_json = "1.0.149"
schemars = "1.2"
schemars = { version = "1.2", features = ["derive"] }
rmcp = { version = "0.8.0", features = [
"server",
"transport-io",
Expand Down
47 changes: 44 additions & 3 deletions docs/extending.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,15 +33,56 @@ Runtimes and first-party tools declare their compilation requirements via the `C
```rust
pub trait CompilerExtension: Send {
fn name(&self) -> &str; // Display name
fn phase(&self) -> ExtensionPhase; // Runtime (0) < Tool (1)
fn required_hosts(&self) -> Vec<String>; // AWF network allowlist
fn required_bash_commands(&self) -> Vec<String>; // Agent bash allow-list
fn prompt_supplement(&self) -> Option<String>; // Agent prompt markdown
fn prepare_steps(&self) -> Vec<String>; // Pipeline steps (install, etc.)
fn mcpg_servers(&self, ctx) -> Result<Vec<(String, McpgServerConfig)>>; // MCPG entries
fn prepare_steps(&self) -> Vec<String>; // Execution job steps (install, etc.)
fn setup_steps(&self, ctx: &CompileContext) -> Vec<String>; // Setup job steps (gates, pre-checks)
fn mcpg_servers(&self, ctx: &CompileContext) -> Result<Vec<(String, McpgServerConfig)>>; // MCPG entries
fn allowed_copilot_tools(&self) -> Vec<String>; // --allow-tool values
fn validate(&self, ctx: &CompileContext) -> Result<Vec<String>>; // Compile-time warnings/errors
fn required_pipeline_vars(&self) -> Vec<PipelineEnvMapping>; // Container env var mappings
fn required_awf_mounts(&self) -> Vec<AwfMount>; // AWF Docker volume mounts
fn awf_path_prepends(&self) -> Vec<String>; // Directories to add to chroot PATH
fn validate(&self, ctx) -> Result<Vec<String>>; // Compile-time warnings
}
```

**`prepare_steps()` vs `setup_steps()`**: `prepare_steps()` injects into the
Execution job (before the agent runs). `setup_steps()` injects into the Setup
job (before the Execution job starts). Use `setup_steps()` for pre-activation
gates or checks that must complete before the agent is launched.

**Phase ordering**: Extensions are sorted by phase — runtimes
(`ExtensionPhase::Runtime`) execute before tools (`ExtensionPhase::Tool`).
This guarantees runtime install steps run before tool steps that may depend
on them.

To add a new runtime or tool: (1) create a directory under `src/tools/` or `src/runtimes/`, (2) implement `CompilerExtension` in `extension.rs`, (3) add a variant to the `Extension` enum and a collection check in `collect_extensions()` in `src/compile/extensions/mod.rs`.

### Filter IR (`src/compile/filter_ir.rs`)

Trigger filter expressions (PR filters, pipeline filters) are compiled to bash
gate steps via a three-pass IR pipeline:

1. **Lower** — `PrFilters` / `PipelineFilters` → `Vec<FilterCheck>` (typed
predicates over typed facts)
2. **Validate** — detect conflicts at compile time (impossible combinations,
redundant checks)
3. **Codegen** — dependency-ordered fact acquisition + predicate evaluation →
bash gate step

To add a new filter type:

1. **Add a `Fact` variant** (if the filter needs a new data source) — implement
`dependencies()`, `kind()`, `ado_exports()`, and
`failure_policy()` on the new variant
2. **Add a `Predicate` variant** (if the filter needs a new test shape) —
implement the codegen match arm in `emit_predicate_check()`
3. **Extend lowering** — add the filter field to `PrFilters` or
`PipelineFilters` in `types.rs`, then add the lowering logic in
`lower_pr_filters()` or `lower_pipeline_filters()` in `filter_ir.rs`
4. **Add validation rules** — check for conflicts with other filters in
`validate_pr_filters()` or `validate_pipeline_filters()`
5. **Write tests** — lowering test, validation test, and codegen test in
`filter_ir.rs`
Loading