Skip to content

test(ci): wire 17 uncollected infra/libs tests into CI and name the second edit in the concurrency guard (#15051, #15302) - #15315

Merged
mrveiss merged 7 commits into
Dev_new_guifrom
issue-15051-uncollected-tests
Aug 30, 2026
Merged

mrveiss merged 7 commits into
Dev_new_guifrom
issue-15051-uncollected-tests

Conversation

@mrveiss

@mrveiss mrveiss commented Aug 30, 2026 •

Copy link
Copy Markdown
Owner

Thinking Path

#15051 re-measured before touching anything, because the issue's own comment said its table predated PR #15048. Static count against current Dev_new_gui:

module test functions marked (integration/slow/distributed/performance) unmarked
test_architecture_compliance.py 15 2 13
test_db_initialization.py 6 6 0
test_distributed_system_integration.py 6 6 (gained module-level pytestmark via #14979/#15166, after the issue was filed) 0
test_performance_optimization.py 5 5 (same #14979/#15166 change) 0
test_redis_db_ssot.py 4 0 4
libs/.../test_integration.py 5 5 0
total 41 24 17

Of the original 28 unmarked, 11 (the whole test_distributed_system_integration.py and test_performance_optimization.py populations) picked up a marker in an unrelated PR (#15166, merged after #15051 was filed and after the #15048 follow-up comment) and now run via marker-tests.yml's third invocation. 17 remain — 13 in test_architecture_compliance.py, 4 in test_redis_db_ssot.py — and those ran in no workflow and no bare pytest, ever.

The dead ci.yml step (Run integration tests, shard 1 only) named infrastructure/shared/tests/integration, a path #734 renamed to autobot-infrastructure/shared/tests/integration without updating this reference. It quietly succeeds: if [ -d "$TEST_DIR" ]; then ...; else echo "::warning::..."; fi has no else exit 1, so the step always exits 0 and has done since #734 — not an error, a silent no-op green on every shard-1 run.

Both defects are fixed, not just documented:

  1. Wiring — autobot-infrastructure/shared/tests and libs added to pytest.ini testpaths and to all four repo_tests-carrying pytest invocations (ci.yml, coverage.yml, test-durations.yml, marker-tests.yml's first invocation), so repo_tests/hook_suites_run_in_ci_test.py's root-set agreement stays true and the 17 unmarked tests run in the PR gate for the first time.
  2. Dead step — retired with a reason recorded inline, not repointed. Repointing at the now-correct path would have duplicated collection of .../tests/integration (already reached by the wired-in invocation above) and put its integration-marked tests into the required, blocking PR gate with no -m filter of its own — the exact "separate decision with its own blast radius" marker-tests.yml's own comment declines to make inline.

Wiring in surfaced two real bugs, fixed on the implementation side per the "fix, don't adjust assertions" rule:

  • get_backend_config() never set a "host"/"port" key — only "server_host"/"server_port" (the bind address). utils/service_discovery.py:236's _register_backend_service already reads backend_config.get("host") and logs an error on every process start when it comes back None, silently falling back to system_defaults. Fixed by wiring in the existing canonical get_host("backend")/get_port("backend") resolvers (env var → infrastructure.hosts.backend → fallback map), the same precedence every sibling accessor here already uses.
  • test_no_hardcoded_ips_in_redis_helper imported from utils.redis_helper import REDIS_HOST — utils/redis_helper.py was deleted from every tree years ago (confirmed via git log --diff-filter=D), and REDIS_HOST was never a real export of it even historically. Repointed at the canonical autobot_shared.redis_client accessor, mirroring the identical fix ci(gates): make four gates that could not fail actually fail (#13543, #13286, #13200) #15048 already made for the sibling TIMEOUT_CONFIG import in the neighboring test.

Also rewrote test_service_discovery_has_defaults: it asserted four keys inside a service_discovery_defaults config section that two call sites (service_discovery.py, distributed_service_discovery.py) already document inline as having "no ssot equivalent". Nothing writes those keys any more post-#13286's SSOT consolidation — the test is now provably wrong, not the implementation, so it now asserts the property those two callers actually depend on: the section resolves to {}, never None.

The VM-topology comparison tests (test_redis_on_vm3_only, test_frontend_on_vm1, etc.) were reasoned through from source as far as static reading allows without executing code (forbidden by task constraints) — several compare a config accessor's output against the same NetworkConstants source it was built from, so they hold by construction. test_redis_on_vm3_only compares against a 5-tier ConfigRegistry resolution chain that cannot be fully verified without running pytest; left as-is for CI to be the actual judge, per the task's own instruction, and will be triaged from real CI output if it turns up red.

#15302: the guard's assertion at :104-108 told an author their omission was wrong but never mentioned DELIBERATELY_EXEMPT — exactly how #15300 got missed. Chose the message route over coupling the two edits: the file's own docstring already weighed this trade-off ("the coupling route is stronger but needs a way to recognise a required-context shim, which is a judgement rather than a pattern") and a judgement-based coupling risks false positives against this repo's preference for mechanical, derived checks over heuristics. The assertion now names the exemption dict, the exact filename, and cites #15300 as the precedent.

What Changed

  • pytest.ini — testpaths gains autobot-infrastructure/shared/tests and libs.
  • .github/workflows/ci.yml — same two roots added to the PR-gate pytest invocation; the dead Run integration tests step is retired with its reasoning recorded inline.
  • .github/workflows/coverage.yml, .github/workflows/test-durations.yml, .github/workflows/marker-tests.yml — same two roots added to keep the four repo_tests-carrying invocations in agreement.
  • autobot-backend/config/service_config.py — get_backend_config() now sets "host"/"port" via the canonical get_host/get_port resolvers.
  • autobot-infrastructure/shared/tests/integration/test_architecture_compliance.py — test_no_hardcoded_ips_in_redis_helper repointed off a deleted module; test_service_discovery_has_defaults rewritten against the current SSOT reality.
  • repo_tests/workflow_concurrency_guard_test.py — the concurrency-guard failure message now names DELIBERATELY_EXEMPT as the second edit.
  • repo_tests/infra_libs_test_wiring_guard_15051_test.py (new) — the AC Dev new gui #5 guard: a tracked test module under autobot-infrastructure/shared/tests or libs must be named by pytest.ini or some CI invocation, marked or not. Scoped to these two roots (not repo-wide) with a reach floor of 5 modules.

Verification

Execution is off-limits for this task (do not run pytest / execute code from the codebase) — reasoning is from source, cross-checked against:

  • Ran this PR's own new guard's discovery logic by hand against the current tree (git ls-files / regex extraction only, no pytest) and confirmed zero orphans under autobot-infrastructure/shared/tests and libs, and 67 pre-existing orphans elsewhere in the repo that a repo-wide version of the same check would have wrongly reported against this PR.
  • git log --diff-filter=D confirming utils/redis_helper.py's deletion and its historical contents (no REDIS_HOST export ever existed).
  • service_discovery.py:236's existing .get("host") read and its logger.error fallback, proving the missing key is a real, already-manifesting defect.
  • Inline comments in service_discovery.py / distributed_service_discovery.py documenting service_discovery_defaults as having no SSOT equivalent.
  • python3 -c "import ast; ast.parse(...)" on every touched .py file and yaml.safe_load on every touched workflow — all parse cleanly.
  • repo_tests/hook_suites_run_in_ci_test.py and repo_tests/marker_suite_root_coverage_test.py read in full to confirm the exact root-set-agreement and floor mechanics the new roots must satisfy, and that none of the existing floors (MARKER_MIN_PASSED=34, infra=10, slm=0) are lowered or bypassed — only more roots are added to invocations that already clear those floors.
  • CI on this PR is the actual judge of the 17 newly-collected tests and the two provisional fixes; any red result will be triaged from real output rather than guessed at further.

Model Used

Claude Sonnet 5

Refs #15051 -- wiring, dead-step retirement, and the two implementation bugs it surfaced are complete; the VM-topology assertions in test_architecture_compliance.py could not be verified without executing pytest (out of scope for this task) and are left for CI to judge, which is why this is Refs rather than Closes.
Refs #15302 -- the message-route fix for the guard's third, previously-unmet criterion is complete; left as Refs rather than Closes per this repository's closing convention (closed by hand, with evidence, not by a merge keyword).

…e dead integration step, and name the second edit in the concurrency guard (#15051, #15302)

#15051 re-measured against current base: 11 of the originally-reported 28
unmarked tests gained a marker since (#14979/#15166) and already run via
marker-tests.yml; the remaining 17 (13 in test_architecture_compliance.py, 4
in test_redis_db_ssot.py) ran in no workflow and no bare `pytest`. Wired both
trees into pytest.ini testpaths and all four repo_tests-carrying invocations,
retired ci.yml's dead `Run integration tests` step (its path was never
updated after #734 moved the suite, so it warned and passed on every run
since), and fixed two real bugs the newly-collected tests surfaced:
get_backend_config() never set the "host"/"port" keys service_discovery.py
already reads (falls back silently in every deployment), and a test imported
utils.redis_helper, a module deleted years before this test ever ran.

#15302: the concurrency guard's failure message told an author their
omission was wrong but never that DELIBERATELY_EXEMPT is the intended second
edit -- named it directly in the assertion, which is how #15300 got missed.
…ollected again (#15051)

repo_tests/marker_suite_root_coverage_test.py only guards the MARKED
population against running nowhere -- AC #5 asks for the unmarked case too,
which is exactly how the 17 tests this PR just wired in got missed for as
long as they did. Scoped to the two roots this issue actually fixed rather
than a repo-wide sweep: a blind repo-wide version fails immediately against
23 pre-existing, already-deferred collection errors under
autobot-infrastructure/shared/scripts (documented inline in pytest.ini) and
67 further orphans elsewhere that are unrelated to this issue's scope.
@github-actions

Copy link
Copy Markdown
Contributor

✅ SSOT Configuration Compliance: Passing

🎉 No new hardcoded values of either class — ssot and other both block.

Known backlog in pipeline-scripts/hardcoded_values_baseline.txt is suppressed and tracked in #14371.

@mrveiss

mrveiss commented Aug 30, 2026

Copy link
Copy Markdown
Owner Author

CI found a real defect — in the guard, not in the wiring. Fixed in 5acf4a80f5.

python-suite shard 7/12 failed on pipeline-scripts/pytest_root_collection_floor_test.py::TestRootDerivation::test_the_derivation_agrees_with_an_independent_yaml_parse:

At index 0 diff: 'autobot-backend' != 'libs'

Both lists held the same thirteen roots. Only libs' position differed — and it came from prose.

That check cross-checks two parses of marker-tests.yml. The script anchors on the literal three-token python -m pytest, which no comment produces. The test did tokens.index("pytest") over the whole run: block and started reading roots from there. This PR added a comment explaining the wiring, and that comment contains the word pytest and names the sibling step "Run marked tests — infrastructure, libs and frontend". So the test's parse began inside the comment and read libs — a real directory, so it passed the existence filter — as the first root, out of English.

The workflow was correct the whole time. The check went red against correct configuration, which is the failure mode that teaches people to ignore a check.

The fix

_command_tokens strips shell comments before tokenising, and _invocation_starts anchors on the full python -m pytest sequence rather than a bare pytest token — matching what the script it cross-checks has always done. Two regression tests pin it:

  • test_a_comment_naming_pytest_does_not_become_a_root — the exact shape above; asserts libs does not survive the strip and the invocation anchors at the command.
  • test_a_pip_install_line_is_not_read_as_an_invocation — a latent second bug the same change closes: step 2's pip install pytest pytest-asyncio … matched the old bare-token search too. It happened to name no existing paths, so it never produced a wrong root — it was one dependency rename away from doing so.

Verified

Recomputed both sides as data (no repo code executed): the new parse yields

autobot-backend, autobot_shared, autobot-tts-worker, repo_tests, tools, scripts,
pipeline-scripts, autobot-infrastructure/shared/scripts/hooks, .claude/skills/claims-audit,
autobot-infrastructure/shared/tests, libs, autobot-frontend/tests, autobot-slm-backend

which matches workflow_roots' output from the failing CI run exactly, in order.

Worth stating plainly: none of the 17 newly-collected tests failed. Every one of the ten required contexts was already green, and python-suite is not a required check — so this could have been merged past. It should not have been: the entire point of this PR is that a test which never runs proves nothing, and merging over a red result from the suite it just wired in would have reproduced that defect in a new place on the same day.

@mrveiss

mrveiss commented Aug 30, 2026

Copy link
Copy Markdown
Owner Author

Triage of the remaining failures.

Run slow / integration / distributed / performance tests fails on autobot-backend/system_benchmarks_performance_test.py::test_system_startup_performance. This is pre-existing on base, not introduced here — marker-tests.yml run on Dev_new_gui (2026-08-28) fails the same test with the same assertion, and this PR does not touch that file or the code path it measures. Evidence and analysis posted to #15055, including that the assertion's claimed load-invariance does not hold: 700 work units on base versus 3451 here, with the calibration absorbing only 1.9x of a 4.9x swing, on a run that changed no relevant code.

The four test_architecture_compliance.py failures were real and are now marked, with reasons, as #15194's — see the commit and the writeup on that issue. They assert a fixed VM topology the platform does not have; the owner has confirmed AutoBot runs in Docker, on one VM, or on any number chosen. I did not edit them green, which would have hidden the defect this PR exists to expose.

@mrveiss
mrveiss merged commit c580893 into Dev_new_gui Aug 30, 2026
75 of 76 checks passed
@mrveiss
mrveiss deleted the issue-15051-uncollected-tests branch August 30, 2026 08:22
mrveiss added a commit that referenced this pull request Sep 12, 2026
…fixed topology (#15194)

PR #15315 wired this file into CI for the first time and four tests failed
by construction: each asserted a fixed six-VM topology AutoBot does not
have. #15194's owner comment marked all four @pytest.mark.skip with the
reason recorded instead of adjusting them to pass. This rewrites each one
against an invariant that holds in every supported deployment (Docker, one
VM, or any host count) and removes the skip:

- test_browser_service_on_vm5 -> test_service_hosts_resolve_via_ssot_config:
  every role's host matches autobot_shared.ssot_config.config.vm directly
  (not NetworkConstants, which is itself only a ConfigRegistry proxy in
  front of the same SSOT) -- non-tautological because the two paths can
  drift (stale ConfigRegistry/Redis cache, a stray literal).
- test_no_localhost_in_distributed_services ->
  test_distributed_service_hosts_are_resolved: loopback is now allowed
  (correct for Docker/single-VM per VM_ROLES.md); every role's host must
  still be a non-empty, syntactically valid address or hostname.
- test_standard_port_assignments -> test_service_ports_match_ssot_constants:
  compares against autobot_shared.ssot_config.config.port instead of
  literals. Also fixes two latent bugs the literal comparison hid: the
  browser-role assertion used 3000 (Grafana's port; SSOT default is 9001,
  #4052) and read the config under the wrong key (`browser_service`, which
  get_distributed_services_config() never populates -- the key is
  `browser`).
- test_only_one_frontend_instance: no longer requires backend and frontend
  to be on different hosts (fails a correct co-located/single-VM install).
  Asserts exactly one `frontend` entry in NetworkConstants.get_host_configs()
  instead, which is a real check on the canonical fleet-wide host registry.

Not touched: test_redis_on_vm3_only, test_frontend_on_vm1,
test_npu_worker_on_vm2, test_ai_stack_on_vm4 assert the same
host-equals-a-fixed-VM-constant shape and currently pass only because both
sides of the comparison trace back to the same SSOT value in this
environment -- the same tautology, just not yet red. They were not in
the skip list this issue scoped, so left as a follow-up finding rather
than rewritten here.
mrveiss added a commit that referenced this pull request Sep 12, 2026
…fixed topology (#15194)

PR #15315 wired this file into CI for the first time and four tests failed
by construction: each asserted a fixed six-VM topology AutoBot does not
have. #15194's owner comment marked all four @pytest.mark.skip with the
reason recorded instead of adjusting them to pass. This rewrites each one
against an invariant that holds in every supported deployment (Docker, one
VM, or any host count) and removes the skip:

- test_browser_service_on_vm5 -> test_service_hosts_resolve_via_ssot_config:
  every role's host matches autobot_shared.ssot_config.config.vm directly
  (not NetworkConstants, which is itself only a ConfigRegistry proxy in
  front of the same SSOT) -- non-tautological because the two paths can
  drift (stale ConfigRegistry/Redis cache, a stray literal).
- test_no_localhost_in_distributed_services ->
  test_distributed_service_hosts_are_resolved: loopback is now allowed
  (correct for Docker/single-VM per VM_ROLES.md); every role's host must
  still be a non-empty, syntactically valid address or hostname.
- test_standard_port_assignments -> test_service_ports_match_ssot_constants:
  compares against autobot_shared.ssot_config.config.port instead of
  literals. Also fixes two latent bugs the literal comparison hid: the
  browser-role assertion used 3000 (Grafana's port; SSOT default is 9001,
  #4052) and read the config under the wrong key (`browser_service`, which
  get_distributed_services_config() never populates -- the key is
  `browser`).
- test_only_one_frontend_instance: no longer requires backend and frontend
  to be on different hosts (fails a correct co-located/single-VM install).
  Asserts exactly one `frontend` entry in NetworkConstants.get_host_configs()
  instead, which is a real check on the canonical fleet-wide host registry.

Not touched: test_redis_on_vm3_only, test_frontend_on_vm1,
test_npu_worker_on_vm2, test_ai_stack_on_vm4 assert the same
host-equals-a-fixed-VM-constant shape and currently pass only because both
sides of the comparison trace back to the same SSOT value in this
environment -- the same tautology, just not yet red. They were not in
the skip list this issue scoped, so left as a follow-up finding rather
than rewritten here.
mrveiss added a commit that referenced this pull request Sep 13, 2026
…fixed topology (#15194)

PR #15315 wired this file into CI for the first time and four tests failed
by construction: each asserted a fixed six-VM topology AutoBot does not
have. #15194's owner comment marked all four @pytest.mark.skip with the
reason recorded instead of adjusting them to pass. This rewrites each one
against an invariant that holds in every supported deployment (Docker, one
VM, or any host count) and removes the skip:

- test_browser_service_on_vm5 -> test_service_hosts_resolve_via_ssot_config:
  every role's host matches autobot_shared.ssot_config.config.vm directly
  (not NetworkConstants, which is itself only a ConfigRegistry proxy in
  front of the same SSOT) -- non-tautological because the two paths can
  drift (stale ConfigRegistry/Redis cache, a stray literal).
- test_no_localhost_in_distributed_services ->
  test_distributed_service_hosts_are_resolved: loopback is now allowed
  (correct for Docker/single-VM per VM_ROLES.md); every role's host must
  still be a non-empty, syntactically valid address or hostname.
- test_standard_port_assignments -> test_service_ports_match_ssot_constants:
  compares against autobot_shared.ssot_config.config.port instead of
  literals. Also fixes two latent bugs the literal comparison hid: the
  browser-role assertion used 3000 (Grafana's port; SSOT default is 9001,
  #4052) and read the config under the wrong key (`browser_service`, which
  get_distributed_services_config() never populates -- the key is
  `browser`).
- test_only_one_frontend_instance: no longer requires backend and frontend
  to be on different hosts (fails a correct co-located/single-VM install).
  Asserts exactly one `frontend` entry in NetworkConstants.get_host_configs()
  instead, which is a real check on the canonical fleet-wide host registry.

Not touched: test_redis_on_vm3_only, test_frontend_on_vm1,
test_npu_worker_on_vm2, test_ai_stack_on_vm4 assert the same
host-equals-a-fixed-VM-constant shape and currently pass only because both
sides of the comparison trace back to the same SSOT value in this
environment -- the same tautology, just not yet red. They were not in
the skip list this issue scoped, so left as a follow-up finding rather
than rewritten here.
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