Skip to content

chore(ci): prove and prevent intermittent GitHub Actions runner-assignment stalls #30

Description

@seonghobae

Problem

Noema must distinguish GitHub Actions runner assignment from a workflow/job that is merely queued. started_at, workflow-level state, a predecessor attempt, a run-wide union of jobs, JavaScript adapter function arity, or non-canonical/invisible runner_name bytes are not runner-assignment authority by themselves.

This issue separates repository-owned evidence classification from organization/platform RCA. A repository diagnostic may classify assignment evidence; it cannot repair GitHub-hosted capacity, billing, enterprise policy, runner-group access, or a GitHub incident, and it cannot substitute for required CI/security/review conclusions.

Current implementation state — 2026-09-07 KST

Repository-owned acceptance

  • Preserve required CI/reviewer/security workflows; no synthetic replacement status.
  • Keep environment/dependency waits distinct from runner-assignment stalls.
  • Preserve bounded true-stall classification for a queued run/job with no assignment evidence after grace.
  • Prevent retained GitHub diagnostics from exposing active delegated credentials.
  • Stop treating timestamps/workflow-level state alone as assignment authority.
  • Bind fetched run id, exact positive run_attempt, exact current head and exact-attempt job pages; retain run_attempt in runner evidence.
  • Require the public evaluator itself to reject invalid/missing run_attempt rather than relying solely on the collector.
  • Treat run-wide filter=all as non-authoritative for current-attempt identity.
  • Stop treating JavaScript function arity as proof of attempt-scoped reader authority.
  • Use the hardened owner-only delegated-token capability-file boundary and reject non-canonical path/token authority.
  • Reject ASCII-control-only and Unicode Control/Format-only runner_name evidence when no positive runner ID exists.
  • Reject raw runner-name identity containing embedded Unicode Control/Format characters rather than deleting those bytes and promoting the normalized result to assignment authority.
  • Keep fix(actions): bind runner evidence to current run attempt #502 closed only after exact ancestry/preservation proved fix(governance): preserve delegated capability path authority #503 is its strict successor; fix(egress): bound anonymous GitHub API authority #500/fix(governance): preserve delegated capability path authority #503 remain integrated on protected lineage.
  • Finish fix(reviewer): fail closed on empty CodeGraph semantics #546 on an unchanged exact head with terminal current reviewer/CI/Security/image evidence and zero valid unresolved findings; it is now protected truth.
  • Finish fix(naming): make runner-assignment evidence semantic #533 only after the repaired reviewer contract produced current-head semantic evidence; it is now protected truth.
  • From protected main, exercise operations:runner-assignment against both assigned and genuinely unassigned/stale evidence and retain the bounded receipt. Current exact unassigned specimens include fix(trust): roll audited central workflow source to 49eb9e7 #554 jobs 101522050369 and 101522051034; a positive assigned control must come from the same bounded evidence procedure rather than a predecessor attempt.

Organization/platform RCA

  • Obtain authorized Actions enablement/hosted-runner policy history if needed.
  • Check billing/usage restrictions where applicable.
  • Check runner-group/access and organization concurrency for affected periods.
  • Check enterprise policy/IP restrictions where applicable.
  • Compare affected timestamps with GitHub platform incident evidence where available.
  • Identify a falsifiable external cause or retain it explicitly unresolved when evidence remains insufficient.

Guardrails

Do not merge with queued/pending/failed applicable checks or non-authoritative scanner evidence. Do not change runs-on, remove checks, synthesize statuses, weaken security/review gates, normalize hostile runner-name bytes into trusted authority, duplicate an already-owned dependency-root repair in a later leaf, reopen a proven superseded predecessor without new contrary evidence, repeatedly rerun an unchanged starved head, or reuse predecessor-attempt jobs to hide allocation latency. Keep runner assignment, check conclusion, scanner evidence, formal review, merge, release, deployment, and production evidence separate.

Related: #5, #27, #29, #96, #500, #502, #503, #527, #533, #542, #546, #548, #554; ContextualWisdomLab/.github#712.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    area: authAuthentication, authorization, identity, or tenant isolationarea: ci-cdCI, GitHub Actions, checks, release, or supply chainarea: dependenciesDependency or lockfile maintenancearea: securitySecurity boundary, hardening, or vulnerability preventionpriority: mediumNormal-priority or P2 workstatus: triagedOpen issue has an organization taxonomy assignmenttype: maintenanceMaintenance, build, dependency, or operational upkeep

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions