Summary
The "[aw] No-Op Runs" tracker issue is always stamped with a 30-day expiration marker at runtime, but the agentics-maintenance.yml workflow that enforces expiration is only generated when some workflow declares an explicit expires: field in its safe-outputs frontmatter. In a repository where no workflow sets expires: — while using noop.report-as-issue: true, which is the default — the marker is written but nothing ever reads it. The issue then carries a checked "expires" checkbox whose deadline silently passes, and it grows without the monthly rotation the expiry implies.
Observed behavior
In our repository, the no-op runs issue was created on 2026-03-27 with:
- [x] expires <!-- gh-aw-expires: 2026-04-26T05:32:51.126Z --> on Apr 26, 2026, 5:32 AM UTC
As of 2026-06-03 — five-plus weeks past the stamped deadline — the issue is still open, still accumulating comments (565 so far, ~272KB), and agentics-maintenance.yml does not exist in the repository (no workflow configures expires:).
Root cause
Two halves of the expiry feature live at different stages and don't see each other:
-
Runtime (always stamps): actions/setup/js/handle_noop_message.cjs unconditionally applies generateFooterWithExpiration({ expiresHours: 24 * 30 }) when creating the no-op runs issue.
-
Compile time (conditionally sweeps): pkg/workflow/maintenance_workflow.go gates generation of agentics-maintenance.yml on scanWorkflowsForExpires, which only inspects CreateDiscussions.Expires, CreateIssues.Expires, and CreatePullRequests.Expires. The runtime-stamped no-op expiry is invisible to this scan, so the !hasExpires path skips (and even deletes) the maintenance workflow.
The intended rotation — handler searches is:issue is:open for the tracker, sweeper closes it after 30 days, handler mints a fresh one on the next no-op — therefore never happens unless the repo coincidentally uses expires: somewhere else.
Suggested fix
Treat noop.report-as-issue: true (including by default) as an expiry source in scanWorkflowsForExpires, contributing the same 30-day value the runtime handler stamps. That keeps the two halves in agreement without new configuration surface. Alternatively, the handler could skip the expiration footer when no maintenance workflow will exist, but compile-time knowledge isn't available at runtime, so aligning the scan seems like the cleaner direction.
Workaround
Closing the tracker issue manually reproduces what the sweeper would have done; the handler creates a fresh tracker on the next no-op. (The issue body's "Do not close this issue manually" note discourages this, which is part of why the dead marker is confusing.)
Summary
The "[aw] No-Op Runs" tracker issue is always stamped with a 30-day expiration marker at runtime, but the
agentics-maintenance.ymlworkflow that enforces expiration is only generated when some workflow declares an explicitexpires:field in itssafe-outputsfrontmatter. In a repository where no workflow setsexpires:— while usingnoop.report-as-issue: true, which is the default — the marker is written but nothing ever reads it. The issue then carries a checked "expires" checkbox whose deadline silently passes, and it grows without the monthly rotation the expiry implies.Observed behavior
In our repository, the no-op runs issue was created on 2026-03-27 with:
As of 2026-06-03 — five-plus weeks past the stamped deadline — the issue is still open, still accumulating comments (565 so far, ~272KB), and
agentics-maintenance.ymldoes not exist in the repository (no workflow configuresexpires:).Root cause
Two halves of the expiry feature live at different stages and don't see each other:
Runtime (always stamps):
actions/setup/js/handle_noop_message.cjsunconditionally appliesgenerateFooterWithExpiration({ expiresHours: 24 * 30 })when creating the no-op runs issue.Compile time (conditionally sweeps):
pkg/workflow/maintenance_workflow.gogates generation ofagentics-maintenance.ymlonscanWorkflowsForExpires, which only inspectsCreateDiscussions.Expires,CreateIssues.Expires, andCreatePullRequests.Expires. The runtime-stamped no-op expiry is invisible to this scan, so the!hasExpirespath skips (and even deletes) the maintenance workflow.The intended rotation — handler searches
is:issue is:openfor the tracker, sweeper closes it after 30 days, handler mints a fresh one on the next no-op — therefore never happens unless the repo coincidentally usesexpires:somewhere else.Suggested fix
Treat
noop.report-as-issue: true(including by default) as an expiry source inscanWorkflowsForExpires, contributing the same 30-day value the runtime handler stamps. That keeps the two halves in agreement without new configuration surface. Alternatively, the handler could skip the expiration footer when no maintenance workflow will exist, but compile-time knowledge isn't available at runtime, so aligning the scan seems like the cleaner direction.Workaround
Closing the tracker issue manually reproduces what the sweeper would have done; the handler creates a fresh tracker on the next no-op. (The issue body's "Do not close this issue manually" note discourages this, which is part of why the dead marker is confusing.)