diff --git a/.github/aw/context.md b/.github/aw/context.md index 788a5209190..e4a4a7f97b2 100644 --- a/.github/aw/context.md +++ b/.github/aw/context.md @@ -175,6 +175,7 @@ When `experiments:` is set in frontmatter, the selected variant is substituted i ### Notes -- **Fenced code blocks are preserved** — `{{#if}}` tags inside `` ``` `` blocks appear verbatim. +- **Malformed conditions fail compilation** — comparisons need an operator (`==`, `!=`, `===`, `!==`); invalid active conditions in the main workflow, imports, or local runtime imports block lock-file generation. +- **Code regions** — only syntactically invalid implicit conditions inside inline code or fenced blocks stay literal; valid conditions and explicit GitHub Actions expressions there are still bound and validated. - **No nested conditionals** — inner tags become literal text. - **Tags are stripped before the agent runs** — never visible in the final prompt. diff --git a/.github/aw/create-agentic-workflow.md b/.github/aw/create-agentic-workflow.md index 27fbb907d11..78f112669ab 100644 --- a/.github/aw/create-agentic-workflow.md +++ b/.github/aw/create-agentic-workflow.md @@ -180,7 +180,7 @@ Do not default every recurring or PR-reactive workflow to the same strategy. Bas See [workflow-constraints.md](workflow-constraints.md) for the read-only security posture. Specific to workflow creation: - Do not grant `issues: write`, `pull-requests: write`, or `contents: write` to the agent job. -- When targeting the Copilot coding agent, recommend `permissions: { copilot-requests: write }` so Copilot can authenticate with `${{ github.token }}`. +- For Copilot inference, recommend `permissions: { copilot-requests: write }` (scope and caveats: [syntax-core.md](syntax-core.md)). - If the user asks for direct writes, explain why the safe-output pattern is required. ### 4. Select tools diff --git a/.github/aw/network.md b/.github/aw/network.md index 9815c476ee6..8cae26aef74 100644 --- a/.github/aw/network.md +++ b/.github/aw/network.md @@ -46,7 +46,7 @@ Keywords expanding to curated domain lists: | Identifier | Runtime / Tool | Key Domains Enabled | |---|---|---| -| `defaults` | Basic infrastructure | Certificate authorities, Ubuntu package verification, JSON schema | +| `defaults` | Basic infrastructure (implicit when `network:` is omitted) | Certificate CRL/OCSP hosts, JSON schema, stock Ubuntu archive/keyserver only — no GitHub, engine, or package-registry hosts | | `github` | GitHub domains | `*.githubusercontent.com`, `codeload.github.com`, `docs.github.com` | | `github-actions` | GitHub Actions artifacts | Azure Blob storage for action caches and artifacts | | `node` | npm / yarn / pnpm | `registry.npmjs.org`, `npmjs.com`, `yarnpkg.com` | @@ -63,7 +63,7 @@ Keywords expanding to curated domain lists: | `perl` | CPAN | `cpan.org`, `metacpan.org` | | `containers` | Docker / GHCR | `ghcr.io`, `registry.hub.docker.com`, `*.docker.io` | | `playwright` | Playwright browsers | `playwright.download.prss.microsoft.com`, `cdn.playwright.dev` | -| `linux-distros` | apt / yum / apk | `deb.debian.org`, `security.debian.org`, Ubuntu/Alpine mirrors | +| `linux-distros` | apt / yum / apk | Debian, Fedora, CentOS, Alpine, Arch, openSUSE mirrors, and third-party apt sources (`ppa.launchpad.net`, `packagecloud.io`, `api.snapcraft.io`, `packages.microsoft.com`, `packages.cloud.google.com`) | | `terraform` | HashiCorp | `releases.hashicorp.com`, `registry.terraform.io` | | `local` | Loopback addresses | `127.0.0.1`, `::1`, `localhost` | | `bazel` | Bazel build | `releases.bazel.build`, `bcr.bazel.build` | diff --git a/.github/aw/safe-outputs-content.md b/.github/aw/safe-outputs-content.md index 3538ee134dc..7f99138a82d 100644 --- a/.github/aw/safe-outputs-content.md +++ b/.github/aw/safe-outputs-content.md @@ -318,7 +318,7 @@ description: Safe-output reference for issue, discussion, comment, and pull requ **Allowed Source Branches**: When `allowed-branches` is set, the branch used for PR creation (agent-provided `branch` or the current checkout branch when omitted) must match one of the configured glob patterns. - **File Restrictions**: **Always specify `allowed-files`** — this is the primary guardrail for `create-pull-request`. Scope it to specific file extensions (e.g., `"**/*.md"`, `"**/*.ts"`) or directory paths (e.g., `"src/**"`, `"docs/**"`) matching the workflow's purpose. Omitting `allowed-files` allows the agent to touch any file in the repository, which significantly expands blast radius. Use `excluded-files` to additionally strip specific files (e.g. lock files) from the patch before any checks. The `protected-files` field controls handling of sensitive files (package manifests, CI configs, agent instruction files): `request-review` (default — create the PR but submit a `REQUEST_CHANGES` review so a human approves before merge), `blocked` (hard-block), `fallback-to-issue` (push branch and create a review issue), or `allowed` (no restriction — use only when the workflow is explicitly designed to manage these files). Object form is also supported: `protected-files: { policy: fallback-to-issue, exclude: [AGENTS.md] }`. Repository-wide exemptions apply across every workflow: set `protected_files.exclude` (root-path globs) in `.github/workflows/aw.json`; these combine with any per-workflow `exclude` list and do not bypass `allowed-files` or change the policy. + **File Restrictions**: **Always specify `allowed-files`** — this is the primary guardrail for `create-pull-request`. Scope it to specific file extensions (e.g., `"**/*.md"`, `"**/*.ts"`) or directory paths (e.g., `"src/**"`, `"docs/**"`) matching the workflow's purpose. Omitting `allowed-files` allows the agent to touch any file in the repository, which significantly expands blast radius. Use `excluded-files` to additionally strip specific files (e.g. lock files) from the patch before any checks. The `protected-files` field controls handling of sensitive files (package manifests, CI configs, agent instruction files): `request-review` (default — create the PR but submit a `REQUEST_CHANGES` review so a human approves before merge), `blocked` (hard-block), `fallback-to-issue` (push branch and create a review issue labeled `pull-request-fallback` that expires with the PR's `expires`, default 7 days), or `allowed` (no restriction — use only when the workflow is explicitly designed to manage these files). Object form is also supported: `protected-files: { policy: fallback-to-issue, exclude: [AGENTS.md] }`. Repository-wide exemptions apply across every workflow: set `protected_files.exclude` (root-path globs) in `.github/workflows/aw.json`; these combine with any per-workflow `exclude` list and do not bypass `allowed-files` or change the policy. **Auto-Expiration**: The `expires` field auto-closes PRs after a time period. Supports integers (days) or relative formats (2h, 7d, 2w, 1m, 1y). Minimum duration: 2 hours. Only for same-repo PRs without target-repo. Generates `agentics-maintenance.yml` workflow. diff --git a/.github/aw/safe-outputs-management.md b/.github/aw/safe-outputs-management.md index f786353b6a3..b24ff49dd82 100644 --- a/.github/aw/safe-outputs-management.md +++ b/.github/aw/safe-outputs-management.md @@ -304,6 +304,8 @@ description: Safe-output reference for update, label, milestone, project, releas Cross-repository pushes are supported via `target-repo` (and `head-repo`/`head-github-token` for fork-backed PRs) plus an `allowed-repos` allowlist. To trigger CI on pushed commits, use `github-token-for-extra-empty-commit` or set the magic secret `GH_AW_CI_TRIGGER_TOKEN`. Set `github-token-for-extra-empty-commit: none` to skip the extra empty commit and keep `GH_AW_CI_TRIGGER_TOKEN` out of the compiled lock file and manifest entirely. + **Shared checkout credential**: same-repository `create-pull-request` and `push-to-pull-request-branch` persist one git credential (precedence: `create-pull-request.github-token`, `push-to-pull-request-branch.github-token`, `safe-outputs.github-app` minted token, `safe-outputs.github-token`, default). Give both handlers the same token, ideally once at `safe-outputs.github-token` or `safe-outputs.github-app`. + **File Restrictions**: Same as `create-pull-request`: **always specify `allowed-files`** scoped to specific file extensions or paths to limit the agent's reach. `excluded-files` strips files before all checks, and `protected-files` controls handling of sensitive files. Object form supported: `protected-files: { policy: fallback-to-issue, exclude: [AGENTS.md] }`. `push-to-pull-request-branch` now uses the same `request-review` default as `create-pull-request`. Protected-file changes are still surfaced in the PR as a `REQUEST_CHANGES` review, while `blocked` remains available when a workflow requires a hard failure. `CHANGELOG.md` is excluded from the PR handlers' default protected-file set so routine release updates do not require an explicit exception; other shared handlers continue to protect it. diff --git a/.github/aw/syntax-agentic.md b/.github/aw/syntax-agentic.md index f14ac157c77..95a63a1ce43 100644 --- a/.github/aw/syntax-agentic.md +++ b/.github/aw/syntax-agentic.md @@ -54,7 +54,7 @@ description: Agentic workflow specific frontmatter fields for GitHub Agentic Wor - **`features:`** - Feature flags for experimental or optional features (object) - Each flag is a key-value pair; boolean flags (`true`/`false`) or string values are accepted - Known feature flags: - - `copilot-requests: true` - Use GitHub Actions token for Copilot authentication instead of `COPILOT_GITHUB_TOKEN` secret + - `copilot-requests: true` - **Deprecated**; use `permissions: { copilot-requests: write }`. `gh aw fix` migrates it. - `disable-xpia-prompt: true` - Disable the built-in cross-prompt injection attack (XPIA) system prompt - `action-tag: "v0"` - Pin compiled action references to a specific version of the `gh-aw-actions` repository. Accepts version tags (e.g., `"v0"`, `"v1"`, `"v1.0.0"`) or a full 40-character commit SHA. When set, overrides the compiler's default action mode and resolves all action references from the external `github/gh-aw-actions` repository at the specified tag. - `action-mode: "script"` - Control how the compiler generates action references: `"dev"` (local paths, default), `"release"` (SHA-pinned remote), `"action"` (gh-aw-actions repo), `"script"` (direct shell calls). Can also be overridden via `--action-mode` CLI flag. @@ -158,24 +158,29 @@ description: Agentic workflow specific frontmatter fields for GitHub Agentic Wor - **`observability:`** - Workflow observability and telemetry configuration (object) - **`otlp:`** - Export OpenTelemetry spans to any OTLP-compatible backend (Honeycomb, Grafana Tempo, Sentry, etc.) (object) - - `endpoint:` - OTLP collector endpoint URL. When a static URL is provided, its hostname is added to the AWF firewall allowlist automatically. Supports GitHub Actions expressions. + - `endpoint:` - OTLP collector URL string, a `{url, headers}` object, or an array of them for concurrent multi-endpoint export. Static hostnames are added to the AWF firewall allowlist automatically. Supports GitHub Actions expressions. - `github-app:` - Optional runtime auth configuration. - Preferred: provide GitHub App credentials (`app-id`/`client-id` + `private-key`) to mint a token with `actions/create-github-app-token` before `actions/setup`. - OIDC mode is used when `github-app` is configured without credentials (`app-id`/`client-id` + `private-key`). - OIDC mode requires `permissions.id-token: write` on the workflow/job. - `workload-identity:` - Exchange a GitHub Actions OIDC token for a cloud access token before OTLP export. Only `provider: google` is currently supported; requires `audience:` (Google Workload Identity Provider resource name) and accepts optional `service-account:` to impersonate after STS token exchange. - - `headers:` - Comma-separated `key=value` HTTP headers included in every OTLP export request (e.g. `Authorization=Bearer `). Injected as `OTEL_EXPORTER_OTLP_HEADERS`. Supports GitHub Actions expressions. + - `headers:` - Map of HTTP header names to values (e.g. `Authorization: ${{ secrets.OTLP_AUTH }}`) for the string `endpoint:` form; object/array endpoints carry their own `headers:`. Injected as `OTEL_EXPORTER_OTLP_HEADERS`. The comma-separated `key=value` string form is deprecated. + - `if-missing:` - `error` (default), `warn`, or `ignore` when endpoint/header values resolve empty at runtime (affects MCP gateway OTLP setup only). + - `attributes:` - Optional map of custom span attributes; values are static strings or `{{ }}` templates. Exported to backends and masked in runner logs. - `resource-attributes:` - Optional map of additional OTEL resource attributes appended to gh-aw/GitHub defaults. Values may be static strings or GitHub Actions expressions. Do not use `secrets.*` or `vars.*` here because resource attributes are exported to external observability backends and are not treated as secret values. + - Runtime controls (Actions variables, not frontmatter; recompile once to add the lookup): `OTEL_EXPORTER_OTLP_PROTOCOL` selects `http/json` (default) or `http/protobuf` (gRPC unsupported; per-signal `OTEL_EXPORTER_OTLP_TRACES_PROTOCOL`/`OTEL_EXPORTER_OTLP_LOGS_PROTOCOL` override it); `GH_AW_OTLP_LOGS_ENABLED=true` opts in to compact unified-session OTLP logs posted to `/v1/logs`, capped by `GH_AW_OTLP_LOGS_MAX_BYTES` (default `65536`). Manage the protocol with `gh aw env` key `default_otlp_protocol`. - Example: ```yaml observability: otlp: - endpoint: ${{ secrets.GH_AW_OTEL_ENDPOINT }} + endpoint: + - url: ${{ secrets.GH_AW_OTEL_ENDPOINT }} + headers: + Authorization: ${{ secrets.GH_AW_OTEL_AUTHORIZATION }} github-app: app-id: ${{ vars.APP_ID }} private-key: ${{ secrets.APP_PRIVATE_KEY }} - headers: ${{ secrets.GH_AW_OTEL_HEADERS }} ``` Every job emits setup and conclusion spans with rich attributes (`gh-aw.job.name`, `gh-aw.workflow.name`, `gh-aw.engine.id`, token usage). All jobs in a run share one trace ID. Dispatched child workflows inherit the parent's trace context via `aw_context`. diff --git a/.github/aw/syntax-core.md b/.github/aw/syntax-core.md index 324e642788b..4804c8bb0a1 100644 --- a/.github/aw/syntax-core.md +++ b/.github/aw/syntax-core.md @@ -109,7 +109,7 @@ The YAML frontmatter supports these fields: - Object with permission levels: `read`, `none` (and limited `write` for specific scopes) - Common permission scopes (not exhaustive; standard GitHub Actions scopes plus `models`, `copilot-requests`): `contents`, `issues`, `pull-requests`, `discussions`, `actions`, `checks`, `statuses`, `models`, `deployments`, `security-events`, `packages`, `pages`, `attestations`, `copilot-requests` - Write permissions are not allowed for security reasons; use `safe-outputs` for write operations instead - - Exceptions: `id-token: write` is allowed to enable OIDC token minting; `copilot-requests: write` is recommended when targeting the Copilot coding agent so it can authenticate with `${{ github.token }}` + - Exceptions: `id-token: write` is allowed to enable OIDC token minting; `copilot-requests: write` is recommended for organization-billed Copilot inference (default `copilot` engine, or Claude/Codex/pi with `copilot/` models) so it authenticates with `${{ github.token }}` and ignores `COPILOT_GITHUB_TOKEN`. Claude on the Copilot provider warns at compile time when it is missing; set `copilot-requests: none` to opt out explicitly. - **`token-broker:`** (experimental; emits a compile warning) - object enabling OIDC-authenticated Copilot credential exchange as an alternative to `permissions.copilot-requests: write`: `copilot-request` (threat-detection/evals jobs only; not combinable with `copilot-requests: write`) and/or `copilot-task` (main agent inference not yet supported). The broker endpoint comes from the `GH_AW_TOKEN_BROKER_URL` Actions variable or secret at runtime; missing config or a failed exchange blocks the operation rather than falling back. Jobs using brokered credentials run an unconditional post-step to invalidate them. See [token broker specification](https://github.com/github/gh-aw/blob/main/docs/src/content/docs/specs/token-broker-specification.md) and [enterprise configuration](https://github.com/github/gh-aw/blob/main/docs/src/content/docs/reference/enterprise-configuration.md#oidc-token-broker). - **`runs-on:`** - Runner type for the main agent job (string, array, or object) - **`runs-on-slim:`** - Runner type for all framework/generated jobs (activation, safe-outputs, unlock, etc.). Defaults to `ubuntu-slim`. `safe-outputs.runs-on` takes precedence for safe-output jobs specifically. diff --git a/.github/aw/token-optimization-observability.md b/.github/aw/token-optimization-observability.md index 36fe439c1fc..0037258ab3c 100644 --- a/.github/aw/token-optimization-observability.md +++ b/.github/aw/token-optimization-observability.md @@ -18,10 +18,11 @@ Add workflow-level OpenTelemetry export so each run emits token and phase data t observability: otlp: endpoint: ${{ secrets.GH_AW_OTEL_ENDPOINT }} - headers: ${{ secrets.GH_AW_OTEL_HEADERS }} + headers: + Authorization: ${{ secrets.GH_AW_OTEL_AUTHORIZATION }} ``` -Setup, agent, and conclusion spans carry token usage attributes. See [Frontmatter syntax](syntax-agentic.md#agentic-workflow-specific-fields). +Setup, agent, and conclusion spans carry token usage attributes. For protobuf encoding or opt-in session logs, see [Frontmatter syntax](syntax-agentic.md#agentic-workflow-specific-fields). When a `github-script` step needs a custom span, load the helper from the portable runner temporary directory: diff --git a/.github/aw/update-agentic-workflow.md b/.github/aw/update-agentic-workflow.md index 75f7291bad2..9b40770dc82 100644 --- a/.github/aw/update-agentic-workflow.md +++ b/.github/aw/update-agentic-workflow.md @@ -41,7 +41,7 @@ This prompt is for **updating existing workflows only**. For new workflows, use ## First Decision: Frontmatter or Prompt Body? -Use [workflow-editing.md](workflow-editing.md) as the source of truth for when recompilation is required. Always compile after any edit to keep `.lock.yml` in sync, even for body-only changes. +Use [workflow-editing.md](workflow-editing.md) as the source of truth for the frontmatter-vs-body recompilation taxonomy and the `.lock.yml` review. Always compile after any edit, even for body-only changes. ## Update Rules @@ -51,7 +51,7 @@ Use [workflow-editing.md](workflow-editing.md) as the source of truth for when r - preserve the existing `intent:` for implementation-only changes, including trigger or output-channel redesigns - when the requested outcome materially expands, contracts, or changes, update `intent:` and re-derive its applicability, required effects, no-op conditions, architecture, and evals using [intent.md](intent.md) - when an implementation-only change selects a different architecture, revalidate activation conditions, evidence window, deduplication or previous-result strategy, no-op behavior, and evals so event-specific rules do not survive an incompatible redesign -- when targeting the Copilot coding agent, recommend `permissions: { copilot-requests: write }` for Copilot authentication +- for Copilot inference, recommend `permissions: { copilot-requests: write }` (scope and caveats: [syntax-core.md](syntax-core.md)) - prefer `toolsets:` for GitHub tools - require `update-release` for agent-generated release notes or release-description changes; never use direct `gh`, API, or GitHub write-tool mutations from the agent - when the user asks for specific skills or agent plugins, add them to the top-level `skills:` / `plugins:` frontmatter fields; never add on-the-fly install steps or prompt instructions to install them at run time (see [skills.md](skills.md)) @@ -61,10 +61,6 @@ Use [workflow-editing.md](workflow-editing.md) as the source of truth for when r See [workflow-constraints.md](workflow-constraints.md) for the read-only security posture (keep the agent job read-only, route writes through `safe-outputs:`). -## Common Update Categories - -See [workflow-editing.md](workflow-editing.md) for the full frontmatter-vs-body recompilation taxonomy and the field list that requires `gh aw compile ` plus a `.lock.yml` review. - ## Cost-Oriented Update Checks When refining existing workflows, keep edits minimal and confirm the design still follows the [High-Volume Triage and Escalation Pattern](workflow-patterns.md#high-volume-triage-and-escalation-pattern): cheap triage before escalation, `noop`/safe output for known/duplicate/stale cases, frontier reasoning reserved for high-value cases, and context pulled on demand. Keep sub-agent fan-out bounded (see [subagents.md](subagents.md)), then measure the change with `gh aw audit` and treat token or quality regressions as failures (see [token-optimization.md](token-optimization.md)). @@ -120,9 +116,7 @@ plugins: - always inspect the workflow before editing - explicitly determine whether the existing intent is preserved or changed -- always compile after any change to keep `.lock.yml` in sync - keep the workflow valid at every step -- summarize what changed and whether recompilation was needed ## Final Steps diff --git a/.github/aw/workflow-constraints.md b/.github/aw/workflow-constraints.md index bea8b1ba112..d5998e434b2 100644 --- a/.github/aw/workflow-constraints.md +++ b/.github/aw/workflow-constraints.md @@ -75,7 +75,7 @@ When `runs-on` is any value other than GitHub-hosted labels (`ubuntu-latest`, `u - Set `runs-on` explicitly (not inherited from imports); accepts string, array, or runner-group object. Framework jobs (activation, safe-outputs, unlock, etc.) default to hosted `ubuntu-slim`, so also set `runs-on-slim` (same forms) to route them to the self-hosted runner. - Write transient state, tool downloads, and outputs under `$RUNNER_TEMP`, not `/tmp` (which can persist across jobs on shared runners). - Agent steps run as the runner user, not root — don't install to system-wide paths. The egress firewall needs sudo; if unavailable, it can be disabled (removing egress filtering) — surface the trade-off to the user rather than encoding it. -- Declare every outbound domain in `network.allowed` (keep `defaults` for core GitHub/Copilot/registry endpoints). Non-allow-listed domains are blocked when the firewall is enabled. +- Declare every outbound domain in `network.allowed`; `defaults` covers only certificate, JSON-schema, and stock Ubuntu hosts, so add `github`, language ecosystems, or engine sets explicitly (see [network.md](network.md)). Non-allow-listed domains are blocked when the firewall is enabled. - Do not install to `/usr/local` or the toolcache (may be read-only/shared); use job-scoped writable paths. - Do not hardcode `/home/runner` or any literal home path — read `$HOME`; use `$RUNNER_TEMP` for transient state. - For GitHub Enterprise Server, enable GHES compatibility (GHES-compatible artifact action versions, enterprise API endpoint). diff --git a/.github/aw/workflow-editing.md b/.github/aw/workflow-editing.md index 6243c46c3e2..26b395a117a 100644 --- a/.github/aw/workflow-editing.md +++ b/.github/aw/workflow-editing.md @@ -26,9 +26,7 @@ Run `gh aw compile ` after changing: ## No Recompile Required for Runtime Behavior -Body-only edits take effect on the next run without recompilation. - -Edit the markdown body directly for: +Body-only text edits take effect on the next run without recompilation: - agent instructions - task descriptions @@ -36,7 +34,7 @@ Edit the markdown body directly for: - formatting guidance - clarifications and guardrails -Body changes take effect on the next run. +Exception: adding or changing GitHub Actions expressions or `{{#if}}` conditions in the body or local runtime imports requires recompilation — the compiler selects their bindings and fails on malformed conditions (see [context.md](context.md)). **Always run `gh aw compile` after any change** (frontmatter or body) to keep `.lock.yml` metadata in sync. @@ -77,7 +75,6 @@ gh aw compile - Smallest change that satisfies the request. - Preserve structure unless reorganization is the task. - Never leave a workflow broken. -- Always run `gh aw compile ` after any change (frontmatter or body) to keep `.lock.yml` in sync. - If compile fails, fix all errors before stopping. - After any change, review the generated `.lock.yml`.