Description
gh aw compile <workflow-id> and gh aw compile (full directory) produce different lock files from the same source. The difference is the value of GH_AW_ACTION_FAILURE_ISSUE_EXPIRES_HOURS.
gh aw compile <workflow-id> writes the implicit default "168".
gh aw compile (no argument) rewrites the value to "0" when no workflow opts in to expiry.
Reproduction
Tested with gh-aw v0.86.2 in a repository with three agentic workflows, no agentics-maintenance.yml, and no explicit expires / maintenance.action_failure_issue_expires configuration anywhere.
$ gh aw compile my-workflow
$ grep EXPIRES_HOURS .github/workflows/my-workflow.lock.yml
GH_AW_ACTION_FAILURE_ISSUE_EXPIRES_HOURS: "168"
$ gh aw compile
$ grep EXPIRES_HOURS .github/workflows/my-workflow.lock.yml
GH_AW_ACTION_FAILURE_ISSUE_EXPIRES_HOURS: "0"
Cause
The compiler always emits the implicit default "168" into the lock file. The correction to "0" happens later, inside maintenance-workflow generation (pkg/workflow/maintenance_workflow.go — actionFailureIssueExpiryLineRegex patching, per ADR-51425): when scanWorkflowsForExpires finds no explicit expiry opt-in, no agentics-maintenance.yml is generated and the implicit "168" markers are patched back to "0".
That patch step only runs on the full-directory path: compileAllFilesInDirectory → runPostProcessingForDirectory → generateMaintenanceWorkflowWrapper. The single-file path (compileSpecificFiles → runPostProcessing in pkg/cli/compile_pipeline.go) intentionally skips maintenance generation ("requires parsing all workflows in the directory"), so the lock file keeps the raw "168".
Impact
- Lock file output is not deterministic across the two command forms. Recompiling a single workflow flips the line to
"168"; the next full compile flips it back to "0". This creates diff churn and confusing code-review threads.
- The single-file output is also incorrect: it leaves an expiry marker of 168 hours that no scheduled
close-expired-issues job will ever enforce, because agentics-maintenance.yml does not exist. This is exactly the "silent correctness gap" ADR-51425 was written to eliminate.
Expected behavior
Both command forms produce the same lock file content. Possible fixes:
- Run the expiry scan (and the 168→0 patch) in the single-file post-processing path as well, or
- Emit
"0" by default and raise it to the configured value only when maintenance generation confirms an enforcing job exists.
Description
gh aw compile <workflow-id>andgh aw compile(full directory) produce different lock files from the same source. The difference is the value ofGH_AW_ACTION_FAILURE_ISSUE_EXPIRES_HOURS.gh aw compile <workflow-id>writes the implicit default"168".gh aw compile(no argument) rewrites the value to"0"when no workflow opts in to expiry.Reproduction
Tested with gh-aw v0.86.2 in a repository with three agentic workflows, no
agentics-maintenance.yml, and no explicitexpires/maintenance.action_failure_issue_expiresconfiguration anywhere.Cause
The compiler always emits the implicit default
"168"into the lock file. The correction to"0"happens later, inside maintenance-workflow generation (pkg/workflow/maintenance_workflow.go—actionFailureIssueExpiryLineRegexpatching, per ADR-51425): whenscanWorkflowsForExpiresfinds no explicit expiry opt-in, noagentics-maintenance.ymlis generated and the implicit"168"markers are patched back to"0".That patch step only runs on the full-directory path:
compileAllFilesInDirectory→runPostProcessingForDirectory→generateMaintenanceWorkflowWrapper. The single-file path (compileSpecificFiles→runPostProcessinginpkg/cli/compile_pipeline.go) intentionally skips maintenance generation ("requires parsing all workflows in the directory"), so the lock file keeps the raw"168".Impact
"168"; the next full compile flips it back to"0". This creates diff churn and confusing code-review threads.close-expired-issuesjob will ever enforce, becauseagentics-maintenance.ymldoes not exist. This is exactly the "silent correctness gap" ADR-51425 was written to eliminate.Expected behavior
Both command forms produce the same lock file content. Possible fixes:
"0"by default and raise it to the configured value only when maintenance generation confirms an enforcing job exists.