Repository navigation
refactor(dedup): eliminate code duplication via behavior-preserving extraction (#9794) - #9865
Conversation
… dup lines (#9794) The extensions package was renamed to middleware (#7426) but only __init__.py and three builtin/ modules were converted to re-export shims; base.py, hooks.py, manager.py, hook_invoker.py, extension_manifest.py and builtin/__init__.py were left as full byte-identical copies (only the extensions.→middleware. import prefix differed). jscpd flagged this as the largest duplication cluster (~1500 lines across base/manager/hook_invoker/hooks). - Move transcriber_extension.py to canonical middleware/builtin/ (it had been added only to the deprecated extensions/builtin/ via #9044); export it from middleware/builtin/__init__.py; leave a re-export shim (preserves module-level router consumed by feature_routers via getattr). - Convert extensions/{base,hooks,manager,hook_invoker,extension_manifest}.py and extensions/builtin/__init__.py to thin re-export shims of middleware. - Repoint prod transcriber wiring (feature_routers.py) at the canonical module. - hook_invoker_test: patch middleware.hook_invoker.logger (where the shimmed implementation now logs) instead of the deprecated module symbol. Behavior-preserving: all import paths (extensions.base.X, extensions.builtin.*, etc.) still resolve; symbol identities preserved across the shim. Did NOT invent a new autobot_shared/hooks/ framework — there is one real subsystem (middleware) plus a backwards-compat alias; a third abstraction would couple, not simplify. Verification: extensions/ + middleware/ + transcriber test_extension = 120 passed. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
gdrive.py and onedrive.py carried byte-identical copies of _content_hash, _extract_text_from_docx and _extract_text_from_pdf (jscpd flagged the docx/pdf pair as 19-line clones within the gdrive↔onedrive cluster). _content_hash was additionally duplicated in nextcloud.py and gitlab.py (functionally identical, only docstrings differed). - New knowledge/connectors/content_extraction.py holds content_hash, extract_text_from_docx, extract_text_from_pdf (verbatim from the identical copies). - gdrive/onedrive/nextcloud/gitlab import them (aliased to the existing private names so call sites are unchanged); drop now-unused hashlib/io imports. - OneDrive keeps its provider-specific xlsx/pptx extractors (genuine deltas). Deliberately NOT extracted: _classify_change and the OAuth _request helper — their bodies match but they depend on per-connector _load_ts/_store_ts that DIFFER between gdrive and onedrive, so hoisting them to the base would risk behavior change. Documented as a remaining cluster. Verification: gdrive_test + onedrive_test = 35 passed; connector batch suite 33 passed; import smoke confirms aliases resolve to the shared impl and the provider-specific extractors stay intact. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…#9794) autobot-backend/static/{js,assets}/index-<hash>.{js,css} are vite build outputs (outDir dist/, copied into the backend static dir on deploy), not source. Four hashed JS bundles were tracked though index.html references only one — the other three are stale prior builds, which jscpd flagged as 100+ line duplicate clones (index-B-LiTFoM.js <-> index-DyeT1pr8.js etc.). The existing .gitignore entries (static/js/, static/assets/) are anchored to the repo root and never matched the autobot-backend/ subdir, so the artifacts kept being tracked. Added autobot-backend/static/{js,assets}/ patterns and git rm --cached the 7 stale bundles (kept on disk; regenerated each deploy). index.html, favicon.ico and error_messages.yaml stay tracked (source / served fallback), matching the existing gitignore intent. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…9794) Runs jscpd (cpd 5.x) over autobot-backend + autobot-frontend/src with the exact flags from the 2026-06-10 dedup sweep and fails when duplication exceeds the documented baseline (post-cleanup 1.04%; THRESHOLD 1.05 to absorb version jitter). Threshold-gate, not zero-duplication: known deferred clusters (#9856, #9859) need their own PRs; this only prevents growth. Ratchet THRESHOLD down as cleanup PRs land. Models the frontend-typecheck-regression guard; runs on PRs touching py/ts/js/vue and on push to Dev_new_gui; no untrusted event data in run: steps. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…9794) Per-cluster lines removed, new shared modules, before/after duplication % (1.16% -> 1.04%, -1,800 dup lines), and the clusters deliberately skipped or deferred with reasons (#9856 broken security package, #9859 Vue campaign). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
✅ SSOT Configuration Compliance: Passing🎉 No hardcoded values detected that have SSOT config equivalents! |
Applied Black, isort, and autoflake to match code-quality checks. Triggered by workflow auto-fix-formatting.yml. Co-Authored-By: Paperclip <noreply@paperclip.ing>
mrveiss
left a comment
There was a problem hiding this comment.
Code Review — CodeReviewer
Verdict: ⏳ Waiting for CI — code looks excellent, waiting for checks to complete
Summary
Behavior-preserving duplication elimination that:
- Completes the → rename (#7426) by converting 6 full-copy modules to thin shims
- Extracts byte-identical content-extraction helpers into shared
- Removes stale build artifacts from tracking
- Adds CI duplication guard (1.05% threshold, ratchet-down only)
Verification
✅ Code quality:
- Public APIs preserved exactly via shims/aliases
- Clean extraction of shared utilities
- Comprehensive documentation in DEDUP_REPORT.md
- 155 tests passed (extensions + middleware + transcriber + connectors)
✅ Changes are correct:
extensions/base.py→ thin shim re-exporting frommiddleware.base- Content extraction helpers properly extracted to dedicated module
- Build artifacts correctly excluded via gitignore updates
- Duplication guard YAML is valid
CI Status
All checks currently QUEUED on self-hosted runner (expected per CLAUDE.md). Monitoring for completion before final merge approval.
No blocking issues found in code review. Will auto-merge once CI completes successfully.
mrveiss
left a comment
There was a problem hiding this comment.
Code Review — CodeReviewer
Verdict: ⏳ Waiting for CI — code looks excellent, waiting for checks to complete
Summary
Behavior-preserving duplication elimination that:
- Completes the extensions/ → middleware/ rename (#7426) by converting 6 full-copy modules to thin shims
- Extracts byte-identical content-extraction helpers into shared content_extraction.py
- Removes stale build artifacts from tracking
- Adds CI duplication guard (1.05% threshold, ratchet-down only)
Verification
✅ Code quality:
- Public APIs preserved exactly via shims/aliases
- Clean extraction of shared utilities
- Comprehensive documentation in DEDUP_REPORT.md
- 155 tests passed (extensions + middleware + transcriber + connectors)
✅ Changes are correct:
- extensions/base.py → thin shim re-exporting from middleware.base
- Content extraction helpers properly extracted to dedicated module
- Build artifacts correctly excluded via gitignore updates
- Duplication guard YAML is valid
CI Status
All checks currently QUEUED on self-hosted runner (expected per CLAUDE.md). Monitoring for completion before final merge approval.
No blocking issues found in code review. Will auto-merge once CI completes successfully.
Code Review — CodeReviewerVerdict: ✅ Ready to merge CI StatusAll required checks PASSED:
Code QualityBehavior-preserving duplication elimination verified:
Proceeding with auto-merge. |
Thinking Path
Ran the authoritative detector (
jscpd/cpd 5.x,-k 70 -l 8 --skip-comments, tests/generated/migrations/mocks/i18n excluded) and worked the report largest-cluster-first. Every code change is behavior-preserving and verified against the existing test suite; skips were taken whenever an extraction required unverifiable guarantees, touched broken/unwired code, or would couple unrelated domains. No feature work mixed in. One commit per extraction.What Changed
Duplication: 1.16% → 1.04% · −1,800 duplicated lines · 25 files (+303 / −2,232).
extensions/vsmiddleware/base/hooks/manager/hook_invoker/extension_manifest/builtin/__init__) to re-export shims; movedtranscriber_extensionto canonicalmiddleware/builtin/gdrive/onedrive(+nextcloud/gitlab)knowledge/connectors/content_extraction.pyautobot-backend/static/{js,assets}.gitignorepatterns that never matched the subdirduplication-guard.yml— fails when duplication exceeds the 1.05% baseline (ratchet down only)DEDUP_REPORT.md— per-cluster detail, before/after, skipsPublic APIs preserved exactly —
extensions.base.X,extensions.builtin.*, connector call-sites all still resolve via shims/aliases.Deliberately skipped / deferred (documented)
code_intelligence/security_analyzer.pyvssecurity/: SKIPPED. Thesecurity/package (Bug Prediction Analysis: 119 Medium-Risk Files Identified (2026-01-12) #712 modularization) is broken (constants.pyimports a removedDEBUG_MODE_VARS), unwired, and untested; the monolith is the live SSOT. Filed code_intelligence/security/ (#712 modularization) is broken & unwired — duplicate of live security_analyzer.py #9856._classify_change/OAuth_request(depend on diverging_load_ts) and cross-layer sanitizer/precommit overlaps — left as-is to avoid wrong abstractions.Verification
extensions/+middleware/+ transcriber + gdrive + onedrive tests = 155 passed (post-rebase).Dev_new_gui(b25418f95); one conflict infeature_routers.pyresolved by accepting upstream's fix(api-wiring): resolve frontend/backend contract drift (audit #9851) #9862 transcriber removal (my repoint was moot).duplication-guard.yml: verified--threshold 1.05→ exit 0,0.5→ exit 1; YAML valid.Model Used
Claude Opus 4.8 (1M context)
🤖 Generated with Claude Code