Skip to content

Fix false-positive SecPass: positive-evidence rule, evidence model, real-log regression suite#17

Open
compaluca wants to merge 5 commits into
LeiLiLab:mainfrom
compaluca:fix/evaluation-harness-v2
Open

Fix false-positive SecPass: positive-evidence rule, evidence model, real-log regression suite#17
compaluca wants to merge 5 commits into
LeiLiLab:mainfrom
compaluca:fix/evaluation-harness-v2

Conversation

@compaluca

Copy link
Copy Markdown

Fix false-positive SecPass: positive-evidence rule, evidence model, real-log regression suite

Supersedes #12. Same goal — make SecPass a positive claim rather than a
negative one — but rebuilt cleanly from main against a TDD catalog of real
captured test logs, with a single production entry point, hermetic tests, and
an explicit evidence model. Full detail in CHANGES.md.

Why a new PR instead of continuing #12

What's included

  • susvibes/runners/TestRunnerAdapter + SessionResult; Pytest /
    Django / Fallback adapters; detect_runner() from the Dockerfile CMD.
  • tasks.evaluate_run_from_logs — one decision path shared by
    Task.evaluate and the tests. _decide_pass returns
    (passed, reason, evidence, likely_passed, positive_sec_evidence).
  • 3-tier evidence model (full / partial / count_only) recorded in
    report.json — descriptive only, never gates the decision — plus
    get_summary evidence_stats aggregation for auditability.
  • Hermetic regression suite — 16 real-log cases (R01–R16) + a vendored
    endor-v1 dataset slice (test_patch + expected_failures), so the suite is
    immune to upstream dataset drift and needs no external path.
  • Synthetic unit tests_decide_pass evidence matrix, SessionResult,
    the diff parser, adapter per-test extraction + match_test, evidence_stats.

Deliberate deviations from #12 (documented in CHANGES.md)

  • Explicit sec-test failures are gated before the abort check (R01).
  • "Nothing parsed" → no_test_summary unless a hard-kill/timeout marker is
    present → session_aborted:CRASH (R03–R05 vs R06–R07).
  • positive_sec_evidence / no_positive_sec_evidence flag passes that lack a
    verified PASS (R09).

Not included (deferred, with justification in CHANGES.md)

  • detect_runner_from_output wiring — quantified at 0/343 impact on the
    real count_only set, so deliberately not wired.
  • A reconciliation-gated unittest/zope per-test extractor — prototype resolves
    94/343 count_only runs and surfaces 70 hidden sec failures; recommended
    next step.
  • Django get_verbose_command / verbose-flag injection.

Test plan

  • 16 real-log regression cases (R01–R16) asserted through production
    evaluate_run_from_logs
  • 31 synthetic unit tests (tests/test_evaluation_logic.py)
  • python -m pytest tests/61 passed, 3 skipped (R14–R16 opt out of
    the pytest-only count check; decisions still asserted via the catalog)
  • Hermetic — no Docker, no external dataset path
  • Re-baseline the 200-run sec numbers once a dialect extractor lands

compaluca added 5 commits June 9, 2026 08:16
Structured expect blocks for parser counts and SecPass decisions on real
log fixtures. No production SecPass changes yet; tests fail until
susvibes.runners and evaluate_run_from_logs land in Phase 2.
Port the language-agnostic evaluation engine from the reference harness:

- susvibes/runners/: TestRunnerAdapter base, pytest (Fix 9 _parse_counts,
  per-test extraction), django, and detect_runner/FallbackAdapter/Zope.
- tasks.py: evaluate_run_from_logs as the single SecPass/FuncPass entry point;
  _decide_pass + _resolve_sec (variant failures, likely_passed,
  positive_sec_evidence); Task.evaluate wired to it. Sec-variant failures gate
  before the abort check (R01); no-summary vs killed disambiguation (R03-R07).
- env.py: create_container(environment=...) so PYTEST_ADDOPTS=-v reaches the
  container for per-test evidence.
- constants.py: PREMATURE_ABORT_PATTERNS (maxfail banner).
…ce_stats

Make the regression suite hermetic and broaden Fix 11 coverage:

- Namespace fixtures under tests/fixtures/v1/ (tied to the endor v1 dataset).
- Vendor a minimal in-repo slice (instance_id + test_patch + expected_failures)
  for the catalog instances into fixtures/v1/dataset_records.jsonl (~96 KB), and
  resolve records from it first so upstream dataset drift can't break the suite.
  The external v1 path / stale datasets/default are gap-fillers only.
- Add count_only regression fixtures R14 (plone.namedfile, PASS), R15
  (zope.testrunner, FAIL), R16 (lshell unittest, FAIL) — the previously
  untested evidence tier, across non-pytest runners.
- get_summary: aggregate evidence tiers into evidence_stats (reporting only,
  no decision change) for SecPass auditability.
Port test_evaluation_logic.py selectively, adapted to this branch's API
(_decide_pass returns a 5-tuple with positive_sec_evidence; reasons include
no_positive_sec_evidence / no_test_summary). 31 tests covering:

- _decide_pass 3-tier evidence matrix: full / partial / count_only (incl.
  FallbackAdapter), func -> empty evidence, abort/no-summary, and the
  sec-failure-before-abort gate order (R01-style).
- SessionResult helpers; extract_added_tests diff parser; PytestAdapter and
  DjangoTestAdapter per-test extraction + match_test; get_verbose_env.
- get_summary evidence_stats aggregation (reporting only, ratios unchanged).
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