diff --git a/.github/skills/ado-aw/SKILL.md b/.github/skills/ado-aw/SKILL.md new file mode 100644 index 00000000..49796b89 --- /dev/null +++ b/.github/skills/ado-aw/SKILL.md @@ -0,0 +1,112 @@ +--- +name: ado-aw +description: Azure DevOps Agentic Workflows (ado-aw) - Create, update, and debug AI-powered Azure DevOps agentic workflows +--- + +# Azure DevOps Agentic Workflows Skill + +This skill helps you create and manage Azure DevOps agentic workflows using **ado-aw**. + +ado-aw compiles human-friendly markdown files with YAML front matter into secure, multi-stage Azure DevOps pipelines that run AI agents in network-isolated sandboxes. + +## Setup + +Before creating or compiling workflows, ensure the ado-aw compiler is available. Use the first-time installer for your platform: + +```bash +# Linux +curl -fsSL https://github.com/githubnext/ado-aw/releases/latest/download/install-linux.sh | sh + +# macOS (Apple Silicon) +curl -fsSL https://github.com/githubnext/ado-aw/releases/latest/download/install-macos.sh | sh + +# Windows (PowerShell) +$script = Join-Path $env:TEMP "install-ado-aw.ps1" +Invoke-WebRequest "https://github.com/githubnext/ado-aw/releases/latest/download/install-windows.ps1" -UseBasicParsing -OutFile $script +Get-FileHash $script -Algorithm SHA256 +Set-ExecutionPolicy -Scope Process -ExecutionPolicy Bypass +& $script +``` + +These scripts validate release checksums, install `ado-aw`, and update PATH when needed. +If Windows reports a `UseShellExecute` environment-variable error, run these commands from your current PowerShell session instead of wrapping them in `powershell -Command`. + +Verify: `ado-aw --version` + +## What This Skill Does + +This is a **dispatcher skill** that routes your request to the appropriate specialized prompt: + +- **Creating new agentic workflows** → Routes to the create prompt +- **Updating existing workflows** → Routes to the update prompt +- **Debugging failing workflows** → Routes to the debug prompt + +## Available Prompts + +### Create New Agentic Workflow +**Load when**: User wants to create a new agentic workflow from scratch + +**Prompt file**: https://raw.githubusercontent.com/githubnext/ado-aw/v0.44.0/prompts/create-ado-agentic-workflow.md + +**Use cases**: +- "Create an agentic workflow that reviews PRs weekly" +- "I need a workflow that triages work items daily" +- "Design a scheduled dependency updater" + +### Update Existing Workflow +**Load when**: User wants to modify an existing agent workflow file + +**Prompt file**: https://raw.githubusercontent.com/githubnext/ado-aw/v0.44.0/prompts/update-ado-agentic-workflow.md + +**Use cases**: +- "Add the Azure DevOps MCP to my workflow" +- "Change the schedule from daily to weekly" +- "Add work item creation as a safe output" + +### Debug Failing Workflow +**Load when**: User needs to troubleshoot a failing agentic workflow + +**Prompt file**: https://raw.githubusercontent.com/githubnext/ado-aw/v0.44.0/prompts/debug-ado-agentic-workflow.md + +**Use cases**: +- "Why is my agentic workflow failing?" +- "The agent can't reach the MCP server" +- "Safe outputs aren't being processed" + +## Instructions + +When a user interacts with you: + +1. **Identify the task type** from the user's request +2. **Load the appropriate prompt** from the URLs listed above +3. **Follow the loaded prompt's instructions** exactly +4. **If uncertain**, ask clarifying questions to determine the right prompt + +## Quick Reference + +```bash +# Compile an agent file to pipeline YAML +ado-aw compile + +# Recompile all detected pipelines +ado-aw compile + +# Verify pipeline matches source +ado-aw check +``` + +## Key Features + +- **Natural language workflows**: Write in markdown with YAML frontmatter +- **3-stage security**: Agent → Threat Analysis → Safe Output Execution +- **Network isolation**: AWF (Agentic Workflow Firewall) with domain whitelisting +- **MCP Gateway**: Tool routing for Azure DevOps, custom MCPs +- **Safe outputs**: Controlled write operations (PRs, work items, wiki pages) +- **Agent memory**: Persistent storage across pipeline runs + +## Important Notes + +- Agent files must be compiled with `ado-aw compile` after YAML frontmatter changes +- Markdown body (agent instructions) changes do NOT require recompilation +- The agent never has direct write access — all mutations go through safe outputs +- Full reference: https://raw.githubusercontent.com/githubnext/ado-aw/v0.44.0/AGENTS.md diff --git a/.github/workflows/doc-freshness-check.md b/.github/workflows/doc-freshness-check.md index aa7040f9..9d2ae5e2 100644 --- a/.github/workflows/doc-freshness-check.md +++ b/.github/workflows/doc-freshness-check.md @@ -134,6 +134,14 @@ Extract the actual CLI commands from `src/main.rs` (the clap `Commands` enum) an verify `docs/cli.md` documents every subcommand with correct arguments, flags, and default values. +Also verify the documented `init` scaffold output matches `src/init.rs`. `init` +writes **both** a dispatcher agent (`.github/agents/ado-aw.agent.md`, from +`src/data/init-agent.md`) **and** a dispatcher skill +(`.github/skills/ado-aw/SKILL.md`, from `src/data/init-skill.md`), plus the +`--agency` plugin tree. If a scaffold file, template, or path changes, ensure +the `init` bullet in `docs/cli.md` and the `src/data/` + `init.rs` entries in +the `AGENTS.md` architecture tree list every emitted file. + ### 4. Front matter fields (`docs/front-matter.md` and the pages it links) Compare the `FrontMatter` struct in `src/compile/types.rs` against the documented diff --git a/AGENTS.md b/AGENTS.md index 1ab3edbe..41667fac 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -117,7 +117,7 @@ fail-closed and only pauses when the agent actually proposed a reviewed output. │ │ ├── lower.rs # IR → serde_yaml::Value lowering │ │ ├── emit.rs # Thin `lower() + serde_yaml::to_string()` wrapper │ │ └── summary.rs # Public, serializable PipelineSummary / GraphSummary for agent-facing tooling (see docs/ir.md Public JSON summary) -│ ├── init.rs # Repository initialization for AI-first authoring (incl. `--agency` plugin scaffold, embeds agency/plugins/ado-aw/ via include_str!) +│ ├── init.rs # Repository initialization for AI-first authoring: scaffolds a dispatcher agent (.github/agents/ado-aw.agent.md) AND skill (.github/skills/ado-aw/SKILL.md); `--agency` plugin scaffold embeds agency/plugins/ado-aw/ via include_str! │ ├── execute.rs # Stage 3 safe output execution │ ├── fuzzy_schedule.rs # Fuzzy schedule parsing │ ├── logging.rs # File-based logging infrastructure @@ -219,7 +219,8 @@ fail-closed and only pauses when the agent actually proposed a reviewed output. │ │ └── extension.rs # CompilerExtension impl │ ├── data/ │ │ ├── ecosystem_domains.json # Network allowlists per ecosystem -│ │ ├── init-agent.md # Dispatcher agent template for `init` command +│ │ ├── init-agent.md # Dispatcher agent template for `init` command (→ .github/agents/ado-aw.agent.md) +│ │ ├── init-skill.md # Dispatcher skill template for `init` command (→ .github/skills/ado-aw/SKILL.md) │ │ └── threat-analysis.md # Threat detection analysis prompt template │ └── tools/ # First-class tool implementations (one dir per tool) │ ├── mod.rs diff --git a/docs/cli.md b/docs/cli.md index 8f743a73..4bc2dbe7 100644 --- a/docs/cli.md +++ b/docs/cli.md @@ -11,6 +11,7 @@ Global flags (apply to all subcommands): `--verbose, -v` (enable info-level logg - `--force` - Bypass the GitHub-remote guard (use when running inside a GitHub-hosted repository like `githubnext/ado-aw` itself) - `--agency` - **Additive.** Also generate an Agency / [Claude Code plugin](https://code.claude.com/docs/en/plugins-reference) and the marketplace catalogs that make the repo directly installable (in addition to the standard Copilot agent file). Writes the plugin under `agency/plugins/ado-aw` (mirroring how it is checked in to ado-aw itself) plus **repo-root** marketplace catalogs `.claude-plugin/marketplace.json` (Claude) and `.github/plugin/marketplace.json` (Copilot) that list the plugin via `source: "./agency/plugins/ado-aw"`. After scaffolding, register with `/plugin marketplace add ` then `/plugin install ado-aw@ado-aw`. The plugin tree is a verbatim copy of the canonical in-repo plugin at [`agency/plugins/ado-aw/`](../agency/plugins/ado-aw): `.claude-plugin/plugin.json`, `.mcp.json` (wires the read-only `ado-aw mcp-author` server), `agency.json` (marketplace governance + external `source` pointer), `README.md`, an `agents/ado-aw.md` dispatcher subagent, six `skills//SKILL.md` playbooks (`create-workflow`, `update-workflow`, `debug-workflow`, `compile-and-validate`, `manage-lifecycle`, `audit-build`), and `scripts/doctor.{sh,ps1}` prerequisite checks. The canonical plugin + catalogs are version-locked to the compiler (release-please bumps the plugin/catalog versions + pinned prompt URLs in lock-step). - Creates `.github/agents/ado-aw.agent.md` — a Copilot dispatcher agent that routes to specialized prompts for creating, updating, and debugging agentic pipelines + - Additively creates `.github/skills/ado-aw/SKILL.md` — the same dispatcher in Copilot **skill** (`SKILL.md`) format, so surfaces that consume skills get the router too (mirrors how gh-aw's `init` emits both an agent and a skill). Both files are version-pinned and kept in sync with their templates (`src/data/init-agent.md`, `src/data/init-skill.md`). - The agent auto-downloads the ado-aw compiler and handles the full lifecycle (create → compile → check) - `compile []` - Compile a markdown file to Azure DevOps pipeline YAML. If no path is given, auto-discovers and recompiles all detected agentic pipelines in the current directory. - `--output, -o ` - Optional output path for the generated YAML (only valid when a path is provided). If the path is an existing directory, the compiled YAML is written inside that directory using the default filename derived from the markdown source (e.g. `foo.md` → `/foo.lock.yml`). diff --git a/release-please-config.json b/release-please-config.json index 99e216d7..94442d21 100644 --- a/release-please-config.json +++ b/release-please-config.json @@ -35,7 +35,8 @@ "agency/plugins/ado-aw/skills/create-workflow/SKILL.md", "agency/plugins/ado-aw/skills/update-workflow/SKILL.md", "agency/plugins/ado-aw/skills/debug-workflow/SKILL.md", - ".github/agents/ado-aw.agent.md" + ".github/agents/ado-aw.agent.md", + ".github/skills/ado-aw/SKILL.md" ] } } diff --git a/src/data/init-skill.md b/src/data/init-skill.md new file mode 100644 index 00000000..75eaaa8e --- /dev/null +++ b/src/data/init-skill.md @@ -0,0 +1,112 @@ +--- +name: ado-aw +description: Azure DevOps Agentic Workflows (ado-aw) - Create, update, and debug AI-powered Azure DevOps agentic workflows +--- + +# Azure DevOps Agentic Workflows Skill + +This skill helps you create and manage Azure DevOps agentic workflows using **ado-aw**. + +ado-aw compiles human-friendly markdown files with YAML front matter into secure, multi-stage Azure DevOps pipelines that run AI agents in network-isolated sandboxes. + +## Setup + +Before creating or compiling workflows, ensure the ado-aw compiler is available. Use the first-time installer for your platform: + +```bash +# Linux +curl -fsSL https://github.com/githubnext/ado-aw/releases/latest/download/install-linux.sh | sh + +# macOS (Apple Silicon) +curl -fsSL https://github.com/githubnext/ado-aw/releases/latest/download/install-macos.sh | sh + +# Windows (PowerShell) +$script = Join-Path $env:TEMP "install-ado-aw.ps1" +Invoke-WebRequest "https://github.com/githubnext/ado-aw/releases/latest/download/install-windows.ps1" -UseBasicParsing -OutFile $script +Get-FileHash $script -Algorithm SHA256 +Set-ExecutionPolicy -Scope Process -ExecutionPolicy Bypass +& $script +``` + +These scripts validate release checksums, install `ado-aw`, and update PATH when needed. +If Windows reports a `UseShellExecute` environment-variable error, run these commands from your current PowerShell session instead of wrapping them in `powershell -Command`. + +Verify: `ado-aw --version` + +## What This Skill Does + +This is a **dispatcher skill** that routes your request to the appropriate specialized prompt: + +- **Creating new agentic workflows** → Routes to the create prompt +- **Updating existing workflows** → Routes to the update prompt +- **Debugging failing workflows** → Routes to the debug prompt + +## Available Prompts + +### Create New Agentic Workflow +**Load when**: User wants to create a new agentic workflow from scratch + +**Prompt file**: https://raw.githubusercontent.com/githubnext/ado-aw/v{{ compiler_version }}/prompts/create-ado-agentic-workflow.md + +**Use cases**: +- "Create an agentic workflow that reviews PRs weekly" +- "I need a workflow that triages work items daily" +- "Design a scheduled dependency updater" + +### Update Existing Workflow +**Load when**: User wants to modify an existing agent workflow file + +**Prompt file**: https://raw.githubusercontent.com/githubnext/ado-aw/v{{ compiler_version }}/prompts/update-ado-agentic-workflow.md + +**Use cases**: +- "Add the Azure DevOps MCP to my workflow" +- "Change the schedule from daily to weekly" +- "Add work item creation as a safe output" + +### Debug Failing Workflow +**Load when**: User needs to troubleshoot a failing agentic workflow + +**Prompt file**: https://raw.githubusercontent.com/githubnext/ado-aw/v{{ compiler_version }}/prompts/debug-ado-agentic-workflow.md + +**Use cases**: +- "Why is my agentic workflow failing?" +- "The agent can't reach the MCP server" +- "Safe outputs aren't being processed" + +## Instructions + +When a user interacts with you: + +1. **Identify the task type** from the user's request +2. **Load the appropriate prompt** from the URLs listed above +3. **Follow the loaded prompt's instructions** exactly +4. **If uncertain**, ask clarifying questions to determine the right prompt + +## Quick Reference + +```bash +# Compile an agent file to pipeline YAML +ado-aw compile + +# Recompile all detected pipelines +ado-aw compile + +# Verify pipeline matches source +ado-aw check +``` + +## Key Features + +- **Natural language workflows**: Write in markdown with YAML frontmatter +- **3-stage security**: Agent → Threat Analysis → Safe Output Execution +- **Network isolation**: AWF (Agentic Workflow Firewall) with domain whitelisting +- **MCP Gateway**: Tool routing for Azure DevOps, custom MCPs +- **Safe outputs**: Controlled write operations (PRs, work items, wiki pages) +- **Agent memory**: Persistent storage across pipeline runs + +## Important Notes + +- Agent files must be compiled with `ado-aw compile` after YAML frontmatter changes +- Markdown body (agent instructions) changes do NOT require recompilation +- The agent never has direct write access — all mutations go through safe outputs +- Full reference: https://raw.githubusercontent.com/githubnext/ado-aw/v{{ compiler_version }}/AGENTS.md diff --git a/src/init.rs b/src/init.rs index efe94b0b..629cca51 100644 --- a/src/init.rs +++ b/src/init.rs @@ -7,6 +7,14 @@ const AGENT_TEMPLATE: &str = include_str!("data/init-agent.md"); const AGENT_DIR: &str = ".github/agents"; const AGENT_FILENAME: &str = "ado-aw.agent.md"; +// The dispatcher skill template is embedded from src/data/init-skill.md. It +// mirrors the agent (same routing/prompt content) in Copilot skill (SKILL.md) +// format, matching how gh-aw's `init` emits both an agent and a skill. +const SKILL_TEMPLATE: &str = include_str!("data/init-skill.md"); + +const SKILL_DIR: &str = ".github/skills/ado-aw"; +const SKILL_FILENAME: &str = "SKILL.md"; + /// Root directory (relative to the target repo) for the generated Agency / /// Claude Code plugin. Mirrors the canonical in-repo layout (`agency/plugins/ /// ado-aw/`) so a scaffolded consumer repo matches how the plugin is checked in @@ -124,6 +132,24 @@ pub async fn run(path: Option<&std::path::Path>, agency: bool) -> Result<()> { // Print success message println!("✓ Created {}", agent_path.display()); + // Additively scaffold the dispatcher skill (SKILL.md format). This mirrors + // gh-aw's `init`, which emits both a dispatcher agent and a dispatcher + // skill so Copilot surfaces that consume skills also get the router. + let skill_dir = base.join(SKILL_DIR); + let skill_path = skill_dir.join(SKILL_FILENAME); + + tokio::fs::create_dir_all(&skill_dir) + .await + .with_context(|| format!("Failed to create directory: {}", skill_dir.display()))?; + + let skill_content = SKILL_TEMPLATE.replace("{{ compiler_version }}", version); + + tokio::fs::write(&skill_path, skill_content) + .await + .with_context(|| format!("Failed to write skill file: {}", skill_path.display()))?; + + println!("✓ Created {}", skill_path.display()); + // `--agency` is additive: keep the standard agent file above and also emit // the Agency / Claude Code plugin. if agency { diff --git a/tests/init_tests.rs b/tests/init_tests.rs index b7f0e95f..15df9148 100644 --- a/tests/init_tests.rs +++ b/tests/init_tests.rs @@ -34,6 +34,27 @@ fn test_init_creates_agent_file() { !content.contains("{{ compiler_version }}"), "Version placeholder should be replaced with actual version" ); + + // `init` additively scaffolds the dispatcher skill (SKILL.md format), + // mirroring gh-aw which emits both an agent and a skill. + let skill_path = temp_dir.path().join(".github/skills/ado-aw/SKILL.md"); + assert!(skill_path.exists(), "Skill file should be created"); + + let skill_content = + fs::read_to_string(&skill_path).expect("Should be able to read skill file"); + assert!( + skill_content.contains("Azure DevOps Agentic Workflows Skill"), + "Skill file should contain the expected title" + ); + assert!( + skill_content.starts_with("---\nname: ado-aw\n") + || skill_content.starts_with("---\r\nname: ado-aw\r\n"), + "Skill file should carry the `name: ado-aw` front matter" + ); + assert!( + !skill_content.contains("{{ compiler_version }}"), + "Version placeholder should be replaced in the skill file" + ); } /// Test that `init` always overwrites an existing agent file (no --force needed) @@ -414,6 +435,34 @@ fn test_committed_agent_file_matches_template_output() { ); } +/// Guard that the committed `.github/skills/ado-aw/SKILL.md` stays in sync with +/// its template `src/data/init-skill.md`: running `init` must reproduce the +/// committed file byte-for-byte. As with the agent file, the committed copy (not +/// the placeholder-bearing template) is what release-please version-bumps. +#[test] +fn test_committed_skill_file_matches_template_output() { + let repo_root = std::path::Path::new(env!("CARGO_MANIFEST_DIR")); + let committed = fs::read_to_string(repo_root.join(".github/skills/ado-aw/SKILL.md")) + .expect("committed skill file should be readable"); + + let temp_dir = tempfile::tempdir().expect("Failed to create temp directory"); + let output = ado_aw_bin() + .args(["init", "--path", temp_dir.path().to_str().unwrap()]) + .output() + .expect("Failed to run ado-aw init"); + assert!(output.status.success(), "init should succeed"); + + let generated = fs::read_to_string(temp_dir.path().join(".github/skills/ado-aw/SKILL.md")) + .expect("generated skill file should be readable"); + + assert_eq!( + generated.replace("\r\n", "\n"), + committed.replace("\r\n", "\n"), + "committed .github/skills/ado-aw/SKILL.md is stale — regenerate it with \ + `ado-aw init --force` after editing src/data/init-skill.md" + ); +} + /// `init --agency` must NOT clobber a consumer's pre-existing, differing root /// marketplace catalog. It should leave the existing file untouched and still /// scaffold the plugin tree.