Skip to content

Verification evidence — issue-348

Executed 2026-09-11 on claude/github-issue-348-vx9u2l, from the repository checkout with uv run --project cli. No network, no GitHub call, no credential read: the receiver tests POST into the stdlib handler with a fixture secret, and the poller tests run against a stub gh on PATH that lists nothing.

Red first

The new suites fail against the base commit 35a08cf, in a worktree of that commit with only the new test files copied in:

SuiteAgainst 35a08cf
cli/tests/test_repositories.pycollection errorImportError: cannot import name 'repos' from 'the_loop'
cli/tests/test_routing.py -k "declared or undeclared or bound or forged"12 failed, 1 passed (the one pre-existing test the filter also selects)
cli/tests/test_migrations.py -k "0_8_0 or repositor or repos"4 failed, 2 passed (pre-existing)

Results

RowCommandOutcome
T1pytest -q cli/tests/test_repositories.py27 passed
T2pytest -q cli/tests/test_routing.py -k "declared or undeclared or bound or forged or host_disagreement or closing_keyword"20 passed, 173 deselected
T3pytest -q cli/tests/test_poller.py222 passed
T4pytest -q cli/tests/test_migrations.py cli/tests/test_cli_config.py80 passed
T5pytest -q cli/tests/test_webhook_routing_integration.py -k "declared or undeclared or wire"3 passed, 36 deselected
T5pytest -q cli/tests/test_poll_daemon_integration.py -k top_level1 passed, 8 deselected
T11the abuse cases, in T1/T2 aboveA1–A9 closed — see security-review.md
T13pytest -q cli/tests/test_config_schema_parity.py cli/tests/test_manifest_schemas.py cli/tests/test_docs_parity.py cli/tests/test_eventlog.py29 passed
T13python scripts/validate_config.py7 VALID, 0 invalid — including .the-loop/cli-config.yaml and the shipped template against the new schema
T15make check3471 passed, 1 skipped; ruff, markdownlint (1065 files, 0 errors), ruff format --check (293 files), pyright (0 errors) and config validation all clean
T16security-review.mdA1–A9 closed; tier 4 — a named human security sign-off is outstanding until the owner signs at the PR

Baseline for comparison: make check on 35a08cf was 3418 passed / 1 skipped at 13.11.1 and 3443 at 13.12.0's merge base; this branch adds 28 tests net.

Requirement trace

RequirementWhere it is proved
R1.1, R1.4, R1.5test_the_declared_set_is_the_top_level_key, test_the_set_is_deduplicated_by_key, test_a_declared_entry_keeps_the_operators_own_slug
R1.2test_a_bare_entry_takes_this_instances_host, test_a_bare_entry_takes_a_configured_enterprise_host, test_a_qualified_entry_keeps_its_host
R1.3test_a_malformed_entry_is_skipped (9 cases), test_an_over_segmented_entry_is_skipped, test_a_broken_section_narrows_rather_than_widens
R1.6test_the_builder_imports_without_channels — a subprocess import of the_loop.repos loads no the_loop.channels.* module
R2.1test_a_delivery_from_a_declared_repository_routes, test_a_delivery_from_an_undeclared_repository_is_dropped, Scenario: A delivery for a repository the operator never declared…
R2.2test_a_ref_outside_the_declared_set_is_filtered_out, test_a_delivery_whose_every_ref_is_undeclared_is_dropped
R2.3test_no_declared_repositories_bounds_nothing, test_repository_bounds_is_none_when_nothing_is_declared
R2.4test_the_repository_bound_is_checked_before_the_actor (the recorded drop carries repository and no actor), test_an_undeclared_delivery_publishes_nothing_to_the_bus
R2.5Scenario: Declaring the repository and reloading routes the next delivery
R2.6test_an_undeclared_delivery_is_not_marked_processed, Scenario: A refusal discloses nothing about what the operator declared
R3.1, R3.2test_provider_from_source_takes_its_repositories_from_the_caller, test_the_daemon_binds_sources_to_the_resolved_host (4 cases), Scenario: The poller builds its GitHub source from the top-level repositories
R3.3the issue-315 isolation suite in test_poller.py, unchanged and green
R3.4test_a_provider_with_no_repositories_names_the_top_level_key
R3.5test_a_source_still_declaring_repos_is_refused
R4.1test_may_target_every_declared_repository, test_a_failing_read_contributes_nothing
R4.2, R4.3test_channels_kickoff.py (43 passed), test_channels_integration.py kickoff scenarios
R4.4channels status reads declared_repositories; test_status_names_the_fallback_and_how_many_a_prefix_may_pick
R5.1, R5.2, R5.6test_the_repository_lists_move_up, test_the_kickoff_repo_joins_the_declared_set_and_stays_where_it_is, test_a_hand_written_top_level_list_is_kept_first
R5.3test_the_repositories_migration_is_idempotent
R5.4, R5.5test_an_un_migrated_repos_key_is_refused, test_the_current_config_version_is_0_8_0

Existing assertions changed, and why

TestChangeWhy
test_channels_kickoff.py::test_the_declared_set_is_kickoff_repo_and_every_poll_sourcerenamed …_is_the_top_level_declaration; the two source-shape assertions (test_a_non_github_source_is_ignored, test_a_malformed_polling_section_widens_nothing) moved to test_repositories.py in their new formthey pinned where the set came from, which is what this work item changes
test_channels_kickoff.py::test_refusal_text_with_no_declared_repositoriesasserts the refusal names repositories, and no longer names polling.sourcesthe wording follows the key
test_channels_commands.py::test_may_target_kickoff_repo_and_poll_sourcesrenamed …_every_declared_repository, reads the top-level listsame
test_poller.py — five provider testsrepos moved from the source dict to the repositories= argumentthe seam the design moves
Nine fixture configs (test_client, test_core_daemons, test_envfile*, test_ghhost_integration, test_instance, test_state_root_integration)version: '0.7.0''0.8.0'the version gate; these fixtures assert no staleness complaint
Four fixture configs (test_poll_command, test_poll_daemon_integration, test_hosted_ingress_integration, test_channels_integration)polling.sources[].repos → top-level repositoriesthe retired key would now refuse to load
test_core_lifecycle.py, test_api_health_integration.py _configdeclare repositoriesan enabled poller with none is now reported misconfigured (see the execution log)

Nothing was deleted to make a test pass, and no test was skipped, disabled or quarantined.

Redaction

No tokens, no member ids, no hostnames beyond the fixtures (octo/…, ghe.corp, ghe.corp.example, stranger/repo, attacker/repo), no paths outside the repository and its pytest tmp dirs.

Released under the MIT License.