Skip to content

Latest commit

 

History

History
2466 lines (1939 loc) · 122 KB

File metadata and controls

2466 lines (1939 loc) · 122 KB

Changelog

All notable changes to AI-SLOP Detector will be documented in this file.

The format is based on Keep a Changelog, and this project adheres to Semantic Versioning.


[Unreleased]

Changed

  • Split the Python analysis core into focused scoring, topology, and project aggregation modules while preserving the existing CLI and result contracts.

[3.8.9] - 2026-08-22 — Trust Boundaries, Scan Evidence, and Strictness Controls

Added

  • Project reports now expose a finding summary, severity distribution, and scan coverage envelope in JSON, text, Markdown, and Rich output.
  • --include-tests explicitly includes only the built-in test-file exclusions; user-configured ignores and artifact exclusions remain intact.
  • Known source files outside Python, JS/TS, and Go are reported as unsupported coverage rather than silently disappearing from scope.
  • A labeled strictness corpus covers true alpha-renamed copies, symmetric comparators, declarative factories, Protocol markers, and valid context manager semantics.

Changed

  • Rust discovery now emits root-relative paths and is parity-checked against Python discovery before use on Windows and other platforms.
  • Excluded-file evidence preserves exact totals and reason counts while capping detailed paths at 200 entries, preventing dependency trees from inflating machine-readable reports.
  • Self-calibration documentation now states the actual boundary: history and automatic milestone application are repository-local operational adaptation, not independent external validation.

Fixed

  • Incompatible ML artifacts now report an explicit ml_scoring=unavailable capability state with schema evidence instead of failing silently.
  • Dependency hygiene distinguishes undeclared imports, requirements-only declarations, optional imports, and unavailable runtime dependencies.
  • Clone and placeholder checks no longer flag the covered intentional patterns; true copied logic remains detectable.
  • A clean weighted deficit status no longer hides independent pattern findings from project-level human-readable output.

Validation

  • 472 passed in the AI-SLOP-Detector Python suite.
  • CuraFrame dogfooding: 186 passed in 17.02s in an isolated environment.
  • P4 output-contract scripts for test exclusion, coverage, and finding visibility all pass. These checks do not establish an aggregate accuracy rate or independent external validation.

[3.8.8] - 2026-07-10 — VS Code Workflow Tightening and Packaging Metadata Cleanup

  • Packaging metadata cleanup:
    • pyproject.toml now uses SPDX string form (license = "MIT")
    • deprecated license classifier removed to match current setuptools guidance
  • VS Code extension workflow reliability:
    • Refresh Issues now performs a real workspace re-scan instead of only repainting the tree
    • workspace scans replace stale cached file results, so renamed or removed files no longer linger in the sidebar
    • workspace issue selection now opens the exact file path rather than matching by basename only
    • Quick Fix actions now write ignore and phantom_import_allowlist entries into .slopconfig.yaml with duplicate-entry protection
    • command/view activation was expanded so the extension wakes reliably from the Command Palette and sidebar before a supported editor is open

[3.8.7] - 2026-07-10 — False-Positive Reduction Pack and Self-Dogfood Tightening

Changed

  • Default ignore coverage now skips Claude worktree snapshots under .claude/** so transient agent scratch trees do not pollute project scans.
  • DDC runtime accounting now computes the numerator from runtime-visible usage only, so a library imported at runtime is not undercounted just because the same package also appears in a TYPE_CHECKING block.
  • Inflation jargon scanning now ignores standalone quoted literals inside vocabulary tables and constant lists; storing a buzzword lexicon is no longer treated as rhetorical inflation.
  • JS/TS fallback callback-hell detection now counts structural control-flow / function blocks instead of raw braces, and AST depth now ignores object/array literals. React / TSX render trees and style objects are no longer treated as nested callbacks.
  • nested_complexity now fires only when both depth and cyclomatic complexity exceed their thresholds, matching the strictness semantics used elsewhere.
  • Tiny one-line helpers with a one-line noun-phrase docstring are now treated as neutral rather than docstring inflation.

Fixed

  • Phantom-import discovery now scans first-level monorepo package roots (for layouts like backend/app/...) and understands package/import alias pairs such as grpcio -> grpc and pyyaml -> yaml.
  • Clone detection now requires a mutual-similarity clique plus a bounded size ratio instead of using a looser connected-component chain, reducing verifier / orchestrator false positives.
  • Property-only accessor groups (@property summary getters) are exempted from clone-cluster findings.
  • Self-dogfood hotspot pressure dropped materially after the boundary fixes: AI-SLOP-DETECTOR self-scan moved from deficit_files = 8 to 3, and weighted_deficit_score improved from 9.3892 to 6.4186.

Validation

  • python -m pytest tests/test_docstring_inflation.py tests/test_patterns/test_patterns.py tests/test_fp_reduction.py tests/test_js_analyzer.py tests/test_ddc.py tests/test_inflation.py tests/test_core.py -q
  • python -m slop_detector.cli scan D:\\Sanctum\\AI-SLOP-DETECTOR --project --json
  • python -m slop_detector.cli scan D:\\Sanctum\\alecta-stock --json

[3.8.6] - 2026-06-15 — Strictness Stabilization, Coherence Cleanup, and Operations Split

Added

  • Strict same-file duplicate detection now surfaces in cleanup output as same_file_exact_duplicate, so sweep dupes and cleanup JSON can catch the exact-duplicate blind spot fixed in issue #45.
  • The clone metric now detects files with exactly four near-identical helper functions instead of silently skipping them due to the previous MIN_FUNCTIONS_FOR_CLONE=5 threshold mismatch.

Changed

  • Dead-code cleanup semantics now require real dead-code evidence (placeholder-only file or explicit dead-code pattern) instead of using generic high-deficit files as dead-code candidates.
  • Clone wording is now consistent across code, renderers, cleanup output, and docs:
    • exact_duplicate_pair = exact same-file duplicates after local-name normalization
    • function_clone_cluster = near-identical function clusters
  • operations.py was split further into focused helper modules:
    • operations_payloads.py
    • operations_cleanup.py
    • operations_architecture.py
    • with the earlier operations_manifest.py and operations_render.py
    • while keeping slop_detector.operations as a compatibility façade.
  • Claude Code skill guidance now uses the canonical product surface: scan, review, pulse, sweep, explain, verify-governance, and mcp, instead of the older /slop*-centric workflow framing.
  • README, roadmap, and development docs now reflect the current clone surfaces, operations split, and agent workflow model.

[3.8.5] - 2026-06-07 — Dual-Audience Output (Plain for Humans, Actionable for Machines)

Changed

  • Human summary hides internal algorithm names. The Project Summary coherence row no longer leaks vr_structural (exact MST); it now reads Structure Coherence: 85% (Higher is more cohesive) with a plain coverage note (full / sampled (large project)) across the rich, text, and markdown renderers. Centralized in renderer_glossary.coherence_display() (OSOT).

Added

  • Machine output is now patch-complete (AI-agent friendly). Project-level JSON / agent route / MCP output gains two additive keys:
    • next_steps — the same deterministic, prioritized action plan humans see (top concern, recommended sweep command, file to start with).
    • metric_guide — per-metric value / healthy direction / plain means, so an agent reading JSON gets the same semantics as a human reader.

Notes

  • The JSON coherence_level value (vr_structural / vr_structural_approx) is unchanged — only the human-facing label was translated. New keys are additive and backward-compatible; no existing key was renamed or removed.

[3.8.4] - 2026-06-07 — Plain-Language Documentation Entry Point

Changed

  • README entry point rewritten benefit-first: a three-line value proposition with no internal mechanism, a de-jargoned "What Is It?" list (technical terms kept in parentheses), plus two new sections — "Why Not Just Use a Linter?" (honest comparison table vs ruff / pylint / ESLint / SonarQube, with Partial marked where they overlap) and "When NOT to Use This".
  • docs/HOW_IT_WORKS.md: added a "What the Acronyms Mean" glossary that decodes every diagram (LDR, Inflation/ICR, DDC, Purity, GQG, Deficit Score, SR9), reusing the exact wordings the CLI prints (renderer_glossary.py).
  • docs/CONFIGURATION.md: added plain-language comments to every key in the advanced: block and glossed GQG / LEDA in the config-validation section.

Notes

  • Documentation only. No code, scoring math, public API, MCP, or npm typed contracts were changed. MATH_MODELS.md (intentionally technical) was left as-is.

[3.8.3] - 2026-06-06 — Readable Output, Next Steps, VS Code Surfaces

Added

Human-friendly output (analysis -> action)

  • Project and per-file reports now render a metrics table with Value, Healthy Direction, and What It Means columns plus a deficit-band legend (CLEAN <30 | SUSPICIOUS 30-50 | INFLATED 50-70 | CRITICAL >=70), so scores are interpretable without prior knowledge (addresses the "no way to gauge the scores" feedback).
  • Deterministic, rule-based Next Steps: each report names the top concern, recommends the matching cleanup command (sweep unused-deps / dead-code + dupes), and points at the highest-priority file plus review scoping.
  • A single renderer_glossary module is the source of truth for metric labels, healthy direction, plain-language meaning, and health bands; the rich, text, and markdown renderers all consume it for identical wording.

VS Code extension

  • Data layer now consumes the ai-slop-detector npm wrapper API and typed contracts instead of hand-rolled child_process calls; all backend execution flows through the wrapper (scan / review / pulse / sweep).
  • New webview panels: 4D + deficit_breakdown (why-not-0.0), confidence-ranked cleanup plan, pulse health dashboard, and diff-aware changed-code review.
  • Getting-started walkthrough, state-aware empty states, context-key view menus, and a domain-profile setting with enumDescriptions.
  • npm wrapper gained options.cwd, runTextCommand, and typed function declarations so editor/agent consumers are fully typed.

Changed

P0 self-dogfood debt reduction

  • operations.py cleanup-family assembly was split into smaller helpers for:
    • dead-code collection
    • duplicate collection
    • manifest hygiene
    • stale suppressions
    • boundary review
  • operations.py manifest hygiene paths now use smaller Python / JS helper stages instead of monolithic scanners.
  • operations.py text and markdown cleanup renderers were split into smaller summary/target/issue formatting helpers.
  • cli_init.py init orchestration was decomposed into smaller helpers for:
    • option resolution
    • domain resolution
    • preview handling
    • existing-config skip handling
    • YAML load / merge support
  • cli_init.py domain detection and language counting now use dedicated collection/scoring helpers rather than single monolithic functions.

Fixed

P0 self-dogfood hotspot reduction

  • self-dogfood pulse weighted deficit score improved from 21.3221 to 18.9637 after refactoring operations.py and cli_init.py.
  • cli_init.py dropped out of the top self-dogfood hotspot set and now scans as clean at the file level.
  • operations.py dead-code heuristics now avoid treating obvious CLI / script entrypoints as placeholder-only files.
  • operations.py no longer imports tomli directly in the scoring surface; runtime import fallback is now used to avoid phantom-import findings on the compatibility path.

Dead-code family semantics

  • sweep dead-code now requires real dead-code evidence (a placeholder file or a dead-code pattern such as pass_placeholder / not_implemented / interface_only_class) instead of any high deficit_score >= 30. Live high-deficit files (e.g. analysis_cache.py, api/server.py) are no longer mislabeled; self-dogfood dead-code dropped from 58 to 10 candidates.

Adaptive init no longer drops hand-written config

  • --force-init combined with --apply-init-suggestions previously overwrote .slopconfig.yaml with the template and then merged onto that template, losing hand-written keys. The pre-existing config is now captured before any overwrite and used as the adaptive merge base.

unused-deps false positives

  • Standard-library modules (abc, ast, collections, ...) are no longer reported as undeclared_import. Detection uses sys.stdlib_module_names with a sysconfig-based discovery fallback for Python 3.8 / 3.9.
  • The unused-dependency check now covers main [project.dependencies] only; optional-dependencies (dev/test tools like black, mypy, pytest) are no longer flagged as unused. Self-dogfood unused-deps dropped from 64 to 20.

[3.8.2] - 2026-06-05 — Adaptive Init, Node Surface, Impact, Telemetry

Added

Adaptive --init onboarding flow

  • --adaptive-init adds a second-stage repository signal scan on top of the existing baseline .slopconfig.yaml generator.
  • --init-preview prints adaptive suggestions without writing config.
  • --apply-init-suggestions opt-in merges bounded suggestions into a new or existing .slopconfig.yaml.
  • Adaptive signal collection now gathers:
    • manifest presence
    • language counts
    • noise directories
    • Python complexity candidates
    • architecture layout markers
    • cleanup markers

NPM thin wrapper surface

  • Added a dedicated npm-wrapper/ package for Node-first distribution.
  • Added a thin launcher:
    • bin/ai-slop-detector.js
  • Added wrapper runtime contract tests and CI coverage.
  • Added explicit install story for:
    • npm
    • pnpm
    • yarn
    • bun
  • Added package-local wrapper README and backend prerequisite documentation.
  • Added version-pinned TypeScript contract exports at ai-slop-detector/types for scan, review, pulse, sweep, and explain JSON outputs.
  • Added a programmatic Node API surface at the package root for:
    • scanProject
    • reviewChanges
    • computeHealth
    • runCleanupFamily
  • Added an agent workflow guide covering JSON-first review, cleanup, health, and MCP-assisted usage patterns.

Local impact and opt-in telemetry

  • Added repo-local impact tracking commands:
    • slop-detector impact enable
    • slop-detector impact
    • slop-detector impact disable
  • Impact snapshots are stored in gitignored .slop-detector/impact.json and summarize trend deltas across repeated runs.
  • Added telemetry control commands:
    • slop-detector telemetry status
    • slop-detector telemetry enable
    • slop-detector telemetry disable
    • slop-detector telemetry inspect --example
  • Added anonymized telemetry payload construction and local queueing.
  • Added inspect-first telemetry mode:
    • AI_SLOP_DETECTOR_TELEMETRY=inspect
    • prints a real payload without queueing or sending it

Changed

  • Adaptive suggestions stay conservative and evidence-backed:
    • ignore suggestions skip patterns already covered by defaults/profile rules
    • god_function.domain_overrides suggestions are exact-name and capped
    • architecture remains stay_disabled unless layered evidence is strong
  • Existing-config init flow remains idempotent by default and only merges adaptive changes with explicit opt-in.
  • README, CLI usage, and configuration docs now describe baseline init, adaptive preview, and explicit merge as distinct flows.
  • npm wrapper documentation now states explicitly that Node is a transport surface over the Python core, not a second implementation.
  • Impact and telemetry surfaces are kept out of the scoring path: scoring remains deterministic, while adoption observability is opt-in and separately controlled.

[3.8.1] - 2026-06-04 — Absorption Chapter: Cleanup Confidence, Manifest Hygiene, Architecture Review

Added

Absorption chapter: cleanup planning and architecture review

  • Cleanup-family output now extends each issues[] item with:
    • confidence
    • action_class
    • evidence
  • Cleanup confidence reuses existing signals instead of inventing a detached model:
    • deficit_score
    • churn
    • coverage
    • cleanup-local evidence
  • unused-deps now includes project-level manifest hygiene for:
    • pyproject.toml
    • package.json
  • New cleanup issue types:
    • manifest_unused_dependency
    • undeclared_import
  • boundary-violations now supports an opt-in architecture review path with a layered preset and explicit layer_boundary_violation findings.

Changed

  • Architecture review remains cycle-only by default; layered boundary rules are opt-in through .slopconfig.yaml.
  • Layered preset evidence now includes matched importer/importee patterns and the exact allow/forbid rule that triggered the finding.
  • README, CLI, architecture, and configuration docs now describe the v3.8.1 operational surface.

[3.8.0] - 2026-06-04 — Canonical CLI Surface & Dogfood Stability

Added

Canonical CLI verbs

  • slop-detector scan <target> is now the preferred stable analysis entry point.
  • slop-detector review <target> is now the preferred changed-code review surface.
  • slop-detector pulse <target> is now the preferred repository health surface.
  • slop-detector sweep <family> <target> is now the preferred cleanup-family surface.
  • Legacy command forms such as audit, health, and direct cleanup-family verbs remain supported for compatibility.

Fixed

Dogfood hotspot prioritization stability

  • prioritization.py no longer assumes every AST body is a list while estimating executable lines for coverage overlays.
  • health and audit now survive lambda-heavy files and other non-list AST body shapes during self-analysis.

Changed

  • README and CLI docs now present the canonical CLI surface first and treat earlier mixed flag/verb paths as compatible legacy entry points.

[3.7.9] - 2026-06-04 — Governance Verification Gate

Added

Fail-closed governance verification

  • slop-detector verify-governance verifies .cr-ep/governance_record.json by recomputing the canonical record hash and failing closed on tamper.
  • The gate also fails closed on policy violations such as halt_count > 0 or trust_tier == "UNTRUSTED".
  • Governance verification is isolated from scoring so mathematical metrics and enforcement policy remain separate layers.

Formal docs

  • docs/MATH_MODELS.md now carries the snapshot audit boundary used by the scoring model.
  • docs/GOVERNANCE.md documents the governance artifact contract and verification command.

Changed

  • README, architecture notes, CLI usage, and release notes now describe the governance verification surface and the math/enforcement split.

[3.7.8] - 2026-06-04 — Sovereign Upgrade Integration (P0-P4)

Added

Structural scaling

  • core.py now caps exact structural coherence at a configurable ceiling and falls back to a deterministic approximation above that limit.
  • CLI flags expose the exact-ceiling and above-ceiling topology mode so the behavior is user-controlled instead of implicit.

Inline suppression

  • Inline directive parsing now supports # slop-disable-next-line, # slop-disable, and # slop-enable with pattern_id or all.
  • Suppressed issues are recorded in an audit ledger and surfaced in terminal, markdown, rich, and CI/gate output.

Repeated-run cache

  • Python file analysis results can now be reused through a SQLite-backed cache.
  • Cache entries are invalidated by file content, metadata, config fingerprint, and engine version drift.

Priority hotspots

  • Project scans now combine deficit, git churn, and coverage gap to rank files by "fix first" priority.
  • Hotspot reasons are exposed in human-readable form for agent and reviewer use.

Agent-native surface

  • The FastAPI API now exposes /agent/schema, /agent/file, and /agent/project for structured consumers.
  • Agent responses bundle summaries, suppression metadata, hotspots, and polyglot analysis results without changing the existing /analyze/* routes.

Fixed

Release documentation sanity

  • README, release notes, architecture docs, and API docs now describe the current integrated release rather than the earlier 3.7.7 baseline.

[3.7.7] - 2026-06-04 — Cross-Language Aggregation Follow-Through & ML Pipeline Reproducibility

Fixed

Cross-language project aggregation completeness

  • core.pyanalyze_project() now aggregates Python, JS/TS, and Go results into a single all_results collection before computing total_files, deficit_files, clean_files, avg_deficit_score, weighted_deficit_score, and overall_status.
  • JS-only and Go-only projects no longer fall through the empty-project path and get mislabeled as clean with total_files = 0.
  • Added language-neutral helpers for project aggregation so Python SlopStatus enum values and JS/Go string statuses are normalized through one boundary.

Repo-relative ignore matching on absolute paths

  • core.py_should_ignore() now accepts an optional root and matches both absolute and repo-relative normalized paths. Patterns such as tests/**, **/*.generated.py, and src/**/*.generated.py now behave consistently during project scans.
  • analyze_project(), _analyze_js_files(), and _analyze_go_files() now pass root=project_path_obj into _should_ignore() so all three language paths use the same ignore semantics.

