Skip to content

CI: run the checks a pull request's changed paths map to (jpdev.json mapping) - #177

Merged
kikashy merged 1 commit into
mainfrom
changed-mapping
Oct 26, 2026
Merged

kikashy merged 1 commit into
mainfrom
changed-mapping

Conversation

@kikashy

@kikashy kikashy commented Oct 26, 2026

Copy link
Copy Markdown
Contributor

What

  • jpdev.json (new) holds a changed mapping. Each rule comes from what a dev.json step's command and the scripts it calls read. The reads were checked twice: by reading each command, script and test, and by recording every file opened under the clone's tracked directories during one full check.sh --all run, attributed to the step that was running.
  • .github/workflows/ci.yml, the Runner (<os>) jobs: the checkout takes the whole history (fetch-depth: 0). The Checks step runs scripts/dev/check.sh --all --changed "origin/$BASE_REF" --skip <the four release steps> on pull_request. Otherwise it runs the current --all --skip <the four release steps>, in the template's env:/if form. A push to main, and the call from release.yml at a tag, still run the whole list. The job names, the "manifest parses" step, the Release contents job (which always runs its four release steps), the triggers and release.yml are unchanged. The repository has no .github/ci-evidence.json.
  • AGENTS.md / CLAUDE.md ("This repository"): a paragraph on the scoped pull-request run, the whole list on main, the local command, the build-pinned prerequisite and where the Go tests read outside their packages.

--changed and --skip combine as the vendored runner defines: the selection becomes the --only set, and --skip then removes the release steps from it. Every rule names the three whole-tree steps, so a pull-request run is never empty.

Inputs: step → paths read

