Skip to content

Commit 90df351

Browse files
authored
feat(compile)!: trigger filter IR with data-driven Python evaluator (#345)
1 parent b66037d commit 90df351

25 files changed

Lines changed: 5637 additions & 100 deletions

.github/workflows/release.yml

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,13 +56,20 @@ jobs:
5656
cd target/release
5757
cp ado-aw ado-aw-linux-x64
5858
59+
- name: Package scripts bundle
60+
run: |
61+
set -euo pipefail
62+
cd scripts
63+
zip -r ../scripts.zip .
64+
5965
- name: Upload release assets
6066
env:
6167
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
6268
run: |
6369
TAG="${{ needs.release-please.outputs.tag_name || github.event.inputs.tag_name }}"
6470
gh release upload "$TAG" \
6571
target/release/ado-aw-linux-x64 \
72+
scripts.zip \
6673
--clobber
6774
6875
build-windows:
@@ -152,11 +159,13 @@ jobs:
152159
TAG="${{ needs.release-please.outputs.tag_name || github.event.inputs.tag_name }}"
153160
gh release download "$TAG" \
154161
--pattern "ado-aw-*" \
162+
--pattern "scripts.zip" \
155163
--repo "${{ github.repository }}"
156164
test -f ado-aw-linux-x64 || { echo "Missing ado-aw-linux-x64"; exit 1; }
157165
test -f ado-aw-windows-x64.exe || { echo "Missing ado-aw-windows-x64.exe"; exit 1; }
158166
test -f ado-aw-darwin-arm64 || { echo "Missing ado-aw-darwin-arm64"; exit 1; }
159-
sha256sum ado-aw-linux-x64 ado-aw-windows-x64.exe ado-aw-darwin-arm64 > checksums.txt
167+
test -f scripts.zip || { echo "Missing scripts.zip"; exit 1; }
168+
sha256sum ado-aw-linux-x64 ado-aw-windows-x64.exe ado-aw-darwin-arm64 scripts.zip > checksums.txt
160169
161170
- name: Upload checksums
162171
env:

.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,4 @@
11
target
22
examples/sample-agent.yml
3+
*.pyc
4+
__pycache__/

AGENTS.md

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,10 +53,13 @@ Every compiled pipeline runs as three sequential jobs:
5353
│ │ ├── standalone.rs # Standalone pipeline compiler
5454
│ │ ├── onees.rs # 1ES Pipeline Template compiler
5555
│ │ ├── gitattributes.rs # .gitattributes management for compiled pipelines
56+
│ │ ├── filter_ir.rs # Filter expression IR: Fact/Predicate types, lowering, validation, codegen
57+
│ │ ├── pr_filters.rs # PR trigger filter generation (native ADO + gate steps)
5658
│ │ ├── extensions/ # CompilerExtension trait and infrastructure extensions
5759
│ │ │ ├── mod.rs # Trait, Extension enum, collect_extensions(), re-exports
5860
│ │ │ ├── github.rs # Always-on GitHub MCP extension
5961
│ │ │ ├── safe_outputs.rs # Always-on SafeOutputs MCP extension
62+
│ │ │ ├── trigger_filters.rs # Trigger filter extension (gate evaluator delivery)
6063
│ │ │ └── tests.rs # Extension integration tests
6164
│ │ └── types.rs # Front matter grammar and types
6265
│ ├── init.rs # Repository initialization for AI-first authoring
@@ -116,6 +119,9 @@ Every compiled pipeline runs as three sequential jobs:
116119
│ └── execute.rs # Stage 3 runtime (validate/copy)
117120
├── ado-aw-derive/ # Proc-macro crate: #[derive(SanitizeConfig)], #[derive(SanitizeContent)]
118121
├── examples/ # Example agent definitions
122+
├── scripts/ # Supporting scripts shipped as release artifacts
123+
│ ├── gate-eval.py # Python gate evaluator (data-driven filter evaluation)
124+
│ └── gate-spec.schema.json # JSON Schema for gate spec (generated from Rust types)
119125
├── tests/ # Integration tests and fixtures
120126
├── docs/ # Per-concept reference documentation (see index below)
121127
├── Cargo.toml # Rust dependencies
@@ -174,6 +180,9 @@ index to jump to the right page.
174180
- [`docs/extending.md`](docs/extending.md) — adding new CLI commands, compile
175181
targets, front-matter fields, template markers, safe-output tools,
176182
first-class tools, and runtimes; the `CompilerExtension` trait.
183+
- [`docs/filter-ir.md`](docs/filter-ir.md) — filter expression IR
184+
specification: `Fact`/`Predicate` types, three-pass compilation (lower →
185+
validate → codegen), gate step generation, adding new filter types.
177186
- [`docs/local-development.md`](docs/local-development.md) — local development
178187
setup notes.
179188

Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ dirs = "6"
1313
serde = { version = "1.0.228", features = ["derive"] }
1414
serde_yaml = "0.9.34"
1515
serde_json = "1.0.149"
16-
schemars = "1.2"
16+
schemars = { version = "1.2", features = ["derive"] }
1717
rmcp = { version = "0.8.0", features = [
1818
"server",
1919
"transport-io",

docs/extending.md

Lines changed: 44 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -33,15 +33,56 @@ Runtimes and first-party tools declare their compilation requirements via the `C
3333
```rust
3434
pub trait CompilerExtension: Send {
3535
fn name(&self) -> &str; // Display name
36+
fn phase(&self) -> ExtensionPhase; // Runtime (0) < Tool (1)
3637
fn required_hosts(&self) -> Vec<String>; // AWF network allowlist
3738
fn required_bash_commands(&self) -> Vec<String>; // Agent bash allow-list
3839
fn prompt_supplement(&self) -> Option<String>; // Agent prompt markdown
39-
fn prepare_steps(&self) -> Vec<String>; // Pipeline steps (install, etc.)
40-
fn mcpg_servers(&self, ctx) -> Result<Vec<(String, McpgServerConfig)>>; // MCPG entries
40+
fn prepare_steps(&self) -> Vec<String>; // Execution job steps (install, etc.)
41+
fn setup_steps(&self, ctx: &CompileContext) -> Vec<String>; // Setup job steps (gates, pre-checks)
42+
fn mcpg_servers(&self, ctx: &CompileContext) -> Result<Vec<(String, McpgServerConfig)>>; // MCPG entries
43+
fn allowed_copilot_tools(&self) -> Vec<String>; // --allow-tool values
44+
fn validate(&self, ctx: &CompileContext) -> Result<Vec<String>>; // Compile-time warnings/errors
45+
fn required_pipeline_vars(&self) -> Vec<PipelineEnvMapping>; // Container env var mappings
4146
fn required_awf_mounts(&self) -> Vec<AwfMount>; // AWF Docker volume mounts
4247
fn awf_path_prepends(&self) -> Vec<String>; // Directories to add to chroot PATH
43-
fn validate(&self, ctx) -> Result<Vec<String>>; // Compile-time warnings
4448
}
4549
```
4650

51+
**`prepare_steps()` vs `setup_steps()`**: `prepare_steps()` injects into the
52+
Execution job (before the agent runs). `setup_steps()` injects into the Setup
53+
job (before the Execution job starts). Use `setup_steps()` for pre-activation
54+
gates or checks that must complete before the agent is launched.
55+
56+
**Phase ordering**: Extensions are sorted by phase — runtimes
57+
(`ExtensionPhase::Runtime`) execute before tools (`ExtensionPhase::Tool`).
58+
This guarantees runtime install steps run before tool steps that may depend
59+
on them.
60+
4761
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`.
62+
63+
### Filter IR (`src/compile/filter_ir.rs`)
64+
65+
Trigger filter expressions (PR filters, pipeline filters) are compiled to bash
66+
gate steps via a three-pass IR pipeline:
67+
68+
1. **Lower**`PrFilters` / `PipelineFilters``Vec<FilterCheck>` (typed
69+
predicates over typed facts)
70+
2. **Validate** — detect conflicts at compile time (impossible combinations,
71+
redundant checks)
72+
3. **Codegen** — dependency-ordered fact acquisition + predicate evaluation →
73+
bash gate step
74+
75+
To add a new filter type:
76+
77+
1. **Add a `Fact` variant** (if the filter needs a new data source) — implement
78+
`dependencies()`, `kind()`, `ado_exports()`, and
79+
`failure_policy()` on the new variant
80+
2. **Add a `Predicate` variant** (if the filter needs a new test shape) —
81+
implement the codegen match arm in `emit_predicate_check()`
82+
3. **Extend lowering** — add the filter field to `PrFilters` or
83+
`PipelineFilters` in `types.rs`, then add the lowering logic in
84+
`lower_pr_filters()` or `lower_pipeline_filters()` in `filter_ir.rs`
85+
4. **Add validation rules** — check for conflicts with other filters in
86+
`validate_pr_filters()` or `validate_pipeline_filters()`
87+
5. **Write tests** — lowering test, validation test, and codegen test in
88+
`filter_ir.rs`

0 commit comments

Comments
 (0)