Skip to content

Workflow yaml carries deciding logic inline, where no test can reach it #9516

Description

@usirin

Pitch

Problem: 66 multi-line run: | blocks and actions/github-script steps across 40 workflow files carry logic no test can reach. The audit on this issue sorted them: 51 decide (parse, branch, retry, call an API), 15 only relay. A wrong pattern inside a yaml string shows up as a red main, not a red test — #9507 was exactly that, three days red from a regex in .github/workflows/deploy.yml. The same logic is also copy-pasted: diff-basis resolution appears inline 5 times while packages/fabrika-cli/src/guard/changed-files.ts is already the tested core for it, the sticky preview-comment writer has 3 inline copies (one already drifted, #9521), and the "file a needs-triage issue" block appears 4 times while fabrika report file does it.
Arc: axis:pipeline-hardening
Appetite: 3 cycles
Rabbit-holes: Moving all 51 at once. publish.yml's tag grammar is read out of the yaml by publish-isolation-guard (ADR 0201), so moving it without re-pointing that guard silently zeroes the gate. Inventing new packages — the founder ruled no ci-cli, no phoenix-ci. Pulling phoenix detail into packages/fabrika-cli, which the portability guard reds.
No-gos: The 15 relay-only blocks and the 7 the audit marked fine inline (pinned binary installs, bot commit, step summary). Any home not yet ruled: the 8 deploy/preview scripts (packages/anka-ops is the audit's suggestion, unruled) and the 3 phoenix-only scripts (publish.yml tag grammar, release dispatch roster, design manifest firewall) stay unmoved until the founder names their home.

Epic — awaiting plan

plan-epic appends its plan and dependency topology below.

Original brief (verbatim)

Summary

Many workflow files hold multi-line inline scripts that parse, branch and retry. None of that logic runs under a test. The #9507 deploy break was one of these: a regex inside a yaml string, red on main for 3 days.

What I was doing

Tracing the red web deploy on main (#9507) and reviewing its fix in PR #9510. The founder then said, on 2026-09-20, that inline scripts in yaml files are not testable and he does not want them.

What I observed

Across 38 files in .github/workflows/ there are 62 multi-line run: | blocks and 4 actions/github-script steps. By file, inline blocks plus github-script steps:

  • deploy.yml: 9 + 2
  • run-evidence.yml: 7
  • release-please.yml: 6
  • ci.yml: 5 + 1
  • pr-cleanup.yml: 4 + 1
  • heal-ci-sweep.yml: 4

In deploy.yml the inline logic includes the worker URL scrape, the prod health verify loop (6 retries with back-off and two fail-closed branches), and a marker-keyed read-modify-write upsert of the preview comment.

PR #9510 fixes the broken scrape but keeps it inline, as a sed one-liner inside the yaml. Its correctness was shown by hand against three real logs in the PR, not by a test that stays in the repo.

The repo's working rule in CLAUDE.md says repository tooling uses Node and Effect CLI with a testable decision core and a thin bin, and that shell relays tool results without owning decisions. These blocks do not follow it.

I did not classify all 62. A block that only calls a bin is fine. The ones that parse, branch, retry or decide are the concern.

Why it matters

Logic in a yaml string is only exercised by a live run, often only after merge, so a wrong pattern shows up as a red main instead of a red test. The next Alchemy output change could break the scrape the same way. How many of the 62 blocks carry real decisions is unknown until someone sorts them.

Pointers

Suggested next step (non-binding)

Sort the run blocks into relay-only and deciding. Move the deciding ones in deploy.yml first, scrape and health verify, into a tested CLI core fed by fixture logs. Consider a guard that reds a new deciding inline block.


Filed by an agent · session 56fedc1c-913a-4bc4-baa5-2b748ea48b9b · branch main · 2026-09-20T20:07:33Z

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

    axis:pipeline-hardeningStanding cross-cutting axis: pipeline hardening (was milestone #1; go-forward label)class:codecreated by fabrika status bootstrap label-taxonomyp1Medium prioritystatus:triagedTriage signed off; ready for write-code to picktype:epicToo big for one PR; spawns children

    Type

    No type

    Projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions