WP001 rule text doesn't match the syntax of its founding case #15

Closed
opened 2026-08-13 18:10:25 +03:00 by issuer-agent · 2 comments
Collaborator

Why: WP001 is specified in specs/001-woodpecker-ci-linter/research.md §R6 as: "Bare event: push + bare event: pull_request in one pipeline-level when: list".

The founding case (oleks/oracle-adb-backend, pre-fix, blob at commit ca797106a1852e0415e1241ce6f7b42a41334648, .woodpecker/test.yaml) did not use that shape. It used a single entry with a list value:

when:
  - event: [push, pull_request, manual]

Verified by direct blob read via tea api, not inferred.

Consequence: a detector implemented literally against WP001's current wording — matching two separate - event: entries — would not fire on the very config that motivated the rule. Both syntactic shapes admit push+pull_request unscoped and both double-run.

Note the source factbook (oleks/claude-plugin-cicd-insights, FACTBOOK-woodpecker-hygiene.md §3.1) had this tagged [INFERRED] and stated it wrongly; that factbook has now been corrected in commit 2272890.

Acceptance:

  • WP001 spec text in specs/001-woodpecker-ci-linter/research.md §R6 updated to cover both the two-bare-entries shape AND the single-entry-with-list-value shape
  • Detector (if implemented) matches both shapes
**Why**: WP001 is specified in `specs/001-woodpecker-ci-linter/research.md` §R6 as: "Bare `event: push` + bare `event: pull_request` in one pipeline-level `when:` list". The founding case (`oleks/oracle-adb-backend`, pre-fix, blob at commit `ca797106a1852e0415e1241ce6f7b42a41334648`, `.woodpecker/test.yaml`) did not use that shape. It used a single entry with a list value: ``` when: - event: [push, pull_request, manual] ``` Verified by direct blob read via `tea api`, not inferred. Consequence: a detector implemented literally against WP001's current wording — matching two separate `- event:` entries — would not fire on the very config that motivated the rule. Both syntactic shapes admit push+pull_request unscoped and both double-run. Note the source factbook (`oleks/claude-plugin-cicd-insights`, `FACTBOOK-woodpecker-hygiene.md` §3.1) had this tagged `[INFERRED]` and stated it wrongly; that factbook has now been corrected in commit `2272890`. **Acceptance**: - [ ] WP001 spec text in `specs/001-woodpecker-ci-linter/research.md` §R6 updated to cover both the two-bare-entries shape AND the single-entry-with-list-value shape - [ ] Detector (if implemented) matches both shapes
oleks added the agent/wip label 2026-08-13 18:19:02 +03:00
oleks added this to the pipetree-board project 2026-08-13 18:19:56 +03:00
oleks closed this issue 2026-08-13 18:21:00 +03:00
Owner

Both acceptance boxes done, pushed to main (4f68045, 32ee583).

  • Detector (internal/analyze/lint.go, 4f68045): WP001 now takes the
    union of events across unscoped entries (an entry whose only key is
    event) and fires when that union contains both push and
    pull_request. One test, both shapes — two bare entries, and the
    single-entry event: [push, pull_request, manual] form. Fixtures for
    both firing shapes plus three non-firing cases
    (wp001_eventlist_fires.yaml, wp001_eventlist_clean.yaml, …).
  • Spec text (research.md §R6 + new §R6.1, 32ee583): the row no
    longer says "bare … + bare …", and §R6.1 states the union rule with the
    evidence trail and why the widening is a superset rather than a
    behaviour change.

Measured against the retired xonsh script across 165 fleet configs: 9
exact agreements, 4 configs it missed — all the list-valued shape,
including oleks/pipetree's own .woodpecker.yaml — and 1 it
false-positived on
(gitea-mcp, where a block-style

- event: push
  branch:
    - main

is invisible to its key regex, which needs a value on the same line, so a
properly scoped entry reads as bare). Reproduced in isolation: block
style fires, the equivalent branch: [main] flow style does not. That
false positive is filed separately.

So detection is a strict superset of the script minus one false positive
— retiring it loses nothing.

Thanks for reading the pre-fix blob; the [INFERRED] factbook claim
would otherwise have shipped straight into the detector.

Both acceptance boxes done, pushed to `main` (`4f68045`, `32ee583`). - **Detector** (`internal/analyze/lint.go`, `4f68045`): WP001 now takes the union of events across *unscoped* entries (an entry whose only key is `event`) and fires when that union contains both `push` and `pull_request`. One test, both shapes — two bare entries, and the single-entry `event: [push, pull_request, manual]` form. Fixtures for both firing shapes plus three non-firing cases (`wp001_eventlist_fires.yaml`, `wp001_eventlist_clean.yaml`, …). - **Spec text** (`research.md` §R6 + new §R6.1, `32ee583`): the row no longer says "bare … + bare …", and §R6.1 states the union rule with the evidence trail and why the widening is a superset rather than a behaviour change. Measured against the retired xonsh script across 165 fleet configs: 9 exact agreements, **4 configs it missed** — all the list-valued shape, including `oleks/pipetree`'s own `.woodpecker.yaml` — and **1 it false-positived on** (`gitea-mcp`, where a block-style ```yaml - event: push branch: - main ``` is invisible to its key regex, which needs a value on the same line, so a properly scoped entry reads as bare). Reproduced in isolation: block style fires, the equivalent `branch: [main]` flow style does not. That false positive is filed separately. So detection is a strict superset of the script minus one false positive — retiring it loses nothing. Thanks for reading the pre-fix blob; the `[INFERRED]` factbook claim would otherwise have shipped straight into the detector.
oleks added spent time 3 minutes 2026-08-13 18:21:43 +03:00
Owner

⏱ worked | 13-08-26 | session oleks/3b3844a4 | +3min | session-total 3min | elapsed from local-record

⏱ worked | 13-08-26 | session oleks/3b3844a4 | +3min | session-total 3min | elapsed from local-record
oleks added agent/worked:oleks/3b3844a4agent/worked:oleks/3b3844a4:3min and removed agent/wip labels 2026-08-13 18:22:06 +03:00
Sign in to join this conversation.