Skip to content

spec/audit.py: _code_view drops a folded-scalar body, so requireTokensInJob cannot see a token in the if: >- shape GOVERNANCE mandates #1133

Description

@ptr727

Found resyncing ptr727/PlexCleaner against hub f3b4cc9 (audit run 2026-08-30T21:49:58Z). Nothing in this issue is a defect in PlexCleaner.

Summary

spec/audit.py's _code_view() drops the body of every block scalar, including a folded one. check_interface()'s requireTokensInJob then scans a job block that no longer contains the condition, so a token written on the continuation line of an if: >- is invisible to it.

That shape is not incidental. It is what the fleet's own style rules mandate:

  • GOVERNANCE.md:229 — "multi-line if: uses folded scalar if: >- so YAML preserves whitespace correctly"
  • WORKFLOW.md:36 — "Conditionals. Multi-line if: uses the folded scalar if: >-"

So a repo that follows the style rule and satisfies the contract is reported as violating the contract, while a repo that violates the style rule by inlining the expression passes.

Reproduction

Two job blocks differing only in the if: shape, both satisfying publish-release.yml's requireTokensInJob for publish:

import importlib.util, sys
sys.path.insert(0, "spec")
spec = importlib.util.spec_from_file_location("audit", "spec/audit.py")
m = importlib.util.module_from_spec(spec); spec.loader.exec_module(m)

TOKEN = "needs.validate.result == 'success'"
folded = """jobs:

  publish:
    name: Publish project release job
    needs: [plan, validate]
    if: >-
      ${{ needs.plan.outputs.publish == 'true' && needs.validate.result == 'success' }}
    uses: ./x.yml
"""
inline = folded.replace(
    "    if: >-\n      ${{", "    if: ${{"
).replace(" }}\n    uses:", " }}\n    uses:")

for label, text in (("folded", folded), ("inline", inline)):
    blk = m._code_view(m.split_jobs(text)["publish"])
    print(label, "->", TOKEN in blk)
folded -> False
inline -> True

What _code_view() leaves for the folded case:

  publish:
    name: Publish project release job
    needs: [plan, validate]
    if: >-
    uses: ./x.yml

Who this hits today

Two repos, and they are precisely the two that have adopted the hub release chain and written the condition as documented:

Repo Ref Token in file Audit says
PhotoCleaner main present, folded missing required 'needs.validate.result == 'success''
PlexCleaner develop present, folded same

The same finding text appears against seven more repos (LanguageTags, ESPHome-NonRoot, VSCode-Server-DotNetCore, KiCadLibrary, MediaTools, Vantage-Config, Blog), but I checked each and those are true findings: the token is genuinely absent because they have not adopted the release chain. Only the two above are false positives. That ratio is the concerning part, since the false positives land on the repos that did the work.

Why the current behavior exists

The docstring is explicit, and the reasoning is sound for what it was written against:

A block-scalar string value (name: | followed by indented text) can hide or fake a token the same way, so its body is dropped too, keeping only the key: line itself (#949).

A run: or name: body is a string value, and dropping it is right. An if: body is a condition, which is exactly the structure requireTokensInJob exists to assert. _BLOCK_SCALAR_KEY does not distinguish them.

Possible directions

Not a recommendation, since the trade-off is yours:

  1. Exempt if: (and any other structural key) from the block-scalar drop, keeping the body for run:, name:, and other string values. Narrow, and preserves check_interface()'s token matching reads YAML block-scalar content as structure #949's intent.
  2. Fold the scalar before scanning rather than dropping it, so if: >- plus its body reads as the single logical line YAML says it is.
  3. Leave _code_view() alone and have requireTokensInJob scan a YAML-parsed value for the named key instead of a text view.

Option 1 or 2 would clear the false positives without weakening the #949 guard, since neither restores a name:/run: body to the scan.

Not filed here

PlexCleaner's own convergence issue is separate. No audit report or registry change is being written back to this repo.

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

    scriptA defect in hub tooling

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions