Skip to content

Cut backend CI runtime 66%: 16m → 5m with isolated semantic test lanes#180

Open
Konan69 wants to merge 2 commits into
Flow-Research:mainfrom
Konan69:codex/ws-ci-001-02-runtime-stabilization
Open

Cut backend CI runtime 66%: 16m → 5m with isolated semantic test lanes#180
Konan69 wants to merge 2 commits into
Flow-Research:mainfrom
Konan69:codex/ws-ci-001-02-runtime-stabilization

Conversation

@Konan69

@Konan69 Konan69 commented Jul 22, 2026

Copy link
Copy Markdown
Contributor

Outcome

Backend test wall time dropped from 975.62 seconds (16m 16s) to 330.70 seconds (5m 31s).

  • 66.1% less wall time
  • 2.95× faster
  • 1,826 tests passed exactly once
  • 87.58% global coverage
  • 90.90–100% across every protected coverage floor

What changed

  • Replaced arbitrary weighted CI shards with four semantic dependency lanes:
    • no PostgreSQL
    • schema contracts
    • control plane
    • execution plane
  • Added exact test-module inventory validation so every backend test module runs once or is explicitly excluded.
  • Shared one PostgreSQL server while giving each database lane an isolated temporary database and role.
  • Shared one MinIO server while keeping test state, coverage files, metadata, and environments isolated.
  • Migrated each runner-owned database once, then reset mutable tables transactionally between ordinary tests.
  • Combined private lane coverage files locally before enforcing the unchanged coverage floors.
  • Added fail-fast subprocess custody, timeout handling, signal propagation, credential stripping, metadata, and 60-second heartbeats.
  • Removed obsolete shard planning, timing artifacts, and cross-job coverage fan-in.
  • Removed repeated Alembic-head setup from Outbox tests.

Safety boundaries

  • No changes under backend/app.
  • No production migration changes.
  • No application architecture or behavior changes.
  • Real PostgreSQL remains mandatory for migrations, triggers, constraints, locks, transactions, concurrency, and asyncpg behavior.
  • No behavior tests were deleted.
  • Coverage requirements remain unchanged: 78% global and all protected 90% floors.
  • Cleanup verification found no leftover runner-owned PostgreSQL databases or roles.

Verification

  • Semantic lanes: 1,826 passed in 314.40s, 330.70s wall including startup and coverage combine
  • Lane runner contracts: 11 passed
  • Isolated database runner lifecycle: 17 passed
  • Outbox suite: 72 passed
  • Agent workflow gates: 91 passed
  • Real API contract drill: passed
  • Ruff: passed
  • git diff --check: passed
  • Blocking diagnostics: none

Redundancy audit

An AST audit found no exact duplicate behavior-test bodies. Six literal-normalized similarity clusters were retained because consolidation would not materially reduce runtime. The only high-confidence runtime redundancy removed was Outbox's repeated Alembic-head setup.

Summary by CodeRabbit

  • New Features

    • Backend CI now runs semantic test lanes concurrently with isolated coverage collection and per-lane time limits.
    • Database-backed tests reuse a migrated baseline, improving test execution efficiency while preserving migration and schema checks.
    • Added stronger runtime monitoring, cleanup, and failure summaries for test processes.
  • Documentation

    • Updated backend testing operations, rollout guidance, risks, verification steps, and hosted CI expectations.
  • Tests

    • Added coverage for lane validation, database reset safety, process handling, and CI workflow requirements.

@coderabbitai

coderabbitai Bot commented Jul 22, 2026

Copy link
Copy Markdown

Review Change Stack

Warning

Review limit reached

@Konan69, you've reached your PR review limit, so we couldn't start this review.

Next review available in: 36 minutes

Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available.
You're only billed for reviews past your plan's rate limits ($0.25/file).

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 20f71b10-ebc6-4058-b43f-e358f13b2c30

📥 Commits

Reviewing files that changed from the base of the PR and between 6b1e19f and c73b289.

