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,27 @@
1
+ #!/usr/bin/env python3
2
+ from __future__ import annotations
3
+
4
+ import argparse
5
+ import json
6
+
7
+ from _mcp_app import load_semantic_module
8
+
9
+
10
+ def main() -> None:
11
+ parser = argparse.ArgumentParser(description="Inspect clean-code semantic chunks.")
12
+ parser.add_argument("--json", action="store_true", help="Print chunks as JSONL.")
13
+ args = parser.parse_args()
14
+ semantic = load_semantic_module()
15
+ chunks = semantic.build_chunks()
16
+ if args.json:
17
+ for chunk in chunks:
18
+ print(json.dumps(chunk.properties, sort_keys=True))
19
+ return
20
+ by_kind: dict[str, int] = {}
21
+ for chunk in chunks:
22
+ by_kind[chunk.chunk_kind] = by_kind.get(chunk.chunk_kind, 0) + 1
23
+ print(json.dumps({"chunks": len(chunks), "by_kind": by_kind}, sort_keys=True))
24
+
25
+
26
+ if __name__ == "__main__":
27
+ main()
@@ -0,0 +1,82 @@
1
+ #!/usr/bin/env python3
2
+ from __future__ import annotations
3
+
4
+ import argparse
5
+ import json
6
+ import re
7
+ from pathlib import Path
8
+
9
+ ROOT = Path(__file__).resolve().parents[1]
10
+ PACKAGE_JSON = ROOT / "package.json"
11
+ PYPROJECT = ROOT / "pyproject.toml"
12
+ RELEASE_VERSION_RE = re.compile(r"^\d+\.\d+\.\d+(?:[a-zA-Z0-9.-]+)?$")
13
+ CORE_VERSION_RE = re.compile(r"^(?P<major>\d+)\.(?P<minor>\d+)\.(?P<patch>\d+)$")
14
+ PYPROJECT_VERSION_RE = re.compile(r'(?m)^version = "([^"]+)"$')
15
+
16
+
17
+ def package_version() -> str:
18
+ return str(json.loads(PACKAGE_JSON.read_text())["version"])
19
+
20
+
21
+ def set_json_version(path: Path, version: str) -> None:
22
+ payload = json.loads(path.read_text())
23
+ payload["version"] = version
24
+ path.write_text(json.dumps(payload, indent=2) + "\n")
25
+
26
+
27
+ def set_pyproject_version(version: str) -> None:
28
+ text = PYPROJECT.read_text()
29
+ updated, count = PYPROJECT_VERSION_RE.subn(f'version = "{version}"', text, count=1)
30
+ if count != 1:
31
+ raise SystemExit("Expected exactly one [project] version in pyproject.toml")
32
+ PYPROJECT.write_text(updated)
33
+
34
+
35
+ def set_versions(*, npm_version: str, python_version: str) -> None:
36
+ set_json_version(PACKAGE_JSON, npm_version)
37
+ set_pyproject_version(python_version)
38
+ print(f"npm_version={npm_version}")
39
+ print(f"python_version={python_version}")
40
+
41
+
42
+ def bumped_version(base: str, part: str) -> str:
43
+ match = CORE_VERSION_RE.match(base)
44
+ if match is None:
45
+ raise SystemExit(f"Version bumps require a plain major.minor.patch base, got: {base}")
46
+ major = int(match.group("major"))
47
+ minor = int(match.group("minor"))
48
+ patch = int(match.group("patch"))
49
+ if part == "major":
50
+ return f"{major + 1}.0.0"
51
+ if part == "minor":
52
+ return f"{major}.{minor + 1}.0"
53
+ return f"{major}.{minor}.{patch + 1}"
54
+
55
+
56
+ def main() -> None:
57
+ parser = argparse.ArgumentParser(description="Set coordinated npm and Python package versions.")
58
+ group = parser.add_mutually_exclusive_group(required=True)
59
+ group.add_argument("--release", help="Release version to write to both manifests, for example 1.2.3.")
60
+ group.add_argument("--bump", choices=("patch", "minor", "major"), help="Bump the base release version.")
61
+ parser.add_argument(
62
+ "--base",
63
+ default=None,
64
+ help="Base SemVer version for --bump. Defaults to package.json.",
65
+ )
66
+ args = parser.parse_args()
67
+
68
+ if args.release:
69
+ if not RELEASE_VERSION_RE.match(args.release):
70
+ raise SystemExit(f"Invalid release version: {args.release}")
71
+ set_versions(npm_version=args.release, python_version=args.release)
72
+ return
73
+
74
+ base = args.base or package_version()
75
+ if not RELEASE_VERSION_RE.match(base):
76
+ raise SystemExit(f"Invalid base version: {base}")
77
+ version = bumped_version(base, args.bump)
78
+ set_versions(npm_version=version, python_version=version)
79
+
80
+
81
+ if __name__ == "__main__":
82
+ main()
@@ -0,0 +1,44 @@
1
+ #!/usr/bin/env python3
2
+ from __future__ import annotations
3
+
4
+ import argparse
5
+
6
+ from _mcp_app import load_semantic_module
7
+
8
+ semantic = load_semantic_module()
9
+ DEFAULT_BATCH_SIZE = semantic.DEFAULT_BATCH_SIZE
10
+ build_chunks = semantic.build_chunks
11
+ ingest_chunks = semantic.ingest_chunks
12
+ reset_collection = semantic.reset_collection
13
+
14
+
15
+ def add_common_args(parser: argparse.ArgumentParser) -> None:
16
+ parser.add_argument("--url", default=semantic.DEFAULT_WEAVIATE_URL)
17
+ parser.add_argument("--collection", default=semantic.COLLECTION_NAME)
18
+ parser.add_argument("--model", default=semantic.DEFAULT_EMBEDDING_MODEL)
19
+
20
+
21
+ def main() -> None:
22
+ parser = argparse.ArgumentParser(description="Ingest clean-code semantic chunks into Weaviate.")
23
+ add_common_args(parser)
24
+ parser.add_argument("--reset", action="store_true", help="Drop and recreate the collection first.")
25
+ parser.add_argument("--batch-size", type=int, default=DEFAULT_BATCH_SIZE)
26
+ args = parser.parse_args()
27
+
28
+ if args.batch_size < 1:
29
+ raise SystemExit("--batch-size must be at least 1")
30
+ if args.reset:
31
+ reset_collection(url=args.url, collection_name=args.collection)
32
+ chunks = build_chunks()
33
+ inserted = ingest_chunks(
34
+ chunks=chunks,
35
+ url=args.url,
36
+ collection_name=args.collection,
37
+ model_name=args.model,
38
+ batch_size=args.batch_size,
39
+ )
40
+ print(f"ingested={inserted} collection={args.collection}")
41
+
42
+
43
+ if __name__ == "__main__":
44
+ main()
@@ -0,0 +1,51 @@
1
+ #!/usr/bin/env python3
2
+ from __future__ import annotations
3
+
4
+ import argparse
5
+
6
+ from _mcp_app import load_semantic_module
7
+
8
+ semantic = load_semantic_module()
9
+ search_chunks = semantic.search_chunks
10
+
11
+
12
+ def add_common_args(parser: argparse.ArgumentParser) -> None:
13
+ parser.add_argument("--url", default=semantic.DEFAULT_WEAVIATE_URL)
14
+ parser.add_argument("--collection", default=semantic.COLLECTION_NAME)
15
+ parser.add_argument("--model", default=semantic.DEFAULT_EMBEDDING_MODEL)
16
+
17
+
18
+ def print_search_results(results: list[dict[str, object]]) -> None:
19
+ for index, row in enumerate(results, start=1):
20
+ additional = row.get("_additional") or {}
21
+ distance = additional.get("distance", "?") if isinstance(additional, dict) else "?"
22
+ print(
23
+ f"{index}. {row.get('recordId') or row.get('chunkId')} "
24
+ f"{row.get('title')} distance={distance}"
25
+ )
26
+ print(f" source={row.get('sourceFile')} kind={row.get('chunkKind', row.get('sourceKind'))}")
27
+ text = " ".join(str(row.get("contentText", "")).split())
28
+ print(f" {text[:280]}")
29
+
30
+
31
+ def main() -> None:
32
+ parser = argparse.ArgumentParser(description="Search clean-code semantic chunks in Weaviate.")
33
+ add_common_args(parser)
34
+ parser.add_argument("query")
35
+ parser.add_argument("--limit", type=int, default=8)
36
+ args = parser.parse_args()
37
+
38
+ if args.limit < 1:
39
+ raise SystemExit("--limit must be at least 1")
40
+ results = search_chunks(
41
+ query=args.query,
42
+ url=args.url,
43
+ collection_name=args.collection,
44
+ model_name=args.model,
45
+ limit=args.limit,
46
+ )
47
+ print_search_results(results)
48
+
49
+
50
+ if __name__ == "__main__":
51
+ main()
@@ -0,0 +1,209 @@
1
+ ---
2
+ name: clean-code-mcp-reviewer
3
+ description: Use this skill whenever reviewing, refactoring, or designing lint checks for TypeScript, JavaScript, Python, or React code where clean-code patterns may help. This skill teaches agents how to use the clean-code MCP interactively: read code first, form concrete smell hypotheses, query the MCP narrowly, suppress weak matches, and apply only guidance anchored to local code evidence. Use it for maintainability reviews, readability concerns, refactor planning, and clean-code lint-rule design, even when the user does not explicitly mention MCP.
4
+ ---
5
+
6
+ # Clean-Code MCP Reviewer
7
+
8
+ Use the clean-code MCP as decision support, not as a generic style rulebook. The
9
+ tool is valuable when a concrete code shape creates a maintainability decision:
10
+ function boundaries, arguments, naming, side effects, comments, duplication,
11
+ tests, error handling, literals, or object navigation.
12
+
13
+ ## Operating Principle
14
+
15
+ Read the code before querying. A good MCP query starts from observed local
16
+ evidence, not from the task title or a generic desire to "make it cleaner." The
17
+ agent remains responsible for judging whether retrieved guidance fits the local
18
+ framework, public API, tests, performance constraints, and project conventions.
19
+
20
+ This skill is self-contained. Do not assume separate language-specific
21
+ clean-code skills are installed. Use the language heuristics below when judging
22
+ Python, JavaScript, TypeScript, or React code.
23
+
24
+ ## Refactor Discipline
25
+
26
+ - Read formatter, linter, type-checker, framework, tests, and nearby files
27
+ before applying generic advice.
28
+ - Name the concrete smell before proposing a cleanup.
29
+ - Keep the refactor local unless the user asks for a broader redesign.
30
+ - Preserve public APIs, return shapes, exception behavior, async boundaries,
31
+ mutability expectations, and framework contracts.
32
+ - Prefer the smallest useful change: rename, flatten control flow, extract one
33
+ cohesive helper, introduce a stable data shape, or clarify an error boundary.
34
+ - Avoid class hierarchies, speculative abstractions, trivial wrappers, and
35
+ extraction that hides the main logic.
36
+ - Optimize for the call site: the best boundary makes the caller obviously
37
+ correct.
38
+ - Verify that tests, lint, types, and the relevant runtime contract still hold.
39
+
40
+ ## When To Use The MCP
41
+
42
+ Use the MCP when you have a specific clean-code concern:
43
+
44
+ - following up deterministic lint triggers emitted as clean-code review
45
+ candidates
46
+ - reviewing a possible maintainability finding
47
+ - planning a behavior-preserving refactor
48
+ - deciding whether a pattern is lintable
49
+ - comparing alternative extraction, naming, or argument-shape choices
50
+ - checking whether a repeated smell should become an ESLint, Ruff, Pylint, or
51
+ Semgrep rule
52
+
53
+ Do not query for:
54
+
55
+ - formatting-only edits
56
+ - dependency bumps
57
+ - obvious build/type errors
58
+ - purely mechanical renames
59
+ - generated files or migrations unless the user explicitly asks
60
+ - code where local conventions or framework idioms already settle the decision
61
+
62
+ ## Query Workflow
63
+
64
+ 1. Inspect the changed code, nearby tests, and local conventions.
65
+ 2. Identify one concrete concern at a time.
66
+ 3. Summarize the concern as a smell hypothesis.
67
+ 4. Query `search_clean_code_patterns` with language and relevant filters.
68
+ 5. If a result looks useful, call `get_clean_code_pattern` for full detail.
69
+ 6. Use the pattern only when it matches a concrete code anchor.
70
+ 7. Say there is no strong clean-code match when results are generic or weak.
71
+
72
+ When a repo provides `clean-code-review-candidates/v1` input, treat each
73
+ candidate as a deterministic tripwire, not as a finding. Read the file plus the
74
+ symbol or anchor named by the candidate, check whether the listed semantic
75
+ questions are actually supported by the code, then run only the relevant MCP
76
+ queries. A candidate may produce `no strong clean-code match`, an advisory note,
77
+ or a targeted refactor plan.
78
+
79
+ Prefer concise queries over whole-file or whole-diff input.
80
+
81
+ If the pattern-first tools are not available yet, use the lower-level
82
+ `search_clean_code` tool as a fallback and be more conservative: treat mixed
83
+ markdown/chunk results as supporting context only, and do not claim full pattern
84
+ applicability without a canonical pattern record.
85
+
86
+ Good query examples:
87
+
88
+ ```text
89
+ typescript function boolean parameter controls behavior in calculatePrice
90
+ python function mutates output argument and also returns status
91
+ react component mixes data normalization conditional rendering and side effects
92
+ typescript review lint candidate TODO comment without tracked issue id
93
+ python long parameter list configuration values passed positionally
94
+ ```
95
+
96
+ Poor query examples:
97
+
98
+ ```text
99
+ make this cleaner
100
+ review this entire diff
101
+ clean code suggestions for app.tsx
102
+ ```
103
+
104
+ ## Result Handling
105
+
106
+ Treat MCP results as candidates. Before using a result, check:
107
+
108
+ - Does the result match the language or framework?
109
+ - Does the result describe the observed code shape?
110
+ - Does `avoid_when` apply?
111
+ - Is the pattern lintable, review-only, or context-dependent?
112
+ - Would applying it preserve the public API and behavior?
113
+ - Is the match specific enough to mention in a review or plan?
114
+
115
+ Use at most 1-3 selected matches in visible output. Do not decorate every
116
+ review finding with pattern IDs. Cite a pattern ID only when it materially
117
+ changed the recommendation.
118
+
119
+ ## Review Output
120
+
121
+ When writing code-review findings, lead with local evidence. Use MCP guidance as
122
+ supporting context.
123
+
124
+ Preferred shape:
125
+
126
+ ```text
127
+ Finding: `calculatePrice(user, includeDiscounts)` uses a boolean selector that
128
+ changes behavior, so callers must understand two execution modes from one
129
+ signature.
130
+
131
+ Clean-code support: CC-043 applies because the boolean argument selects behavior
132
+ rather than representing plain data. A safer remediation is to introduce
133
+ intention-revealing functions while keeping a compatibility wrapper if the API
134
+ is public.
135
+ ```
136
+
137
+ Avoid findings that say only "Clean code says..." or "Pattern CC-043 says...".
138
+ The issue must stand on the code.
139
+
140
+ ## Language Heuristics
141
+
142
+ For Python:
143
+
144
+ - Prefer Pythonic clarity over abstract purity.
145
+ - Use plain functions when data flow is simple.
146
+ - Use `TypedDict` for stable mapping-shaped data, `dataclass` for value-like
147
+ data, and richer models only when validation, serialization, or invariants
148
+ justify them.
149
+ - Use keyword-only parameters when they improve call-site clarity.
150
+ - Preserve the local failure style: exceptions, `None`, result objects, or
151
+ framework responses.
152
+ - Separate parsing, validation, transformation, and side effects when they are
153
+ tangled.
154
+ - Do not add docstrings to every private helper; comments should explain why,
155
+ constraints, or surprising behavior.
156
+
157
+ For JavaScript and TypeScript:
158
+
159
+ - Prefer domain names over implementation names; drop vague suffixes like
160
+ `Data`, `Info`, `Manager`, or `Helper` unless they distinguish real concepts.
161
+ - Use boolean names that read like questions: `isReady`, `hasAccess`,
162
+ `shouldRetry`.
163
+ - Prefer stronger TypeScript types over explanatory comments.
164
+ - Narrow external data early and keep internal code on trusted shapes.
165
+ - Use discriminated unions when the code already branches on variants.
166
+ - Prefer object parameters when several values travel together, but do not
167
+ introduce options objects only to satisfy an arbitrary parameter count.
168
+ - Follow the existing error boundary style: throw, result object, or
169
+ framework-specific response.
170
+
171
+ ## Refactor Output
172
+
173
+ When planning a refactor, translate selected patterns into constraints:
174
+
175
+ - what behavior must stay unchanged
176
+ - what code shape should change
177
+ - what compatibility wrapper is needed, if any
178
+ - what tests or checks should verify the change
179
+
180
+ Keep the refactor small unless the user asks for a broader rewrite.
181
+
182
+ ## Lint-Rule Design
183
+
184
+ For lint-rule work, filter toward high and medium lintability. If the MCP accepts
185
+ a list, pass `["high", "medium"]`; if it accepts only one value, run separate
186
+ queries or use the lint-rule recommendation tool. Keep
187
+ `review_only` patterns out of automated lint checks unless there is a narrow,
188
+ low-false-positive signal.
189
+
190
+ A lint recommendation should include:
191
+
192
+ - target tool: ESLint, Ruff, Pylint, Semgrep, or review-only
193
+ - static signal
194
+ - likely false positives
195
+ - safe contexts to ignore
196
+ - suppression strategy
197
+ - autofix feasibility
198
+
199
+ ## Weak-Match Policy
200
+
201
+ Suppress weak or generic MCP results. Say `no strong clean-code match` when:
202
+
203
+ - the top results are broad clean-code advice without a local code anchor
204
+ - the result depends on context the agent has not verified
205
+ - the code is idiomatic for the framework
206
+ - the evidence comes from generated, fixture, migration, or test-helper code
207
+ - applying the pattern would conflict with stable public API constraints
208
+
209
+ Missing a weak suggestion is better than producing a noisy style finding.
@@ -0,0 +1,30 @@
1
+ {
2
+ "skill_name": "clean-code-mcp-reviewer",
3
+ "evals": [
4
+ {
5
+ "id": 1,
6
+ "prompt": "Review this TypeScript helper. Use the clean-code MCP only if it helps.\n\n```ts\nexport function calculatePrice(customer: Customer, includeDiscounts: boolean): Money {\n let total = customer.cart.subtotal;\n if (includeDiscounts) {\n total = total.minus(customer.discountAmount);\n }\n return total;\n}\n\nconst invoicePrice = calculatePrice(customer, false);\nconst checkoutPrice = calculatePrice(customer, true);\n```",
7
+ "expected_output": "The agent reads the code first, queries for a boolean selector or flag argument pattern, uses a high-fit match, and anchors the finding to the local function/callers."
8
+ },
9
+ {
10
+ "id": 2,
11
+ "prompt": "Review this React component and decide whether clean-code MCP guidance should block it.\n\n```tsx\nexport function SaveDialog({ isSaving }: { isSaving: boolean }) {\n return (\n <Modal open>\n <Button disabled={isSaving}>Save</Button>\n </Modal>\n );\n}\n```",
12
+ "expected_output": "The agent treats declarative React boolean props as a near-miss and avoids a flag-argument finding unless there is behavior-selection evidence."
13
+ },
14
+ {
15
+ "id": 3,
16
+ "prompt": "Plan a Python refactor for this function. Use the clean-code MCP only after identifying the concern.\n\n```python\ndef normalize_order(order: Order, errors: list[str]) -> str:\n if order.total <= 0:\n errors.append(\"total must be positive\")\n return \"invalid\"\n order.customer_email = order.customer_email.strip().lower()\n return \"valid\"\n```",
17
+ "expected_output": "The agent queries for output argument mutation or side-effect concerns, fetches details only for a relevant match, and proposes a behavior-preserving refactor with verification."
18
+ },
19
+ {
20
+ "id": 4,
21
+ "prompt": "Design a clean-code lint check for repeated TODO comments in TypeScript and Python.\n\nExamples that should pass:\n```ts\n// TODO(PROJ-123): remove legacy tax fallback after migration.\n```\n\nExamples that should fail:\n```python\n# TODO fix this later\nresult = legacy_process(data)\n```",
22
+ "expected_output": "The agent uses lintability filters, distinguishes valid tracked TODOs from weak comments, and recommends appropriate target tooling and false-positive controls."
23
+ },
24
+ {
25
+ "id": 5,
26
+ "prompt": "Review this generated API client fixture change and decide whether clean-code patterns should block it.\n\n```ts\n// generated from billing-openapi.yaml\nexport const fixture = {\n account: { owner: { address: { city: \"London\" } } },\n status: \"active\"\n};\n\nexport const city = fixture.account.owner.address.city;\n```\n\nThe file path is `src/generated/billingClient.fixture.ts`.",
27
+ "expected_output": "The agent recognizes generated/fixture code as a weak-match context and reports no strong clean-code finding unless local project rules say otherwise."
28
+ }
29
+ ]
30
+ }