Skip to main content

g6-design-governance

Use when an agent has changed a codebase's structure (moved code, added imports, split a module) and must check before reporting it done that it added no import cycle, broke no layer rule and added no wrapper that only forwards its arguments; it reads a file map you give for any package and refuses rather than calling a check with nothing to check clean.

Source facts

Repository
basicisabc1994/g6solver
Last source activity
October 26, 2026 at 01:52
Detected SKILL.md language
English
Stars
0
Forks
0

Install options

The review-first prompt is selected by default. You can switch to a direct command or download a local copy.

Review the source files

Read SKILL.md and any companion files shown by SkillsMP before deciding whether to install.

Showing SKILL.md

SKILL.md
Source instructions · Read-only preview
name
g6-design-governance
description
Use when an agent has changed a codebase's structure (moved code, added imports, split a module) and must check before reporting it done that it added no import cycle, broke no layer rule and added no wrapper that only forwards its arguments; it reads a file map you give for any package and refuses rather than calling a check with nothing to check clean.
# G6 design_governance Checks a package's import structure from a file map you give it (path to source): the imports between its modules, the cycles among them, the imports that break a layer contract, the functions that only forward their arguments, and the cycles a change introduced. It parses each file with `ast` and runs none of it. A check that found nothing to check is refused, never read as clean. ## When to use it - Before reporting a refactor done: `diff_cycles` on the files before and after. - To hold a codebase to its layers (an api over a domain over a store): `layer_violations`. - To find the cycles already there, or wrappers that add nothing. ## When not to use it - For complexity inside a function (long functions, deep branching): `meta_programming`'s `analyze` gives decision counts. - For imports made at run time (`importlib.import_module`, `__import__`): they are not seen. - To enforce the contract in continuous integration: import-linter does that over an installed package. ## Ops - `import_graph`: the imports between the modules of `package` in `files`, grouped by their first `depth` dotted parts (default 2), each edge with how many imports and an example file and line. - `cycles`: the import cycles, each with its modules, one cycle through them and the imports that close it. - `layer_violations`: imports that break `contract` (`layers`, highest first, each a dotted module prefix, and `forbidden` pairs of `source` and `forbidden`). - `pass_through`: functions in `files` whose one statement returns a call forwarding their parameters unchanged and in order. - `diff_cycles`: the cycles introduced and removed between `before` and `after`, and the new imports inside the introduced ones. ## Reading the result Each module belongs to its longest matching layer prefix. A layer with no assigned module is refused as G6_E_DESIGN_CONTRACT_UNMATCHED, including a layer hidden by more specific prefixes. Only the true branch of if TYPE_CHECKING is guarded; its else imports remain runtime imports. Recursion or memory exhaustion is G6_E_CODE_RESOURCE_LIMIT. A forwarding return with trailing statements is G6_E_DESIGN_INCOMPLETE rather than a clean pass-through result. Paths are relative to the folder that holds the package (`shop/cart/model.py` is `shop.cart.model`). Imports inside a function and under `if TYPE_CHECKING` count unless `include_lazy` or `include_type_checking` is false. Each result carries `modules`, `imports_inside`, `external_imports`, `unparsed` (files that did not parse) and `not_python`. A finding is `qualified-draft` with `clean: false` (`G6_E_DESIGN_FINDINGS`, a red card); none found is `qualified-draft` with `clean: true` (`G6_E_DESIGN_NONE_FOUND`), in structure only. Refused, `blocked-escalated`: `G6_E_DESIGN_NO_MODULES` (no file is a module of `package`), `G6_E_DESIGN_NO_EDGES` (no import between its modules, so a clean result would mean nothing), `G6_E_DESIGN_CONTRACT_UNMATCHED` (a layer or pair names no module, as a typo would), `G6_E_DESIGN_INCOMPLETE` (nothing found while a file did not parse), `G6_E_DESIGN_BAD_PATH` and `G6_E_DESIGN_INPUT`. At most 2,000 files, 500,000 characters each. ## Alone and composed Over MCP: `g6_invoke("design_governance", "diff_cycles", {"before": {...}, "after": {...}, "package": "shop"})`; every op is open there. From Python: `DesignGovernanceBlock().infer(DesignGovernanceInput(op="cycles", ...))`. Composed: `swe_diagnostics`' `patch_check` names the changed files; read them before and after, then `diff_cycles` and `layer_violations`, and give the findings to `coding_agent_gate` as evidence about the diff. ## Failure modes it catches - `unmanaged_complexity` (code growing more complex than anyone can safely change): an import cycle a change introduced, with the import that closed it; an import that breaks the layers; a wrapper that adds nothing; for any package, with a check that matched nothing refused rather than passed. ## Blind spots - Dynamic imports and imports through strings are not seen; neither is coupling through shared data or globals. - Complexity inside a function, and design that is not structural, are not measured. - Grouping by depth decides what a cycle is: at depth 2, modules of one subpackage importing each other is no cycle. - Its own use causes no failure mode it can name, and a clean result is structure only. ## What it needs Nothing outside G6 and no extra: `ast` and pydantic. No model; no file is read from a disk. ## Examples ```g6-example op=cycles {"files": {"shop/__init__.py": "", "shop/cart.py": "from shop import price", "shop/price.py": "from shop import cart"}, "package": "shop"} ``` One cycle: `shop.cart`, `shop.price`, `shop.cart`, with the imports that close it. ```g6-example op=import_graph {"files": {"shop/__init__.py": "", "shop/api/__init__.py": "", "shop/api/routes.py": "from shop.domain import cart", "shop/domain/__init__.py": "", "shop/domain/cart.py": "import sqlite3"}, "package": "shop"} ``` One edge, `shop.api` to `shop.domain`, and one external import. ```g6-example op=layer_violations {"files": {"shop/__init__.py": "", "shop/api/__init__.py": "", "shop/api/routes.py": "from shop.store import db", "shop/store/__init__.py": "", "shop/store/db.py": "from shop.api import routes"}, "package": "shop", "contract": {"layers": ["shop.api", "shop.store"]}} ``` One breach: `shop.store.db` imports `shop.api.routes`, a higher layer. ```g6-example op=pass_through {"files": {"m.py": "def save(record, path):\n return write(record, path)\n"}} ``` `save` forwards its parameters to `write` unchanged. ```g6-example op=diff_cycles {"before": {"shop/__init__.py": "", "shop/a.py": "from shop import b", "shop/b.py": ""}, "after": {"shop/__init__.py": "", "shop/a.py": "from shop import b", "shop/b.py": "from shop import a"}, "package": "shop"} ``` One cycle introduced, and the new import in `shop/b.py` that closed it. ```python from g6.code.design_governance import DesignGovernanceBlock, DesignGovernanceInput files = {"shop/__init__.py": "", "shop/a.py": "import shop.b\n", "shop/b.py": "x = 1\n"} out = DesignGovernanceBlock().infer(DesignGovernanceInput(op="layer_violations", files=files, package="shop", contract={"layers": ["shop.a", "shop.c"]})).unwrap() assert out["code"] == "G6_E_DESIGN_CONTRACT_UNMATCHED" # shop.c names no module: refused, never clean ``` ## The four open problems - **Learning signals**: each reply records what it read (modules, imports, external imports, unparsed files) and each finding with its file and line. Not yet: whether a flagged cycle was later removed is not tracked. - **Evaluators the model cannot influence**: Python's parser and Tarjan's algorithm over the files given; no model is called. - **Transfer by failure mode**: bound to `unmanaged_complexity`; it reads any package's layout, with the package and the contract as input. - **Enough held-out cases**: Not yet: tested on small packages made in the tests, not on a frozen set of real refactors with known cycles.
View on GitHub