arch-optimize
This server does not currently have a deployable release on Glama. Follow the repository's setup instructions to install and configure it for your MCP client, including any required credentials and local dependencies.
arch-optimize
Architecture optimization skill: a design-review layer (what a design problem is), six decay risk scanning (R1-R6), architect-programmer dual-agent collaboration, and quantitative regression guarding. 5 stdlib-only Python scripts, zero external dependencies.
Overview
arch-optimize delivers a workflow from design judgement through architecture analysis and incremental optimization to regression guarding:
Design Review Layer (Stage Zero): seven classes of design problem + a five-part finding contract, answered by reading code and git history before running any script —
references/design-review.mdSix Decay Risk Scanning (brooks-lint, based on 12 classic engineering books): structured R1-R6 diagnosis with Symptom -> Source -> Consequence -> Remedy findings. These are lead generators, not conclusions.
Architect-Programmer Dual-Agent Collaboration: strategy (architect) separated from execution (programmer)
Quantitative Regression Guarding: asymmetric scoring; quality drops are penalized more than gains are rewarded
The split matters: design problems (where a boundary is drawn, who owns an invariant, whether an abstraction is in the right place) have no mechanical criterion, so no script in this repo detects them. A high health score therefore means "no threshold tripped", not "the design is fine" — and the heaviest design problems usually produce zero findings here.
Related MCP server: Code-Oracle
Script Tools
All scripts use Python 3.10+ standard library only (zero external dependencies; CI matrix tests 3.10, 3.12 and 3.13) and output structured JSON.
Script | Stage | Function |
| 1 | Directory scanning, entry point detection, tech stack identification |
| 1 | Dependency graph (Mermaid/DOT), circular dependency detection |
| 2 | R1-R6 six decay risk scanning, four-part findings |
| 3 | MI/CC/HV/Health Score calculation, hotspot identification |
| 5 | Test baseline recording, regression comparison (incl. vanished tests) |
Six Decay Risks (R1-R6)
Risk | Concept | What the script actually asserts |
R1 Cognitive Overload | understanding cost | function >50 lines, nesting >5, CC >15 = Critical; 20–50 lines / 4–5 nesting = Warning; params >4 = Warning |
R2 Change Propagation | one change hits many places | per-file deduplicated top-level dependency count: >7 Critical, ≥5 Warning (Python folds |
R3 Knowledge Duplication | one decision expressed twice | 8-gram Jaccard ≥0.6/≥0.8 within the same top-level directory; 2+-digit literals repeated ≥3 times across ≥2 files = Critical, aggregated into one finding (magnitude lives in its |
R4 Accidental Complexity | code harder than the problem | CC >20 = Critical (Warning on algorithmic paths); an abstraction with a single implementation in the same file = Warning — and "abstraction" only means a base class named |
R5 Dependency Disorder | dependencies point one way | file-level cycles = Critical (Python relative imports such as |
R6 Domain Model Distortion | code mirrors the domain | generic directory name = Warning; cross-context keyword = Warning; Python class whose public surface is only accessors = Warning, field-only class = Suggestion |
Thresholds and every known blind spot (dep_graph still does not graph relative imports at directory granularity, @dataclass never flagged as anemic, cross-context duplication reported as Warning only — scaffolding vs domain vocabulary cannot be separated, non-Python CC still a regex approximation over comments/strings, pub/export leaking into Rust/TS finding names) are listed in references/architecture-principles.md §四 "脚本实测口径". An empty result from a scanner is not evidence of absence.
False-positive protection (composition-root wiring is not DIP violation, DTOs are not anemic models, etc.) lives in references/architecture-principles.md.
Design Problems (Stage Zero)
Stage Zero runs before the scripts. Seven classes, each reduced to one question you can actually answer against this repo:
Class | The question |
Change boundaries | Which unrelated directories did the last real requirement touch? |
Coupling direction and strength | If B changes, must A change too — and which part of B does A actually use? |
Abstraction level and location | How many real callers does this abstraction have? How many files does adding a second implementation hit? |
Invariant ownership | If this rule is bypassed, which line blows up, and who notices first? |
Evolvability / reversibility | To replace X in six months, how many files move, and which test goes red? |
Concept -> code fidelity | The word product uses — how many names does it have in code, and are they the same thing? |
Consistency / single source of truth | When this value or contract changes, how many places must you remember to edit? |
Every design finding must be written as five parts, none optional: the decision (naming the file/symbol) -> its cost and its benefit -> the evidence I bet it is wrong on -> what happens if change X lands -> why the scripts cannot see it. Severity comes from how soon X arrives, not from a score. Findings like "N violations found" or "consider refactoring" are rejected by contract: they carry no decision, no cost, no condition.
Full definitions, evidence-gathering steps, per-class explanations of why the scanners stay silent, and the case for not reporting a design problem: references/design-review.md.
Installation
Requires Python 3.10+ only. No dependencies to install.
git clone https://github.com/bfxh/arch-optimize.git
cd arch-optimize
python scripts/risk_diagnose.py --target ./src --jsonOptional: pip install -e . installs a metadata-only package (pyproject.toml declares no runtime dependencies); use pip install -e .[dev] to also get pytest.
Testing
python tests/test_smoke.py # zero-dependency smoke tests (standalone)
pytest # same suite via pytest, if installedThe suite builds a sample two-package project, runs all five scripts against it, asserts that each JSON payload contains the expected keys (plus one pkg_a -> pkg_b edge), checks that risk_diagnose output is deterministic, verifies that a real pass -> fail is reported as a regression and that compare exits non-zero for it, fails loudly when record fails instead of skipping, and pins the documented CLI surface: every flag used in SKILL.md/README.md must exist in the corresponding script's argparse, and references to non-existent helper scripts or to an untested Python version make the run fail. It also pins the design layer: references/design-review.md must exist with all seven problem classes and the five-part finding contract, SKILL.md must keep Stage Zero plus the "lead generator" framing, and no file under references/ may stay un-indexed.
Detectors that have a firing fixture: R1 (long/nested functions, via the density and self-scan checks), R2 (fan-out Warning/Critical thresholds, plus the top-level-normalization case pinned as "must not fire"), R3 cross-context downgrade, R4 (ABC with one implementation, and CC>20 — plus the duck-typed class Base: interface pinned as not recognized, so widening that detector fails the suite until the docs are corrected), R5 infrastructure word-boundary, R6 anemic two-tier, and the CC boolean-operator count. Scanner-wide invariants are pinned too: the four scripts must share one byte-identical ignore-dir table, their language tables may differ only by .java/.kt, and files under venv/env/testdata must stay out of every stage's analysis set. The skip itself is now reported: all four scanners emit skipped_dirs (dir name -> how many files inside it were never read), skipped_files_total and ignore_dirs_allowed, and the human-readable output prints the same detail; --allow-ignored-dir NAME puts a directory back in scope without editing the table, and risk_diagnose no longer says “looks healthy” on an empty result when directories were skipped (it says an empty result is not proof of absence instead). Also pinned now: R5 file-level cycles (_check_r5_cycle_fires — a two-file absolute cycle, a three-file chain, a same-package relative import, from .nested import b into a submodule, from . import sub into a sub-package __init__.py, and from ..b import z across one level; that last fixture only holds because a decoy b.py sits at the repo root, so the old basename fallback becomes ambiguous and an off-by-one in the level arithmetic fails the suite), plus a negative case proving a one-way relative import is not reported as a cycle, and _check_cross_lang_function_names (Rust/TS finding locations must carry the real function name for pub fn, pub async fn, export function and export async function — not pub/export/async). Two defensive branches in detect_r5 are knowingly not pinned: the seen_cycles dedup and the * filter on relative-import names are unobservable — measured 0 dedup hits across 20,000 random dependency graphs, and deleting the dedup produced identical output on the four corpora used to verify this change (this repo plus three cycle fixtures). SKILL.md 已知限制第 2 条 records them as insurance rather than verified behaviour, so nobody reads "cycles are deduped" as a tested property. Deliberately still uncovered: dep_graph's src/ collapse has no firing fixture, and the sample project keeps both packages at the repository root — the one layout that hides that collapse. Those blind spots are documented instead (SKILL.md 「已知限制」) rather than silently asserted-away.
One meta-guard: _check_all_assertions_wired() parses this file and fails if any _check_* function is defined but not called from test_smoke() (or called but missing). It exists because a check added without wiring reports green forever — that happened during this suite's development and was only caught by mutation testing.
The self-scan figures above are not taken on trust: _verify_readme_self_scan_claims() parses the four Critical/Warning counts and the MI range out of this README and recomputes them by running both scorers on scripts/, so editing a scanner without updating the paragraph fails the suite. R3's magic-number branch is pinned the same way (_check_r3_magic_literal_aggregation): 51 distinct literals must collapse to one Critical carrying metrics.distinct_literals == 51, and the ≥3-occurrence / cross-file conditions are pinned negatively (2 uses, or repetition inside a single file, must not report). _check_asymmetric_score_bounds() pins the regression score contract: bounded to [-1, 1], one vanished test = -0.5, and a single regression costing exactly twice a single fix. _check_action_pin_checker_bites() loads tests/check_action_pins.py with the upstream lookup stubbed out, so the pin verifier is falsifiable offline as well: a matching pin must be green (a ruler that is too strict is also broken), a mismatched pin red, an unresolvable tag red, and a pin missing its # v… comment must exit 1 rather than be skipped.
CI/CD Gates
Three workflows, and one gate that watches the gates:
Workflow | Blocks on | Deliberately not blocking |
|
| — (matrix has no ` |
|
|
|
|
|
|
_check_ci_workflows_are_strict() in the smoke suite re-reads those YAML files on every run and fails if:
an action is referenced by a mutable tag instead of a 40-character commit SHA;
a workflow lacks
permissions: contents: readat workflow level;any job lacks
timeout-minutes(a hung job holds a runner and never turns red);continue-on-erroror|| trueappears in a step that is not a declaredreport onlystep;a
pip installline is unpinned, or installs through an extras group (-e .[dev], whosepytest>=7.0would let the tool that judges us drift with PyPI);a workflow references a file that does not exist in the repo (e.g.
requirements.txt) — that branch never executes, so it is decoration, not setup;tests.ymlstops actually executingpytest, which SKILL.md/README promise as an entry point.tests/check_action_pins.pyis missing, or no workflow runs it from a non-comment line.
Nine mutations were run against this gate (unpinned action, dropped permissions, missing timeout, continue-on-error on a blocking step, unpinned pip, .[dev] install, phantom requirements.txt, removing the pytest run, and a negative control) — all eight breakages turn red and the negative control (|| true mentioned only inside a YAML comment) stays green, because comments are stripped before the checks look at the text.
A well-formed SHA is not a right SHA, so tests/check_action_pins.py closes the remaining hole: it parses every - uses: owner/repo@<40-sha> # v1.2.3 line, runs git ls-remote https://github.com/owner/repo refs/tags/v1.2.3^{} refs/tags/v1.2.3 (preferring the peeled commit so annotated tags compare as commits) and fails when the pinned SHA is not that tag, when the tag cannot be resolved at all, or when a pin is missing its version comment — unresolvable means red, never "not measured, so passed". Nine mutations were run against it: a real-shaped but wrong SHA (12 zeros), deleting the invocation line, making the SHA comparison constant-true, treating an unresolvable tag as a pass, dropping the missing-version shape check, and four that only weaken the readability of a verdict (the green case no longer prints OK, the mismatch line hides the upstream SHA, the unresolvable line drops the FAIL prefix, the shape line loses file:line). All nine turn red. The fourth does so by crashing with a TypeError on the removed guard branch rather than by printing a clean FAIL, so it proves "the run goes red", not "the message is readable". This job needs the network, so an offline runner turns red by design.
tests.yml intentionally has no paths: filter, so editing a workflow alone still runs the suite — that is what keeps this section honest. concurrency.cancel-in-progress is disabled for pushes to main so the record of which commit was verified never gets cancelled mid-flight.
Self-Scan Note
Running these tools on this repository itself reports poor numbers: over scripts/ the average MI is about 22, and all five scanners sit below the 15 gate (0.0–9.8) — the only file clearing it is the two-line __init__.py. Both scorers return health 0, risk_diagnose from 32 Critical + 47 Warning and quality_metrics from 13 Critical + 7 Warning. These figures move every time the scanners themselves change length: risk_diagnose.py now scores MI 0.0 purely because of its own size, which is precisely the artifact being illustrated — MI here is computed per whole file and dominated by the 16.2·ln(LOC) term, the health score subtracts a flat 15 per finding with no normalization by code volume (health_score now also reports scanned_lines and penalty_per_kloc so cross-project comparison has an anchor; score itself stays absolute so the gate contract is unchanged), and the two scorers run different detectors over different file sets, hence different inputs for the same directory. The four numbers above are pinned by _check_self_scan_claims() in the smoke suite, so if they drift the run fails and the paragraph must be updated rather than silently going stale.
The scanners target production codebases, not skill packages bundled with scripts-as-data. Treat self-scan results as demo output, not a quality claim about your project.
Usage
# Stage 1: architecture perception
python3 scripts/arch_scan.py --target ./src --json
python3 scripts/dep_graph.py --target ./src --json
# Stage 2: risk diagnosis
python3 scripts/risk_diagnose.py --target ./src --json
python3 scripts/risk_diagnose.py --target ./src --risk R5 --min-severity Critical --json
# Stage 3: quality metrics
python3 scripts/quality_metrics.py --target ./src --json
python3 scripts/quality_metrics.py --file src/main.py --json
# Stage 5: regression guard
python3 scripts/regression_guard.py record --output baseline.json --test-cmd "python -m pytest -v"
python3 scripts/regression_guard.py compare --baseline baseline.json --current current.json --json
# 有意的测试删除要逐条放行,否则会判红(见 Quality Gate Rules 下)
python3 scripts/regression_guard.py compare --baseline baseline.json --current current.json \
--allow-removed test_removed_on_purposeTypical agent pipeline: stage zero design judgement (questions + evidence, no script) → arch_scan → dep_graph → risk_diagnose → quality_metrics → regression_guard, passing each stage's JSON as context to the next. Scripts narrow the suspicion; they do not close it.
Two caveats when chaining them: arch_scan embeds a scan_timestamp, so two runs are byte-different across a second boundary and must not be diffed naively; dep_graph treats the first directory level under --target as a module, so pointing it at a repository root with a src/ layout collapses every file into one src node and yields an empty graph — point it at the module root instead.
Supported Languages
Python (.py via ast), Go, C/C++, Rust, TypeScript/JavaScript, plus Java/Kotlin — but not every script sees every language: .java/.kt are only in arch_scan and quality_metrics, while dep_graph and risk_diagnose have no Java/Kotlin detectors and therefore skip those files entirely (measured: on a fixture with one .java + one .kt + one .py, quality_metrics reported 5 files analyzed, risk_diagnose 1). The pinned assertion is that this is the only remaining difference between the four language tables.
For non-Python languages, CC and function extents still come from regex plus brace counting: comments and string literals pollute brace matching, and switch/match counts both the construct and its case arms. Boolean operators (&&, ||), the ternary ? and Rust => arms are counted now — they used to be wrapped in a \b(...)\b group where punctuation can never match, which silently under-counted CC (an if with seven && reported 2 instead of 9). Treat these numbers as hints, not verdicts.
Quality Gate Rules
Gate | Threshold | Type | Failure Behavior |
Zero regression rate | = 100% | Hard | Block PR merge |
Health score | >= 70 | Soft | Warning + manual approval |
New code MI | >= 15 | Hard | Block PR merge |
Cyclomatic complexity | <= 15 | Hard | Block PR merge (Python only; see Supported Languages) |
Circular dependencies | = 0 | Hard | Block PR merge |
The MI and CC rows are thresholds you enforce yourself — no script judges "new code" or exits non-zero on CC; see SKILL.md 的「质量门禁」列(含每条"脚本能否直接判红")。non_asymmetric_score 现在有界([-1,1],2:1 非对称,由 _check_asymmetric_score_bounds 钉住),但它依旧不是判合并的依据。
Only the regression gate is enforceable straight from an exit code, and it now covers both failure modes: a previously-passing test failing and a previously-passing test disappearing (delete, rename, skip, or an emptied suite) — the latter fails unless each name is allow-listed with --allow-removed / --allow-removed-file. Deleting a test that was already failing is allowed. A runnable workflow using only the scripts in this repo is in references/regression-guard.md §5.1.
Design Principles
Diagnosis before fix: never propose fixes before completing risk diagnosis
Incremental over large-scale: at most 5 improvement requirements per iteration
Zero regression tolerance: breaking existing functionality costs more than adding features
Division of labor over omniscience: architect handles strategy, programmer handles execution
Quantitative as evidence, not verdict: MI and health score are repeatable baselines for the same scope over time; they are heuristic proxies, and architecture-level judgement (layering, boundaries, whether an abstraction earns its keep) stays with the reader
False positive protection: avoid misclassifying normal design pattern usage as violations — note that several guards suppress real findings too (see §四 of architecture-principles.md), so absence of a finding is not absence of a problem
Executable over pure documentation: every rule has a corresponding script implementation
Project Structure
arch-optimize/
├── SKILL.md # Skill definition and workflow documentation
├── README.md
├── LICENSE # MIT License
├── pyproject.toml # Metadata only, no runtime deps
├── .github/workflows/ # tests.yml (smoke + pytest), ruff.yml, mypy.yml
├── tests/
│ └── test_smoke.py # Zero-dep suite; also gates the CI config itself
├── scripts/
│ ├── arch_scan.py # Stage 1: architecture perception
│ ├── dep_graph.py # Stage 1: dependency graph + cycle detection
│ ├── risk_diagnose.py # Stage 2: R1-R6 diagnosis
│ ├── quality_metrics.py # Stage 3: MI/CC/HV/health score
│ └── regression_guard.py # Stage 5: baseline record & compare
└── references/ # 7 docs, load on demand per SKILL.md index
├── design-review.md # Stage 0: seven classes of design problem + five-part finding contract
├── architecture-principles.md # Clean Architecture, SOLID thresholds, R1-R6 detail + measured script caliber
├── coding-conventions.md # C/C++/Rust/Go/TypeScript conventions
├── quality-metrics.md # MI formula details, tech debt Pain×Spread ranking
├── regression-guard.md # Zero regression rate, asymmetric scoring, CI gate
├── collaboration-workflow.md # Architect-programmer dual-agent workflow
└── engineering-responsibility.md # Root philosophy, src/bin project layout rulesCompanion Skills
Split out of this repo into standalone skills:
anti-ai-flavor: AI-flavor detection for code and docs (
detect_code_ai.py,detect_text_ai.py, 18-pattern catalog)vuln-hunting: local security scanning and hardening (
vuln-scan.ps1,wf.ps1)project-launcher: meta-orchestration skill for starting any project
License
MIT License. See LICENSE for details.
捐赠支持 (Donate)
如果这个项目对你有帮助,可以请我喝杯咖啡 ☕ 感谢支持!

你也可以看看我的 unified-rx-mcp。
This server cannot be deployed
Maintenance
Related MCP Connectors
MCP server for static security analysis of Android source code
Repository knowledge graph MCP server for codebase understanding and debugging.
MCP server for secureFlows: token-free URL builders and integration-linting tools for AI agents.
AI-native git hosting — repos, PRs, issues, CI gates, and AI code review over MCP (60 tools).
Related MCP Servers
AlicenseNot gradedqualityAmaintenanceMCP server that gives AI assistants impact analysis, cross-project reference tracking, and code health scoring.162 PyPI4Apache 2.0- FlicenseNot gradedqualityDmaintenanceMCP server for automated architectural mapping, security vulnerability detection, ML asset tracking, and code metrics in local repositories.-
- AlicenseAqualityAmaintenanceAn MCP server that provides local code quality analysis for AI coding assistants, supporting file analysis, git diff review, and full project scanning with quality scoring.540 PyPI3MIT
- FlicenseNot gradedqualityDmaintenanceMCP server for AI coding agents that builds a complete code structure graph and semantic vector index, enabling fast querying of code entities, relationships, and impact analysis.20 npm11-