diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 0a08df9..e0c7f43 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -78,7 +78,8 @@ jobs: - name: Mutation test (storage_json) run: | timeout 900 cargo mutants -f '*storage_json*' 2>&1 | tee mutation.log || true - MISSED=$(grep -E '[0-9]+ missed' mutation.log | tail -1 | grep -oE '[0-9]+' | head -1 || echo "0") + # Extract the missed count (e.g. "14 mutants ... 2 missed, 9 caught" -> 2), not the total + MISSED=$(grep -E '[0-9]+ missed' mutation.log | tail -1 | sed -n 's/.* \([0-9][0-9]*\) missed.*/\1/p' | head -1 || echo "0") echo "missed=$MISSED" >> "$GITHUB_OUTPUT" id: mutation - name: Check mutation baseline diff --git a/README.md b/README.md index 4156f10..fcfc276 100644 --- a/README.md +++ b/README.md @@ -1002,6 +1002,8 @@ The summary includes: Contributions are welcome! Please open an issue first to discuss what you would like to change. +**PR workflow:** Open a PR → ensure CI is green (version, lint, security, test, mutation, review) → merge when ready. Use a short test plan in the PR description. Small, focused PRs are preferred. + ### Local Development Checks Enable the repository-managed git hooks after cloning: diff --git a/docs/mutation-testing.md b/docs/mutation-testing.md index fc1c170..10cc9f4 100644 --- a/docs/mutation-testing.md +++ b/docs/mutation-testing.md @@ -15,7 +15,7 @@ cargo mutants -f '*storage_pg*' cargo mutants -f '*cost*' ``` -CI runs mutation on `*storage_json*` with a timeout; see [CI job](#ci) below. +CI runs mutation on `*storage_json*` with a timeout; see [CI job](#ci) below. The `*state*` and `*storage_pg*` globs are not run in CI (too many mutants, longer runtime); run locally when auditing those areas. ## Known equivalent / accepted mutants @@ -37,6 +37,17 @@ After adding targeted tests (refresh_summary, get_event_stats exact aggregates/s If new mutants appear in these regions, add assertions that would fail on the wrong operator/formula, or add them to this table with a one-line rationale. +### state.rs and storage_pg.rs (local only) + +Mutation on `*state*` and `*storage_pg*` is not in CI. Summary from a local run (interrupted; full run is slow): + +| Glob | Mutants | Notes | +|---------------|---------|--------| +| `*state*` | ~90 | Many missed: arithmetic in cost/age, `load_reviews_from_disk`, `mark_running` / `complete_review` / `fail_review` / `prune_old_reviews` (no-op or wrong operator), `current_timestamp`, `ReviewEventBuilder`. Killing these would need more unit tests or integration tests that assert side effects. | +| `*storage_pg*`| ~67 | Many missed: `migrate`, `is_empty`, `parse_comment_status`, `save_review` / `get_review` / `list_reviews` / `delete_review` / `save_event` / `list_events` (stubbed return or wrong operator). Would need PostgreSQL-backed tests or contract tests to kill. | + +To re-run: `cargo mutants -f '*state*'` and `cargo mutants -f '*storage_pg*'` (allow several minutes each). + ## Pre-push vs CI - **Pre-push** (`.githooks/pre-push`): Runs unit tests, `cargo audit`, web build+test. Does *not* run mutation (too slow for every push). diff --git a/src/commands/eval/runner/execute/dag.rs b/src/commands/eval/runner/execute/dag.rs index 39f9aa6..14b7fba 100644 --- a/src/commands/eval/runner/execute/dag.rs +++ b/src/commands/eval/runner/execute/dag.rs @@ -188,6 +188,7 @@ fn stage_hints(stage: EvalFixtureStage) -> DagNodeExecutionHints { side_effects: false, subgraph: Some("review_pipeline".to_string()), }, + // Linear chain (each depends on previous); parallelizable kept for consistency / future DAG shape. EvalFixtureStage::ExpectationMatching | EvalFixtureStage::CommentCountValidation | EvalFixtureStage::BenchmarkMetrics => DagNodeExecutionHints {