Step Paths it reads
local-paths every tracked file (git grep) except *.png, *.jpg and two files named in scripts/checks/local-paths.sh
agent-docs AGENTS.md, CLAUDE.md, scripts/sync-agent-docs.sh
diff-check every tracked file (git diff --check against the empty tree)
go-fmt every .go file (gofmt -l walks each package directory, test data included); go.mod, go.sum (go list ./...); .gitignore (read during the go command's VCS lookup)
go-vet every .go file outside test data; go.mod, go.sum
build-pinned scripts/checks/build-pinned.sh (plus the pinned commits fetched over the network)
manual-gate scripts/checks/manual-gate.sh; the .go files of internal/runner and its imports; go.mod, go.sum; internal/runner/testdata/**; docs/design/manual-admission-wire.json; the binaries build-pinned writes to .ci/bin
unit-tests scripts/checks/unit-tests.sh; every .go file (including internal/runner/testdata/async-mcp, which a test builds); go.mod, go.sum; internal/runner/testdata/**, internal/derivation/testdata/**, cmd/jpack-runner/testdata/**; vectors/**; openapi.json; docs/MAPPING-V2.md, docs/design/manual-admission-wire.json, docs/design/executor-ownership-boot.json; .gitignore; the .ci/bin binaries
chain-tests scripts/checks/chain-tests.sh; the .go files of internal/runner, cmd/jpack-runner and their imports; go.mod, go.sum; internal/runner/testdata/**; the .ci/bin binaries
openapi openapi.json
build the .go files in the import graphs of cmd/jpack-runner and cmd/jpack-source-worker; go.mod, go.sum; .gitignore
release-toolchain scripts/checks/release-toolchain.sh, .github/workflows/release.yml, go.mod (via go env GOVERSION)
third-party-notices tools/third_party_notices.py, THIRD_PARTY_NOTICES; the .go files in ./cmd/...'s import graph; go.mod, go.sum; the module cache and GOROOT
release-archives tools/test_release_archives.py, tools/release_archives.py, go.mod (it builds a synthetic tree in a temporary directory)
release-programs scripts/checks/release-programs.sh, .goreleaser.yml, the names under cmd/

The trace found no file read that the mapping leaves uncovered. Its other events were directory listings: the go command's package walk over the module (./, docs/, deploy/, scripts/, tools/, vectors/) and Python's import lookup in tools/. A listing depends only on which files exist. A new .go file selects every Go step through **/*.go, and a file in a new place is unmapped.

The rules

local-paths, agent-docs and diff-check read the whole tree. They are in every rule rather than in one ** rule, so an unmapped path still runs the whole list. Each rule below also selects those three.

  • **/*.go, go.mod, go.sum → go-fmt, go-vet, build-pinned, manual-gate, unit-tests, chain-tests, build, third-party-notices.
  • go.mod, go.sum → release-toolchain, release-archives (as well).
  • cmd/**, internal/**, tools/preparation-vectors/** → go-vet, build-pinned, manual-gate, unit-tests, chain-tests, build.
  • cmd/** → release-programs (as well).
  • vectors/**, docs/MAPPING-V2.md, docs/design/*.json → build-pinned, manual-gate, unit-tests, chain-tests.
  • openapi.json → openapi, build-pinned, manual-gate, unit-tests, chain-tests.
  • scripts/checks/{build-pinned,manual-gate,unit-tests,chain-tests}.sh → build-pinned, manual-gate, unit-tests, chain-tests.
  • THIRD_PARTY_NOTICES, tools/third_party_notices.py → third-party-notices.
  • tools/release_archives.py, tools/test_release_archives.py → release-archives.
  • .goreleaser.yml, scripts/checks/release-programs.sh → release-programs.
  • scripts/checks/release-toolchain.sh → release-toolchain.
  • *.md, docs/**, LICENSE, deploy/**, scripts/checks/local-paths.sh, scripts/sync-agent-docs.sh, scripts/dev/handover_check.sh → the three whole-tree steps only.

manual-gate, unit-tests and chain-tests run against the binaries build-pinned writes to .ci/bin, which a fresh CI checkout does not have. So every rule that selects one of them selects build-pinned too.

Mapped broad on purpose:

  • Every .go file selects all the Go steps (and third-party-notices), tests and tools/preparation-vectors included.
  • Every file under cmd/** and internal/**, not only testdata/, selects go-vet and build as well as the test steps. That covers a future //go:embed.
  • vectors/**, openapi.json, docs/MAPPING-V2.md and docs/design/*.json select manual-gate and chain-tests too. The trace shows that the fixed test lists of those two steps read only internal/runner/testdata/**, docs/design/manual-admission-wire.json (manual-gate) and Go files.
  • go.mod and go.sum select release-archives, although its test builds a synthetic module.

Left unmapped on purpose (whole list):

  • .github/workflows/**: ci.yml names the toolchains, and release.yml is read by release-toolchain and decides the release.
  • .gitattributes and .gitignore. The go command reads .gitignore during go-fmt, build and unit-tests.
  • Any file in a new place, for example a new top-level directory, a new tools/*.py or a nested go.mod outside cmd/ and internal/.

jpdev.json, dev.json, scripts/dev/check.sh and scripts/dev/changed_checks.py always select the whole list. Every other tracked path matches a rule (checked against git ls-files), and every dev.json step appears in at least one rule.

Simulated pull requests (selection only, scratch copy)

Each case is one commit on top of this branch, run through scripts/dev/changed_checks.py --base <branch head>. The count is out of 15 steps. In the CI Runner jobs, --skip then removes any of the four release steps, and Release contents runs those four on every pull request.

  • (a) Core source, internal/runner/workflow_read.go: 11 of 15. local-paths, agent-docs, diff-check, go-fmt, go-vet, build-pinned, manual-gate, unit-tests, chain-tests, build, third-party-notices. In the Runner jobs that is all 11 non-release steps.
  • (b) Test data, internal/runner/testdata/triage.pack.json: 9 of 15. local-paths, agent-docs, diff-check, go-vet, build-pinned, manual-gate, unit-tests, chain-tests, build.
  • (c) Schema, openapi.json: 8 of 15. local-paths, agent-docs, diff-check, openapi, build-pinned, manual-gate, unit-tests, chain-tests. docs/design/manual-admission-wire.json and vectors/preparation/README.md each select 7 (the same without openapi).
  • (d) Docs, docs/releasing.md: 3 of 15. local-paths, agent-docs, diff-check. README.md selects the same three.
  • (e) go.mod: 13 of 15. Every step except openapi and release-programs.

Other cases: .goreleaser.yml selects the whole-tree three plus release-programs; tools/test_release_archives.py selects the three plus release-archives; .github/workflows/release.yml selects the whole list.

End to end, a docs-only commit run with the CI form (check.sh --all --changed <base> --skip <release steps>) ran exactly local-paths, agent-docs and diff-check.

Checks

scripts/dev/check.sh --all --changed origin/main on this branch selected the whole list, because jpdev.json changed: 15 passed, 0 failed, 0 skipped, 0 not run (unit-tests 612 s). This is the run that was traced.

🤖 Generated with Claude Code

…mapping)

jpdev.json gains a `changed` mapping from each dev.json step's inputs. On a
pull request the Runner jobs run `check.sh --all --changed origin/<base>`
less the four release steps; a push to main and the release call keep the
whole list. Release contents is unchanged.

Signed-off-by: kikashy <35789537+kikashy@users.noreply.github.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@kikashy

kikashy commented Oct 26, 2026

Copy link
Copy Markdown
Contributor Author

Review record: runner #177 (changed-path mapping, PR Runner jobs on --changed)

Narrow review at cfb7052 over base 8d1bf14 (4 files, +94/-2); same-vendor review, not a cross-vendor claim.
Every input I derived for the 15 steps is covered, and on a PR --skip removes only the four release steps. merge: yes.

Uncovered (step, input) pairs

Step Input Severity Rule to add
none

What the steps read: the Go tests read files outside their packages only at ../../openapi.json, ../../docs/MAPPING-V2.md, ../../docs/design/{manual-admission-wire,executor-ownership-boot}.json, ../../vectors/preparation/** and ../../internal/runner/testdata/**. No test reads any other doc, .github/, deploy/, tools/, go.mod or the repository through git. There is no //go:embed. manual-gate and chain-tests are fixed subsets of the same packages, and every test rule selects them together with build-pinned. local-paths, agent-docs and diff-check are in every rule, so a PR run is never empty. third-party-notices hard-codes its target list (it does not read .goreleaser.yml). The release steps are skipped in the Runner jobs, and Release contents runs them on every commit.

What was simulated (vendored runner, scratch clone, origin/main set to the PR head)

  • changed_checks.py gave the whole list for: jpdev.json, dev.json, scripts/dev/check.sh, changed_checks.py, ci.yml, release.yml, .gitattributes, and a file in a new directory.
  • Scoped selections: go.mod 13/15, go.sum 13/15, a core Go file 11/15, a cmd Go file 12/15, a testdata pack 9/15, an untracked new testdata file 9/15, openapi.json 8/15, docs/releasing.md 3/15.
  • Each of these selects 7/15 (the three whole-tree steps, build-pinned and the three test steps): MAPPING-V2.md, a design wire json, a vector file, a vector deletion, a vector renamed into docs/, a nested vector README, unit-tests.sh, build-pinned.sh.
  • tools/preparation-vectors selects 11/15. deploy/, README.md, AGENTS.md and a design .md select 3/15.
  • The PR's selections I checked: core Go 11/15, testdata 9/15, openapi 8/15, releasing.md 3/15 and go.mod 13/15 all match.
  • check.sh --all --changed origin/main --skip <four release steps> was run on a stub manifest (each step runs echo, kept outside the clone) for 11 change kinds. In each, the steps that ran were exactly the selection minus the four release steps; nothing else was dropped. The push branch (--all --skip) ran all 11 non-release steps.
  • If changed_checks refuses, check.sh exits 2, so the job fails rather than passing silently.

ci.yml against templates/ci-check.yml

  • Matches the template: the env: EVENT/BASE_REF and if [ "$EVENT" = pull_request ] form, and fetch-depth: 0 on the Runner checkout.
  • workflow_call from release.yml carries the caller's push event, so it takes the --all branch.
  • Unchanged: the "manifest parses" step, the Release contents job and release.yml; there is no CI evidence file.

Public text

  • No machine-local paths, personal names or organisations in jpdev.json, ci.yml, AGENTS.md or the PR body.
  • AGENTS.md and CLAUDE.md are byte-identical. Commit is DCO-signed with the noreply author.

merge: yes

@kikashy
kikashy merged commit 28b0c81 into main Oct 26, 2026
5 checks passed
@kikashy
kikashy deleted the changed-mapping branch October 26, 2026 12:12
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.

1 participant