📒 Files selected for processing (30)
  • .agent-loop/initiatives/WS-CI-001-backend-ci-acceleration/CHUNK_MAP.md
  • .agent-loop/initiatives/WS-CI-001-backend-ci-acceleration/PLAN.md
  • .agent-loop/initiatives/WS-CI-001-backend-ci-acceleration/RISKS.md
  • .agent-loop/initiatives/WS-CI-001-backend-ci-acceleration/STATUS.md
  • .agent-loop/initiatives/WS-CI-001-backend-ci-acceleration/chunks/WS-CI-001-02-runtime-stabilization-timing.md
  • .agent-loop/initiatives/WS-CI-001-backend-ci-acceleration/chunks/WS-CI-001-02-safe-routing-cache-timing.md
  • .github/workflows/backend.yml
  • backend/pyproject.toml
  • backend/scripts/ci_test_shards.py
  • backend/scripts/run_isolated_tests.py
  • backend/scripts/run_test_lanes.py
  • backend/tests/conftest.py
  • backend/tests/test_actors.py
  • backend/tests/test_alembic.py
  • backend/tests/test_api_rate_controls.py
  • backend/tests/test_artifact_admission.py
  • backend/tests/test_artifact_recovery.py
  • backend/tests/test_audit.py
  • backend/tests/test_auth.py
  • backend/tests/test_authorization.py
  • backend/tests/test_checkers.py
  • backend/tests/test_ci_test_lanes.py
  • backend/tests/test_ci_test_shards.py
  • backend/tests/test_database_reset.py
  • backend/tests/test_isolated_database_runner.py
  • backend/tests/test_outbox.py
  • backend/tests/test_projects.py
  • backend/tests/test_tasks.py
  • docs/operations_backend_testing.md
  • scripts/test_agent_gates.py
📝 Walkthrough

Walkthrough

The PR replaces backend CI sharding with four concurrent semantic lanes, centralizes PostgreSQL test isolation around migrated baselines and guarded resets, updates workflow coverage handling, and migrates backend fixtures and validation tests to the new runtime.

Changes

Backend CI acceleration

Layer / File(s) Summary
Semantic lane runner and workflow
.github/workflows/backend.yml, backend/scripts/run_test_lanes.py, backend/scripts/run_isolated_tests.py, backend/pyproject.toml
Adds concurrent lane execution, strict test inventory validation, isolated coverage files, heartbeat and timeout handling, and the postgres_schema_contract marker.
Database baseline and fixture migration
backend/tests/conftest.py, backend/tests/test_database_reset.py, backend/tests/test_*.py
Introduces migrated database baselines, guarded transactional resets, schema-contract rebuilds, and replaces module-local Alembic setup with shared fixtures.
Validation and operations
backend/tests/test_ci_test_lanes.py, backend/tests/test_isolated_database_runner.py, docs/operations_backend_testing.md, scripts/test_agent_gates.py
Adds lane and reset coverage, updates operational guidance, and validates workflow structure and coverage-floor ordering.

Estimated code review effort: 4 (Complex) | ~60 minutes

Possibly related PRs

Suggested reviewers: abiorh-claw

🚥 Pre-merge checks | ✅ 3 | ❌ 2

❌ Failed checks (2 warnings)

