Skip to content

ci: expansion to whole test suite - #44

Draft
suraj-subrahmanyan wants to merge 10 commits into
openJiuwen-Solarfrom
ci/test-regression-gate
Draft

suraj-subrahmanyan wants to merge 10 commits into
openJiuwen-Solarfrom
ci/test-regression-gate

Conversation

@suraj-subrahmanyan

Copy link
Copy Markdown
Collaborator

What this changes

CI already runs. It covers about 30 named files in narrow smoke jobs, out of
887 test files and roughly 7,200 checks. This expands it to all of them, across
nine parallel shards: pytest 0-5, script 0, shell 0-1.

Because several hundred tests are already red, the expanded CI gates on
regressions, not on a pass rate. It records which tests are already failing
by identity, and blocks a pull request that turns a green test red.

The existing smoke jobs are untouched.

The three pieces

scripts/check-test-census.py
Every test file under tests/ either collects under pytest or declares a lane
and a written reason in tests/ci_lanes.json. Anything that is neither fails
the build. Currently 887 files, 0 unclassified — 714 pytest, 155 shell,
14 script, 4 excluded. This is what stops a test from silently falling out of
CI, which is how 39 tests stopped running in August without anyone noticing.

scripts/run-test-shard.py
Runs one shard and emits JUnit. Suite name carries shard identity, testcase name
carries the lane, so a test keeps its identity if the shards are ever
renumbered. Per-test and per-file timeouts with a process-group kill, so a hung
grandchild cannot hold the output pipe open.

scripts/check-test-baseline.py
The gate. Eight blocking verdicts: new failure, baseline addition, stale
baseline entry, unrecorded fix, missing shard, unexpected shard, duplicate
identity, unreadable JUnit.

The known-failure list may only shrink. CI extracts the same file from the base
commit and blocks any entry this branch added, so a test cannot be silenced by
adding it to the list. Deleting or renaming a failing test looks like a stale
entry and is blocked too.

Shard counts live in tests/ci_lanes.json, and both the workflow matrix and the
gate read that one file. A matrix that gains or loses a shard fails the gate
rather than quietly changing what CI covers.

Fixes needed to get the suite running

tests/conftest.py — 313 module names exist in both harness/lib and
harness/tools. The path loop inserted each entry at position 0, reversing its
own tuple and putting tools first, so the suite imported thin CLI wrappers
instead of implementations. That alone produced 101 setup errors in
tests/harness/scenarios.

20 path and state repairs left behind by the August tests/ move: ten shell
tests running cd "$(dirname "$0")/.." that now land in tests/ instead of
harness/, four Python tests reading fixtures through the stale
harness/tests/ copy, two carrying a literal ~/Solar/harness that Path
never expands, and one appending to a tracked fixture on every run.

GAP-006 — the secret scan and shellcheck block pull requests again. Five
key-shaped literals in secret-scrubbing tests are pinned by SHA-256 rather than
excusing the whole gate.

No file is moved, renamed, or deleted. 37 files, +3,915 / −74.

ENFORCING is "false" on this PR

Two things need a real CI run before enforcement is honest:

  • The expanded CI has never run on GitHub Actions. Every measurement so far is
    one laptop, and nine shards on one machine is not nine shards on nine VMs.
  • The known-failure list is provisional. It was recorded from a composed local
    run. Re-running 255 of its 324 entries on a quiet machine showed five that
    pass
    — never product failures, only machine contention. They are not
    hand-removed, because a partial correction would imply the other 319 were
    checked. The file carries "provisional": true.

So this PR's run reports into the job summary and blocks nothing. The baseline
is regenerated from that run and enforcement flipped in a follow-up. It is one
word.

Verification

18 mutations applied to the gate and the highest-risk control paths, all caught
by a named test through its own assertion rather than an import error. Zero
survived. 24 tests guard the gate itself. Negative controls were replayed
against real generated artifacts rather than hand-authored fixture XML.

Known gaps are tracked with IDs in docs/testing/COVERAGE-GAPS.md, including
one weakness left unfixed on purpose: test_pm_dispatch.py detects removal of
the graph status write but not corruption of it, and 2 of 3 mutations survive
it.

313 module names exist in both directories, and for the refactored ones the
tools file is a CLI wrapper around the lib implementation. The path loop
inserted each entry at position 0, reversing its own tuple and putting tools
first, so the suite imported wrappers. That alone caused 101 setup errors in
tests/harness/scenarios.

Asserted by tests/repository/governance/test_import_precedence.py, including
the case where PYTHONPATH already orders tools first.
Runs all 883 runnable test files across nine shards and blocks a pull request
that turns a passing test red. Several hundred tests are already failing, so
the gate compares against a recorded set of known failures rather than a pass
rate. That set may only shrink; CI extracts the same file from the base commit
and rejects any entry the branch added.

- scripts/check-test-census.py   every test file collects or declares a lane
- scripts/run-test-shard.py      runs one shard, emits JUnit
- scripts/check-test-baseline.py eight blocking verdicts

18 adversarial tests cover the gate. Nine mutations reintroducing each bypass
are caught by a named assertion.

