diff --git a/AGENTS.md b/AGENTS.md index 9960640f79..63a0e0cc78 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -25,6 +25,7 @@ Detailed guidance lives in `docs/contributing/`. Read only the file relevant to | [Go Code](docs/contributing/go-code.md) | Changing Go code under `cmd/` or `internal/` — covers mint sync, coverage, vet, e2e tests | | [Shell Scripting](docs/contributing/shell-scripting.md) | Writing or reviewing shell scripts — covers `gh api --paginate` pitfalls and jq patterns | | [Forge Abstraction](docs/contributing/forge-abstraction.md) | Adding forge operations — covers `forge.Client` interface rules | +| [CEL Triggers](docs/contributing/cel-triggers.md) | Writing or reviewing harness `trigger` CEL expressions or `.feature` CEL filters — covers normalized transition kinds | | [ADRs](docs/contributing/adrs.md) | Touching `docs/ADRs/` or reviewing ADR changes — covers immutability and status rules | | [Sandbox Topology](docs/contributing/sandbox-topology.md) | Modifying sandbox images, CI image pulling, or agent harness configs | | [Bot Identities](docs/contributing/bot-identities.md) | Referencing bot identities in code — covers GitHub App logins and shared identities | diff --git a/docs/contributing/cel-triggers.md b/docs/contributing/cel-triggers.md new file mode 100644 index 0000000000..a958f7ff00 --- /dev/null +++ b/docs/contributing/cel-triggers.md @@ -0,0 +1,31 @@ +# CEL Triggers and Normalized Events + +Harness `trigger` expressions — and the CEL filters in `.feature` fixtures that +exercise them — match against the **normalized event model**, not raw +forge-specific webhook payloads. Whenever you write or review a CEL trigger, use +the normalized `transition.kind` vocabulary. A raw forge webhook action name +used where a `transition.kind` is expected silently evaluates to `false`, so the +trigger never fires and nothing warns you. + +**Source of truth:** +[`docs/normative/normalized-event/v1/README.md`](../normative/normalized-event/v1/README.md). +Its [Transition kind vocabulary](../normative/normalized-event/v1/README.md#transition-kind-vocabulary), +[Transition sub-objects](../normative/normalized-event/v1/README.md#transition-sub-objects), +and [CEL trigger examples](../normative/normalized-event/v1/README.md#cel-trigger-examples) +sections are authoritative for the full enumerated kind list and the sub-object +each kind requires (`label`, `comment`, `review`, …). Do not re-copy that list +here — a duplicated table drifts from the schema. + +**Highest-value pitfall — `synchronize` vs `synchronized`:** GitHub's raw +webhook action is `synchronize` (no trailing `d`), but the normalized kind is +**`synchronized`**. A CEL expression written as +`event.transition.kind == "synchronize"` silently never matches — this exact +typo appeared in a fork-dispatch scenario and was eliminated in PR #5309. The +same raw→normalized gap exists elsewhere (e.g. `labeled` / `unlabeled` → +`label_changed`); when unsure, check the vocabulary section above rather than +guessing from the webhook name. + +**When reviewing** harness triggers or `.feature` CEL filters: flag any raw +forge webhook action name used where a normalized `transition.kind` is expected +(e.g. `"synchronize"`, `"labeled"`) as a **medium-severity** finding — it will +silently fail to match.