Skip to content

fix(ci): four workflows are parse-dead on main — re-fix + guard against recurrence - #69

Merged
hyperpolymath merged 2 commits into
mainfrom
ci/refix-scalar-permissions
Jul 28, 2026
Merged

fix(ci): four workflows are parse-dead on main — re-fix + guard against recurrence#69
hyperpolymath merged 2 commits into
mainfrom
ci/refix-scalar-permissions

Conversation

@hyperpolymath

Copy link
Copy Markdown
Owner

Four gates are dead on main right now. This restores them and stops the loop.

What is broken

zig.yml, e2e.yml, container-build.yml, install-smoke.yml — the Zig FFI gate, the
Julia test suite, the container build and the install smoke test — are unparseable:

permissions: read-all
  actions: read        # mapping values are not allowed here

All four declare permissions in the scalar form. Hanging a mapping key under a scalar
is invalid YAML.

Why nobody noticed

Actions rejects a malformed workflow at parse timezero jobs, no check run.
Not a red X — an absence. gh pr checks shows nothing wrong.

The only visible tell, and how this was caught:

$ gh run list --branch main
failure   .github/workflows/zig.yml        <-- PATH, not "Zig FFI"
failure   .github/workflows/e2e.yml
failure   .github/workflows/container-build.yml
failure   .github/workflows/install-smoke.yml
success   Governance

When gh run list prints a path where it normally prints a name, the workflow
never parsed.

How it came back

#64 fixed all four
#68 re-ran the sweep → reintroduced all four

#68’s stated purpose (repointing codeql-action at a SHA that exists) was correct and is
untouched here. It simply carried the sweep along with it.

Same root cause both times: the sweep matches permissions: as text, not as a YAML
node
, so it cannot distinguish the scalar form from the mapping form. The insertion is
redundant regardless — read-all already grants every read scope, actions: read included.

The guard

Fixing this twice without a guard just queues up a third time. Added
.githooks/validate-workflow-yaml.sh, wired as the first job of the dogfood gate:
parse every workflow, fail on any that does not parse or that declares no jobs — a
workflow can be valid YAML and still be inert.

Deliberately dumb and total. A text-only sweep cannot satisfy it.

Proven fail-closed, not assumed

Case Result
A. clean tree exit 0 — "all 19 workflows parse and declare jobs"
B. actions: read reintroduced into zig.yml exit 1 — names the file and the reason
C. restored exit 0

Case B is the one that matters: the guard fails on the exact defect it exists to catch.

Verification

  • All 19 workflows parse under yaml.safe_load
  • Guard proven to fail on the reintroduced bug (case B above)
  • Zig FFI, E2E + Aspect, Container Build, Install Smoke appear by NAME in
    the checks below — their appearance is the fix; absence is the failure mode
  • Workflows parse (no silent-dead gates) passes

Follow-up

The sweep script itself should be made YAML-aware before it is run against the estate
again — this repo is unlikely to be the only one with scalar permissions: blocks.

hyperpolymath and others added 2 commits July 28, 2026 19:47
…recurring

#68 ("repoint codeql-action at a SHA that exists") re-ran the sweep that
appends `actions: read` after every `permissions:` line, undoing the fix landed
in #64. Four workflows are parse-dead on main RIGHT NOW:

    zig.yml  e2e.yml  container-build.yml  install-smoke.yml

i.e. the Zig FFI gate, the Julia test suite, the container build and the install
smoke test. All four declare permissions in the scalar form, so the appended key
is invalid YAML:

    permissions: read-all
      actions: read        # mapping values are not allowed here

Actions rejects a malformed workflow at PARSE time — zero jobs, NO check run.
Not a red X, an absence. The only visible tell is `gh run list` printing the
workflow's PATH instead of its NAME, which is exactly how this was spotted.

Same cause both times: the sweep matches `permissions:` as TEXT, not as a YAML
node, so it cannot tell the scalar form from the mapping form. The insertion is
redundant anyway — `read-all` already grants every read scope, `actions: read`
included.

Fixing it a second time without a guard would just queue up a third. So this
also adds `.githooks/validate-workflow-yaml.sh`, wired as the first job of the
dogfood gate: parse every workflow, fail on any that does not parse OR that
declares no jobs (a workflow can be valid YAML and still be inert).