Project metric consistency

  • core.pyavg_ddc now uses the Python-result count as its denominator (max(1, len(results))) instead of total_files. This restores consistency with avg_inflation, which is Python-derived only, and prevents JS/Go file counts from artificially depressing DDC averages.

ML pipeline reproducibility and report correctness

  • ml/pipeline.pyTrainingSample now preserves generated source in code.
  • _build_dataset() reuses sample.code instead of regenerating synthetic files, eliminating hidden drift between labeled sample creation and feature extraction.
  • _train_from_dataset() centralizes dataset training, report writing, and fail-fast validation.
  • Training now raises ValueError when only one class remains after filtering, instead of proceeding into an invalid one-class training run.
  • PipelineReport.n_samples, n_train, and n_test now reflect usable feature rows rather than originally requested raw sample count.

Added

  • tests/test_core.py — regression tests for:
    • JS/Go-inclusive project aggregation
    • JS-only project status
    • repo-relative ignore behavior on absolute paths
    • recursive generated-file glob ignores
  • tests/test_ml_pipeline.py — regression tests for:
    • synthetic sample code preservation
    • no-regeneration dataset building
    • usable-sample report counts
    • one-class fail-fast behavior

[3.7.6] - 2026-05-24 — UX & Distribution: Deficit Breakdown, Idempotent --init, Windows Output Path

Added

Per-file deficit_breakdown (SLOP-003)

  • core.py — new _compute_deficit_breakdown() attributes a non-zero file score to its source dimensions via log-loss share allocation. Emits five penalty fields (ldr_penalty, inflation_penalty, ddc_penalty, purity_penalty, pattern_hits) plus total. Penalties sum to total within 0.01 when deficit_score < 100.
  • core.py_calculate_slop_status signature extended to return the breakdown alongside (score, status, warnings).
  • models.pyFileAnalysis gains a deficit_breakdown: Dict[str, float] field; to_dict() includes it when populated.
  • README "Scoring Model" section now documents the five-field shape and the sum-to-total invariant.

coherence_level documentation (SLOP-002)

  • README "Scoring Model" now lists the actual emitted values (vr_structural, none) — the v3.7.5 audit listed mst_persistence / not_applicable, but those names are not present in the code. Verify-first applied.

60-Second First Run block (SLOP-005)

  • README gains a top-level "60-Second First Run" section that produces a working JSON result on any folder of Python without requiring --init.
  • Quick Start and 60-Second blocks both recommend --output <path> over > path redirection (PowerShell BOM safety; SLOP-001).

Changed

--init is idempotent (SLOP-006)

  • cli_commands.py:_run_init — re-running --init on an initialized project now prints [*] .slopconfig.yaml already initialized. and exits 0 (previously exited 1). CI scripts that call --init unconditionally no longer fail on repeat invocations. --force-init retains the explicit overwrite semantic.

Tests

  • tests/test_core.pytest_calculate_slop_status_thresholds updated for the new 4-tuple return; new test_deficit_breakdown_attribution_on_clean_file covers field shape, conservation, and to_dict round-trip.
  • tests/test_domain_init.pyTestInitIdempotency::test_rerun_returns_zero covers SLOP-006 acceptance.
  • Full suite: 323 passed, 5 skipped (was 321 passed, 5 skipped).

Notes

  • SLOP-001 was filed against v3.7.5 but the --output flag and UTF-8 (no BOM) write path already existed in that release. v3.7.6 keeps the code path unchanged and only adds documentation that points users away from shell redirection.
  • SLOP-004 (per-file JSON schema) is deferred — docs/SCHEMA_VALIDATION.md already covers input-config validation; a separate output-shape schema requires more design work and was not material to the immediate UX gap.

[3.7.5] - 2026-05-20 — False Positive Patch: Flat-Module Sibling Discovery + phantom_import_allowlist

Fixed

phantom_import false positives on flat-module projects (no pyproject.toml / __init__.py)

  • patterns/python_imports.pyPhantomImportPattern: added __init__(allowlist) parameter; modules listed in phantom_import_allowlist inside .slopconfig.yaml are now respected and skip phantom detection.
  • patterns/python_imports.py_discover_sibling_modules(): new helper that collects stem names of all .py files in the scanned file's own directory. Used as an additional skip set in check() so that sibling modules in flat projects (e.g. cas_parser.py, cas_html.py) are never flagged as phantom regardless of whether a project root is found.
  • config.py — added phantom_import_allowlist: [] to DEFAULT_CONFIG and get_phantom_import_allowlist() getter.
  • patterns/__init__.pyget_all_patterns() now accepts phantom_import_allowlist and forwards it to PhantomImportPattern.
  • core.pySlopDetector.__init__ passes phantom_import_allowlist from config to get_all_patterns().

Root causes addressed

  1. _discover_project_packages only recognised Python packages (directories with __init__.py); single-file modules in flat projects were invisible to it.
  2. phantom_import_allowlist was a documented .slopconfig.yaml key that was parsed into the config dict but never read by PhantomImportPattern.

Effect on CAS audit (Flamehaven Code Audit Standard)

Flat-module project cas_*.py with project-local imports (from cas_parser import ...): phantom_import false positives eliminated. overall_status for the CAS package corrected from suspicious to clean.

Tests

  • tests/test_fp_reduction.py — 3 new regression tests: test_sibling_module_not_flagged_as_phantom, test_phantom_import_allowlist_respected, test_discover_sibling_modules_returns_stems.

[3.7.4] - 2026-05-19 — False Positive Patch: ABC / Optional / FastAPI / Extras

Fixed

Pattern accuracy — 6 false-positive sources eliminated

  • patterns/placeholder.pyEllipsisPlaceholderPattern: added @abstractmethod guard; def method(self) -> None: ... in an ABC no longer fires ellipsis_placeholder
  • patterns/placeholder.pyInterfaceOnlyClassPattern._count_placeholder_methods: @abstractmethod decorated methods are now excluded from the placeholder count; a pure ABC with N abstract stubs no longer triggers interface_only_class
  • patterns/placeholder.pyReturnNonePlaceholderPattern: added @abstractmethod guard + _has_optional_return() helper; return None in a method annotated -> Optional[T] or -> T | None is the Null Object pattern, not a placeholder stub
  • metrics/stub_density.pycalculate_stub_density(): @abstractmethod functions are filtered before _find_largest_clone_group; an ABC with N identical abstract stubs no longer generates a spurious CRITICAL clone cluster
  • patterns/python_imports.py_add_dep_names(): PEP-508 extras specifiers (psycopg[binary]) are now stripped via explicit regex before canonicalisation; guarded imports for properly declared optional dependencies are no longer flagged as phantom
  • patterns/python_clones.py_is_dispatcher_pattern(): Signal 3 added — if the file contains a module-level app or router assignment (FastAPI / Flask route file), the entire file is exempt from clone-cluster flagging

Additional accuracy fixes

  • metrics/inflation.pyInflationCalculator._scan_for_jargon(): word matching now uses \b regex boundaries; previously "neural" would match inside neural_network_training identifier names
  • metrics/inflation.pyacademic jargon list: theorem, proof, lemma removed; these are primary domain vocabulary in formal-methods and governance code, not AI slop signals
  • metrics/inflation.py_MIN_DENSITY_LINES = 15: jargon density is now computed against max(logic_lines, 15); prevents a single jargon word in a 7-line file from scoring the same as 2 hits in a 14-line file
  • patterns/python_complexity.pyGodFunctionPattern: pure line-length violations where complexity < 4 are no longer flagged; declarative setup code (argparse subcommand tables, config blocks) is computationally simple and should not trigger god_function

Tests

  • tests/test_fp_reduction.py: 6 regression tests added (cases ⑩–⑮), one per fixed FP source; all 324 tests pass
  • tests/corpus/placeholder_code.py: ABC regression fixtures appended (abstract ellipsis stubs, Optional return, concrete NullImpl)
  • tests/test_inflation.py: test_justified_jargon updated to use standalone word in comment; validates word-boundary detection

Docs

  • docs/PATTERNS.md: version header updated; descriptions corrected for ellipsis_placeholder, return_none_placeholder, interface_only_class (severity HIGH, threshold 50%), function_clone_cluster (algorithm: JSD < 0.05, not Jaccard 0.85), phantom_import (extras handling)

[3.7.3] - 2026-05-04 — Hotfix: Graceful pydantic import + CI stability

Fixed

  • config.py: pydantic imports moved inside try/except ImportError; when pydantic is absent _validate_yaml_config() returns immediately — package imports cleanly in stripped environments (e.g. pip install ai-slop-detector before deps resolve)
  • tests/test_api_models.py: guard changed from importorskip("pydantic") to importorskip("fastapi"); pydantic is now a base dep so the old guard no longer skipped the test, causing a collection error when fastapi (api extra) was absent

CI

  • ci.yml (Docker job): Docker Hub login now uses continue-on-error: true; push step conditional on steps.docker_login.outcome == 'success' — missing DOCKER_USERNAME/DOCKER_TOKEN secrets no longer fail the build
  • ci-gate-fixed.yml: install pinned to "ai-slop-detector>=3.7.3" to prevent the self-referential quality gate from resolving to the broken v3.7.2 PyPI package

[3.7.2] - 2026-05-04 — Runtime Schema Validation + VS Code Typed Boundary

Added

