diff --git a/.cursor/skills/plan-prompts/SKILL.md b/.cursor/skills/plan-prompts/SKILL.md index 7c02930..b296f56 100644 --- a/.cursor/skills/plan-prompts/SKILL.md +++ b/.cursor/skills/plan-prompts/SKILL.md @@ -63,8 +63,8 @@ Per [`propose/completed/TEST-SUITE-FAST-LOOP-PROPOSE.md`](../../../propose/compl - Add a markdown section with the **exact heading** `## Tests to run (iteration loop)` inside the fenced **Prompt** block, **immediately after** `## Deliverables` and **before** `## Tests`. - Content: bullet list of `tests/test_*.py` paths, each with a **one-line rationale** tied to the PR’s code paths. -- **Merge gate:** state that the **full** default suite (`pytest tests`, `JAVA_CODEBASE_RAG_RUN_HEAVY` unset or `0`) is enforced at merge time by CI once the repo workflow exists; the iteration list is for speed only. -- **Docs-only (UC15):** if the PR is documentation-only with no test signal, use an explicit empty pattern, e.g. a single bullet `*(none — docs-only change; full suite still runs in CI.)*` — do not invent a fake file list. +- **Merge gate:** state that CI enforces a green `test` check on every PR; code changes run the full default suite (`pytest tests`, `JAVA_CODEBASE_RAG_RUN_HEAVY` unset or `0`), docs-only PRs skip pytest but still need a green `test` job; the iteration list is for speed only. +- **Docs-only (UC15):** if the PR is documentation-only with no test signal, use an explicit empty pattern, e.g. a single bullet `*(none — docs-only change; CI test job passes but pytest is skipped.)*` — do not invent a fake file list. This heading must stay verbatim so reviewers (and the repo **`pr-review`** skill in `.cursor/skills/pr-review/`) can grep for it. @@ -108,12 +108,12 @@ Read the PR-XX section first. The plan is the source of truth. ## Tests to run (iteration loop) -Run only these files during local iteration; full suite is the merge gate (CI on PR + `master`). +Run only these files during local iteration; CI `test` on PR + `master` is the merge gate (full pytest when code changes). - `tests/test_.py` — - `tests/test_.py` — -Docs-only PRs (UC15): use a single bullet such as *(none — docs-only change; full suite still runs in CI.)* instead of inventing paths. +Docs-only PRs (UC15): use a single bullet such as *(none — docs-only change; CI test job passes but pytest is skipped.)* instead of inventing paths. ## Tests Run: `` diff --git a/.cursor/skills/pr-review/SKILL.md b/.cursor/skills/pr-review/SKILL.md index 9a60f34..5139376 100644 --- a/.cursor/skills/pr-review/SKILL.md +++ b/.cursor/skills/pr-review/SKILL.md @@ -31,15 +31,15 @@ The PR body or thread must include **pasteable proof** that the author ran the f - A vague “ran pytest” with no file list and no exit code. - Substituting a different file list than the prompt declared, without explanation. -If the task prompt declared **docs-only** (empty iteration list per UC15), subset evidence is: state that no test files were required for iteration, and still require **full-suite CI green** below. +If the task prompt declared **docs-only** (empty iteration list per UC15), subset evidence is: state that no test files were required for iteration, and still require a **green `test` CI** run below (pytest may be skipped when only documentation paths changed). -**Subset green does not replace the merge gate:** If full-suite CI is red, the PR is not merge-ready even when the declared subset passed locally. +**Subset green does not replace the merge gate:** If the required `test` CI check is red (or missing), the PR is not merge-ready even when the declared subset passed locally. ## 3. Test evidence — full suite / CI (mandatory when repo CI exists) -When this repository has a required GitHub Actions workflow that runs the **full** default suite (e.g. `pytest tests` with `JAVA_CODEBASE_RAG_RUN_HEAVY` unset or `0`): +When this repository has a required GitHub Actions workflow (`.github/workflows/test.yml`): -- [ ] The PR description or review comment includes a **link** to a **green** Actions run for the **full** suite on **this PR** at the **same commit** being reviewed (or the tip the reviewer approves). +- [ ] The PR description or review comment includes a **link** to a **green** `test` Actions run on **this PR** at the **same commit** being reviewed (or the tip the reviewer approves). For code changes, the run must include `pytest tests` with `JAVA_CODEBASE_RAG_RUN_HEAVY` unset or `0`. For docs-only PRs, a green run with pytest skipped is sufficient. If CI is not yet enabled for the repo, note that in the review; once the workflow exists, **withhold approval** until both §2 and §3 are satisfied. diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 1433b12..3c90c1f 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -11,15 +11,51 @@ jobs: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 + with: + fetch-depth: 0 + - uses: dorny/paths-filter@v3 + id: changes + with: + filters: | + docs: + - '**/*.md' + - '**/*.mdc' + - 'docs/**' + - 'propose/**' + - 'plans/**' + - 'reports/**' + - '.cursor/**' + - 'AGENTS.md' + - 'README.md' + - 'CODEBASE_REQUIREMENTS.md' + - '.github/CODEOWNERS' + code: + - '**/*.py' + - 'requirements.txt' + - 'pyproject.toml' + - 'pytest.ini' + - 'mcp.json.example' + - '.gitignore' + - '.github/workflows/**' + - 'tests/**' + - '!tests/**/*.md' + - 'automation/**' + - '!automation/**/*.md' - uses: actions/setup-python@v5 + if: steps.changes.outputs.code == 'true' with: python-version: "3.11" - name: Install dependencies + if: steps.changes.outputs.code == 'true' run: | python -m pip install --upgrade pip pip install -r requirements.txt pip install -e . - name: Run tests + if: steps.changes.outputs.code == 'true' env: JAVA_CODEBASE_RAG_RUN_HEAVY: "0" run: pytest tests -v + - name: Skip tests (docs-only) + if: steps.changes.outputs.code != 'true' + run: echo "Docs-only change; pytest skipped." diff --git a/tests/README.md b/tests/README.md index 96a5f18..c9e86e5 100644 --- a/tests/README.md +++ b/tests/README.md @@ -33,9 +33,9 @@ cd /path/to/java-codebase-rag ## CI merge gate and fixture tiers -**Merge gate (mechanical):** [`.github/workflows/test.yml`](../.github/workflows/test.yml) runs `pytest tests` with `JAVA_CODEBASE_RAG_RUN_HEAVY=0` on every pull request and on every push to `master`. Branch protection on `master` requires the `test` status check to pass before merge and disables force-push. Break-glass policy: `enforce_admins: false` so the sole maintainer can bypass for emergency hotfixes — explain the bypass in the merge commit. +**Merge gate (mechanical):** [`.github/workflows/test.yml`](../.github/workflows/test.yml) always runs the `test` job on every pull request and on every push to `master`. When any **source** path changes (Python, deps, `pytest.ini`, `mcp.json.example`, `.gitignore`, workflows, non-markdown under `tests/` or `automation/`), it runs `pytest tests` with `JAVA_CODEBASE_RAG_RUN_HEAVY=0`. Documentation-only changes (`propose/`, `plans/`, `reports/`, `.cursor/`, `docs/`, `**/*.md`, etc.) still produce a green `test` check but skip pytest. Branch protection on `master` requires the `test` status check to pass before merge and disables force-push. Break-glass policy: `enforce_admins: false` so the sole maintainer can bypass for emergency hotfixes — explain the bypass in the merge commit. -**Iteration subset (convention):** During implementation, authors name a `pytest` file subset inside each per-PR execution prompt (for example in `plans/CURSOR-PROMPTS-*.md`). The repo **[`plan-prompts`](../.cursor/skills/plan-prompts/SKILL.md)** skill (`.cursor/skills/plan-prompts/`) requires a **`## Tests to run (iteration loop)`** section in that scaffold, placed **after Deliverables and before Tests**. Reviewers follow the repo **[`pr-review`](../.cursor/skills/pr-review/SKILL.md)** skill (`.cursor/skills/pr-review/`): pasted subset command + exit code, plus a green full-suite CI link from the now-real merge gate documented above. Canonical skill sources live under `.cursor/skills/`; you may copy them into `~/.cursor/skills/` if your Cursor setup loads personal skills only. See [`propose/completed/TEST-SUITE-FAST-LOOP-PROPOSE.md`](../propose/completed/TEST-SUITE-FAST-LOOP-PROPOSE.md) and [`plans/completed/PLAN-TEST-SUITE-FAST-LOOP.md`](../plans/completed/PLAN-TEST-SUITE-FAST-LOOP.md). +**Iteration subset (convention):** During implementation, authors name a `pytest` file subset inside each per-PR execution prompt (for example in `plans/CURSOR-PROMPTS-*.md`). The repo **[`plan-prompts`](../.cursor/skills/plan-prompts/SKILL.md)** skill (`.cursor/skills/plan-prompts/`) requires a **`## Tests to run (iteration loop)`** section in that scaffold, placed **after Deliverables and before Tests**. Reviewers follow the repo **[`pr-review`](../.cursor/skills/pr-review/SKILL.md)** skill (`.cursor/skills/pr-review/`): pasted subset command + exit code, plus a green `test` CI link from the merge gate documented above (full pytest for code changes; pytest skipped for docs-only PRs). Canonical skill sources live under `.cursor/skills/`; you may copy them into `~/.cursor/skills/` if your Cursor setup loads personal skills only. See [`propose/completed/TEST-SUITE-FAST-LOOP-PROPOSE.md`](../propose/completed/TEST-SUITE-FAST-LOOP-PROPOSE.md) and [`plans/completed/PLAN-TEST-SUITE-FAST-LOOP.md`](../plans/completed/PLAN-TEST-SUITE-FAST-LOOP.md). **Fixture tiers (PR-1):**