Date: 2026-04-16 Status: Draft Deciders: pelikhan, Copilot
The gh-aw workflow compiler translates markdown workflow files into GitHub Actions YAML. It already supports two custom step extension points: pre-steps (injected before the checkout step, very early in the agent job) and post-steps (injected after AI engine execution). A gap exists for steps that must run after all framework initialization — including checkout, credential setup, and environment preparation — but immediately before the AI engine starts. Use cases include final context preparation scripts, last-moment environment variable injection, and validations that depend on checked-out code being available.
We will add a new pre-agent-steps frontmatter field that is injected into the compiled GitHub Actions YAML immediately before the engine execution step, after all setup steps (including the CLI proxy start step). Like pre-steps, pre-agent-steps participates in the import merge system: imported pre-agent-steps are prepended before the main workflow's pre-agent-steps, preserving a deterministic, layered execution order. The existing validateStepsSecrets infrastructure is extended to cover the new field, applying identical secret expression restrictions.
The existing steps field (custom steps) could be repurposed or extended with explicit positioning metadata (e.g., position: before-engine). This was rejected because steps already has a defined execution context and adding positional metadata would complicate both the schema and the compiler without providing a clearer mental model. A dedicated named field communicates intent more directly.
pre-steps could accept an optional phase: post-setup attribute to signal late-bound execution. This was rejected because it conflates two very different lifecycle positions (before checkout vs. just before the engine) into a single field, making the execution model harder to reason about. Keeping phase-specific fields separate aligns with how GitHub Actions itself structures job steps.
Users could approximate "run before engine" behaviour by placing steps in post-steps with if: always() or condition expressions that short-circuit. This is semantically backwards, error-prone to write, and would not actually execute before the AI engine — it would run after, defeating the use case entirely.
- Users can inject pre-execution logic (context preparation, validation, environment mutations) at exactly the right lifecycle point — after setup, before the agent starts.
- The new field mirrors the naming and import-merge semantics of
pre-stepsandpost-steps, keeping the mental model consistent and the feature discoverable. - Secret expression validation is automatically enforced on the new field using the existing
validateStepsSecretsinfrastructure, preserving the security model without new code. - Integration tests cover placement order (after clean-git-credentials, before engine execution) and import merge ordering.
- The workflow extension model now has three named step positions (
pre-steps,pre-agent-steps,post-steps) plus the mainstepsfield; the distinction betweenpre-stepsandpre-agent-stepsrequires documentation to avoid confusion. - Each new step type requires coordinated changes across the schema, type definitions, import extractor, compiler builder, YAML generator, serialization, and documentation — increasing the cost of future schema evolution.
- The import merge ordering convention (imported steps prepend, main steps append) is the same as
pre-steps; this is a neutral consistency consequence rather than a new design choice. - The
docs/adr/filename uses the PR number as the sequence identifier, consistent with existing ADR naming in this repository.
The key words MUST, MUST NOT, REQUIRED, SHALL, SHALL NOT, SHOULD, SHOULD NOT, RECOMMENDED, MAY, and OPTIONAL in this section are to be interpreted as described in RFC 2119.
- Workflows MAY define a
pre-agent-stepstop-level frontmatter field containing an array of GitHub Actions step definitions. - The
pre-agent-stepsfield MUST conform to the same step schema aspost-steps(object or string items, withadditionalProperties: true). - Implementations MUST NOT treat
pre-agent-stepsandpre-stepsas interchangeable; they represent different lifecycle positions and MUST be processed independently.
- Implementations MUST inject all resolved
pre-agent-stepsinto the compiled GitHub Actions YAML immediately before the engine execution step. pre-agent-stepsMUST be placed after all framework setup steps (including the CLI proxy start step) and MUST NOT be placed before any framework-owned initialization steps.- If no
pre-agent-stepsare defined (neither in the main workflow nor in any imports), the compiler MUST NOT emit any placeholder or empty steps block.
- When a workflow imports other workflows that also define
pre-agent-steps, implementations MUST prepend importedpre-agent-stepsbefore the main workflow'spre-agent-stepsin the merged output. - Import merge order MUST follow the same topological ordering used for all other merged fields.
- Implementations MUST apply secret expression validation to the
pre-agent-stepsfield using the same rules applied topre-steps,steps, andpost-steps. - In strict mode, secrets expressions in non-
env/withcontexts withinpre-agent-stepsMUST cause a compilation error. - In non-strict mode, secrets expressions in
pre-agent-stepsSHOULD emit a warning.
- Implementations MUST apply action pin resolution (SHA substitution) to
uses:references inpre-agent-steps, consistent with how pinning is applied topre-stepsandpost-steps.
An implementation is considered conformant with this ADR if it satisfies all MUST and MUST NOT requirements above. Specifically: pre-agent-steps are injected immediately before the engine execution step (not before setup steps), imports are merged in prepend order, secret validation is applied, and action pinning is applied. Failure to meet any MUST or MUST NOT requirement constitutes non-conformance.
This is a DRAFT ADR generated by the Design Decision Gate workflow. The PR author must review, complete, and finalize this document before the PR can merge.