Core — data boundary validation

  • config.py: _validate_yaml_config() validates critical sections of .slopconfig.yaml before merging — Pydantic schemas _WeightsSchema (range [0.0, 1.0] per weight), _DomainOverrideSchema (str pattern, int thresholds ≥ 1), _GodFunctionSchema — Bad user config (e.g. weights.ldr: "hello", complexity_threshold: "high") raises ValueError with exact field path at load time, before it can reach the GQG formula
  • models.py: __post_init__ range guards on computed metric results — LDRResult: clamps ldr_score to [0, 1] with WARNING log — protects math.log() in GQG scorer — InflationResult: clamps inflation_score to [0, ∞) — prevents negative score artefacts — DDCResult: clamps usage_ratio to [0, 1] with WARNING log
  • history.py: HistoryEntry.__post_init__ sanitises all numeric fields before SQLite insertion — Clamps deficit_score ≥ 0, ldr_score / ddc_usage_ratio ∈ [0, 1], n_critical_patterns / pattern_count ≥ 0 — Validates fired_rules as parseable JSON at write time (not silently on read); LEDA calibration grid search inputs are now structurally guaranteed

VS Code Extension v3.7.2

  • schema.ts (new, 185 L): ISlopReport, ILdrResult, IInflationResult, IDdcResult, ISlopPattern TypeScript interfaces mirroring FileAnalysis.to_dict() contract; ParseResult<T> discriminated union (ok / error, never throws); parseSlopReport(data: unknown): ParseResult<ISlopReport> — handwritten type predicate guards on all required fields, status enum membership, ldr.ldr_score numeric, pattern_issues[i] shape
  • analyzer.ts: runSlopDetector() return type narrowed any → Promise<ISlopReport>; parseSlopReport() applied after extractJson(); schema mismatch throws with exact field / expected / got path and version-hint message

[3.7.1] - 2026-05-03 — Self-Scan Quality Pass + LintEscape False Positive Fix

Fixed

Pattern accuracy

  • patterns/python_lint.py: LintEscapePattern.check() now skips lines that fall inside string/docstring literals — # noqa: text in docstrings (e.g., """...has '# noqa: F401'...""") was incorrectly flagged as a live lint suppression; fix uses _string_literal_lines() to collect all ast.Constant[str] line ranges and exclude them from the regex scan

Code quality (self-scan audit — avg_deficit 13.85 → 9.80)

  • cli_commands.py L215: except OSError: pass in detect_domain() replaced with debug-level log — domain detection is best-effort but the exception should be observable
  • cli_commands.py L380: except Exception: pass in _check_calibration_hint() replaced with debug-level log — calibration hint failure is informational, but silent discard masked the exception; # noqa: BLE001 retained (broad catch is intentional for never-block semantics)
  • scripts/global_injector.py: Patch 1 (DEFAULT_CONFIG["weights"] rewrite) removed from inject_config_py() — dogfooding-calibrated values belong only in DOMAIN_PROFILES["general"]["capability_vector"], not in the canonical production fallback; the regex was also outdated (3-key pattern, no purity) so it already MISS-ed, but the wrong design intent was preserved in code

Documentation accuracy

  • docs/LEDA_CALIBRATION.md §2 diagram: removed config.py L31: DEFAULT_CONFIG["weights"] injection target — injector only writes to DOMAIN_PROFILES["general"]; added clarifying note
  • docs/LEDA_CALIBRATION.md §3.1 GQG formula: added max(1e-4, ...) clamp guards (matching core.py:484-487) — previously showed bare log(x) which would be −inf at zero
  • docs/LEDA_CALIBRATION.md §4.3 Before column: ddc corrected to 0.20² with footnote explaining pre-3.7.0 historical value was 0.30
  • docs/CLAUDE_CODE_SKILL.md: loop label scan -> interpret -> patch -> re-scan -> gate corrected to scan -> diagnose -> patch -> re-scan -> gate -> calibrate in 4 locations; Quality Loop section updated to 7 numbered steps with role labels
  • claude-skills/slop-detector/SKILL.md (installed copy): same loop correction applied

README balance

  • Claude Code Skill section demoted to compact "Claude Code Integration" block (38 lines → 10 lines) — convenience feature was given equal billing with core detection features
  • LEDA Engine section restored as "Empirical Weight Calibration (LEDA)" with Mermaid flywheel diagram; "Breaking the Self-Referential Bias" bullet list merged into single intro paragraph — three redundant restatements collapsed to one cohesive statement; [Calibration] nav link restored

Changed

.slopconfig.yaml — domain_overrides expanded for justified structural complexity

  • god_function: added overrides for detect_domain (cc=13, domain trigger scanner), _collect_imports (cc=21/depth=7, DDC import resolver), _analyze_regex (118L, Go line dispatcher), _run_self_calibration (118L, CLI calibration orchestrator), _check_calibration_hint (56L, result formatter)
  • nested_complexity: added overrides for same functions plus _collect_all_members, _collect_noqa_imports
  • ignore: added scripts/generate_download_chart.py — legacy chart utility with optional matplotlib/numpy deps not in main venv; phantom_import flags are expected

.gitignore: added scripts/injection_report.json — auto-generated audit trail from global_injector.py, not source

Claude Code Skill — workflow upgrade

  • claude-skills/slop-detector/SKILL.md: 3-Phase Pipeline execution model added
    • Phase 1 Triage: structured table (file / score / status / top issue) with session baseline stored for delta comparison
    • Phase 2 Deep-Dive: Confidence Routing by status band — CRITICAL_DEFICIT immediate; SUSPICIOUS routes through /slop-file second-pass before escalation (reduces false escalation of borderline files)
    • Phase 3 Action Plan: ordered fixes with explicit gate-readiness assessment
  • /slop-delta new command: before/after comparison table against session baseline; regression detection; "never say fixed without a measured delta" rule enforced
  • Each command ends with explicit → Next: guidance — eliminates user uncertainty about next step
  • lint_escape added to Patch Guidance table

VS Code Extension v3.7.1 (vscode-extension/)

  • P1: 855-line monolith split into 8 focused modules (state / analyzer / diagnostics / statusbar / commands / calibration / codeActions / treeview / codelens)
  • P2: SlopCodeActionProvider — QuickFix for phantom_import / god_function / lint_escape; "Add to .slopconfig.yaml ignore" action
  • P3: TreeView sidebar — 3-level hierarchy (file → 4D metric row → issue list); CRITICAL→LOW sort; click-to-navigate; Refresh + Analyze Workspace title-bar buttons
  • P4: SlopCodeLensProvider — file-level summary at line 0 + per-function issue hints; slopDetector.enableCodeLens setting

[3.7.0] - 2026-05-02 — Dogfooding Model Calibration + SKILL.md Contract Repair

Added

Real-world Dogfooding Model

  • scripts/retrain_model.py: new ThresholdClassifier (pure-Python, no sklearn required) trained on real dogfooding data
  • Handled 784 actual samples from 7 distinct repositories with 55.1% bad class distribution
  • Achieved stable evaluation: accuracy=0.7962, precision=0.9524, recall=0.6742 replacing previous initial baseline models (accuracy=1.0)
  • Extracted and applied key thresholds for ldr_score, inflation_score, ddc_score, god_function_count
  • Completely replaced models/training_data.json and models/slop_classifier.pkl with live representations
  • Removed legacy _real suffixed files to streamline models structure

SKILL.md — CLI surface documented

  • --emit-leda-yaml / --leda-output / --leda-profile (choices: internal | restricted | public)
  • --cross-file cross-file dependency + clone analysis
  • --governance CR-EP session artifact emission
  • --gate (SNP) vs --ci-mode hard (CIGate) gate path distinction
  • ML score availability: appears in --json output when ML model is loaded
  • domain_overrides corrected to per-function pattern exemption format

Fixed

SKILL.md — 10 OSOT violations repaired (Sentinel-verified)

Critical (command contract errors):

  • G1: ddc default weight 0.30 -> 0.20 (matches core.py:479)
  • G2: /slop-gate split -- --gate (SNP/sr9/di2/jsd/ove, PASS/HALT) vs --ci-mode hard --ci-report (CIGate, exit code)
  • G3: DEPENDENCY_NOISE status added with exact trigger (DDC < 20% AND no critical patterns AND inflation <= 1.0)
  • D1: Project-level CRITICAL_DEFICIT threshold corrected to weighted_deficit_score >= 50; file vs project scope distinguished
  • D2: CI hard gate completed -- 4 conditions: deficit >= 70, patterns >= 3, inflation >= 1.5, ddc < 0.5

Medium (documentation drift):

  • G4: fhval spar marked as external Flamehaven tool with install prerequisite
  • D3: Domain profile names corrected (web/api, library/sdk, cli/tool, scientific/ml, scientific/numerical, bio, finance)
  • D4: domain_overrides YAML corrected -- per-function pattern exemption, not metric threshold override
  • D5: Self-calibration two-gate structure documented -- outer trigger: 10 multi-run files milestone (CALIBRATION_MILESTONE=10); inner floor: >= 5 improvements + >= 5 fp_candidates per class. Previous docs described only one gate, causing confusion
  • D6: DDC warning threshold added (< 0.70 = WARNING, < 0.50 = CRITICAL); LEDA profile internal documented; DDC three-band zone table added

Code bugs (Sentinel post-calibration audit)

Critical:

  • BUG-1: config.py:31 DEFAULT_CONFIG weights corrected to {ldr:0.40, inflation:0.30, ddc:0.20, purity:0.10} — calibration had accidentally written general domain capability_vector values into weights key, causing no-init path to use ddc=0.6215 instead of 0.20; purity was absent (always fell back to GQG hardcoded 0.10)
  • BUG-1: config.py:150 get_weights() fallback aligned to same values + purity added (was dead code but divergent)
  • BUG-2: cli_renderer.py:500 Markdown findings filter threshold corrected 0.3 -> 30.0 — was comparing 0-100 scale deficit_score to 0.3, causing all files to appear in Detailed Findings section regardless of CLEAN status

High:

  • BUG-3: cli_renderer.py:446,450 Test function counts replaced with AST-actual counts via _count_test_functions_ast() — hardcoded += 5 / += 10 per file caused fabricated "Test Evidence" statistics in Markdown/text reports

Medium:

  • BUG-5: self_calibrator.py:697 _rewrite_key() scoped to weights: YAML block only — global MULTILINE regex could corrupt identically-named keys in other YAML sections (e.g., comments or custom domain stanzas)

Refactored

cli_renderer.py split (730 lines → 4 renderer modules)

  • renderer_rich.py (~270 lines): Rich console rendering, RICH_AVAILABLE, list_patterns, print_rich_report, all _build_* panel helpers
  • renderer_markdown.py (~240 lines): get_mitigation, test-evidence helpers, _md_* section builders, generate_markdown_report
  • renderer_text.py (~80 lines): _text_* helpers, generate_text_report
  • renderer_html.py (~30 lines): generate_html_report
  • cli_renderer.py converted to 17-line re-export shim — all existing cli.py imports unchanged

patterns/python_advanced.py split (1150 lines → 5 domain modules)

  • python_complexity.py (327 lines): GodFunctionPattern, DeadCodePattern, DeepNestingPattern, NestedComplexityPattern
  • python_lint.py (102 lines): LintEscapePattern
  • python_imports.py (282 lines): PhantomImportPattern + 8 resolution helpers
  • python_clones.py (76 lines): FunctionClonePattern
  • python_naming.py (123 lines): PlaceholderVariableNamingPattern

[3.6.0] - 2026-04-28 — Claude Code Skill + Documentation Fixes

Added

Claude Code Skill — claude-skills/slop-detector/

  • SKILL.md with YAML frontmatter (name: slop-detector, description 456 chars)
  • Four slash commands: /slop (full project scan + interpretation), /slop-file [path] (single file + per-pattern fix guidance), /slop-gate (CI hard gate PASS/FAIL), /slop-spar (adversarial validation via fhval spar)
  • Implements full scan -> patch -> re-scan -> gate quality loop with delta reporting
  • Session-persistent review criteria: quality policy lives in skill layer, not prompt
  • docs/CLAUDE_CODE_SKILL.md — full skill documentation with command reference, metric explanation table, patch reference, and calibration guide
  • README Claude Code Skill section with install instructions and loop diagram

Fixed

Documentation accuracy

  • What It Detects table: corrected "Three metric axes" to "Four metric axes"; added Purity row (exp(-0.5 x n_critical_patterns)) — consistent with 4D scoring model stated in introduction and docs/MATH_MODELS.md
  • Scoring Model: added normalization note — weights sum to 1.10; GQG divides by total_w so exact normalization is not required (matches docs/MATH_MODELS.md:160)
  • Quick Start: added missing pip install "ai-slop-detector[go]" extra (was listed in Key Features and pyproject.toml but absent from Quick Start)
  • Positioning: added Not a style linter. A structural-risk scanner for AI-assisted code. under the tagline

Removed

  • tests/manual_test/audit_report.md, audit_report_full.md, report.md — stale artifacts from previous manual runs; no automated test dependency

[3.5.0] - 2026-04-13 — Phase 3: Domain-Aware Init + JS/TS + Go Analysis

Added

Phase 3a — Domain-Aware --init (v3.5.0)

  • DOMAIN_PROFILES dict in config.py: 8 built-in profiles (general, web_frontend, data_science, cli_tool, library, ml_research, backend_api, scientific) each with normalized capability_vector weights (w_ldr, w_inf, w_ddc, w_pur)
  • detect_domain(project_path): heuristic auto-detection from file patterns and directory structure; returns the closest matching domain key
  • Domain-aware _run_init(): generates .slopconfig.yaml pre-seeded with the detected domain's weight profile; printed as a user-visible suggestion in CLI output
  • --domain CLI flag: explicitly override auto-detection (slop-detector --init --domain web_frontend)
  • 21 new tests in tests/test_domain_init.py covering all 8 profiles and CLI flag

Phase 3b — JS/TS Analysis via JSAnalyzer v2.8.0

  • languages/__init__.py: activated JSAnalyzer for .js, .jsx, .ts, .tsx extensions (was commented-out stub); LANGUAGE_ANALYZERS dict now maps all four extensions
  • models.py: added js_file_results: List[Any] field to ProjectAnalysis dataclass; to_dict() serializes each entry via .to_dict() when available
  • core.py: _JS_EXTENSIONS frozenset; _get_js_analyzer() lazy-loader; _analyze_js_files() private method scanning with rglob; analyze_js_file() public API; JS analysis is computed before the Python early-return path so pure-JS projects return correct results
  • analyze_project() early-return path now includes js_file_results in the returned ProjectAnalysis (previously JS results were lost when no Python files were found)
  • optional dep [js]: tree-sitter>=0.25.0, tree-sitter-javascript>=0.23.0, tree-sitter-typescript>=0.23.0 (regex fallback active when not installed)
  • 32 new tests in tests/test_js_analyzer.py: instantiation, line counting, slop scoring, issue detection (regex fallback), TS-specific any detection, AST mode (skipped without tree-sitter), and SlopDetector integration

Phase 3c — Go Analysis via GoAnalyzer v1.0.0

  • languages/go_analyzer.py: standalone GoAnalyzer class with GoIssue + GoFileAnalysis dataclasses; detects go_empty_func, go_panic, go_fmt_print, go_ignored_error, go_todo_comment, go_god_function; regex fallback always active; optional tree-sitter-go guard for future AST enrichment
  • languages/__init__.py: imports GoAnalyzer; .go added to LANGUAGE_ANALYZERS
  • models.py: go_file_results: List[Any] field added to ProjectAnalysis; to_dict() serializes via .to_dict() per entry
  • core.py: _GO_EXTENSIONS frozenset; _get_go_analyzer() lazy-loader; _analyze_go_files() private method; analyze_go_file() public API; Go analysis hoisted before early-return (same pattern as JS — pure-Go projects populate go_file_results correctly)
  • optional dep [go]: tree-sitter>=0.25.0, tree-sitter-go>=0.23.0
  • 24 new tests in tests/test_go_analyzer.py covering all patterns, slop scoring, and SlopDetector integration

CI

  • New test-js job: installs .[dev,js] and runs tests/test_js_analyzer.py on Python 3.11
  • New test-go job: installs .[dev,go] and runs tests/test_go_analyzer.py on Python 3.11

Added (self-calibration improvements — v3.5.0 patch)

  • Schema v5 project_id (history.py): project_id TEXT column added (auto-migrated). Set to sha256[:12] of the resolved cwd at scan time. Prevents cross-project signal pollution in the global ~/.slop-detector/history.db.
  • Project-scoped calibration (self_calibrator.py, cli_commands.py): calibrate() accepts project_id and passes it to _load_history() and _extract_events(). _record_history() and _check_calibration_hint() now compute and thread project_id via new _compute_project_id() helper.
  • Better calibration trigger (cli_commands.py, history.py): milestone is now count_files_with_multiple_runs(project_id) instead of count_total_records(). A first-time scan of N files records N rows but zero repeat-file pairs, so total_records % 10 == 0 was a false trigger. Only files scanned ≥2× can produce improvement/fp_candidate events.
  • Domain-anchored grid search (self_calibrator.py): _grid_search() accepts domain_anchor dict; when provided each dimension's range is constrained to [anchor - DOMAIN_TOLERANCE(0.15), anchor + DOMAIN_TOLERANCE] (clipped to absolute MIN_W/MAX_W). _check_calibration_hint() passes current_weights as the anchor so calibration stays within the domain's meaningful weight region.
  • DOMAIN_TOLERANCE = 0.15 constant added to self_calibrator.py.
  • Domain-drift warning (self_calibrator.py): CalibrationResult gains warnings: List[str] field (empty by default). After a successful calibration, calibrate() compares each optimal dimension weight against domain_anchor (or current_weights as fallback); any dimension that drifts more than DOMAIN_DRIFT_LIMIT = 0.25 appends a human-readable warning. Warnings are surfaced by _run_self_calibration() with a yellow [!] prefix (rich) or plain [!] prefix (plain output).
  • DOMAIN_DRIFT_LIMIT = 0.25 constant added to self_calibrator.py.
  • 16 unit tests in tests/test_calibration_patches.py: P2 (6 tests: empty DB, single-run exclusion, multi-run count, 3-run dedup, project_id scoping, cross-contamination guard), P1 (3: project_id persisted, null stored as null, _load_history filter), P3 (3: unconstrained covers full ldr range, constrained stays within ±DOMAIN_TOLERANCE, fewer candidates), P4 (4: field exists + defaults empty, independent instances, drift warning fires, no warning when drift small). 308/308 green.

Fixed

  • jq parse error in "Self SLOP Detection" CI job (cli_commands.py): root cause was _check_calibration_hint() printing calibration milestone text to stdout after the JSON block when src/ contained ≥10 files (a CALIBRATION_MILESTONE=10 multiple). jq received {...json...}\n[*] Calibration milestone... and rejected it as invalid JSON. All _check_calibration_hint() prints now go to file=sys.stderr.
  • float("inf") in JSON output (metrics/inflation.py L157): _compute_inflation_score() returned float("inf") when logic_lines == 0 and effective_jargon > 0. Python's json.dumps serialises this as Infinity (invalid RFC 8259). Changed to 10.0 (same cap as the normal code-path min(..., 10.0)) — maximally-inflated sentinel, no JSON leakage.
  • avg_inflation filter regression (core.py): previous fix used status != "error" as an inf guard; with the sentinel changed to 999.0 the guard became dead code. Replaced with math.isfinite(r.inflation.inflation_score) — correctly excludes any non-finite value regardless of status string.
  • _sanitize_for_json hardened (cli.py): added tuple handling alongside list; added json.dumps(..., allow_nan=False) so any residual non-finite float raises ValueError immediately rather than silently emitting invalid JSON.
  • E2E calibration tests (tests/e2e_v321/test_e2e_v321.py): milestone_fired and auto_calibrated assertions now check both stdout and stderr so the tests remain green after the print redirection.

[3.4.1] - 2026-04-12 — CI Fixes + STUB FileRole + Auto-Config Detection

Added

  • FileRole.STUB (file_role.py): new role for pure Protocol/ABC interface stubs. Files where all top-level class definitions inherit from Protocol, ABC, or ABCMeta and contain no top-level function definitions are now classified as STUB. STUB skips ldr and patterns checks — ...-body stubs and clone patterns are structurally expected, not quality deficits.
  • STUB regression test (tests/test_fp_reduction.py ⑥): asserts Protocol-stub files produce FileRole.STUB and SlopStatus.CLEAN to prevent silent regression.
  • Auto-detect .slopconfig.yaml (cli.py): when --config is not specified the CLI now probes the project root (project mode) or the file's parent directory (single-file mode) for .slopconfig.yaml and loads it automatically.

Fixed

  • classify_file() signature: tree: ast.ASTtree: ast.Module; ast.AST has no .body attribute — ast.parse() always returns ast.Module. Fixes mypy attr-defined error.
  • Python 3.8 CI compatibility: replaced with (A, B): parenthesized context manager syntax (Python 3.9+) with nested with statements in test_leda_injection.py and test_cli.py::test_main_emit_leda_yaml.

Added

LEDA injection emission for SPAR-adjacent review

  • Added slop_detector/leda_injection.py to emit a structured YAML surface for downstream SPAR review.
  • Added CLI flags:
    • --emit-leda-yaml
    • --leda-output
  • The emitted payload carries:
    • project identity
    • live analysis summary
    • calibration surface
    • claim-risk candidates
    • suggested maturity hints
    • SPAR review hints
  • Added tests covering payload generation and CLI emission.
  • Added LEDA redaction profiles:
    • internal
    • restricted
    • public
  • Default CLI emission now uses restricted to reduce accidental exposure of implementation weakness surfaces in exported YAML.

[3.4.0] - 2026-04-12 — Phase 2: Per-Rule FP Tracking + Purity Weight Ceiling

Added

Per-Rule FP Rate Tracking (LEDA v3.4.0 — Phase 2A)

  • history.py schema v4: new fired_rules TEXT DEFAULT NULL column stores {"pattern_id": count} JSON per scan row; old rows degrade gracefully to NULL
  • HistoryEntry.fired_rules: Optional[str] field + record() builds the JSON dict from file_analysis.pattern_issues
  • SelfCalibrator._calc_per_rule_fp_rates(): computes per-rule FP rate across all labeled CalibrationEvents; only rules seen ≥ MIN_RULE_OCCURRENCES=3 times included
  • _parse_fired_rules(json_str) -> List[str]: module-level helper for safe JSON parsing
  • CalibrationEvent.rule_ids: List[str]: pattern IDs fired during that event
  • CalibrationResult.per_rule_fp_rates: Dict[str, float]: rule_id → FP rate output
  • Rich per-rule FP table in --self-calibrate output (rules ≥50% shown; ≥70% = HIGH FP)
  • Plain-text fallback for non-rich environments

Purity Weight Ceiling (LEDA v3.4.0 — Phase 2B)

  • MAX_PURITY_WEIGHT = 0.25 constant: caps purity dimension at 25% of weight budget (was implicitly up to 65% via MAX_W; purity is count-based and more volatile than ratios)
  • MIN_RULE_OCCURRENCES = 3 constant: minimum events per rule to include in FP rate stats
  • Grid search _grid_search() respects ceiling: purity iterates [0.10, 0.15, 0.20, 0.25] only

[3.3.0] - 2026-04-12 — Phase 1 False-Positive Reduction

Added

File Role Classifier (file_role.py)

  • New FileRole enum: SOURCE, INIT, RE_EXPORT, TEST, MODEL, CORPUS
  • classify_file() auto-detects the role of each file being analyzed
  • ROLE_SKIP map: per-role metric suppression (e.g., INIT skips ldr+ddc)
  • _SkipProxy in core.py: thin proxy that nullifies skipped metric contributions without duplicating the GQG scoring formula

DDC Annotation-Only Import Tracking (FP ①)

  • UsageCollector now tracks annotation_used — names referenced only in type annotations
  • Imports used exclusively in type hints (e.g., argparse.Namespace) are excluded from both unused list and usage_ratio denominator
  • Eliminates false-positive SUSPICIOUS on files with annotation-heavy APIs

# noqa: F401 Recognition (FP ②)

  • _collect_noqa_imports() scans inline comments for # noqa: F401 markers
  • Such imports are excluded from unused and denominator — treated as intentional suppressions

__all__ Re-Export Recognition (FP ③)

  • _collect_all_members() collects names published via __all__
  • Imports re-exported through __all__ are excluded from unused — they have runtime value

Changed

  • analyze_file() and analyze_code_string() in core.py now accept a skip set derived from file role classification
  • _calculate_slop_status() and _build_metric_warnings() accept skip parameter
  • DEPENDENCY_NOISE override respects skip — won't fire for INIT/RE_EXPORT files

Fixed

  • usage_ratio calculation now correctly uses runtime_imports (all imports minus excluded set) as denominator, not raw total imports

[3.2.1] - 2026-04-11

Added

P1 — Auto-calibration at milestone (cli.py _check_calibration_hint())

  • At every CALIBRATION_MILESTONE (10) scans, calibration now runs automatically and applies to .slopconfig.yaml (if it exists and calibration is confident).
  • Prints per-weight diff: ldr: 0.40 -> 0.45 etc. for full transparency.
  • Only applies when result.status == "ok"CONFIDENCE_GAP and no_change safety gates prevent noisy or regressive updates.
  • This closes the "The more you use it, the smarter it becomes" loop end-to-end; no manual --self-calibrate / --apply-calibration required.

P2 — Git commit context as noise filter (history.py + cli.py + self_calibrator.py)

  • _get_git_context() in cli.py: captures git rev-parse --short HEAD and git branch --show-current once per run (3 s timeout, graceful None fallback).
  • history.py record() accepts git_commit and git_branch kwargs and stores them.
  • self_calibrator.py _load_history() now SELECTs git_commit and includes it in the returned dict.
  • _classify_run_pair() uses git context as a noise signal:
    • improvement filter: same commit + score drop → measurement noise, skip.
    • FP candidate filter: different commits + stable hash → ambiguous signal, skip.
    • When git_commit is NULL (non-git projects), original heuristic applies unchanged.
  • Result: fewer but higher-fidelity labeled events → more reliable calibration signal.

P3 — Per-class minimum thresholds (self_calibrator.py)

  • MIN_EVENTS = 20 replaced by MIN_IMPROVEMENTS = 5 / MIN_FP_CANDIDATES = 5.
  • CALIBRATION_MILESTONE = MIN_IMPROVEMENTS + MIN_FP_CANDIDATES (= 10).
  • calibrate() checks each class independently: both must meet their floor before grid search runs. Prevents class-imbalanced calibration.
  • 4D model's continuous tiebreak signal makes 5+5 statistically sufficient (where 3D binary rates required 10+10).
  • --min-history CLI arg: default changed from 20 → 5 (per-class floor).
  • cli.py import updated: MIN_EVENTSCALIBRATION_MILESTONE.

Fixed

  • self_calibrator.py calibrate(): default min_events changed from CALIBRATION_MILESTONE (10) to MIN_IMPROVEMENTS (5); old default caused max(10, MIN_IMPROVEMENTS=5) = 10 per-class floor, defeating the 5+5 design intent. Now correctly yields max(5, 5) = 5 per class.
  • cli.py _run_self_calibration(): getattr(args, "min_history", 20) default corrected to 5.

[3.2.0] - 2026-04-11

Added

ml/self_calibrator.py — F1: 4D calibration (purity dimension)

  • CalibrationEvent and WeightCandidate now carry a purity weight dimension.
  • _recompute_deficit() computes purity_score = exp(-0.5 * n_critical_patterns): 1.0 when no critical patterns, decays toward 0 as critical patterns accumulate.
  • _grid_search() extended from 3D to 4D simplex: three nested loops (i, j, p), k = GRID_STEP − i − j − p; constraints keep each weight in [MIN_W, MAX_W].
  • apply_to_config() now writes all four keys: ldr, inflation, ddc, purity.
  • CalibrationResult.optimal_weights now includes a "purity" key.
  • Backward compatible: old history.db rows default n_critical_patterns = 0purity_score = 1.0 → no change to deficit from old records.

ml/self_calibrator.py — internal refactor: event extraction decomposed

  • _extract_events() split into three focused helpers:
    • _group_runs_by_file(rows) — groups + sorts rows by file and timestamp
    • _classify_consecutive_runs(file_path, runs, seen_fp_files) — per-file loop
    • _classify_run_pair(file_path, r_now, r_next, drop, seen_fp_files) — single pair
  • Reduces nesting depth (depth=4 → depth=3), CC (11 → 3 per function), and lines per function (54 → 10 each). No behaviour change.

history.py — F1 schema: n_critical_patterns column

  • _SCHEMA_V2 includes n_critical_patterns INTEGER NOT NULL DEFAULT 0.
  • _migrate() adds the column when upgrading from schema v1.
  • HistoryEntry dataclass gains n_critical_patterns: int = 0.
  • record() computes the count from pattern_issues (CRITICAL severity only).
  • _insert() writes the value in the 12-column INSERT.
  • count_total_records() -> int method added for auto-trigger hint.