Check name Status Explanation Resolution
Description check ⚠️ Warning The description captures the outcome, but it omits most required template sections and the merge-intent/chunk details. Fill the PR trust-bundle template: add chunk/merge-intent info, goal, intent, design, alternatives, evidence, test delta, reviewer results, and remaining-risk sections.
Docstring Coverage ⚠️ Warning Docstring coverage is 23.78% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (3 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly summarizes the main change: faster backend CI via isolated semantic test lanes.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@Abiorh001
Abiorh001 self-requested a review July 22, 2026 08:20

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

🧹 Nitpick comments (3)
backend/tests/test_actors.py (1)

1-2: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Narrow the module-wide Pyright suppressions.

These directives disable four diagnostics for the entire test module, allowing unrelated type and attribute errors to pass silently. Prefer local suppressions for the dynamic stubs or fix their annotations.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@backend/tests/test_actors.py` around lines 1 - 2, Narrow the module-wide
Pyright suppressions in test_actors.py by removing the file-level directives and
addressing each resulting diagnostic locally. Add targeted suppressions only
around dynamic stubs where necessary, and correct inaccurate annotations for
genuine type or attribute issues.
backend/tests/test_database_reset.py (1)

8-14: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Import TRUNCATE_GUARDED_TABLES from conftest.py instead of duplicating the literal.

This module redefines TRUNCATE_GUARDED_TABLES as a separate set literal identical to conftest.py's tuple. If the canonical list in conftest.py changes (add/remove a guarded table), this copy can drift silently out of sync until this specific test happens to fail. Importing the shared constant removes the duplication and guarantees this test always asserts against the real contract.

♻️ Suggested fix
-TRUNCATE_GUARDED_TABLES = {
-    "admin_role_grants",
-    "audit_events",
-    "authority_control",
-    "authority_idempotency_records",
-    "outbox_events",
-}
+from conftest import TRUNCATE_GUARDED_TABLES
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@backend/tests/test_database_reset.py` around lines 8 - 14, Remove the local
TRUNCATE_GUARDED_TABLES set literal and import the canonical
TRUNCATE_GUARDED_TABLES from conftest.py, updating any references in this test
module to use the imported shared constant.
backend/tests/test_checkers.py (1)

1137-1139: 🎯 Functional Correctness | 🔵 Trivial | ⚡ Quick win

Truthiness assertions weaken several boolean-field checks.

Across this file, assert x is True/assert x is False on API boolean fields (eligible_to_submit, would_block_if_submitted, blocks_review, worker_visible, authoritative, is_current_for_submission, etc.) were rewritten to assert x/assert not x. not x is also satisfied by None, 0, or "", so a future bug where the API returns None instead of False for one of these fields would silently keep passing these tests instead of failing.

♻️ Example fix (repeat pattern at each cited line)
-    assert not body["authoritative"]
-    assert not body["eligible_to_submit"]
+    assert body["authoritative"] is False
+    assert body["eligible_to_submit"] is False

Also applies to: 1150-1150, 1177-1187, 1684-1685, 1765-1765, 1826-1826, 1858-1858, 1886-1886, 1918-1918, 1939-1939, 1957-1957, 2086-2086, 2201-2201, 2472-2472

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@backend/tests/test_checkers.py` around lines 1137 - 1139, Restore strict
identity assertions for all cited API boolean fields in
backend/tests/test_checkers.py, replacing truthiness checks such as assert x and
assert not x with assert x is True and assert x is False. Apply this
consistently to fields including authoritative, eligible_to_submit,
would_block_if_submitted, blocks_review, worker_visible, and
is_current_for_submission while preserving the existing expected values.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In
@.agent-loop/initiatives/WS-CI-001-backend-ci-acceleration/chunks/WS-CI-001-02-runtime-stabilization-timing.md:
- Around line 113-134: Resolve the missing signed-start state for WS-CI-001-02
before external review: create the required
.agent-loop/merge-intents/WS-CI-001-02.json record with the canonical signed
start, or update the documented requirements consistently. Apply any necessary
changes in the chunk’s Stop conditions, CHUNK_MAP.md, PLAN.md, and STATUS.md so
all four sites reflect the same actual state, and keep the chunk out of review
until they do.

In @.agent-loop/initiatives/WS-CI-001-backend-ci-acceleration/RISKS.md:
- Line 5: Update the R1 mitigation entry in RISKS.md to describe the shipped
four concurrent semantic-lane processes, using validate_lane_inventory as the
mechanism that verifies every test module is assigned exactly once across the
lanes. Remove the outdated reference to a single ordinary pytest process and
preserve the existing risk and severity.

In `@backend/tests/test_actors.py`:
- Line 843: Update both retryable assertions in the relevant tests to use an
identity check against True rather than truthiness. Preserve the existing
response.json()["error"]["retryable"] access while enforcing the boolean
contract emitted by the API.

---

Nitpick comments:
In `@backend/tests/test_actors.py`:
- Around line 1-2: Narrow the module-wide Pyright suppressions in test_actors.py
by removing the file-level directives and addressing each resulting diagnostic
locally. Add targeted suppressions only around dynamic stubs where necessary,
and correct inaccurate annotations for genuine type or attribute issues.

In `@backend/tests/test_checkers.py`:
- Around line 1137-1139: Restore strict identity assertions for all cited API
boolean fields in backend/tests/test_checkers.py, replacing truthiness checks
such as assert x and assert not x with assert x is True and assert x is False.
Apply this consistently to fields including authoritative, eligible_to_submit,
would_block_if_submitted, blocks_review, worker_visible, and
is_current_for_submission while preserving the existing expected values.

In `@backend/tests/test_database_reset.py`:
- Around line 8-14: Remove the local TRUNCATE_GUARDED_TABLES set literal and
import the canonical TRUNCATE_GUARDED_TABLES from conftest.py, updating any
references in this test module to use the imported shared constant.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 594408c9-1ba1-4009-81be-42479b4fdaea

📥 Commits

Reviewing files that changed from the base of the PR and between afde967 and 6b1e19f.

📒 Files selected for processing (29)
  • .agent-loop/initiatives/WS-CI-001-backend-ci-acceleration/CHUNK_MAP.md
  • .agent-loop/initiatives/WS-CI-001-backend-ci-acceleration/PLAN.md
  • .agent-loop/initiatives/WS-CI-001-backend-ci-acceleration/RISKS.md
  • .agent-loop/initiatives/WS-CI-001-backend-ci-acceleration/STATUS.md
  • .agent-loop/initiatives/WS-CI-001-backend-ci-acceleration/chunks/WS-CI-001-02-runtime-stabilization-timing.md
  • .agent-loop/initiatives/WS-CI-001-backend-ci-acceleration/chunks/WS-CI-001-02-safe-routing-cache-timing.md
  • .github/workflows/backend.yml
  • backend/pyproject.toml
  • backend/scripts/ci_test_shards.py
  • backend/scripts/run_isolated_tests.py
  • backend/scripts/run_test_lanes.py
  • backend/tests/conftest.py
  • backend/tests/test_actors.py
  • backend/tests/test_alembic.py
  • backend/tests/test_api_rate_controls.py
  • backend/tests/test_artifact_admission.py
  • backend/tests/test_audit.py
  • backend/tests/test_auth.py
  • backend/tests/test_authorization.py
  • backend/tests/test_checkers.py
  • backend/tests/test_ci_test_lanes.py
  • backend/tests/test_ci_test_shards.py
  • backend/tests/test_database_reset.py
  • backend/tests/test_isolated_database_runner.py
  • backend/tests/test_outbox.py
  • backend/tests/test_projects.py
  • backend/tests/test_tasks.py
  • docs/operations_backend_testing.md
  • scripts/test_agent_gates.py
💤 Files with no reviewable changes (3)
  • .agent-loop/initiatives/WS-CI-001-backend-ci-acceleration/chunks/WS-CI-001-02-safe-routing-cache-timing.md
  • backend/scripts/ci_test_shards.py
  • backend/tests/test_ci_test_shards.py

| R13 | Mutable PostgreSQL tag changes CI behavior | High | Replace `postgres:16` with a reviewed digest pin in 01 |
| R14 | Parameter display values change across pytest processes | Critical | Execute whole modules; compare exact collection/completion within one process and bind only stable test-base cardinalities across processes |
| --- | --- | ---: | --- |
| R1 | A test is omitted or duplicated | Critical | One ordinary pytest process discovers and executes the complete suite exactly once |

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

R1 mitigation text describes the old single-process design, not the shipped 4-lane model.

The rest of the table (and PLAN.md/run_test_lanes.py) describes four concurrent semantic-lane processes with exact module-inventory validation, not "one ordinary pytest process." As written, R1 misdescribes the actual mitigation (validate_lane_inventory ensuring exactly-once assignment across the four lanes) and could mislead a reader auditing risk coverage.

✏️ Suggested wording
-| R1 | A test is omitted or duplicated | Critical | One ordinary pytest process discovers and executes the complete suite exactly once |
+| R1 | A test is omitted or duplicated | Critical | Lane inventory validation assigns every discovered test module to exactly one of the four semantic lanes before any lane runs |
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
| R1 | A test is omitted or duplicated | Critical | One ordinary pytest process discovers and executes the complete suite exactly once |
| R1 | A test is omitted or duplicated | Critical | Lane inventory validation assigns every discovered test module to exactly one of the four semantic lanes before any lane runs |
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In @.agent-loop/initiatives/WS-CI-001-backend-ci-acceleration/RISKS.md at line
5, Update the R1 mitigation entry in RISKS.md to describe the shipped four
concurrent semantic-lane processes, using validate_lane_inventory as the
mechanism that verifies every test module is assigned exactly once across the
lanes. Remove the outdated reference to a single ordinary pytest process and
preserve the existing risk and severity.

assert response.status_code == 503
assert response.json()["error"]["code"] == "service_unavailable"
assert response.json()["error"]["retryable"] is True
assert response.json()["error"]["retryable"]

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Keep retryable assertions type-strict.

Truthiness accepts malformed payloads such as 1 or "true" and no longer enforces the API’s boolean contract. Restore is True in both assertions; backend/app/core/api_controls.py:75-124 emits this field from a boolean parameter.

Also applies to: 891-891

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@backend/tests/test_actors.py` at line 843, Update both retryable assertions
in the relevant tests to use an identity check against True rather than
truthiness. Preserve the existing response.json()["error"]["retryable"] access
while enforcing the boolean contract emitted by the API.

@Abiorh001 Abiorh001 left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Blocking review — preserve this PR as discovery evidence; do not merge the implementation in its current lifecycle state.

  1. Canonical start and PR custody are missing.
    The signed loop has no active WS-CI-001 chunk. This PR adds no .agent-loop/merge-intents/WS-CI-001-02.json and no changed internal-review evidence/trust bundle. That directly caused Agent Gates run 29904741566 and Backend run 29904741582 to fail before backend tests ran. Therefore the hosted runtime, coverage, reset, and 1,826-test claims are not yet proven on this head.

  2. The reviewed chunk identity was changed retroactively.
    Current main defines WS-CI-001-02-safe-routing-cache-timing.md as a planning-phase contract. This PR deletes it and replaces it after implementation with a different implementation contract that omits "## Start phase". The new contract cannot be selected through the explicit-event workflow, and its own CHUNK_MAP, PLAN, STATUS, and stop condition say push/PR was prohibited until signed start.

Correct adoption path:

  • preserve PR #180 and Konan's commits as discovery/input evidence;
  • signed-start the existing WS-CI-001-02 planning contract;
  • publish a planning-only 02 PR declaring a bounded implementation successor such as WS-CI-001-02A;
  • signed-start 02A;
  • adopt these commits into Konan's implementation PR and re-prove the exact contracted head.
  1. Exact test-node custody was weakened.
    run_test_lanes.py proves each top-level test module is assigned once, but no longer proves every collected pytest node completed exactly once. A lane can remain green after deselection, lost parameter cases, unexpected skips, or a module collecting fewer/zero tests. The removed shard/fan-in runner had node-level custody. Restore a lightweight collected-node versus completed-node ledger inside the semantic lanes and reject missing, duplicate, foreign, deselected, or unexpectedly skipped nodes. Add mutation tests for those cases.

  2. Test assertions were weakened.
    Examples include backend/tests/test_actors.py and backend/tests/test_checkers.py, where "is True"/"is False" became truthiness checks. This allows None, 0, strings, or other non-boolean values to satisfy API and repository boolean contracts. Restore strict identity assertions throughout the changed tests.

  3. Reset guard proof is incomplete.
    conftest.py disables USER triggers for seven guarded tables, but test_database_reset.py asserts restoration for only five and omits project_role_grants and project_role_qualification_snapshots. Import/use the canonical guarded-table constant and prove every disabled guard is restored.

  4. Scope and docs need reconciliation.
    The retrospective contract does not allow backend/pyproject.toml, deletion of backend/scripts/ci_test_shards.py, or explicitly authorize deletion of its test. Define this scope prospectively in 02A. Also update the risk mitigation that still describes one ordinary pytest process even though four semantic lanes are shipped.

Positive review results: database/role isolation, secret stripping, cleanup ownership checks, coverage floors, fail-closed coverage combine, MinIO lane isolation, and separation between lane orchestration and isolated-resource custody look sound.

Please keep Konan as author. The issue is not contributor permission or attribution; it is establishing immutable intent/contract/start evidence before adopting the implementation.

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