The guard is proven fail-closed, not assumed:

  A. clean tree                    -> exit 0, "all 19 workflows parse"
  B. `actions: read` reintroduced  -> exit 1, names zig.yml and the reason
  C. restored                      -> exit 0

A text-only sweep cannot satisfy this check, which is the point.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Two clean-ups, both closing loose ends left by earlier sweeps.

1. GOVERNANCE — recover what was lost, fix the dangling references
------------------------------------------------------------------
#68 deleted GOVERNANCE.adoc as a duplicate of GOVERNANCE.md. It was not one.
Fifteen sections existed ONLY in the .adoc, and went with it:

  Contribution Lifecycle · Conflict Resolution · Project Policies ·
  Repository-Specific Conventions · Governance Evolution · See Also · Changelog

"Repository-Specific Conventions" is the load-bearing one — it is where the
signing requirement, the SPDX rule, the contractile layout and the
.machine_readable/6a2/ convention were written down.

That content is recovered here from 5501ec6^ and merged into GOVERNANCE.md,
converted from AsciiDoc to Markdown. GOVERNANCE.md is now genuinely the single
source, which is what #68 intended but did not achieve.

The deletion also left two dangling references, now repointed:

  .machine_readable/contractiles/Trustfile.a2ml:74  areas: GOVERNANCE.adoc
  .machine_readable/contractiles/Mustfile.a2ml:38   "GOVERNANCE.adoc ... must exist"

The Mustfile one is worth flagging: it is a `severity: critical` contract whose
`run:` is literally

    test -f GOVERNANCE.adoc && test -f MAINTAINERS.adoc && test -f .github/CODEOWNERS

That assertion has been FALSE since #68 and nothing went red — because nothing
executes it. grep finds no runner for Mustfile contracts; validate-a2ml.sh only
parses them as TOML. So a critical contract silently became false. Repointed to
GOVERNANCE.md, and the assertion now genuinely holds — but the contracts being
declarative-only is a separate gap, filed rather than papered over here.

2. push-email-notify.yml — deleted, not left disabled
-----------------------------------------------------
Estate dual-use policy removes push-email everywhere except 007,
robodog-defensive-systems-lab and defensive-multiplicity. statistikles is not
one of the three, so it was already `disabled_manually`. Verified dormant:
PUSH_EMAIL_ENABLED is not set on this repo, and nothing else references it.

Deleting beats leaving it disabled — a disabled-but-present workflow reads as an
oversight to the next person, and it is one re-run of a farm sweep away from
being re-enabled.

Verified: all 18 remaining workflows parse and declare jobs.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@sonarqubecloud

Copy link
Copy Markdown

Quality Gate Failed Quality Gate failed

Failed conditions
C Security Rating on New Code (required ≥ A)

See analysis details on SonarQube Cloud

Catch issues before they fail your Quality Gate with our IDE extension SonarQube for IDE

@gitar-bot

gitar-bot Bot commented Jul 28, 2026

Copy link
Copy Markdown

⚠️ Gitar auto-approved this PR but could not enable auto-merge: auto-merge is disabled for this repository — enable "Allow auto-merge" in the repository settings.

@gitar-bot gitar-bot Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Gitar has auto-approved this PR and enabled auto-merge (configure)

@gitar-bot gitar-bot Bot added the gitar-approved Added by Gitar label Jul 28, 2026
@gitar-bot

gitar-bot Bot commented Jul 28, 2026

Copy link
Copy Markdown

Note

Automatic reviews are paused because your trial's included automatic processing has been used for this period. Upgrade now, or comment "Gitar review" to run a review anytime.
Learn more

Code Review ✅ Approved

Restores four parse-dead workflows caused by malformed scalar permissions and adds a dogfood validation gate to prevent recurrence. No issues found.

Auto-approved and auto-merge armed: No blocking issues found.
Please see Auto-approve Docs for details on setting custom approval criteria. — merges when pipeline and required approvals pass.

Options

Display: compact → Showing less information.

Comment with these commands to change the behavior for this request:

Compact
gitar display:verbose         

Was this helpful? React with 👍 / 👎 | Gitar

@hyperpolymath
hyperpolymath merged commit 364a4ec into main Jul 28, 2026
29 of 30 checks passed
@hyperpolymath
hyperpolymath deleted the ci/refix-scalar-permissions branch July 28, 2026 19:02
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

gitar-approved Added by Gitar

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant