Skip to content

fix: derive the preflight matrix from every CI workflow - #984

Closed
thekevinbot wants to merge 3 commits into
mainfrom
claude/issue-981-preflight-workflows
Closed

thekevinbot wants to merge 3 commits into
mainfrom
claude/issue-981-preflight-workflows

Conversation

@thekevinbot

Copy link
Copy Markdown
Collaborator

Fixes #981

just preflight — the command AGENTS.md mandates before every push — has been dying with FileNotFoundError since #861. It hard-coded .github/workflows/conventions.yml, which that PR deleted when it split the eight caller jobs across six per-domain workflows.

FileNotFoundError: [Errno 2] No such file or directory: '.github/workflows/conventions.yml'

It is local-only tooling, so no gate went red. Its own unit test was the thing that should have caught it and didn't: test_defaults_to_the_ci_workflow_and_main asserted the default equals the literal stale path, pinning the wrong value instead of checking a file exists there.

What changed

parse_gate_matrix now takes the set of workflow documents rather than one, and the CLI globs .github/workflows/*.yml (sorted, so the matrix and the failure report don't depend on readdir order). A document that calls the reusable workflow nowhere — release, docs, the gate itself — contributes nothing rather than raising on a missing jobs: key.

The derivation is now reshuffle-proof in a way the old one wasn't: a lane added in a new per-domain file is a pair preflight runs, with no constant to update.

Restores all 8 scan roots / 40 pairs (37 run + 3 artifact-skips).

Manual verification

$ uv run --project internals/checks dirsql-checks preflight --dry-run
==> python-sdk [python] uv-sync: uv sync --project packages/python
...
==> plugins-embeddings [python] e2e-verify: uvx testing-conventions e2e verify --base origin/main --scope plugins/dirsql-plugin-embeddings/src plugins/dirsql-plugin-embeddings
preflight: 0 failing pair(s), 3 skipped

All eight roots present: python-sdk, rust-python-binding, typescript-sdk, rust-napi-binding, rust, internals-checks, internals-distcheck, plugins-embeddings.

Red/green

test: and fix: are separate commits in that order. CI was not observed red, because the red commit was pushed before this PR existed and every workflow here is pull_request-triggered — so nothing ran on it. The 16 failing tests were confirmed locally at 8aa77d6 (16 failed, 42 passed), failing on the absent multi-document API rather than incidentally.

Gates run locally

  • internals/checks unit suite: 313 passed, coverage 100.00% (floor 100)
  • unit mutation (diff-scoped, --base origin/main): 0 survivors / 9 mutants. One survived the first pass — ReplaceContinueWithBreak at matrix.py:90 — because my fixture refactor had moved the non-caller job to the end of its document, making continue and break indistinguishable. Killed with a new assertion that puts a caller on both sides of it, not by weakening anything.
  • unit colocated-test, unit lint: pass

E2E Verification

  • Ran e2e suites locally for every affected SDK
  • Python SDK e2e: N/A — no packages/python change
  • TypeScript SDK e2e: N/A — no packages/ts change
  • Rust core e2e (if applicable): N/A — no packages/rust change
  • packages/python/e2e-attestation.json refreshed if packages/python changed — N/A
  • packages/ts/e2e-attestation.json refreshed if packages/ts changed — N/A
  • Command(s) run: cd internals/checks && uvx testing-conventions e2e attest 'uv run python -m pytest tests/e2e -x -q'
  • Result summary: 17 passed. internals/checks is the package this PR changes; its receipt is refreshed as the last commit touching the package, and e2e verify --scope internals/checks/src exits 0.

Changelog / Migrations

  • Changelog fragment added for each changed package — not required: internals/ is not a published package root, and every commit carries a skip-changelog: reason
  • Migration fragment added — not required: repo tooling, no public API

No PARITY.md change — no SDK public API touched.

🤖 Generated with Claude Code

https://claude.ai/code/session_01KcNqe44kvgP5mBRr9LjQcE


Generated by Claude Code

claude added 3 commits August 20, 2026 19:09
preflight reads one workflow file, `.github/workflows/conventions.yml`,
which #861 deleted when it split that file into one workflow per domain.
`just preflight` -- the command AGENTS.md mandates before every push --
has been dying with FileNotFoundError ever since.

These assert the shape the fix needs: parse_gate_matrix takes the set of
workflow documents rather than one, and the CLI globs the workflow
directory (sorted, so the report does not depend on readdir order).

skip-changelog: internals/ is not a published package root

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KcNqe44kvgP5mBRr9LjQcE
#861 split conventions.yml into one workflow per domain, but preflight
still opened that single deleted file, so `just preflight` raised
FileNotFoundError instead of running a gate.

parse_gate_matrix now folds the callers across every document, and the
CLI globs .github/workflows for them. Documents that call the reusable
workflow nowhere -- release, docs, the gate itself -- contribute nothing
rather than raising on a missing `jobs:` key.

Restores all 8 scan roots and 40 pairs.

skip-changelog: internals/ is not a published package root

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KcNqe44kvgP5mBRr9LjQcE

Copy link
Copy Markdown
Collaborator Author

Closing as a duplicate of #983, which is the earlier PR and tracked by the earlier issue (#973, filed an hour before mine).

I hit the same FileNotFoundError while doing #932's item 1 — AGENTS.md documents just preflight as deriving its matrix from conventions.yml, and that sentence cannot be made true while the command is dead. I searched for an existing issue first and got zero hits, but #973 was already open; the search index evidently hadn't caught up. My fault for not looking harder before writing code — and #973 explicitly carves the code defect out of #932 ("Docs half only: #932 item 1 already covers retiring the old workflow names… This issue is the code defect, which that pass does not touch"), so the separation was already decided.

#983 is the better patch, independent of who was first. Its tests read the repo's real workflow files at the integration and e2e tiers, and it wires internals/checks' integration tier into internals-checks-ci.yml. That is the actual root-cause gap: my version stayed at the unit tier with a mocked glob, so it would not have caught this regression either, and would not catch the next rename. #983's own PR body names exactly that ("the colocated unit tests feed parse_gate_matrix inline YAML, so none of them can see that the default target stopped existing").

One thing from here worth folding in if it isn't already covered: the mutation gate kills a ReplaceContinueWithBreak mutant on the continue that skips non-caller jobs, and only if a fixture places a caller on both sides of a non-caller within a single document. A fixture whose non-caller sits last makes continue and break indistinguishable and the mutant survives.

#981 closed as a duplicate of #973. #932's docs PR (#985) is unaffected and now sits directly on main.


Generated by Claude Code

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

just preflight is dead — it opens the deleted conventions.yml

2 participants