ENFORCING is false pending a baseline recorded on CI rather than locally.
The August move relocated tests one directory deeper. Ten shell tests reached
harness/ with `cd "$(dirname "$0")/.."`, which now lands in tests/. Four Python
tests read fixtures through the stale harness/tests/ copy. Two carried a
literal ~/Solar/harness that Path never expands.

test_smoke_run.py appended to a tracked fixture on every run, leaving the
checkout dirty. test_pm_dispatch.py read task_graph.json directly, which no
longer holds node status; it now goes through load_graph.

Adds test_neutralized_record_never_consumable: deleting the applied=False check
from is_gate_consumable survived all 126 existing gate-ledger tests.
Both were excused on pull requests, so a new secret or shellcheck warning
reported and merged.

The five findings behind the secret-scan excuse are fixtures for the scrubber
itself, and are now pinned in .secret-scan-allowlist by rule, SHA-256 and path.
The shellcheck excuse covered one SC2034 on an unused assignment in
lib/installer/common.sh, which is removed.
The previous revision was generated locally from a working tree with 65 files
staged for deletion, so tests that inspect repository state saw a tree that
exists nowhere. That produced 10 missing entries and 8 entries never red on CI.
Net 324 -> 326, matching the run's reported count.

All 10 additions also fail at the base commit with a clean worktree, so none is
a regression from this branch.

ENFORCING stays false for one more run: flipping it in the same change that
rewrote the baseline would make a clean verdict unfalsifiable.
Red tests made each shard exit 1, putting nine failure annotations on every
pull request even when the gate verdict was clean. The step already carried
continue-on-error, so the jobs were green and only the annotations were not.

A shard reports and the gate judges, so the shard now fails only when it
produced no usable JUnit. For the pytest lane, exit 0, 1 and 5 mean the run
worked; 2, 3 and 4 stay fatal.

Four tests cover the exit paths, each confirmed by mutation.
scripts/check-repo-hygiene.sh has been failing on this branch, on
openJiuwen-Solar, and on every pull request against it. It names 21 tracked
paths: 19 under a machine source archive, one harness runtime stderr dump, and
one raw test workbook. Eleven are zero bytes and three are the same spreadsheet
committed three times.

Nothing references them, and all 21 remain in git history.
Python smoke, HF and AI Influence smoke, Harness shell smoke and Verification
release gate ran 32 files between them, all of which the nine shards already
run. Their one unique step, a py_compile of three runtime files, moves to
repository-hygiene.

autosci-premerge-gate stays: test_autosci_phase_c_premerge_readiness.py asserts
the job exists by name. It was failing because 44 generated artifacts under
harness/artifacts/autosci/runs/ were tracked, which its own guard forbids.
Removing them fixes the job and the test, so that test leaves the baseline.

ENFORCING is now true. This change removes four blocking jobs, and leaving the
gate advisory while deleting them would drop protection rather than move it.
Run 87 named every discrepancy in the local baseline; run 88 reported clean
against the corrected one.
The census inspected only Python and shell, then reported 887 files with none
unclassified. Extending it raises the count to 916 and surfaces 34 test files
that nothing executes: 17 TypeScript files no workflow runs, 9 Electron tests
reachable only from a workflow that does not trigger on this branch, 6 Node
files referenced nowhere, and 2 PowerShell files of which CI runs one.

All 34 now carry an excluded lane and a written reason. They are recorded, not
covered.

Also removes seven stale duplicates at the root of tests/, each with a live twin
deeper in the tree. CI ran both copies, and they had drifted:
test-release-checklist.sh was red while test_release_checklist.sh passes. Four
were in the baseline; those entries go with them, 325 -> 321.
@suraj-subrahmanyan suraj-subrahmanyan changed the title ci: expand CI from 30 files to the whole test suite ci: expansion to whole test suite Aug 17, 2026
The first enforcing run blocked on one unrecorded fix. That test was red on run
87, is green now, and is green at the base commit. Nothing in this branch
touches it, so it is nondeterministic.

The baseline cannot hold a green-side flaky test: recorded, it blocks as an
unrecorded fix; absent, it blocks as a new failure. Removed because it passes,
which the ratchet requires.

No fix attempted. The test spawns a subprocess with a 5 second timeout and
asserts on the resulting error type, but run 87's failure reason was not
captured. GAP-005 records the instance and the quarantine state still owed.
@Coconut-ch1ken

Coconut-ch1ken commented Aug 18, 2026

Copy link
Copy Markdown
Collaborator

The PR direction looks correct overall and is likely mergeable. The expanded suite (test-suite across 9 shards + 3 shell channels) is passing in CI, and the new test suite gate also passed. The key risk areas this PR addresses are covered, including import precedence, regression baseline enforcement, and exception handling.

Before merge, please add a short operational note on baseline governance:

  1. who is responsible for regenerating tests/ci_baseline.json when tests/layers change,
  2. explicit conditions for enabling/disabling ENFORCING,
  3. the review window for validating baseline/evidence after any baseline update.

This helps prevent future baseline drift from becoming an untracked process risk.

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.

2 participants