cli.py + config.py — F2: --init bootstrap

  • slop-detector --init [path] generates a fully documented .slopconfig.yaml in the target project root (or . by default).
  • Project type auto-detected (python / javascript / go) from package.json / go.mod.
  • .gitignore entry injected automatically with an explanatory security comment.
  • --force-init flag overwrites an existing .slopconfig.yaml.
  • generate_slopconfig_template(project_type) added to config.py.

cli.py — F3: auto-trigger calibration hint

  • After every run that records history, _check_calibration_hint() fires when total records cross a MIN_EVENTS milestone (every 20 records).
  • Output: [*] Calibration available (N events). Run --self-calibrate to optimize weights.
  • Closes the LEDA loop: --init → scan (auto-log) → hint → --self-calibrate--apply-calibration.

README.md — F4: Security Considerations section

  • Documents what .slopconfig.yaml contains (domain overrides = codebase weakness map) and why it should default to .gitignore for private projects.
  • Documents history.db location (~/.slop-detector/) and its safety properties.
  • Navigation bar updated; scoring section reflects all 4 calibrated dimensions.

Changed

.slopconfig.yaml — purity weight added + ML calibrator overrides

  • weights: block now includes purity: 0.10 (4D calibration, v3.2.0+).
  • nested_complexity.domain_overrides adds _grid_search (depth=6, cc=10): 4D grid search requires n-1 nested loops by mathematical necessity.
  • god_function.domain_overrides adds calibrate (lines=100) and apply_to_config (lines=70): orchestrator and YAML comment-preserving updater patterns are inherently multi-step.
  • Self-scan result: 44/44 files CLEAN (was 42/43 before this patch).

Fixed

cli.py — P6: --min-history default / fallback drift (doc drift)

  • --min-history argparser default was hardcoded 10; fallback in _run_self_calibration also used 10. Both now sync to MIN_EVENTS = 20 from self_calibrator.py.
  • Impact: without this fix, slop-detector --self-calibrate (no --min-history flag) would trigger calibration with only 10 events — contradicting the documented threshold and reducing statistical reliability of the result.
  • Fix: default=20 in add_argument, getattr(args, "min_history", 20) in runner.

[3.1.3] - 2026-04-11

Fixed

ml/self_calibrator.py — P1: apply_to_config comment preservation

  • Replaced yaml.safe_load + yaml.dump full-file rewrite with a targeted regex in-place approach: only the numeric values on the ldr:, inflation:, ddc: lines are rewritten. All comments, domain_overrides, ignore patterns, and every other key are left untouched.
  • Handles three edge cases: all keys present (common), some keys missing (insert under existing weights: block), no weights: block (append one).
  • Eliminates the risk of losing annotated .slopconfig.yaml governance docs on --apply-calibration.

ml/self_calibrator.py — P2: FP candidate deduplication

  • _extract_events() previously emitted one fp_candidate per consecutive run pair per file. A file unchanged across 50 runs generated 49 fp_candidates, heavily biasing the FP pool and causing the calibrator to recommend inflated w_ddc values.
  • Fix: introduced seen_fp_files set — each file now contributes at most one fp_candidate event regardless of how many stable consecutive runs it has.

ml/self_calibrator.py — P4: MIN_EVENTS raised from 10 → 20

  • At 10 events, a binary fp_rate on 3 FP candidates has only 4 possible values (0.0 / 0.33 / 0.67 / 1.0), making grid-search rankings statistically unreliable.
  • Raised to 20 events for minimum viable calibration signal.

README.md — P3: weight drift correction

  • Scoring Model section showed ddc=0.20; actual default in config.py and .slopconfig.yaml is ddc=0.30. Corrected.
  • Added explicit note that purity=0.10 is a fixed coefficient, not calibrated.

Security

.gitignore — P5: slop-detector runtime artifact exclusion

  • Added .slop-detector/ to cover any local cache directories created by workflow variants. Documents that .slopconfig.yaml is intentionally committed in this project (open-source governance transparency) while explaining that private projects should exclude it via --init (coming in v3.2.0).

[3.1.2] - 2026-04-11

Fixed

ml/data_collector.py — structural refactor + debug output

  • Extracted two inner counting loops in from_analysis() as static helpers: _count_severities(issues) and _count_cross_lang(issues). Reduces from_analysis from 75 lines / depth=7 to ~30 lines / depth=3.
  • print(f"[!] Failed ...") error handlers replaced with logger.warning(...). Module-level logger = logging.getLogger(__name__) added. save_dataset() progress prints marked # noqa: T201 (intentional CLI output).

.slopconfig.yaml — domain overrides gap fill

  • Added nested_complexity overrides for functions not previously covered: _analyze_function, _detect_unused_imports, _count_implementation_lines, _count_module_implementation_lines, analyze.
  • Added god_function overrides for the same functions, plus ML pipeline: run, run_on_real_data, _train_from_samples, _build_dataset, _extract_features.
  • Removed duplicate god_function block introduced by incremental editing.
  • Self-scan result: 43/43 files CLEAN (was 4 suspicious before this patch).

[3.1.1] - 2026-04-08

Fixed

Clone Detection visibility

  • function_clone_cluster results were only visible in the Issues section; Core Metrics table showed no duplication signal (reported via community issue).
  • Fix: added "Clone Detection:" row to the Core Metrics table. CRITICAL/HIGH severity shown when function_clone_cluster fires; PASS otherwise. No model changes — reads from existing pattern_issues list.

Table style unification (CLI UX)

  • Project-level output mixed three Rich table box styles (SIMPLE, MINIMAL_DOUBLE_HEAD, ROUNDED). All tables now use box.ROUNDED with header_style="bold cyan".
  • Jargon entries in File Analysis Notes column trimmed to first 3 terms
    • "+N more" — prevents column overflow on heavily-flagged files.
  • File Analysis Status severity color extended to critical_deficit variant.

VS Code extension (v3.1.1)

  • extractJson(): strips [INFO] log lines before JSON.parse — prevents parse failures when CLI emits log output alongside JSON.
  • recordHistory setting now correctly passes --no-history to the CLI.
  • Summary diagnostic message includes Clone Detection signal from pattern_issues.
  • Status bar tooltip uses null-safe metric access and shows Clone PASS/CRITICAL.
  • Workspace analysis: replaced single-line notification with a QuickPick list of deficit files sorted by score; clicking a file opens it in the editor.
  • History Trends: formatted column table (Runs/Latest/Best/Worst/Trend) replaces raw JSON dump in Output panel.

uv tooling

  • Added .python-version and uv.lock to .gitignore.

Internal

Pattern refactoring (self-inspection driven)

  • placeholder.py: extracted _strip_docstring, _has_abstractmethod, _empty_container_repr, _is_placeholder_stmt as module-level helpers. All check_node methods now delegate to helpers (8–15 lines each vs. 20–70). Self-scan deficit score: 70.3 → 43.7.
  • python_advanced.py: added _make_god_issue() to GodFunctionPattern; added _collect_numbered_vars() to reduce nesting depth in PlaceholderVariableNamingPattern. Self-scan deficit score: 74.0 → 66.7.
  • No behavior changes; all 188 tests pass.

[3.1.0] - 2026-04-08

Added

Mathematical model refinements — formula alignment and precision improvements

ml/self_calibrator.py_recompute_deficit: aligned to geometric mean

  • The calibrator's objective function now mirrors GQG exactly. First-generation calibrator used a weighted arithmetic mean; the scorer uses a weighted geometric mean. AM ≥ GM always — on files with uneven dimension profiles, this produced a ~5-7pt gap between what the calibrator optimized for and what the scorer computed. Weights were tuned against a simpler approximation of the target formula.
  • Refinement: replaced ldr*w + (1-inf)*w + ddc*w with exp(Σw_i*ln(v_i)/Σw_i). Purity excluded from calibrator (it depends on pattern count, not weights).

metrics/inflation.py — complexity modifier baseline: cc=3 → cc=1

  • Previous formula: max(1.0, 1.0 + (cc - 3.0) / 10.0) produced modifier=1.0 for cc=1,2,3 — the three most common complexity levels paid no complexity premium on jargon inflation. Minimum meaningful baseline is cc=1.
  • Refinement: max(1.0, 1.0 + (cc - 1.0) / 10.0). cc=2 now gets modifier=1.10.

core.py — purity weight now configurable

  • w_pur = 0.10 was hardcoded, invisible to the calibrator and not honored by .slopconfig.yaml weights.purity field despite being documented.
  • Refinement: w_pur = weights.get("purity", 0.10). Default unchanged; the config surface now matches the implementation.

New patterns — stub evasion and complexity fragmentation detection

return_constant_stub (extended) — empty container stubs

  • return {}, return [], return (), return set() now trigger return_constant_stub alongside existing return True/False/"string"/0 detection.
  • Same applies to interface_only_class placeholder check.

function_clone_cluster (new) — DI2-based AST clone detection

  • Detects files where a large cluster of functions have near-identical AST node-type distributions (pairwise JSD < 0.05).
  • Addresses the complexity_hidden_in_helpers adversarial evasion pattern: a god function split into N structurally identical one-liners evades all per-function gates (god_function, nested_complexity) but produces a measurable file-level signal.
  • Thresholds: ≥ 6 clones → CRITICAL; ≥ 4 clones → HIGH.
  • Algorithm: 30-dim AST histogram per function → pairwise JSD → BFS connected components. Ported and adapted from Protocol-ReGenesis-Engine src/core/math_models.py (itself a Python port of Flamehaven-TOE v4.5.0 toe/math/di2.py).
  • New module: metrics/stub_density.py_jsd(), _node_histogram(), _find_largest_clone_group(), calculate_stub_density().

placeholder_variable_naming (new, v1.0) — naming pattern detection

  • Two sub-checks:
    1. High single-letter parameter count: ≥ 5 single-letter params (excluding self, cls, _) → HIGH. E.g. def process(a, b, c, d, e, f, g).
    2. Sequential numbered variable pattern: ≥ 8 in sequence → HIGH; ≥ 4 → MEDIUM. E.g. r1, r2, r3 ... r12.
  • Addresses vocab_clean_meaningless adversarial evasion: meaningful-vocabulary code with zero semantic content evades all existing pattern gates, but placeholder naming is structurally detectable.
  • v1.0 design note: detects naming style, not semantic quality. Known false positive zone: math/science libraries using single-letter variable conventions. Configure with domain_overrides or --config ignore to suppress.

fhval — SPAR-Code subcommand (fhval spar)

New spar subcommand in fhval (flamehaven-validator) providing a 3-layer adversarial regression loop for the scoring model:

  • Layer A (ground truth anchors): 5 known code patterns with expected deficit ranges. Any deviation = scoring model regression.
    • clean_trivial: deficit ≤ 15 (regression guard)
    • extreme_jargon: deficit ≥ 40 (regression guard)
    • stub_class_8_methods: deficit ≥ 30 (was ANOMALY in v3.0.x)
    • fragmented_god_function: deficit ≥ 10 (was ANOMALY in v3.0.x)
    • vocab_clean_meaningless: deficit ≥ 8 (was ANOMALY in v3.0.x)
  • Layer B (peer challenges): 4 documented architectural limitations with severity classification.
  • Layer C (existence probes): 4 probes testing whether each metric measures what it claims (LDR genuineness, inflation blindspot, DDC annotation gap, calibrator consistency).

SPAR score progression: 55 → 85 PASS after v3.1.0 refinements.

Changed

  • patterns/__init__.py: registered FunctionClonePattern, PlaceholderVariableNamingPattern.

Notes

  • All 188 tests pass. No public API changes.
  • vocab_clean_meaningless SPAR check remains CONSISTENT via naming pattern detection (v1.0). The deeper semantic gap (arithmetic with no meaning) is documented in SPAR Layer C as a known scope limitation of static analysis.

[3.0.3] - 2026-04-08

Changed

Structural debt reduction — top-3 deficit files refactored (self-eating-own-dog-food)

Self-scan before: avg_deficit=23.57, 15 deficit files, status=suspicious Self-scan after: avg_deficit=20.33, 12 deficit files, status=clean

analysis/cross_file.py — deficit 70.3 → 28.7 (critical_deficit → clean)

  • Extracted _hash_function_body(func_node) from _extract_functions — removes 4-deep nesting
  • Rewrote _extract_imports using early-continue; removed single-value for ext in (".py",) loop
  • Promoted nested dfs() closure to _dfs(self, ...) private method (was triggering nested_complexity as a closure inside _detect_cycles)
  • Extracted _build_exact_duplicate_pairs(hash_index) from _detect_duplicates — separates hash indexing from pair enumeration

ci_gate.py — deficit 69.3 → 22.3 (inflated_signal → clean)

  • Extracted _classify_files(result) — removes file-classification loop from _evaluate_project
  • Added _verdict_soft/hard/quarantine() helpers — replaces 87-line if/elif/else mode dispatch with a dict-dispatch pattern; reduces _evaluate_project to ~20 lines
  • Extracted _evaluate_file_quarantine(result, verdict) — removes nested QUARANTINE branch from _evaluate_file
  • Extracted _has_uncovered_production_claims(ctx_jargon) — flattens the 4-deep loop in _check_claims_evidence
  • Replaced for file_result in result.file_results: if ...: break with next() in _update_quarantine
  • Moved production-claim strings to _PRODUCTION_CLAIMS class constant (was re-declared inline)

cli.py — deficit 68.4 → 20.9 (inflated_signal → clean)

  • Extracted _categorize_pattern(pattern) → str — removes 4-branch if/elif from list_patterns
  • Extracted _print_pattern_category(category, patterns) — removes triple-nested print loop
  • Extracted _file_has_production_claims(f_res) — removes 4-deep evidence-detail loop from _collect_test_evidence_stats; moved shared production-claim set to _PRODUCTION_CLAIMS_CLI module constant
  • Extracted _write_json_output(args, result) — removes if args.output: nesting inside if args.json:
  • Extracted _route_file_output(out, result, rich_ok) — separates format routing from _handle_output dispatcher
  • Extracted _run_analysis_phase(args, detector) — removes inner if args.project: branch from main's try block
  • Extracted _text_file_lines(fr) — removes 4-deep jargon-detail loop from _text_project_section; converts inner for-with-if to list comprehension

.slopconfig.yaml — Rule-0 false-positive prevention

  • Added explicit # RULE-0 NOTE block documenting that tests/corpus/ and __init__.py are intentional slop fixtures and packaging boilerplate respectively
  • Documents correct invocation: --config .slopconfig.yaml is required when running SIDRCE or slop-detector from project root

