clean-code-tools 1.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (77) hide show
  1. package/README.md +66 -0
  2. package/configs/eslint.clean-code.recommended.mjs +211 -0
  3. package/configs/python.clean-code.pyproject.toml +143 -0
  4. package/data/clean-code-patterns.jsonl +264 -0
  5. package/data/vector-record.schema.json +77 -0
  6. package/docs/README.md +29 -0
  7. package/docs/eslint-custom-rules.md +74 -0
  8. package/docs/eslint-recommended-config.md +87 -0
  9. package/docs/fastmcp-local-server.md +104 -0
  10. package/docs/publishing.md +125 -0
  11. package/docs/python-lint-recommended-config.md +57 -0
  12. package/docs/python-pylint-custom-rules.md +77 -0
  13. package/docs/semantic-weaviate.md +80 -0
  14. package/docs/static-trigger-semantic-review.md +97 -0
  15. package/evals/clean-code-retrieval.jsonl +13 -0
  16. package/ops/dev/weaviate/README.md +34 -0
  17. package/ops/dev/weaviate/compose.yaml +34 -0
  18. package/ops/dev/weaviate/smoke.sh +28 -0
  19. package/package.json +96 -0
  20. package/pyproject.toml +303 -0
  21. package/sample-apps/README.md +40 -0
  22. package/sample-apps/python-app/pyproject.toml +113 -0
  23. package/sample-apps/python-app/src/clean_pricing.py +10 -0
  24. package/sample-apps/python-app/src/smelly_pricing.py +8 -0
  25. package/sample-apps/ts-backend/eslint.config.mjs +3 -0
  26. package/sample-apps/ts-backend/package.json +18 -0
  27. package/sample-apps/ts-backend/src/clean-handler.ts +19 -0
  28. package/sample-apps/ts-backend/src/smelly-handler.ts +29 -0
  29. package/sample-apps/ts-backend/tsconfig.json +9 -0
  30. package/sample-apps/ts-frontend/eslint.config.mjs +3 -0
  31. package/sample-apps/ts-frontend/package.json +18 -0
  32. package/sample-apps/ts-frontend/src/CleanWidget.tsx +18 -0
  33. package/sample-apps/ts-frontend/src/SmellyWidget.tsx +27 -0
  34. package/sample-apps/ts-frontend/tsconfig.json +10 -0
  35. package/scripts/_mcp_app.py +21 -0
  36. package/scripts/check_clean_code_review_candidates.py +302 -0
  37. package/scripts/check_fastmcp_server.py +106 -0
  38. package/scripts/check_packages.py +137 -0
  39. package/scripts/check_python_config.py +130 -0
  40. package/scripts/check_repo_python_lint.py +46 -0
  41. package/scripts/check_retrieval_evals.py +132 -0
  42. package/scripts/check_sample_apps.py +169 -0
  43. package/scripts/check_semantic_search_tooling.py +102 -0
  44. package/scripts/clean_code_eslint_triggers.py +272 -0
  45. package/scripts/clean_code_mcp_server.py +7 -0
  46. package/scripts/clean_code_python_triggers.py +318 -0
  47. package/scripts/clean_code_review_candidates.py +291 -0
  48. package/scripts/clean_code_review_io.py +36 -0
  49. package/scripts/clean_code_review_models.py +43 -0
  50. package/scripts/clean_code_semantic.py +27 -0
  51. package/scripts/set_package_versions.py +82 -0
  52. package/scripts/weaviate_ingest_clean_code.py +44 -0
  53. package/scripts/weaviate_search_clean_code.py +51 -0
  54. package/skills/clean-code-mcp-reviewer/SKILL.md +209 -0
  55. package/skills/clean-code-mcp-reviewer/evals/evals.json +30 -0
  56. package/src/js/eslint-plugin-clean-code.mjs +758 -0
  57. package/src/python/clean_code_tools_pylint/__init__.py +14 -0
  58. package/src/python/clean_code_tools_pylint/ast_checker.py +122 -0
  59. package/src/python/clean_code_tools_pylint/comments.py +83 -0
  60. package/src/python/clean_code_tools_pylint/helpers.py +196 -0
  61. package/src/python/mcp_server/__init__.py +1 -0
  62. package/src/python/mcp_server/corpus.py +160 -0
  63. package/src/python/mcp_server/markdown.py +126 -0
  64. package/src/python/mcp_server/models.py +73 -0
  65. package/src/python/mcp_server/ranking.py +125 -0
  66. package/src/python/mcp_server/ranking_scoring.py +232 -0
  67. package/src/python/mcp_server/semantic.py +192 -0
  68. package/src/python/mcp_server/server.py +235 -0
  69. package/src/python/mcp_server/server_payloads.py +83 -0
  70. package/src/python/mcp_server/text.py +104 -0
  71. package/src/python/mcp_server/utils/__init__.py +1 -0
  72. package/src/python/mcp_server/utils/httpx_loader.py +14 -0
  73. package/src/python/mcp_server/utils/increment.py +7 -0
  74. package/src/python/mcp_server/utils/sha256_text.py +8 -0
  75. package/src/python/mcp_server/utils/unique_strings.py +15 -0
  76. package/src/python/mcp_server/weaviate.py +182 -0
  77. package/uv.lock +2012 -0
