From 3c4d315be7f05dda1269b1df35bde3ca2453e521 Mon Sep 17 00:00:00 2001 From: Claude Date: Wed, 21 Oct 2026 20:56:55 -0400 Subject: [PATCH 1/5] Run every test file a change touches in the merge queue Smoke only collects the suite, so two PRs on 2026-10-21 reported a touched test green while it failed (2510, 2560) and nothing hosted ran it. touched-tests runs the added or modified test files of the change against the base, with the pinned native package prepared (plan 9.5). Co-Authored-By: Claude Opus 5.5 Claude-Session: https://claude.ai/code/session_01AeUaZjvChAcb6qAd6zPYmw --- .github/workflows/debt-ratchet.yml | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/.github/workflows/debt-ratchet.yml b/.github/workflows/debt-ratchet.yml index 9958d20ee3..33506bf779 100644 --- a/.github/workflows/debt-ratchet.yml +++ b/.github/workflows/debt-ratchet.yml @@ -47,6 +47,36 @@ jobs: - name: Stack clients import only modules Core has run: python tools/module_layers.py --check + touched-tests: + # A pull request that edits a test file runs it: two PRs on 2026-10-21 reported a touched + # test green while it failed (2510, 2560), and smoke only collects the suite. + name: touched-tests + runs-on: ubuntu-latest + timeout-minutes: 20 + steps: + - uses: actions/checkout@v4 + with: + submodules: recursive + fetch-depth: 0 + - uses: actions/setup-python@v5 + with: + python-version-file: pyproject.toml + - name: Install agent-comms and test dependencies + run: python -m pip install -e src/agent_comms/skills/refactor-audit -e '.[dev]' + - name: Prepare pinned native Pi + uses: ./.github/actions/prepare-native + - name: Install locked runtime host dependencies + working-directory: src/agent_comms + run: npm ci --ignore-scripts --omit=dev --no-audit --no-fund + - name: Run every test file the change touches + env: + BASE: ${{ github.event.merge_group.base_sha || github.event.pull_request.base.sha }} + run: | + mapfile -t touched < <(git diff --name-only --diff-filter=AM "$BASE" HEAD -- 'tests/test_*.py' 'tests/**/test_*.py') + if [ ${#touched[@]} -eq 0 ]; then echo "no test file touched"; exit 0; fi + printf '%s\n' "${touched[@]}" + pytest -q -p no:cacheprovider "${touched[@]}" + native-scripts: name: native-scripts runs-on: ubuntu-latest From 6169e57290fd75dc4cec263282ea9d6786cf1dc4 Mon Sep 17 00:00:00 2001 From: Claude Date: Wed, 21 Oct 2026 22:44:23 -0400 Subject: [PATCH 2/5] touched-tests: run the npm step with plain bash from its working directory The workflow's default shell is .github/run-step.sh, a path relative to the checkout root, so a step with working-directory src/agent_comms could not find it (exit 127), as ci.yml already notes for the same step. Co-Authored-By: Claude Opus 5.5 Claude-Session: https://claude.ai/code/session_01AeUaZjvChAcb6qAd6zPYmw --- .github/workflows/debt-ratchet.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/debt-ratchet.yml b/.github/workflows/debt-ratchet.yml index 33506bf779..df3535be10 100644 --- a/.github/workflows/debt-ratchet.yml +++ b/.github/workflows/debt-ratchet.yml @@ -67,6 +67,8 @@ jobs: uses: ./.github/actions/prepare-native - name: Install locked runtime host dependencies working-directory: src/agent_comms + # The default shell is a script path relative to the checkout root. + shell: bash run: npm ci --ignore-scripts --omit=dev --no-audit --no-fund - name: Run every test file the change touches env: From fb78cc2f1d5063ae85c9ace5cb9683a6c194f009 Mon Sep 17 00:00:00 2001 From: Claude Date: Wed, 21 Oct 2026 22:50:26 -0400 Subject: [PATCH 3/5] touched-tests: install the host dependencies with --prefix from the checkout root Keeps the workflow's one default shell instead of overriding it for one step. Co-Authored-By: Claude Opus 5.5 Claude-Session: https://claude.ai/code/session_01AeUaZjvChAcb6qAd6zPYmw --- .github/workflows/debt-ratchet.yml | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/.github/workflows/debt-ratchet.yml b/.github/workflows/debt-ratchet.yml index df3535be10..b9baab3998 100644 --- a/.github/workflows/debt-ratchet.yml +++ b/.github/workflows/debt-ratchet.yml @@ -66,10 +66,7 @@ jobs: - name: Prepare pinned native Pi uses: ./.github/actions/prepare-native - name: Install locked runtime host dependencies - working-directory: src/agent_comms - # The default shell is a script path relative to the checkout root. - shell: bash - run: npm ci --ignore-scripts --omit=dev --no-audit --no-fund + run: npm ci --prefix src/agent_comms --ignore-scripts --omit=dev --no-audit --no-fund - name: Run every test file the change touches env: BASE: ${{ github.event.merge_group.base_sha || github.event.pull_request.base.sha }} From a5ae91a20f352f4de11f536efc59a3e569f92265 Mon Sep 17 00:00:00 2001 From: Tristan Simas Date: Fri, 23 Oct 2026 02:02:58 -0400 Subject: [PATCH 4/5] touched-tests: bound the run with timeout and faulthandler, count renames The touched files run under `timeout 15m` with `-o faulthandler_timeout=60` so a hang prints its stacks and fails by name inside the job budget. A renamed test file is a touched one (--diff-filter=AMR), and a failing git diff now fails the step instead of being swallowed by process substitution. Co-Authored-By: Claude Opus 5.5 --- .github/workflows/debt-ratchet.yml | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/.github/workflows/debt-ratchet.yml b/.github/workflows/debt-ratchet.yml index f39800db24..58325854af 100644 --- a/.github/workflows/debt-ratchet.yml +++ b/.github/workflows/debt-ratchet.yml @@ -71,10 +71,11 @@ jobs: env: BASE: ${{ github.event.merge_group.base_sha || github.event.pull_request.base.sha }} run: | - mapfile -t touched < <(git diff --name-only --diff-filter=AM "$BASE" HEAD -- 'tests/test_*.py' 'tests/**/test_*.py') - if [ ${#touched[@]} -eq 0 ]; then echo "no test file touched"; exit 0; fi + changed=$(git diff --name-only --diff-filter=AMR "$BASE" HEAD -- 'tests/test_*.py' 'tests/**/test_*.py') + if [ -z "$changed" ]; then echo "no test file touched"; exit 0; fi + mapfile -t touched <<<"$changed" printf '%s\n' "${touched[@]}" - pytest -q -p no:cacheprovider "${touched[@]}" + timeout 15m pytest -q -p no:cacheprovider -o faulthandler_timeout=60 "${touched[@]}" native-scripts: name: native-scripts From 065977a60c52ea6527bd0d6ee8bbf504c2553107 Mon Sep 17 00:00:00 2001 From: Tristan Simas Date: Fri, 23 Oct 2026 02:06:43 -0400 Subject: [PATCH 5/5] CI: derive Python and host-dependency setup from composite actions smoke, touched-tests and ci.yml's test job each restated the same Python setup (setup-python from pyproject.toml plus the editable Core, refactor-audit and dev install), and touched-tests and ci.yml's test job each restated the locked runtime host `npm ci` in src/agent_comms. The copies already drifted: one used working-directory with a shell override, the other --prefix. .github/actions/prepare-python now owns the Python setup. The host install moves into prepare-native behind `host-dependencies: "true"`: that action already owns the job's Node toolchain and its locked npm installs, and the host packages are pi-durable, pi-ai and chord, which the native runtime imports from beside Core. The default stays off, so native-scripts and ci.yml's stack job are unchanged. Dropped with the copy: ci.yml test's `pip install --upgrade pip`. Co-Authored-By: Claude Opus 5.5 --- .github/actions/prepare-native/action.yml | 9 +++++++++ .github/actions/prepare-python/action.yml | 11 +++++++++++ .github/workflows/ci.yml | 21 +++++---------------- .github/workflows/debt-ratchet.yml | 20 +++++++------------- 4 files changed, 32 insertions(+), 29 deletions(-) create mode 100644 .github/actions/prepare-python/action.yml diff --git a/.github/actions/prepare-native/action.yml b/.github/actions/prepare-native/action.yml index b584a86e72..e209da771d 100644 --- a/.github/actions/prepare-native/action.yml +++ b/.github/actions/prepare-native/action.yml @@ -5,6 +5,10 @@ inputs: description: Installed Core interpreter command or executable path required: false default: python + host-dependencies: + description: Also install the locked runtime host packages Core's durable host imports from beside it (src/agent_comms) + required: false + default: "false" runs: using: composite steps: @@ -18,3 +22,8 @@ runs: - name: Prepare pinned native Pi shell: bash run: stack/bin/prepare-pi-native --python "$(command -v '${{ inputs.python }}')" + - name: Install locked runtime host dependencies + if: inputs.host-dependencies == 'true' + shell: bash + working-directory: src/agent_comms + run: npm ci --ignore-scripts --omit=dev --no-audit --no-fund diff --git a/.github/actions/prepare-python/action.yml b/.github/actions/prepare-python/action.yml new file mode 100644 index 0000000000..919a0ca00c --- /dev/null +++ b/.github/actions/prepare-python/action.yml @@ -0,0 +1,11 @@ +name: Prepare Python +description: Set up the interpreter pyproject.toml names and install Core, the refactor-audit skill and the test dependencies, editable. +runs: + using: composite + steps: + - uses: actions/setup-python@v5 + with: + python-version-file: pyproject.toml + - name: Install agent-comms and test dependencies + shell: bash + run: python -m pip install -e src/agent_comms/skills/refactor-audit -e '.[dev]' diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 38e53fe931..6191c7f3bd 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -72,18 +72,13 @@ jobs: with: submodules: recursive - - name: Setup Python - uses: actions/setup-python@v5 - with: - python-version-file: pyproject.toml + - name: Prepare Python + uses: ./.github/actions/prepare-python - - name: Install dependencies - run: | - python -m pip install --upgrade pip - pip install -e src/agent_comms/skills/refactor-audit -e ".[dev]" - - - name: Prepare pinned native Pi + - name: Prepare pinned native Pi and its runtime host dependencies uses: ./.github/actions/prepare-native + with: + host-dependencies: "true" - name: Check the native pin matches the tree run: pytest tests/test_native_pin.py --no-cov -q @@ -95,12 +90,6 @@ jobs: run: | npm install -g --prefix "$HOME/.local/pi-npm" --ignore-scripts --no-audit --no-fund @earendil-works/pi-coding-agent@0.85.1 - # The durable host imports pi-durable, pi-ai and chord from beside it. - - name: Install locked runtime host dependencies - working-directory: src/agent_comms - shell: bash - run: npm ci --ignore-scripts --omit=dev --no-audit --no-fund - - name: Run tests with coverage (85% enforced on Linux) if: matrix.os == 'ubuntu-latest' run: | diff --git a/.github/workflows/debt-ratchet.yml b/.github/workflows/debt-ratchet.yml index 58325854af..9ada8de4d7 100644 --- a/.github/workflows/debt-ratchet.yml +++ b/.github/workflows/debt-ratchet.yml @@ -21,11 +21,8 @@ jobs: - uses: actions/checkout@v4 with: submodules: recursive - - uses: actions/setup-python@v5 - with: - python-version-file: pyproject.toml - - name: Install agent-comms and test dependencies - run: python -m pip install -e src/agent_comms/skills/refactor-audit -e '.[dev]' + - name: Prepare Python + uses: ./.github/actions/prepare-python - name: Compile production and tools run: python -m compileall -q src tools - name: Import every Core and hook module @@ -58,15 +55,12 @@ jobs: with: submodules: recursive fetch-depth: 0 - - uses: actions/setup-python@v5 - with: - python-version-file: pyproject.toml - - name: Install agent-comms and test dependencies - run: python -m pip install -e src/agent_comms/skills/refactor-audit -e '.[dev]' - - name: Prepare pinned native Pi + - name: Prepare Python + uses: ./.github/actions/prepare-python + - name: Prepare pinned native Pi and its runtime host dependencies uses: ./.github/actions/prepare-native - - name: Install locked runtime host dependencies - run: npm ci --prefix src/agent_comms --ignore-scripts --omit=dev --no-audit --no-fund + with: + host-dependencies: "true" - name: Run every test file the change touches env: BASE: ${{ github.event.merge_group.base_sha || github.event.pull_request.base.sha }}