All 188 tests pass. No public API changes.


[3.0.2] - 2026-03-15

Fixed

P0 — PhantomImportPattern: context-aware 3-tier import classification

Project package auto-discovery (_find_project_root, _discover_project_packages)

  • Walks up to 12 directory levels to locate pyproject.toml, setup.py, setup.cfg, or .git.
  • Scans the found root for internal project packages: src/ layout, flat layout, and [tool.setuptools.packages.find] where directive.
  • Parses [project.dependencies] and [project.optional-dependencies] to extract declared package names, stripping vendor prefixes (e.g. flamehaven_nnslnnsl).
  • Results cached per-process (_PROJECT_PACKAGES_CACHE) — zero repeated I/O within a run.

Import guard detection (_collect_import_guard_lines, _IMPORT_GUARD_EXC_NAMES)

  • AST walk of every ast.Try node in the file; collects line numbers of import/from statements inside try bodies whose except handlers catch any of: ImportError, ModuleNotFoundError, Exception, BaseException.
  • Prevents false positives on broad-guard patterns (except Exception:) used in API adapter modules and framework bridges.

3-tier classification (_make_issue)

Tier Condition Severity Message
Internal Module is part of current project (skip)
Guarded Import inside try/except ImportError block MEDIUM "Undeclared optional dependency"
Hard Unresolvable, no guard CRITICAL "Phantom import"

Result: eliminates the cascade where 252 project-internal phantom hits drove DDC → 0, GQG → ln(1e-4), and deficit_score → 100 for every file in a src-layout project.


P1 — LDR: packaging __init__.py no longer collapses GQG

  • ldr.calculate() now detects empty (content-free) __init__.py files before computing the ratio. Empty packaging init → ldr_score=1.0, grade="N/A", is_packaging_init=True.
  • Prevents total_lines=0ldr_score=0.0GQG → ln(1e-4) cascade on standard src/<pkg>/__init__.py files.
  • LDRResult model: new is_packaging_init: bool = False field, serialized via to_dict().

P2 — GodFunctionPattern: length-only paths demoted to LOW

Previously any function exceeding lines_threshold OR complexity_threshold was flagged HIGH. This produced false positives on verbose-but-simple domain code: physics constant tables, routing dispatch blocks, and rule interpreters with low cyclomatic complexity.

New severity routing:

Condition Severity
cc > complexity_threshold (regardless of length) HIGH
lines > lines_threshold AND cc > complexity_threshold HIGH
lines > lines_threshold AND cc <= 5 LOW

P3 — Placeholder pattern precision

NotImplementedPattern — skip @abstractmethod

  • raise NotImplementedError inside an @abstractmethod-decorated method is the correct Python ABC pattern, not a placeholder. Added the same decorator check already present in PassPlaceholderPattern.

EmptyExceptPattern — rewritten as 3-tier

Handler Severity Message
Bare except: pass CRITICAL "Bare 'except: pass' swallows all exceptions including SystemExit"
except (ImportError|ModuleNotFoundError): pass LOW "optional dependency guard; verify this is intentional"
except SomeType: pass MEDIUM "silently discards the exception"

InterfaceOnlyClassPatternreturn self/return cls counted as placeholder

  • Method-chaining stubs (return self) provide no meaningful domain value in an otherwise unimplemented class. Now counted toward the placeholder threshold.

Validation

  • Applied to Flamehaven-TOE v4.5.0 (83 files, src-layout, 11 optional deps):
    • Before: 252 CRITICAL phantom imports, deficit_score=100 on all files, status=critical_deficit
    • After: 0 CRITICAL phantom imports, 11 MEDIUM (correctly classified optional deps), deficit_score avg ~18.1, status=clean
  • 188 tests pass; ruff + mypy clean.

[3.0.1] - 2026-03-10

Added

D4 — ReturnConstantStubPattern (return_constant_stub, HIGH)

  • New pattern detecting functions whose entire body (excluding docstring) is a single return <constant> statement (return 42, return True, return "ok", etc.).
  • Targets the ldr_gaming / stub_with_real_structure adversarial evasion: dense one-liner stubs score high on LDR but carry zero semantic value.
  • Excluded: dunder methods (__len__, __bool__, __hash__, ...) which legitimately return constants; @abstractmethod decorated functions; return None (already covered by ReturnNonePlaceholderPattern).
  • InterfaceOnlyClassPattern updated to also count return <constant> methods as placeholders.

D2 — Configurable god_function thresholds with domain_overrides

  • GodFunctionPattern now accepts complexity_threshold, lines_threshold, and domain_overrides constructor arguments.
  • Thresholds configurable per-project via .slopconfig.yaml:
    patterns:
      god_function:
        complexity_threshold: 10    # default
        lines_threshold: 50         # default
        domain_overrides:
          - function_pattern: "evaluate"    # fnmatch wildcard supported
            complexity_threshold: 80
            lines_threshold: 300
  • function_pattern uses fnmatch — supports evaluate, validate_*, check_?, etc. First matching override wins. Falls back to global thresholds if no match.
  • Config.get_god_function_config() added; core.py passes it to get_all_patterns().
  • Rationale: clinical governance engines, rule interpreters, and safety systems have inherent domain complexity that is not accidental. A single config entry suppresses false positives without disabling the pattern globally.

Fixed

  • get_all_patterns() now accepts optional god_function_config dict — no breaking change, default behavior (cc=10, lines=50, no overrides) is identical to v3.0.0.

[3.0.0] - 2026-03-09

Added

CQMS Level 2 — Code Quality Metric Space (Mathematical Foundation)

DCF (Distributional Code Fingerprint)

  • _compute_dcf(tree) module-level function: P(node_type | file) = count(node_type) / total_nodes. Genuine probability distribution over AST node types; values in [0,1], sum to 1.
  • FileAnalysis.dcf: Dict[str, float] — stores the DCF for each analyzed file.
  • analyze_file() and analyze_code_string() now compute and attach DCF (reuses already-parsed AST).

GQG (Geometric Quality Gate)

  • _calculate_slop_status now uses weighted geometric mean (GQG) instead of arithmetic mean.
  • Formula: Omega = exp(sum(w_i * ln(max(1e-4, v_i))) / sum(w_i))
  • AND-gate property: any dimension collapsing to 0 drives Omega to 0; no compensation.
  • Dimensions: ldr (w=config), inflation_q (w=config), ddc (w=config), purity (w=0.10 fixed).
  • Purity: exp(-0.5 * n_critical_patterns) — exponential penalty for CRITICAL-severity patterns.

MST H0 VR Structural Coherence

  • _js_divergence(p, q) — Jensen-Shannon divergence in [0,1] (log-base-e, normalized).
  • _compute_coherence_vr(file_dcfs) — MST H0 persistence coherence over file DCFs. coherence = 1 - max_mst_edge where max_mst_edge = longest edge in Prim's MST of pairwise sqrt-JSD distances. Epsilon-free; equivalent to max H0 persistence in the Vietoris-Rips filtration.
  • analyze_project() now collects file_dcfs and computes structural coherence when >= 2 files.
  • ProjectAnalysis.structural_coherence: float — 1.0 = all files structurally uniform.
  • ProjectAnalysis.coherence_level: str — "vr_structural" when computed, "none" otherwise.

Gate comment fix

  • gate/slop_gate.py: _normalize_jsd() now documents that the jsd key is not information-theoretic JSD. Key name preserved for SNP contract backward compatibility. True DCF-JSD is available via FileAnalysis.dcf (v3.0+).

Changed

  • _calculate_slop_status: arithmetic mean replaced with GQG (breaking: scoring values change).
  • DEPENDENCY_NOISE override now guarded by not critical_patterns and inflation <= 1.0 to prevent mislabeling multi-cause failures as dependency noise under GQG.

[2.9.3] - 2026-03-09

Added

Self-Calibration Engine — --self-calibrate

  • New src/slop_detector/ml/self_calibrator.py — adaptive weight optimizer.
  • Labels derived from user behaviour, not formula outputs (breaks tautology):
    • improvement_event: deficit > 25 in run[i], dropped > 10 in run[i+1] → user fixed it
    • fp_candidate: deficit > 25, same file_hash in next run, no change → user ignored it
  • Grid search over weight simplex {w_ldr + w_inflation + w_ddc = 1.0, wi ∈ [0.10, 0.65]} at 0.05 resolution (no new dependencies — pure stdlib + yaml).
  • Continuous tiebreaker (LEDA MetaLearning pattern): when candidates tie on binary FN+FP rate, secondary sort by avg_fp_deficit − avg_tp_margin breaks the tie.
  • Copilot Guardian-style confidence gap: if gap between #1 and #2 < 0.10, reports insufficient_data rather than applying a weakly-supported calibration.
  • --apply-calibration [CONFIG]: writes optimal weights to .slopconfig.yaml (default) only when status == ok.
  • --min-history N: override minimum event threshold (default: 10).
  • CLI output: 3-panel Rich layout (status, event counts, weight delta table with ± colors).

First live run on Flamehaven history.db (180 unique files, 62 improvements, 176 FP candidates):

Current Optimal
ldr 0.40 0.10
inflation 0.30 0.25
ddc 0.30 0.65
combined error 1.1069 0.9985
confidence gap 0.1088

Interpretation: high FN rate (91.9%) against metric-only recomputed deficits indicates pattern penalties dominate this codebase's scoring. Weight calibration operates on the metric component only; pattern-driven deficits are orthogonal and unaffected.


[2.9.2] - 2026-03-09

Fixed

Rich 3-Panel Single-File UI — Reconnected Missing Feature

  • _render_rich_single_file was rendering a single box.DOUBLE panel containing raw key-value text — inconsistent with the documented 3-panel layout described in README and shown in interface screenshots.
  • Reconnected the intended design:
    • Panel 1 (box.ROUNDED): File path, status badge, deficit score — right-aligned.
    • Panel 2 (box.ROUNDED): LDR / ICR / DDC / Justification Ratio / ML Prediction with per-row color coding (red/yellow/green).
    • Panel 3 (box.ROUNDED): Review questions with inline severity badges ([CRITICAL] red, [WARNING] yellow, [INFO] blue).
  • Header banner unified to box.ROUNDED to match panel chrome.
  • Helpers added: _build_header_table, _build_metrics_table, _build_questions_panel.
  • Single-file text-report path (_build_single_file_content) preserved unchanged.

[2.9.1] - 2026-03-08

Changed

Self-Inspection Patch — cli.py God Function Decomposition

  • print_rich_report() split into six focused helpers: _build_rich_summary_tables, _build_rich_files_table, _render_rich_project, _build_single_file_content, _append_pattern_issues_rich, _render_rich_single_file. Each is now ≤ 40 logic lines.
  • main() extracted to _build_arg_parser(), _evaluate_ci_gate(), _run_optional_features(). Complexity reduced from 25 → 14.
  • _handle_output() refactored with _write_file() helper; nesting depth reduced from 5 → 3.
  • generate_markdown_report() split into _md_summary_section(), _md_test_evidence_section(), _md_findings_section().
  • generate_text_report() split into _text_project_section() and _text_single_file_section().

DDC False-Positive Fix — registry.py and question_generator.py

  • Both files had DDC = 0.00 because BasePattern / FileAnalysis were imported only for type annotations, which UsageCollector correctly skips.
  • Fix: annotation-only project imports moved under if TYPE_CHECKING: guard. DDC now correctly classifies them as type-checking imports (excluded from usage ratio), resolving the false positive without changing runtime behavior.
  • registry.py: added from __future__ import annotations, replaced eager global _global_registry lazy-init pattern with module-level eager initialization (eliminates global statement, DDC HIGH flag).
  • question_generator.py: restored from __future__ import annotations, converted Python 3.10+ union syntax (int | None, str | None, list[Q], dict[...]) to Optional[int], Optional[str], List[Q], Dict[...] for Python 3.8 compatibility.

Fixed

  • Self-inspection result (dogfooding on own src/):
    • deficit_files: 3 → 0 (cli.py 53.5→29.1, registry.py 39.5→clean, question_generator.py 30.0→clean)
    • avg_deficit_score: 11.65 → 9.57
    • weighted_deficit_score: 15.88 → 12.42
    • overall_status: clean (unchanged)
  • 188 tests pass; ruff + mypy clean.

[2.9.0] - 2026-03-08

Added

PhantomImportPattern — Hallucinated Package Detection (CRITICAL)

  • New pattern phantom_import detects imports referencing packages that do not exist in the current environment: not in stdlib, built-in C extensions, or installed distributions.
  • Resolution index built once per process from three sources:
    1. sys.builtin_module_names — C extension modules
    2. sys.stdlib_module_names — standard library (Python 3.10+)
    3. importlib.metadata.packages_distributions() — pip-installed packages
  • importlib.util.find_spec fallback covers namespace packages and editable installs.
  • Relative imports (from . import X) excluded — local project structure is environment-dependent.
  • Severity: CRITICAL, Axis: QUALITY, ID: phantom_import
  • Errs toward False Negative on resolution errors to avoid false positives.

History Auto-Tracking (v2.9.0)

  • Every CLI run automatically records results to ~/.slop-detector/history.db (SQLite).
  • Schema: deficit_score, ldr_score, inflation_score, ddc_usage_ratio, pattern_count, grade, git_commit, git_branch, file_hash (SHA256 prefix).
  • Auto-migration on first run — safe ALTER TABLE for schema evolution.
  • New CLI flags:
    • --show-history — per-file trend table (timestamp, deficit, LDR, patterns, grade)
    • --history-trends — project-wide daily aggregates for last 7 days
    • --export-history <path> — full JSONL export for ML training pipeline
    • --no-history — opt-out from recording this run
  • Trend analysis: direction indicator (improved / degraded / stable) + delta across N runs.
  • export_jsonl() produces training-ready JSONL for DatasetLoader.load_jsonl().

Real Training Data Pipeline ([ml-data] extra)

  • MLPipeline.run_on_real_data(): loads CodeSearchNet / the-stack / custom JSONL, applies self-supervised labelling (deficit_score >= 30 → slop), trains classifier.
  • DatasetLoader: load_codesearchnet(), load_stack(), load_jsonl().
  • New extra: pip install "ai-slop-detector[ml-data]" (scikit-learn + numpy + datasets>=2.9.0).
  • datasets added to full extra and mypy ignore list.

Core Identity Reframe

  • README primary statement updated to reflect the project's ontology: "Catches the slop that AI produces — before it reaches production." Authorship (human / Claude / Cursor / custom agent) is irrelevant; the code speaks for itself.

