Repository navigation
ci(lint): enforce architecture contracts with import-linter - #1813
Closed
zoroyihan7 wants to merge 1 commit into
Closed
zoroyihan7 wants to merge 1 commit into
zoroyihan7 wants to merge 1 commit into
Conversation
Add .importlinter with seven contracts: hyperloom top-level layers, kernelforge depends on hyperloom.common only, hyperloom.common is a leaf, agent packages and kernel backends are independent, only the orchestrator and hyperloom.cli import kernelforge directly, and no cycles between sibling packages. Existing violations are recorded as exact ignore_imports lines (56 upward imports of hyperloom.inference_optimizer.cli, 155 cycle breakers) with unmatched_ignore_imports_alerting = error, so the baselines can only shrink. Run it as a hard gate in lint.yml (import-linter==2.15 pinned) and as a local pre-commit hook; document the rules in the style guide. Co-Authored-By: Claude <noreply@anthropic.com>
Contributor
Author
|
Superseded by #1812, which now carries this change. |
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.
Description: Enforce the package dependency direction as a CI gate. Adds
.importlinterwith seven import-linter contracts and runs them in a newimport-linter (architecture contracts)job inlint.yml(import-linter pinned to 2.15,PYTHONPATH=src lint-imports --no-cache, no project install) and as a local pre-commit hook. The style guide gains a "Dependency direction" subsection under Module structure that lists the contracts.hl-top-layershyperloom.cli>orchestrator>agents>inference_optimizer>commonhyperloom.inference_optimizer.cli(an entry point that sits in the core layer)kf-only-commonkernelforgeimports onlyhyperloom.commonfrom hyperloomcommon-is-leafhyperloom.commonimports nothing else from the projectagents-independenthyperloom.agents.{critic,framework,quantization}do not import each otherkf-backends-independentkernelforge.kernel_backends.*do not import each otherkf-entry-protectedhyperloom.agents,inference_optimizer,commondo not importkernelforgedirectlyacyclichyperloom/kernelforgeBoth baselines set
unmatched_ignore_imports_alerting = error, so they can only shrink: removing a baselined import without deleting its line fails the check. Tests andif TYPE_CHECKING:imports are exempt; imports inside functions are checked. Measured on main 880c167: 7 kept, 0 broken, about 0.6 s wall clock.Admin action needed for this to block merges: ruleset "main" has no required status checks today. Mark
import-linter (architecture contracts)(job in workflowLint) as a required check. Note thatlint.ymlhaspaths-ignorefor Markdown/docs, so a docs-only PR never produces this check; requiring it directly would leave such PRs pending (the same is true ofrufftoday). Either require it through an always-run aggregate job or accept that limitation.Independent of ci: code-metrics gate on touched files with baseline-free checks; fold in import-linter, PR hygiene and ruff principle rules #1812 (code metrics gate): no shared files except
docs/contributing/style-guide.md, where this PR only touches the Module structure section and the Related configuration files table.Linked issue(s): none
Tests: no Python code changed. Reverse proofs, each on a scratch copy (not committed):
Contracts: 7 kept, 0 broken, rc 0hyperloom.common.timeutillazily importshyperloom.orchestrator.loop.coordinator: rc 1,hl-top-layers,common-is-leaf("hyperloom.common is not allowed to import hyperloom.orchestrator"),agents-independent(indirect chain via common) andacyclicBROKENkernelforge.durable_ioimportshyperloom.orchestrator.state: rc 1, onlykf-only-commonBROKEN ("kernelforge is not allowed to import hyperloom.orchestrator")hyperloom.agents.criticimportshyperloom.agents.framework.kb: rc 1, onlyagents-independentBROKENkernel_backends.aiterimportskernel_backends.triton: rc 1, onlykf-backends-independentBROKENhyperloom.inference_optimizer.gpu_typesimportskernelforge.durable_io: rc 1, onlykf-entry-protectedBROKEN ("hyperloom.inference_optimizer is not allowed to import kernelforge")orchestrator.state.task_registrylazily importsorchestrator.loop.coordinator: rc 1, onlyacyclicBROKEN ("No cycles are allowed in hyperloom.orchestrator ... .state -> .loop")inference_optimizer.cli.quantization -> orchestrator.phases.quantization_request_handlers: rc 1, "No matches for ignored import hyperloom.inference_optimizer.cli.quantization -> hyperloom.orchestrator.phases.quantization_request_handlers"common.llm_config -> common.claude_oneshotimports: rc 1, "No matches for ignored import hyperloom.common.llm_config -> hyperloom.common.claude_oneshot"pre-commit run import-linter --all-files: Passed; with theagents.critic -> agents.frameworkmutation staged: Failed withagent packages are independent BROKENactionlint .github/workflows/lint.yml,yamllint(repo config),check-yaml,codespell,reuse lint: cleanSize/complexity triggers crossed: none (config, workflow and docs only;
.importlinteris long because it lists the 211 baseline lines explicitly)If this simplifies or refactors: n/a
Observable effect: contributors see a new
import-linter (architecture contracts)check on PRs and pushes to main; it fails, naming the contract and the import chain, when a PR adds an import that points up a layer, couples two agents or two kernel backends, makescommonorkernelforgedepend upward, or closes a new cycle between sibling packages. Until now these rules lived only in review and drifted silently (the layering violations and cycles in the baselines are what that cost).Breaking changes: no
PR addresses single concern: yes
Root cause is upstream (Magpie/TraceLens/GEAK/IntelliKit/AgentKernelArena), ticket filed: n/a
Known limits: import-linter is static, so
importlib/ string-path imports are invisible; the baselines are per module pair, so another import between two modules already listed is not caught.🤖 Generated with Claude Code