@@ -0,0 +1,80 @@
1
+ # Semantic Weaviate Search
2
+
3
+ This repo uses local Weaviate with self-provided vectors. Weaviate stores chunks and performs vector search; Python generates CPU embeddings with FastEmbed.
4
+
5
+ ## Local Setup
6
+
7
+ ```bash
8
+ uv sync
9
+ bun run weaviate:dev:start
10
+ bun run weaviate:dev:smoke
11
+ ```
12
+
13
+ If port `8080` is busy:
14
+
15
+ ```bash
16
+ WEAVIATE_HTTP_PORT=18080 WEAVIATE_GRPC_PORT=15051 bun run weaviate:dev:start
17
+ WEAVIATE_HTTP_PORT=18080 bun run weaviate:dev:smoke
18
+ ```
19
+
20
+ ## Ingest
21
+
22
+ ```bash
23
+ bun run semantic:chunks
24
+ bun run semantic:ingest -- --reset
25
+ ```
26
+
27
+ The default collection is `CleanCodeChunks`. The default embedding model is `BAAI/bge-small-en-v1.5`, running through `fastembed/cpu`.
28
+
29
+ ## Search
30
+
31
+ ```bash
32
+ bun run semantic:search -- "boolean flag argument"
33
+ bun run semantic:search -- "comments that explain bad code"
34
+ bun run semantic:search -- "train wreck deep property chain"
35
+ bun run semantic:search -- "too many function arguments"
36
+ ```
37
+
38
+ Expected useful matches include:
39
+
40
+ - `boolean flag argument`: `CC-043`, `CC-208`, `CC-224`
41
+ - `comments that explain bad code`: `CC-060`, `CC-071`, `CC-073`
42
+ - `train wreck deep property chain`: `CC-107`, `CC-245`
43
+ - `too many function arguments`: `CC-041`, `CC-045`, `CC-206`
44
+
45
+ The MCP pattern search builds on this chunk search but adds a pattern-first
46
+ retrieval layer:
47
+
48
+ - overfetch semantic matches from Weaviate
49
+ - add local exact matches over pattern IDs, titles, aliases, and lint candidates
50
+ - filter by source kind, language, rule family, topic, and lintability
51
+ - rerank with transparent semantic, lexical, metadata, and context scores
52
+ - deduplicate by `record_id`
53
+ - return `no_strong_match` for weak or conservative contexts
54
+
55
+ Run the offline retrieval evals with:
56
+
57
+ ```bash
58
+ bun run check:retrieval-evals
59
+ ```
60
+
61
+ ## Chunking
62
+
63
+ The ingestion builds two chunk families:
64
+
65
+ - `pattern_record`: one chunk per canonical `data/clean-code-patterns.jsonl` record
66
+ - `markdown_section`: one chunk per heading section in markdown docs
67
+
68
+ Markdown parsing is code-fence aware and preserves code blocks with the nearest semantic section. Oversized sections are split by paragraph/code-block groups instead of arbitrary character windows.
69
+
70
+ ## Schema
71
+
72
+ The collection uses a named self-provided vector:
73
+
74
+ ```text
75
+ collection: CleanCodeChunks
76
+ vector: content
77
+ vectorizer: none
78
+ ```
79
+
80
+ Stored properties include source identity, section path, clean-code rule metadata, lintability, language hints, `contentText`, `embeddingText`, `textHash`, `chunkerVersion`, `embeddingModel`, and `embeddingProvider`.
@@ -0,0 +1,97 @@
1
+ # Static Trigger to Semantic Review
2
+
3
+ This repo uses deterministic lint rules as tripwires for deeper clean-code
4
+ review. The static layer stays fast and reproducible; the semantic layer decides
5
+ whether a finding is a real maintainability issue and what refactor would be
6
+ safe.
7
+
8
+ ## Flow
9
+
10
+ ```text
11
+ ESLint / Pylint / Ruff
12
+ -> clean-code review candidates
13
+ -> clean-code-mcp-reviewer skill
14
+ -> clean-code MCP pattern lookup
15
+ -> advisory finding or refactor plan
16
+ -> normal tests and lint verification
17
+ ```
18
+
19
+ The scanner output uses schema `clean-code-review-candidates/v1`. Each
20
+ candidate contains:
21
+
22
+ - `language`
23
+ - `file`
24
+ - `symbol`
25
+ - `anchor`
26
+ - `skill`
27
+ - deterministic `triggers`
28
+ - `semantic_questions`
29
+ - suggested `mcp_queries`
30
+
31
+ ## Run
32
+
33
+ From lint JSON files:
34
+
35
+ ```bash
36
+ bun run clean-code:candidates -- \
37
+ --eslint-json eslint-report.json \
38
+ --pylint-json pylint-report.json \
39
+ --ruff-json ruff-report.json
40
+ ```
41
+
42
+ From lint commands:
43
+
44
+ ```bash
45
+ bun run clean-code:candidates -- \
46
+ --pylint-command "uv run --group lint pylint src/python/mcp_server --output-format=json" \
47
+ --ruff-command "uv run --group lint ruff check src/python/mcp_server --output-format=json"
48
+ ```
49
+
50
+ Markdown is useful for agent prompts:
51
+
52
+ ```bash
53
+ bun run clean-code:candidates -- \
54
+ --pylint-command "uv run --group lint pylint src/python/mcp_server --output-format=json" \
55
+ --ruff-command "uv run --group lint ruff check src/python/mcp_server --output-format=json" \
56
+ --format markdown
57
+ ```
58
+
59
+ ## Trigger Policy
60
+
61
+ Only rules with a strong relationship to maintainability are promoted into
62
+ semantic candidates. Formatting and ordinary style rules are intentionally
63
+ ignored.
64
+
65
+ Good triggers include:
66
+
67
+ - large files, functions, or classes
68
+ - high complexity or nesting
69
+ - too many arguments, locals, statements, branches, or public methods
70
+ - duplicated branches or functions
71
+ - boolean flag arguments
72
+ - output argument mutation
73
+ - TODO/comment hygiene, commented-out code, and traceable technical debt
74
+ - policy literals, magic values, duplicate strings, and repeated domain values
75
+ - train-wreck object navigation, broad imports, and dependency cycles
76
+ - dead stores, unused symbols, and incomplete cleanup
77
+
78
+ The trigger is not the recommendation. For example, `max-lines` means "inspect
79
+ this file for mixed responsibilities"; it does not mean "split the file."
80
+
81
+ ## Agent Contract
82
+
83
+ `skill` is always `clean-code-mcp-reviewer`. The candidate does not name
84
+ language-specific skills because consuming systems may only install this repo's
85
+ MCP reviewer skill.
86
+
87
+ Agents should:
88
+
89
+ 1. Read the candidate's file plus its `symbol` or `anchor` first.
90
+ 2. Confirm or reject the semantic questions using local code evidence.
91
+ 3. Query the MCP narrowly with the suggested query or a refined one.
92
+ 4. Suppress weak matches.
93
+ 5. Produce a scoped refactor plan only when it preserves behavior and follows
94
+ local conventions.
95
+
96
+ This keeps the deterministic check useful without turning clean-code guidance
97
+ into noisy doctrine.
@@ -0,0 +1,13 @@
1
+ {"id":"flag-argument-ts","query":"typescript boolean parameter controls behavior selector argument calculatePrice true false","language":"typescript","expected_top_ids":["CC-043","CC-208"],"vector_ids":["CC-047","CC-043","CC-208","CC-195"],"should_strong_match":true}
2
+ {"id":"todo-without-issue","query":"TODO fix this later comment without issue id","language":"typescript","expected_top_ids":["CC-068"],"vector_ids":["CC-064","CC-068","CC-071","CC-012"],"should_strong_match":true}
3
+ {"id":"train-wreck","query":"deep property chain account owner address city train wreck transitive navigation","language":"typescript","expected_top_ids":["CC-107"],"vector_ids":["CC-106","CC-107","CC-245","CC-001"],"should_strong_match":true}
4
+ {"id":"output-argument-python","query":"python function mutates output argument errors list and returns status","language":"python","expected_top_ids":["CC-050","CC-207"],"vector_ids":["CC-047","CC-050","CC-207","CC-052"],"should_strong_match":true}
5
+ {"id":"tracked-todo-nearmiss","query":"TODO(PROJ-123) remove legacy fallback after migration tracked issue marker","language":"typescript","expected_top_ids":["CC-068"],"vector_ids":["CC-068","CC-064","CC-071"],"should_strong_match":false}
6
+ {"id":"generated-fixture-nearmiss","query":"generated api client fixture deep dto property chain hard coded fixture literal","language":"typescript","expected_top_ids":["CC-107"],"vector_ids":["CC-107","CC-002","CC-245"],"should_strong_match":false}
7
+ {"id":"vague-nonsense","query":"do this thing with code","language":"typescript","expected_top_ids":[],"vector_ids":["CC-001","CC-012","CC-191"],"should_strong_match":false}
8
+ {"id":"broad-comment-category","query":"python comment","language":"python","expected_top_ids":[],"vector_ids":["CC-199","CC-200","CC-201"],"should_strong_match":false}
9
+ {"id":"broad-error-category","query":"error handling","language":"typescript","expected_top_ids":[],"vector_ids":["CC-054","CC-112","CC-113"],"should_strong_match":false}
10
+ {"id":"generic-clean-code","query":"clean code","language":"typescript","expected_top_ids":[],"vector_ids":["CC-001","CC-012","CC-191"],"should_strong_match":false}
11
+ {"id":"generic-code-smell","query":"code smell","language":"python","expected_top_ids":[],"vector_ids":["CC-199","CC-200","CC-201"],"should_strong_match":false}
12
+ {"id":"generic-planning-guidance","query":"planning guidance","language":"typescript","expected_top_ids":[],"vector_ids":["CC-001","CC-012","CC-191"],"should_strong_match":false}
13
+ {"id":"generic-refactoring-rule","query":"refactoring rule","language":"python","expected_top_ids":[],"vector_ids":["CC-050","CC-107","CC-207"],"should_strong_match":false}
@@ -0,0 +1,34 @@
1
+ # Local Weaviate
2
+
3
+ This stack runs a local Weaviate instance for clean-code semantic search.
4
+
5
+ It uses the same shape as the BusyBots local stack:
6
+
7
+ - no Weaviate vectorizer module
8
+ - anonymous local access
9
+ - self-provided vectors inserted by Python tooling
10
+ - HTTP on `http://127.0.0.1:8080`
11
+ - gRPC on `127.0.0.1:50051`
12
+ - persistent Docker volume `clean-code-tools-weaviate_weaviate_data`
13
+
14
+ ## Commands
15
+
16
+ From the repo root:
17
+
18
+ ```bash
19
+ uv sync
20
+ bun run weaviate:dev:start
21
+ bun run weaviate:dev:smoke
22
+ bun run weaviate:dev:status
23
+ bun run weaviate:dev:logs
24
+ bun run weaviate:dev:stop
25
+ ```
26
+
27
+ If port `8080` is already taken:
28
+
29
+ ```bash
30
+ WEAVIATE_HTTP_PORT=18080 WEAVIATE_GRPC_PORT=15051 bun run weaviate:dev:start
31
+ WEAVIATE_HTTP_PORT=18080 bun run weaviate:dev:smoke
32
+ ```
33
+
34
+ The semantic ingestion scripts default to `WEAVIATE_URL=http://127.0.0.1:8080`.
@@ -0,0 +1,34 @@
1
+ name: clean-code-tools-weaviate
2
+
3
+ services:
4
+ weaviate:
5
+ image: cr.weaviate.io/semitechnologies/weaviate:1.38.1
6
+ mem_limit: "${WEAVIATE_MEMORY_LIMIT:-4g}"
7
+ command:
8
+ - --host
9
+ - 0.0.0.0
10
+ - --port
11
+ - "8080"
12
+ - --scheme
13
+ - http
14
+ ports:
15
+ - "${WEAVIATE_HTTP_PORT:-8080}:8080"
16
+ - "${WEAVIATE_GRPC_PORT:-50051}:50051"
17
+ restart: on-failure:0
18
+ environment:
19
+ AUTHENTICATION_ANONYMOUS_ACCESS_ENABLED: "true"
20
+ CLUSTER_HOSTNAME: node1
21
+ DEFAULT_VECTORIZER_MODULE: none
22
+ DISABLE_TELEMETRY: "${WEAVIATE_DISABLE_TELEMETRY:-true}"
23
+ ENABLE_MODULES: ""
24
+ ASYNC_INDEXING: "${WEAVIATE_ASYNC_INDEXING:-true}"
25
+ GOMEMLIMIT: "${WEAVIATE_GOMEMLIMIT:-3072MiB}"
26
+ GOMAXPROCS: "${WEAVIATE_GOMAXPROCS:-4}"
27
+ PERSISTENCE_DATA_PATH: /var/lib/weaviate
28
+ QUERY_DEFAULTS_LIMIT: "${WEAVIATE_QUERY_DEFAULTS_LIMIT:-100}"
29
+ volumes:
30
+ - weaviate_data:/var/lib/weaviate
31
+
32
+ volumes:
33
+ weaviate_data:
34
+
@@ -0,0 +1,28 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+
4
+ http_port="${WEAVIATE_HTTP_PORT:-8080}"
5
+ base_url="http://127.0.0.1:${http_port}"
6
+
7
+ ready_url="${base_url}/v1/.well-known/ready"
8
+ meta_url="${base_url}/v1/meta"
9
+ ready=false
10
+
11
+ for _attempt in $(seq 1 60); do
12
+ if curl -fsS "${ready_url}" >/dev/null 2>&1; then
13
+ ready=true
14
+ break
15
+ fi
16
+ sleep 1
17
+ done
18
+
19
+ if [[ "${ready}" != "true" ]]; then
20
+ echo "Weaviate did not become ready at ${base_url}" >&2
21
+ curl -sS "${ready_url}" || true
22
+ exit 1
23
+ fi
24
+
25
+ curl -fsS "${meta_url}" | python3 -m json.tool >/dev/null
26
+
27
+ echo "Weaviate ready at ${base_url}"
28
+
package/package.json ADDED
@@ -0,0 +1,96 @@
1
+ {
2
+ "name": "clean-code-tools",
3
+ "version": "1.0.1",
4
+ "description": "Clean-code pattern corpus and lint tooling.",
5
+ "type": "module",
6
+ "packageManager": "bun@1.3.13",
7
+ "homepage": "https://github.com/wnz99/clean-code-tools#readme",
8
+ "bugs": {
9
+ "url": "https://github.com/wnz99/clean-code-tools/issues"
10
+ },
11
+ "repository": {
12
+ "type": "git",
13
+ "url": "git+https://github.com/wnz99/clean-code-tools.git"
14
+ },
15
+ "main": "src/js/eslint-plugin-clean-code.mjs",
16
+ "exports": {
17
+ ".": "./src/js/eslint-plugin-clean-code.mjs",
18
+ "./eslint-plugin": "./src/js/eslint-plugin-clean-code.mjs",
19
+ "./configs/eslint.clean-code.recommended.mjs": "./configs/eslint.clean-code.recommended.mjs",
20
+ "./configs/python.clean-code.pyproject.toml": "./configs/python.clean-code.pyproject.toml"
21
+ },
22
+ "files": [
23
+ "configs/",
24
+ "docs/",
25
+ "evals/",
26
+ "data/",
27
+ "pyproject.toml",
28
+ "uv.lock",
29
+ "sample-apps/",
30
+ "scripts/*.py",
31
+ "skills/",
32
+ "ops/",
33
+ "src/python/clean_code_tools_pylint/*.py",
34
+ "src/js/eslint-plugin-clean-code.mjs",
35
+ "src/python/mcp_server/*.py",
36
+ "src/python/mcp_server/utils/*.py",
37
+ "README.md",
38
+ "package.json"
39
+ ],
40
+ "directories": {
41
+ "doc": "docs"
42
+ },
43
+ "scripts": {
44
+ "test": "bun test tests/*.test.mjs",
45
+ "test:eslint-plugin": "bun test tests/eslint-plugin-clean-code.test.mjs",
46
+ "check:python-config": "uv run --group lint python scripts/check_python_config.py",
47
+ "check:sample-apps": "uv run --group lint python scripts/check_sample_apps.py",
48
+ "check:semantic-search": "uv run python scripts/check_semantic_search_tooling.py",
49
+ "check:review-candidates": "uv run python scripts/check_clean_code_review_candidates.py",
50
+ "check:retrieval-evals": "uv run python scripts/check_retrieval_evals.py",
51
+ "check:python-repo-lint": "uv run --group lint python scripts/check_repo_python_lint.py",
52
+ "check:packages": "uv run python scripts/check_packages.py",
53
+ "check:fastmcp": "uv run python scripts/check_fastmcp_server.py",
54
+ "weaviate:dev:start": "docker compose -f ops/dev/weaviate/compose.yaml up -d",
55
+ "weaviate:dev:stop": "docker compose -f ops/dev/weaviate/compose.yaml down",
56
+ "weaviate:dev:status": "docker compose -f ops/dev/weaviate/compose.yaml ps",
57
+ "weaviate:dev:logs": "docker compose -f ops/dev/weaviate/compose.yaml logs -f weaviate",
58
+ "weaviate:dev:smoke": "bash ops/dev/weaviate/smoke.sh",
59
+ "semantic:chunks": "uv run python scripts/clean_code_semantic.py",
60
+ "clean-code:candidates": "uv run python scripts/clean_code_review_candidates.py",
61
+ "semantic:ingest": "uv run python scripts/weaviate_ingest_clean_code.py",
62
+ "semantic:search": "uv run python scripts/weaviate_search_clean_code.py",
63
+ "mcp:stdio": "uv run python scripts/clean_code_mcp_server.py",
64
+ "mcp:http": "uv run python scripts/clean_code_mcp_server.py --transport http --host 127.0.0.1 --port 8765",
65
+ "check": "bun --check src/js/eslint-plugin-clean-code.mjs && bun --check configs/eslint.clean-code.recommended.mjs && bun test && bun run check:python-config && bun run check:sample-apps && bun run check:semantic-search && bun run check:review-candidates && bun run check:retrieval-evals && bun run check:python-repo-lint && bun run check:packages"
66
+ },
67
+ "keywords": [
68
+ "clean-code",
69
+ "eslint",
70
+ "pylint",
71
+ "ruff",
72
+ "mcp",
73
+ "static-analysis"
74
+ ],
75
+ "author": "",
76
+ "license": "UNLICENSED",
77
+ "engines": {
78
+ "node": "^22.13.0 || >=24"
79
+ },
80
+ "peerDependencies": {
81
+ "@eslint/js": "^10.0.0",
82
+ "eslint": "^10.4.0",
83
+ "eslint-plugin-sonarjs": "^4.0.0",
84
+ "eslint-plugin-unicorn": "^69.0.0",
85
+ "typescript-eslint": "^8.0.0"
86
+ },
87
+ "devDependencies": {
88
+ "@eslint/js": "^10.0.1",
89
+ "@typescript-eslint/parser": "^8.0.0",
90
+ "eslint": "^10.6.0",
91
+ "eslint-plugin-sonarjs": "^4.1.0",
92
+ "eslint-plugin-unicorn": "^69.0.0",
93
+ "typescript": "^5.0.0",
94
+ "typescript-eslint": "^8.0.0"
95
+ }
96
+ }
package/pyproject.toml ADDED
@@ -0,0 +1,303 @@
1
+ #:schema https://json.schemastore.org/pyproject.json
2
+
3
+ [build-system]
4
+ requires = ["hatchling>=1.27.0"]
5
+ build-backend = "hatchling.build"
6
+
7
+ [project]
8
+ name = "clean-code-tools-python"
9
+ version = "1.0.1"
10
+ description = "Python clean-code lint plugin and recommended Ruff/Pylint config."
11
+ readme = "README.md"
12
+ requires-python = ">=3.12"
13
+ keywords = [
14
+ "clean-code",
15
+ "pylint",
16
+ "ruff",
17
+ "static-analysis",
18
+ ]
19
+ dependencies = [
20
+ "pylint>=4.0.0",
21
+ "ruff>=0.15.0",
22
+ ]
23
+
24
+ [project.urls]
25
+ Homepage = "https://github.com/wnz99/clean-code-tools"
26
+ Repository = "https://github.com/wnz99/clean-code-tools"
27
+ Issues = "https://github.com/wnz99/clean-code-tools/issues"
28
+ Documentation = "https://github.com/wnz99/clean-code-tools/tree/main/docs"
29
+
30
+ [dependency-groups]
31
+ lint = [
32
+ "ruff>=0.15.0",
33
+ "pylint>=4.0.0",
34
+ ]
35
+ mcp = [
36
+ "fastembed>=0.8.0",
37
+ "fastmcp>=2.0.0",
38
+ "httpx>=0.27.0",
39
+ ]
40
+ typecheck = [
41
+ "pyright>=1.1.403",
42
+ ]
43
+
44
+ [tool.hatch.build.targets.wheel]
45
+ packages = ["src/python/clean_code_tools_pylint"]
46
+
47
+ [tool.hatch.build.targets.wheel.force-include]
48
+ "configs/python.clean-code.pyproject.toml" = "clean_code_tools_pylint/configs/python.clean-code.pyproject.toml"
49
+
50
+ [tool.ruff]
51
+ target-version = "py312"
52
+ line-length = 100
53
+ fix = true
54
+ show-fixes = true
55
+ output-format = "grouped"
56
+ extend-exclude = [
57
+ ".git",
58
+ ".mypy_cache",
59
+ ".nox",
60
+ ".ruff_cache",
61
+ ".tox",
62
+ ".venv",
63
+ "__pycache__",
64
+ "build",
65
+ "dist",
66
+ "node_modules",
67
+ "sample-apps",
68
+ ]
69
+
70
+ [tool.ruff.lint]
71
+ select = [
72
+ "E",
73
+ "W",
74
+ "F",
75
+ "I",
76
+ "UP",
77
+ "B",
78
+ "C4",
79
+ "SIM",
80
+ "RET",
81
+ "PTH",
82
+ "TID",
83
+ "RUF",
84
+ "S",
85
+ "BLE",
86
+ "A",
87
+ "G",
88
+ "TRY",
89
+ "FA",
90
+ "ISC",
91
+ "ICN",
92
+ "PIE",
93
+ "T20",
94
+ "Q",
95
+ "RSE",
96
+ "PERF",
97
+ "FURB",
98
+ "LOG",
99
+ "FBT",
100
+ "COM",
101
+ "INP",
102
+ "ARG",
103
+ "ERA",
104
+ "TD",
105
+ "PGH",
106
+ "PL",
107
+ "PYI",
108
+ ]
109
+ ignore = [
110
+ "E501",
111
+ "COM812",
112
+ "ISC001",
113
+ "TD001",
114
+ ]
115
+ fixable = [
116
+ "E",
117
+ "W",
118
+ "F",
119
+ "I",
120
+ "UP",
121
+ "B",
122
+ "C4",
123
+ "SIM",
124
+ "RET",
125
+ "PTH",
126
+ "TID",
127
+ "RUF",
128
+ "S",
129
+ "BLE",
130
+ "A",
131
+ "G",
132
+ "TRY",
133
+ "FA",
134
+ "ISC",
135
+ "ICN",
136
+ "PIE",
137
+ "T20",
138
+ "Q",
139
+ "RSE",
140
+ "PERF",
141
+ "FURB",
142
+ "LOG",
143
+ "FBT",
144
+ "COM",
145
+ "INP",
146
+ "ARG",
147
+ "PGH",
148
+ "PL",
149
+ "PYI",
150
+ ]
151
+ unfixable = [
152
+ "ERA",
153
+ "TD",
154
+ "PLR2004",
155
+ ]
156
+
157
+ [tool.ruff.lint.isort]
158
+ known-first-party = []
159
+ combine-as-imports = true
160
+ split-on-trailing-comma = true
161
+
162
+ [tool.ruff.lint.per-file-ignores]
163
+ "scripts/**/*.py" = [
164
+ "T201",
165
+ ]
166
+ "scripts/check_*.py" = [
167
+ "S101",
168
+ "PLC0415",
169
+ "S603",
170
+ "TRY003",
171
+ "FBT001",
172
+ "FBT002",
173
+ "PLR2004",
174
+ ]
175
+ "scripts/clean_code_eslint_triggers.py" = [
176
+ "INP001",
177
+ ]
178
+ "scripts/clean_code_python_triggers.py" = [
179
+ "INP001",
180
+ ]
181
+ "scripts/clean_code_review_io.py" = [
182
+ "INP001",
183
+ ]
184
+ "scripts/clean_code_review_models.py" = [
185
+ "INP001",
186
+ ]
187
+ "scripts/set_package_versions.py" = [
188
+ "TRY003",
189
+ ]
190
+ "scripts/_mcp_app.py" = [
191
+ "TRY003",
192
+ ]
193
+ "scripts/weaviate_ingest_clean_code.py" = [
194
+ "TRY003",
195
+ ]
196
+ "scripts/weaviate_search_clean_code.py" = [
197
+ "TRY003",
198
+ ]
199
+ "src/python/mcp_server/server.py" = [
200
+ "PLC0415",
201
+ "PLR0913",
202
+ "TRY003",
203
+ ]
204
+ "src/python/mcp_server/semantic.py" = [
205
+ "PLC0415",
206
+ "TRY003",
207
+ ]
208
+
209
+ [tool.ruff.format]
210
+ quote-style = "double"
211
+ indent-style = "space"
212
+ line-ending = "auto"
213
+
214
+ [tool.pylint.main]
215
+ py-version = "3.12"
216
+ jobs = 0
217
+ recursive = true
218
+ load-plugins = [
219
+ "clean_code_tools_pylint",
220
+ ]
221
+ ignore-paths = [
222
+ "^\\.venv/.*$",
223
+ "^build/.*$",
224
+ "^dist/.*$",
225
+ "^node_modules/.*$",
226
+ "^sample-apps/.*$",
227
+ ]
228
+
229
+ [tool.pylint."messages control"]
230
+ disable = [
231
+ "all",
232
+ ]
233
+ enable = [
234
+ "cyclic-import",
235
+ "clean-code-boolean-flag-argument",
236
+ "clean-code-business-policy-literal",
237
+ "clean-code-commented-out-code",
238
+ "clean-code-noisy-comment",
239
+ "clean-code-output-argument-mutation",
240
+ "clean-code-redundant-comment",
241
+ "clean-code-todo-format",
242
+ "clean-code-train-wreck",
243
+ "duplicate-code",
244
+ "import-error",
245
+ "too-many-ancestors",
246
+ "too-many-arguments",
247
+ "too-many-branches",
248
+ "too-many-instance-attributes",
249
+ "too-many-lines",
250
+ "too-many-locals",
251
+ "too-many-nested-blocks",
252
+ "too-many-public-methods",
253
+ "too-many-return-statements",
254
+ "too-many-statements",
255
+ "too-many-boolean-expressions",
256
+ "too-few-public-methods",
257
+ ]
258
+
259
+ [tool.pylint.design]
260
+ max-args = 5
261
+ max-attributes = 7
262
+ max-bool-expr = 5
263
+ max-branches = 12
264
+ max-locals = 15
265
+ max-nested-blocks = 4
266
+ max-public-methods = 12
267
+ max-returns = 6
268
+ max-statements = 40
269
+ max-parents = 7
270
+ min-public-methods = 1
271
+
272
+ [tool.pylint.format]
273
+ max-line-length = 100
274
+ max-module-lines = 300
275
+
276
+ [tool.pylint.imports]
277
+ allow-any-import-level = []
278
+
279
+ [tool.pylint.reports]
280
+ score = false
281
+
282
+ [tool.pyright]
283
+ include = ["src/python/clean_code_tools_pylint", "src/python/mcp_server", "scripts"]
284
+ extraPaths = ["src/python"]
285
+ exclude = [
286
+ "**/__pycache__",
287
+ "**/.venv",
288
+ "**/.pytest_cache",
289
+ "**/.ruff_cache",
290
+ "node_modules",
291
+ "sample-apps",
292
+ ]
293
+ pythonVersion = "3.12"
294
+ typeCheckingMode = "strict"
295
+ reportMissingImports = "error"
296
+ reportMissingTypeStubs = "warning"
297
+ reportUnusedImport = "error"
298
+ reportUnusedVariable = "warning"
299
+ reportPrivateUsage = "warning"
300
+ reportUnknownArgumentType = "warning"
301
+ reportUnknownMemberType = "warning"
302
+ reportUnknownVariableType = "warning"
303
+ reportUnusedFunction = "warning"