Changed

  • history.py fully rewritten: bcr_scoreinflation_score (v2.8.0 alignment), pattern_count added, global DB path ~/.slop-detector/history.db, export_jsonl() replaces export_history().
  • RandomForestClassifier now trained with class_weight="balanced" to handle real-data class imbalance (~4% slop rate in public datasets).
  • load_codesearchnet(): removed deprecated trust_remote_code=True (datasets>=4.x).
  • pyproject.toml version: 2.8.02.9.0.

Fixed

  • --show-history resolves relative paths to absolute before DB lookup.

[2.8.0] - 2026-03-07

Added

Python Advanced Pattern Detectors (AST-based)

  • god_function (HIGH): flags functions where logic_lines > 50 OR cyclomatic_complexity > 10. Complexity computed as 1 + count(If, For, While, ExceptHandler, With, BoolOp).
  • dead_code (MEDIUM): detects statements after terminal nodes (return, raise, break, continue) in any block, including orelse, finalbody, and exception handler bodies.
  • deep_nesting (HIGH): detects control-flow nesting depth > 4. Depth is computed recursively over If/For/While/With/Try bodies.
  • New file: src/slop_detector/patterns/python_advanced.py
  • patterns/__init__.py registers all three via get_all_patterns()

JS/TS Tree-Sitter Analysis ([js] extra)

  • Full AST-based analysis: cyclomatic complexity, god function, dead code, callback hell detection — replaces regex-based heuristics when tree-sitter is available
  • FunctionMetrics dataclass: per-function complexity, max depth, is_god_function
  • JSFileAnalysis extended with: function_metrics, max_complexity, god_function_count, dead_code_count, ast_mode
  • Graceful fallback to regex when tree-sitter is not installed

ML Secondary Signal ([ml] extra)

  • MLScore dataclass: slop_probability, confidence, model_type, agreement, features_used
  • MLScorer.from_model(path) — returns None silently on missing model or missing scikit-learn; zero import overhead without the extra installed
  • FileAnalysis.ml_score field (v2.8.0, Any = None)
  • SlopDetector.__init__ accepts optional model_path: Path parameter
  • MLScore.label property: "slop" (>= 0.70), "uncertain" (>= 0.40), "clean" (< 0.40)
  • Agreement: (deficit_score >= 30) == (slop_probability >= 0.40)
  • New file: src/slop_detector/ml/scorer.py
  • MLScore, MLScorer exported from slop_detector.__init__

CLI Improvements

  • print_rich_report() single-file panel: Pattern Issues section (severity- sorted, top 10 + overflow count), Advanced summary (N god-fn, N dead-code, N deep-nest), ML Score section (probability, confidence, model_type, agreement) — shown only when model is present
  • list_patterns() now includes "Python Advanced" category

VS Code Extension

  • Summary diagnostic message includes ML score when result.ml_score present
  • Status bar tooltip includes ML confidence and label
  • New pattern IDs (god_function, dead_code, deep_nesting) automatically appear as diagnostics via existing generic pattern_id code handler

Documentation

  • docs/MATH_MODELS.md — comprehensive mathematical specification of all scoring formulas, thresholds, SR9 aggregation, AST models, ML feature vector, and formula change history

Packaging

  • New extras: js, ml-full, full
  • ml extra no longer includes xgboost (moved to ml-full)
  • requires-python raised from >=3.8 to >=3.9

Changed

Inflation Score Formula (ICR) — Breaking

  • Complexity now amplifies jargon penalty (max(1.0, 1+(cc-3)/10)) instead of dividing it
  • Formula: min((jargon/logic_lines) * complexity_modifier * 10, 10.0)
  • A function with complexity=13 receives 2x penalty vs. complexity=3

Status Determination — Breaking

  • Single monotonic axis on deficit_score replaces multi-branch logic
  • INFLATED_SIGNAL threshold: deficit_score >= 50
  • SUSPICIOUS threshold: deficit_score >= 30
  • CRITICAL_DEFICIT threshold: deficit_score >= 70
  • Two supplementary overrides: critical-pattern count and DDC ratio

Project LDR — SR9 Conservative Aggregation

  • project_ldr = 0.6 * min(file_ldrs) + 0.4 * mean(file_ldrs)
  • Worst file weighted 60% to prevent masking by majority of clean files

Jargon Justification — Function-Scoped

  • Justification scope changed from file-level to per-function scope
  • Scope includes decorator lines (scope_start = min(decorator.lineno))
  • One import no longer justifies jargon across the entire file

ML Feature Vector

  • bcr_score renamed to inflation_score
  • 3 new features added: god_function_count, dead_code_count, deep_nesting_count
  • Total: 16 features (was 13)

MLScore.to_dict() — Python 3.14 Compatibility

  • Explicit bool(), float(), int() casts for JSON serialization

[2.7.0] - 2026-02-12

Added - VS Code Extension v2.7.0

  • Docstring inflation diagnostics: Line-level detection from docstring_inflation.details[] with severity mapping (critical -> Error, warning -> Warning)
  • Context jargon evidence diagnostics: Flags unjustified claims from context_jargon.evidence_details[] where is_justified === false
  • Hallucinated dependency diagnostics: Surfaces hallucination_deps.hallucinated_deps[] as Info-level diagnostics
  • Pattern fix suggestions: Appends suggestion field to pattern issue messages when present
  • Lint-on-type debounce: 1500ms debounce timer prevents excessive analysis during typing
  • LDR grade in status bar: Tooltip now displays LDR Grade: {grade}

Changed

  • VS Code extension surfaces ~95% of CLI JSON output (up from ~40%)
  • Version alignment: pyproject.toml, __init__.py, package.json all at 2.7.0

[2.6.4] - 2026-02-08

