#949 taught _code_view() to drop block-scalar bodies, so a token sitting in a documentation
string could not be read as structure. That defense does not distinguish a documentation
block scalar from an expression one, and if: is routinely written as a folded scalar. The
body it drops there is not prose about the gate. It is the gate.
The result is inverted: check_interface() reports a required release gate as missing on a
workflow that has it.
Reproduction, constructed
jobs:
publish:
name: Publish project release job
needs: [plan, validate]
if: >-
${{ needs.plan.outputs.publish == 'true' && needs.validate.result == 'success' }}
uses: owner/repo/.github/workflows/build-release-task.yml@<pin>
requireTokensInJob looks for needs.validate.result == 'success' in this job. Run
_code_view() over it and the job reduces to:
publish:
name: Publish project release job
needs: [plan, validate]
if: >-
uses: owner/repo/.github/workflows/build-release-task.yml@<pin>
The if: key survives and its entire condition is gone, so the token is absent and the audit
emits:
DRIFT interface: .github/workflows/publish-release.yml job 'publish' missing required 'needs.validate.result == 'success''
Measured directly, importing the module and calling it on that job text: token present in the raw
job text True, token present in the _code_view() output False.
Writing the same condition inline on one line passes. The two forms are identical to GitHub
Actions, so the check is testing how the YAML is wrapped rather than whether the gate exists.
Where it showed up
The 2.0.577 resync pilot, audit run 2026-09-07T02:37:02Z | hub f8e7491, reported this against
PlexCleaner's publish-release.yml. The condition is present and correct there at both main
and develop, byte-identical, in the folded form above. The finding was carried into the resync
as real work before being checked, which is the cost this issue is about: a false positive on a
release gate invites someone to "fix" a workflow that is not broken, and the plausible fix is to
rewrite a correct condition.
Why a blanket rule cannot resolve it
The two cases genuinely conflict, and neither yields to a heuristic over the text:
The distinguishing fact is the key, not the scalar style: if, and the other
expression-bearing keys, hold a value that is always structure. A candidate fix is to keep the
folded or literal body for a known expression-bearing key set (if at minimum) and keep dropping
it everywhere else. Parsing the YAML and reading the value, rather than substring-matching the
text, resolves it more completely, and #949's own reasoning about the text view would then apply
only to the keys where a string body really is prose.
Whichever way it goes, spec/audit.py's self-test deserves a case for each of the two forms, since
the current suite passes with the inline form only and that is why this reached a downstream
repository.
Found during the #1399 fleet resync pilot.
#949 taught
_code_view()to drop block-scalar bodies, so a token sitting in a documentationstring could not be read as structure. That defense does not distinguish a documentation
block scalar from an expression one, and
if:is routinely written as a folded scalar. Thebody it drops there is not prose about the gate. It is the gate.
The result is inverted:
check_interface()reports a required release gate as missing on aworkflow that has it.
Reproduction, constructed
requireTokensInJoblooks forneeds.validate.result == 'success'in this job. Run_code_view()over it and the job reduces to:The
if:key survives and its entire condition is gone, so the token is absent and the auditemits:
Measured directly, importing the module and calling it on that job text: token present in the raw
job text
True, token present in the_code_view()outputFalse.Writing the same condition inline on one line passes. The two forms are identical to GitHub
Actions, so the check is testing how the YAML is wrapped rather than whether the gate exists.
Where it showed up
The
2.0.577resync pilot,audit run 2026-09-07T02:37:02Z | hub f8e7491, reported this againstPlexCleaner'spublish-release.yml. The condition is present and correct there at bothmainand
develop, byte-identical, in the folded form above. The finding was carried into the resyncas real work before being checked, which is the cost this issue is about: a false positive on a
release gate invites someone to "fix" a workflow that is not broken, and the plausible fix is to
rewrite a correct condition.
Why a blanket rule cannot resolve it
The two cases genuinely conflict, and neither yields to a heuristic over the text:
name: |followed by prose that happens to contain a token is what check_interface()'s token matching reads YAML block-scalar content as structure #949 closed. The body isdocumentation and must not be read as structure.
if: >-followed by an expression is structure, and dropping it loses the only copy.The distinguishing fact is the key, not the scalar style:
if, and the otherexpression-bearing keys, hold a value that is always structure. A candidate fix is to keep the
folded or literal body for a known expression-bearing key set (
ifat minimum) and keep droppingit everywhere else. Parsing the YAML and reading the value, rather than substring-matching the
text, resolves it more completely, and #949's own reasoning about the text view would then apply
only to the keys where a string body really is prose.
Whichever way it goes,
spec/audit.py's self-test deserves a case for each of the two forms, sincethe current suite passes with the inline form only and that is why this reached a downstream
repository.
Found during the #1399 fleet resync pilot.