ci: run every central module's own gate in hosted CI - #55
Merged
Merged
Conversation
`dagger call ci` ran only the root .dagger gate, so a module could go red on main without any hosted check noticing. It now runs each module's `poe gate` (lint, typecheck, complexity, tests with coverage floors, branch rates, schema, audit) inside Dagger, after root quality and before security: - one container per module from digest-pinned python:3.13.14-bookworm, with uv, uvx and the v0.21.8 Dagger CLI; the engine-generated SDK is overlaid on the explicit source, and nesting gives `dagger -m ..` in the gate its engine; - MODULE_GATES must equal modules/*/dagger.json, so a new module cannot skip it; - all gates run concurrently and the error names every failed module; - tests that need host Docker or a host Dagger CLI working in a temp directory are deselected by exact node id, pinned by a test that also checks each id still names a real test. Red: on main's module trees the new step fails on python-package (test_should_observe_bounded_forced_zip64_wheel, CPython 3.13.14); fixed in the base branch. Mutation: deleting foundation tests/test_github.py drops its coverage to 68.79% and fails the step with "module gates failed: modules/portfolio-foundation". Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015oBArfm762nN1r4F4Fst5a
hseshadr
added a commit
that referenced
this pull request
Sep 27, 2026
Merging main brought in #55, which runs every central module's own gate in hosted CI. The portfolio-foundation quality contract then failed on provenance_context (16 lines). Move the two constant keys into the helper; the rendered context is unchanged (keys are sorted). Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Khf33gPHi4bBojkDy8ZNRq
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Reopened from #54, which GitHub closed when its stacked base branch (#53, now merged) was deleted. Same single commit 0398e1a; #53's changes are already on main.
TL;DR
Hosted CI now runs every central module's own
poe gate. Before this,dagger call ciran only the root.daggergate, so a module could go red onmainand no hosted check would notice.Claim touched: "module regressions cannot reach main unchecked."
Stacked on #53 (python-package ZIP64 fix), which this gate found on its first run. Merge #53 first.
What changed (CI config + tests only)
Ci.ciruns_module_gates()after root quality and before security. Each module (cloudflare-pages,portfolio-foundation,python-package) runsuv run poe gatein its own container: digest-pinnedpython:3.13.14-bookworm, with uv, uvx, and the v0.21.8 Dagger CLI from the pinned engine image. The engine-generated SDK is overlaid on the explicit source. Privileged nesting givesdagger -m .. functions(theschematask) its engine.MODULE_GATESmust equalmodules/*/dagger.json, so a new module cannot skip the gate.dagger.ymlstays a thin ingress, astest_central_workflows.pyrequires.What hosted CI still does not run
These tests are deselected by exact node id, and a test pins the list and checks that each id still names a real test:
test_guard_integration.py(7 tests)docker run; no Docker daemon inside Dagger. Hosted CI still runs gitleaks for real throughfoundation.guard.test_artifact.py,test_bootstrap.py,test_source_integration.pytest_deploy_contract.py::test_should_run_real_dagger_mock_provider_contractdagger initissueThese still run locally with each module's
poe gate.Evidence (local engine v0.21.8,
dagger call ci)ImportError: cannot import name 'ENGINE_IMAGE', and the ci-order test failsmodule gates failed: modules/python-package.test_should_observe_bounded_forced_zip64_wheelfails withProbeError: wheel physical EOF differson CPython 3.13.14. Fixed in #53.git rmfoundationtests/test_github.pyFAIL Required test coverage of 90% not reached. Total coverage: 68.79%→module gates failed: modules/portfolio-foundationpoe gategit merge-treevs #47, #48, #50, #51The requested "foundation stops at 86% on main" did not reproduce on a clean
main: foundation's gate is 93.97% there. The 86.50% log came from a tree with #50'slineage.pybut notest_lineage.py(lineage.py at 0%). This gate would catch that tree. No floor was lowered, and no foundation tests were needed.🤖 Generated with Claude Code
https://claude.ai/code/session_015oBArfm762nN1r4F4Fst5a