Fixed

  • run_scan ignore handling: run_scan.py now applies configured ignore patterns before file analysis.
  • Fixture exclusion consistency: Paths matched by config ignore rules (for example tests/**) are excluded from scanner input.
  • Scan/report alignment: run_scan.py behavior now aligns with SlopDetector.analyze_project() path filtering.

Changed

  • Pattern matching implementation: Added normalized path matching with fnmatch, including compatibility handling for **/ prefixes.

[2.6.3] - 2026-01-16

Added - Consent-Based Complexity (Phase 1)

Core Feature: Allow developers to explicitly whitelist intentional complexity, shifting responsibility from the tool to the sovereign developer.

@slop.ignore Decorator

  • New decorator: @slop.ignore(reason="...", rules=[...]) to mark functions as intentionally complex
  • Reason required: All ignored functions must provide explanation
  • Selective rules: Optionally ignore specific rules only (LDR, INFLATION, DDC, PLACEHOLDER)
  • AST detection: Decorator detected at analysis time, not runtime
  • Filtered issues: Pattern issues inside ignored functions are excluded from reports

Innovation Zone Exemptions

  • Playground directories: playground/, labs/, experiments/, prototypes/, sandbox/ now exempt from strict analysis
  • Configuration: New consent_complexity section in .slopconfig.yaml
  • Report tracking: Ignored functions logged in "Whitelisted Complexity" section

Usage Examples

import slop

@slop.ignore(reason="Bitwise optimization for O(1) performance")
def fast_inverse_sqrt(number):
    # Complex but intentional implementation
    i = 0x5f3759df - (number >> 1)
    return i

@slop.ignore(reason="Domain algorithm", rules=["LDR"])
def complex_calculation():
    # Only LDR check ignored, other rules still apply
    ...

Changed

  • Version alignment: Unified version to 2.6.3 (was incorrectly showing 3.0.0)
  • FileAnalysis model: Added ignored_functions field
  • Pattern detection: Now filters issues from ignored function ranges

Technical Details

  • New files:
    • src/slop_detector/decorators.py (decorator implementation)
    • tests/test_ignore_pattern.py (10 test cases)
  • Modified files:
    • src/slop_detector/core.py (+100 lines: AST detection, filtering)
    • src/slop_detector/models.py (+15 lines: IgnoredFunction dataclass)
    • src/slop_detector/__init__.py (exports)
    • .slopconfig.example.yaml (new sections)

Philosophy

"Rules should be the soil for the dream to grow, not the cage that kills it."

This release implements the "Dream-Saver Protocol" from SIDRCE_SLOP_EVOLUTION_PLAN.md, ensuring that innovation is not killed by overly strict enforcement.


[2.6.2] - 2026-01-15

Added - Integration Test Evidence Detection

Thanks to @OnlineProxy for the critical feedback: "CI is green, but 0 integration tests" — This release addresses exactly that gap.

Phase 1 + 2: Core Detection (v2.6.2-alpha)

  • Split test evidence: teststests_unit + tests_integration
  • 4-layer detection:
    1. Path-based: tests/integration/, e2e/, it/
    2. File name: test_integration_*.py, *_integration_test.py
    3. Pytest markers: @pytest.mark.integration, @pytest.mark.e2e
    4. Runtime signals: TestClient, testcontainers, docker-compose
  • Enhanced EVIDENCE_REQUIREMENTS:
    • production-ready: Now requires both tests_unit AND tests_integration
    • enterprise-grade: Now requires both test types
    • scalable: Now requires tests_integration
    • fault-tolerant: Now requires tests_integration
  • False positive prevention: _is_real_test_file() excludes helper files

Phase 3: Report Output (v2.6.2-beta)

  • Markdown reports: New "Test Evidence Summary" section
    • Table showing unit vs integration test breakdown
    • Warning when integration tests missing but production claims exist
  • Text reports: Test statistics in project summary
  • Enhanced questions: Human-readable evidence names
    • tests_integration → "integration tests"
    • Special note: "Integration tests are critical for production claims"

Phase 4: Configuration & CI Gate (v2.6.2-rc)

  • Configuration Extension: .slopconfig.yaml support for integration test detection
    • Customizable dir/file patterns, pytest markers, runtime signals
    • Quality claims validation requirements (production_ready, enterprise_grade, scalable, fault_tolerant)
  • CI Gate Claim-Based Mode: --ci-claims-strict flag
    • Fails build if production/enterprise/scalable/fault-tolerant claims lack integration tests
    • Integrates with existing soft/hard/quarantine modes

Changed

  • Evidence tracking: 14 types → 15 types (split tests into unit/integration)
  • Context-jargon coverage: 74% → 95% (+21%)
  • Question readability: Raw evidence names replaced with formatted versions

Technical Details

  • Tests: 170/170 passed (165 existing + 5 new)
  • Coverage: 85% overall
  • New files:
    • tests/test_integration_evidence.py (5 tests)
  • Modified files:
    • src/slop_detector/metrics/context_jargon.py (+47 lines)
    • src/slop_detector/cli.py (+43 lines)
    • src/slop_detector/question_generator.py (+14 lines)
    • README.md (updated evidence list)

Contributing

Special thanks to community feedback that drives these improvements. This release demonstrates responsive development based on real-world usage patterns.


[2.6.1] - 2026-01-12

Added

  • Configuration Sovereignty: Externalized CATEGORY_MAP and INTENT_PATTERNS to src/slop_detector/config/known_deps.yaml
  • Question Generator Tests: Comprehensive test suite with 8 test cases
  • VS Code Extension: Synchronized to v2.6.1

Changed

  • Hallucination Dependencies: Refactored to load configuration dynamically from YAML
  • Test Coverage: Increased from 43% to 85% (overall), question_generator.py: 11% → 88%

Fixed

  • Import Issues: Resolved test import conflicts
  • Documentation: Updated all version references to 2.6.1
  • Date Consistency: Unified all dates to 2026-01-12

Technical Details

  • Tests: 165/165 passed (100% pass rate)
  • Coverage: 85% overall (target: 80%, achieved: +5%)
  • New Module Coverage: 88-92% (all above 90% target)
    • context_jargon.py: 91%
    • docstring_inflation.py: 89%
    • question_generator.py: 88%
    • hallucination_deps.py: 92%

[2.6.0] - 2026-01-12

Added - 6 Killer Upgrades (Phase 2 Complete)

1. Context-Based Jargon Detection

  • Evidence-based validation for quality claims (production-ready, enterprise-grade, etc.)
  • 14 evidence types: error_handling, logging, tests, input_validation, config_management, monitoring, documentation, security, caching, async_support, retry_logic, design_patterns, advanced_algorithms, optimization
  • Justification ratio: justified_claims / total_claims
  • Missing evidence reporting: Specific feedback on what's lacking per claim
  • Cross-validation of buzzwords against actual codebase artifacts

2. Docstring Inflation Analysis

  • Ratio-based detection: docstring_lines / implementation_lines
  • Severity levels: CRITICAL (>=2.0x), WARNING (>=1.0x), INFO (>=0.5x)
  • Per-entity tracking: Functions, classes, and modules analyzed separately
  • File-level aggregation: Overall ratio and top 10 offenders
  • Detects AI-generated documentation without substance

3. Placeholder Pattern Catalog

  • 5 new patterns added:
    • NotImplementedPattern (HIGH) - Functions raising NotImplementedError
    • EmptyExceptPattern (CRITICAL) - Empty exception handlers
    • ReturnNonePlaceholderPattern (MEDIUM) - Functions only returning None
    • InterfaceOnlyClassPattern (MEDIUM) - Classes with 75%+ placeholder methods
    • EllipsisPlaceholderPattern (HIGH) - Ellipsis-only functions
  • Total: 14 placeholder patterns across 4 severity tiers
  • Integration with existing pattern detection system

4. Hallucination Dependencies

  • 12 purpose categories: ML, Vision, HTTP, Database, Async, Data, Serialization, Testing, Logging, CLI, Cloud, Security
  • 60+ libraries tracked across categories
  • Category-level usage analysis: Detects unused ML stack, HTTP libs, etc.
  • Intent inference: "Why was this dependency added?"
  • Per-library and per-category reporting

5. Question Generation UX

  • Actionable review questions instead of raw scores
  • 3 severity levels: Critical, Warning, Info
  • Context-aware phrasing: Line numbers, specific evidence, intent
  • Examples:
    • "Why import 'torch' for ML but never use it?"
    • "'production-ready' claim lacks: error_handling, logging, tests"
    • "Function has 15 lines of docstring, 2 lines of code"
  • Integrated into CLI output with Rich formatting

6. CI Gate 3-Tier Enforcement

  • Soft Mode: PR comments only, never fails (informational)
  • Hard Mode: Fail build on thresholds (strict enforcement)
  • Quarantine Mode: Track repeat offenders, escalate after 3 violations
  • Configurable thresholds: deficit_score, pattern counts, inflation, DDC
  • Persistent tracking: .slop_quarantine.json database
  • GitHub Action examples provided
  • CLI flags: --ci-mode, --ci-report

Changed

  • Improved exception handling: Specific exceptions instead of broad catch
  • Added encoding specifications: UTF-8 for all file I/O operations
  • Removed unused imports: Cleaned up ci_gate.py, question_generator.py

Fixed

  • Broad exception catching in quarantine DB load/save
  • Missing encoding in file operations
  • Unused variable in pattern question generation

Technical Details

  • Files added: 7 (ci_gate.py, docstring_inflation.py, hallucination_deps.py, context_jargon.py + 3 test files)
  • Lines of code: ~2,500 new lines
  • Test coverage: 68% overall, 90%+ for new modules
  • Pylint score: 9.30/10
  • All tests: 58/58 passed

[2.5.1] - 2026-01-10

Fixed

  • Type Hint Detection: Implemented proper _is_in_annotation() using NodeVisitor pattern for accurate import usage detection
  • API Compatibility: Migrated run_scan.py to v2.x API (was using deprecated v1.x API)
  • Type Safety: Enabled mypy type checking (removed ignore_errors = true)
  • Code Quality: Removed dead code and unnecessary return statements

Added

  • Comprehensive CLI Tests: 58 test cases covering all CLI functionality (JSON, HTML, Markdown outputs)
  • Test Coverage: Achieved 80% coverage on core modules (up from 26%)

Changed

  • Coverage Measurement: Focused on core modules (excluded enterprise features in beta)
  • Documentation: Updated badges and status to reflect actual metrics
  • ASCII Safety: Replaced emoji markers with ASCII equivalents in run_scan.py

Includes all features from 2.5.0

  • Polyglot architecture with LanguageAnalyzer interface
  • Pattern refinement for anti-pattern detection
  • Professional terminology (Deficit, Inflation, Jargon)
  • Python-focused quality analysis

[2.5.0] - 2026-01-09

Added

  • Re-architected src/slop_detector/languages with LanguageAnalyzer interface
  • Robust PythonAnalyzer implementation
  • Pattern-based detection system

Changed

  • Renamed metrics for clarity: Slop→Deficit, Hype→Inflation/Jargon
  • Removed conflicting slop_detector.py from root

Fixed

  • Obfuscated regex patterns to prevent self-detection of TODO/FIXME tags

[2.4.0] - 2026-05-15

Added - REST API + Team Dashboard

REST API

  • FastAPI Server: Production-ready REST API with OpenAPI docs
  • Endpoints:
    • POST /analyze/file: Analyze single file with history tracking
    • POST /analyze/project: Full project analysis (async background tasks)
    • GET /history/file/{path}: Get file analysis history
    • GET /trends/project: Quality trends over time
    • POST /webhook/github: GitHub push event handler
    • GET /status/project/{id}: Real-time project status
  • Auto-documentation: Swagger UI at /docs, ReDoc at /redoc
  • CORS Support: Cross-origin requests for dashboard integration

Team Dashboard

  • Real-time Monitoring: Auto-refresh every 30 seconds
  • Visualizations:
    • Overall quality score across all projects
    • Total files monitored
    • Critical issues count
    • 30-day quality trend chart (Chart.js)
  • Project List: Quick overview with scores and grades
  • Alert System: Recent warnings and critical issues
  • Dark Theme: Developer-friendly UI with Tailwind-inspired design
  • ASCII-safe Icons: Cross-platform compatible symbols

GitHub Integration

  • Webhook Handler: Automatic analysis on push events
  • Changed Files Detection: Only analyze modified/added files
  • Status Updates: Post analysis results back to GitHub
  • Branch Filtering: Configure which branches to monitor

CLI Enhancements

  • New Command: slop-api to start REST API server
  • Server Config: --host, --port, --config options
  • Background Mode: Detached server execution

Changed

  • Dependencies: Added FastAPI, Uvicorn, Pydantic
  • Architecture: Separated API layer from core logic
  • Data Models: Pydantic models for request/response validation

Technical Details

  • Performance: Async/await for non-blocking operations
  • Scalability: Background tasks for heavy operations
  • Security: HMAC signature validation for webhooks (production)
  • Monitoring: Health endpoint for uptime checks

[2.3.0] - 2026-01-08

Added - IDE Plugins + Historical Tracking

History Tracking System

  • HistoryTracker: SQLite-based analysis history storage
  • Regression Detection: Automatic detection when scores worsen
  • Trend Analysis: Project-wide quality trends over time
  • File-level History: Track individual file evolution
  • Export Capability: Export history to JSON for external analysis

Git Integration

  • GitIntegration: Extract commit/branch info automatically
  • Pre-commit Hook: Automatic quality detection before commits
  • Staged Files Detection: Only analyze files being committed
  • Fail on Regression: Block commits with quality degradation

VS Code Extension (v2.3.0)

  • Real-time Linting: Analyze on save or while typing
  • Inline Diagnostics: Show warnings/errors directly in editor
  • Status Bar Integration: Quick quality overview
  • Commands:
    • Analyze Current File
    • Analyze Workspace
    • Show File History
    • Install Git Pre-Commit Hook
  • Configuration: Customizable thresholds, auto-lint settings
  • Multi-language: Python, JavaScript, TypeScript support

CLI Enhancements

  • --record-history: Store analysis results in history DB
  • --show-history: Display file analysis history
  • --fail-on regression: Exit with error on quality degradation
  • --install-git-hook: Setup pre-commit hook automatically

Changed

  • History database stored in .slop_history.db by default
  • CLI now supports history-aware operations
  • Improved error messages for missing dependencies

Fixed

  • Git repository detection on Windows
  • File hash calculation for large files
  • Thread-safety for concurrent history writes

[2.2.0] - 2026-01-08

Added - ML Detection + JavaScript/TypeScript Support

Machine Learning Classification (Experimental)

  • SlopClassifier: ML-based quality detection with ensemble models
  • Training Data Collection: Automatic data collection from high-quality repos
  • Model Support:
    • RandomForest: Baseline ensemble model
    • XGBoost: Gradient boosting for improved accuracy
    • Ensemble: Combines RF + XGBoost via voting
  • Performance Targets Achieved:
    • Accuracy: >90% on test set
    • Precision: >85% (minimizes false positives)
    • Recall: >95% (catches most deficits)
    • F1-Score: >90%

Feature Engineering

  • 15 ML Features:
    • Metric-based: LDR, ICR, DDC scores
    • Pattern-based: Critical/High/Medium/Low pattern counts
    • Code-quality: Avg function length, comment ratio, complexity
    • Cross-language patterns, hallucination count
    • Volume metrics: Total lines, logic lines, empty lines

Training Infrastructure

  • TrainingDataCollector: Clones and analyzes GitHub repos
  • Good Data Sources: NumPy, Flask, Django, Requests, CPython
  • Bad Data Sources: Known low-quality repositories
  • Dataset Format: JSON with features and labels
  • Model Persistence: Pickle-based save/load

CLI Enhancements

  • --ml flag to enable ML-based detection
  • --ml-model <path> to specify custom trained model
  • --confidence-threshold for ML prediction filtering
  • ML confidence score in output

Optional Dependencies

  • pip install ai-slop-detector[ml] for ML support
  • scikit-learn, xgboost, numpy as extras

Technical

  • Training data module: slop_detector/ml/training_data.py
  • Classifier module: slop_detector/ml/classifier.py
  • Feature extraction from file analysis results
  • Cross-validation support
  • Feature importance analysis

Documentation

  • ML training guide in README
  • Feature engineering documentation
  • Model performance benchmarks

[2.1.0] - 2026-01-08

Added - Pattern Detection System

  • Pattern Registry: Extensible system for managing detection patterns
  • 23 Detection Patterns:
    • 6 Structural patterns (bare_except, mutable_default_arg, star_import, global_statement, exec_eval, assert)
    • 5 Placeholder patterns (pass, TODO, FIXME, HACK, ellipsis)
    • 12 Cross-language patterns (JavaScript, Java, Ruby, Go, C#, PHP)
  • Hybrid Scoring: Combines metric-based (LDR/ICR/DDC) with pattern-based detection
  • Pattern Penalties: Critical=10pts, High=5pts, Medium=2pts, Low=1pt (capped at 50pts)
  • Pre-commit Hooks: Full integration with .pre-commit-hooks.yaml
  • CLI Enhancements:
    • --list-patterns to show all available patterns
    • --disable <pattern_id> to disable specific patterns
    • --patterns-only to skip metrics and only run patterns
  • Configuration Examples: CONFIG_EXAMPLES.md with pyproject.toml examples

Changed

  • SlopDetector now includes pattern detection alongside metrics
  • FileAnalysis model includes pattern_issues field
  • Deficit score calculation includes pattern penalties
  • Config system supports patterns.disabled list
  • README updated with v2.1.0 features and examples

Technical

  • Pattern base classes: BasePattern, ASTPattern, RegexPattern
  • Pattern registry with enable/disable functionality
  • 8 unit tests for pattern detection
  • Test corpus with 30+ code examples (good and bad)
  • Documentation: CONFIG_EXAMPLES.md for setup guides

[2.1.0-alpha] - 2026-01-08

Added - Pattern Detection System

  • Pattern Registry: Extensible system for managing detection patterns
  • 23 Detection Patterns:
    • 6 Structural patterns (bare_except, mutable_default_arg, star_import, global_statement, exec_eval, assert)
    • 5 Placeholder patterns (pass, TODO, FIXME, HACK, ellipsis)
    • 12 Cross-language patterns (JS, Java, Ruby, Go, C#, PHP)
  • Hybrid Scoring: Combines metric-based (LDR/ICR/DDC) with pattern-based detection
  • Pattern Penalties: Critical=10pts, High=5pts, Medium=2pts, Low=1pt (capped at 50pts)
  • Test Corpus: 3 corpus files with good/bad code examples
  • Configuration: Pattern enable/disable via config file

Changed

  • SlopDetector now includes pattern detection alongside metrics
  • FileAnalysis model includes pattern_issues field
  • Deficit score calculation includes pattern penalties
  • Config system supports patterns.disabled list

Technical

  • Pattern base classes: BasePattern, ASTPattern, RegexPattern
  • Pattern registry with enable/disable functionality
  • 8 unit tests for pattern detection
  • Test corpus with 30+ code examples

[2.0.0] - 2026-01-08

Added - Initial Release

  • Metric-based architecture: LDR, ICR, DDC calculators
  • YAML configuration system: .slopconfig.yaml with deep customization
  • Context-aware jargon detection: Justification checking (e.g., "neural" OK if torch used)
  • Docker support: Production Dockerfile + docker-compose.yml
  • GitHub Actions CI/CD: Full pipeline (test, lint, docker, publish)
  • HTML report generation: Rich visual reports with charts
  • Weighted project analysis: Files weighted by LOC
  • TYPE_CHECKING awareness: Type hint imports excluded from DDC
  • Formula-based scoring: Configurable weights (LDR: 40%, ICR: 30%, DDC: 30%)
  • Environment variable support: SLOP_CONFIG for config path

Core Metrics

  • LDR (Logic Density Ratio): Measures actual logic vs empty shells

    • Empty patterns: pass, ..., return None, raise NotImplementedError, # TODO
    • ABC interface exception (50% penalty reduction)
    • Type stub file support (.pyi)
    • Thresholds: S++ (0.85+), A (0.60+), C (0.30+), F (0.15-)
  • ICR (Inflation-to-Code Ratio): Technical jargon vs implementation complexity

    • 60+ jargon terms tracked (AI/ML, architecture, quality, academic)
    • Radon integration for accurate complexity
    • Config file exception (ICR = 0.0 for settings files)
    • Context-aware justification (jargon OK if backed by code)
    • Thresholds: PASS (<0.5), WARNING (0.5-1.0), FAIL (>1.0)
  • DDC (Deep Dependency Check): Imported vs actually used libraries

    • TYPE_CHECKING block detection
    • Heavyweight library identification (torch, tensorflow, numpy, etc.)
    • Usage ratio: actually_used / imported
    • Thresholds: EXCELLENT (0.90+), ACCEPTABLE (0.50+), SUSPICIOUS (0.30-)

CLI Features

  • Single file analysis mode
  • Project analysis mode (--project flag)
  • JSON output support (--json flag)
  • HTML report generation (--output report.html)
  • Custom config file (--config)
  • Fail threshold for CI/CD (--fail-threshold)
  • Verbose debug output (--verbose)
  • Version flag (--version)

Technical

  • Dependencies: pyyaml, radon, jinja2
  • Python support: 3.8, 3.9, 3.10, 3.11, 3.12
  • Build system: Modern pyproject.toml
  • Testing: Unit tests for LDR, ICR, DDC modules
  • Single-pass AST analysis: Read file once, parse once
  • Documentation: Comprehensive README, CONTRIBUTING, CHANGELOG

Version History Summary

Version Date Focus Status
3.0.2 2026-03-15 Phantom import 3-tier classification, LDR packaging init fix, god_function LOW path, placeholder precision [+] Current
3.0.1 2026-03-10 ReturnConstantStubPattern, configurable god_function thresholds + domain_overrides [+] Released
3.0.0 2026-03-09 GQG scoring, DCF fingerprint, MST H0 VR coherence [+] Released
2.9.3 2026-03-09 Self-calibration engine [+] Released
2.9.2 2026-03-09 Rich 3-panel single-file UI reconnected [+] Released
2.9.1 2026-03-08 Self-inspection patch, DDC false positive fix [+] Released
2.9.0 2026-03-08 PhantomImportPattern, history auto-tracking [+] Released
2.8.0 2026-03-07 Python advanced patterns, JS tree-sitter, ML secondary signal [+] Released
2.7.0 2026-02-12 VS Code extension full diagnostic surface [+] Released
2.6.x 2026-01-12 Consent-based complexity, integration test evidence, config sovereignty [+] Released
2.0.0 2026-01-08 Initial production release [+] Released

Deprecation Notices

Future v3.0

  • Stdlib fallback for radon: Will become optional dependency
  • Text-only output: HTML will be default

Contributors

  • Flamehaven Labs - Core development
  • Community - Bug reports and feature requests

Links


Notes

Versioning Strategy

  • Major (X.0.0): Breaking changes, architectural rewrites
  • Minor (X.Y.0): New features, non-breaking changes
  • Patch (X.Y.Z): Bug fixes, documentation updates

Release Cadence

  • Major releases: Quarterly (Q1, Q2, Q3, Q4)
  • Minor releases: Monthly
  • Patch releases: As needed

Last Updated: 2026-03-15 Current Version: 3.0.2 Status: Production Ready