Skip to content

Releases: Heyosseus/sloppy

v1.7.2

Choose a tag to compare

@github-actions github-actions released this 19 Oct 13:42
c36168a

A patch release that makes some output formats cheaper, and the test suite much faster.

Fixed

  • --format=rector, sarif, github and gitlab no longer read the git history.
    Every format used to compute the risk ranking first, which runs git log and looks
    for a coverage report, although only the console, JSON and Markdown reports use it.
    A CI run that only annotates or writes SARIF now starts fewer git processes.

Internal

  • The test suite runs in parallel. composer test:fast runs the 1,400 tests that stay
    inside PHP in seconds; the ones that build git repositories, start processes or boot
    Laravel are in the integration group, and CI runs both.

Full changelog: v1.7.1...v1.7.2

v1.7.1

Choose a tag to compare

@github-actions github-actions released this 19 Oct 10:23
6fbc27e

Fixed

  • sloppy --version reports the right version. The v1.7.0 tag was
    placed one commit before the release commit, so installs of 1.7.0 still
    called themselves 1.6.0. Upgrading to 1.7.1 fixes it.
  • agents install --dry-run names the files a real install writes.
    In projects that use Laravel Boost, the dry run listed CLAUDE.md,
    GEMINI.md and AGENTS.md, but the install writes the Boost guideline
    (.ai/guidelines/sloppy.blade.php) instead.

Upgrading

composer update heyosseus/sloppy. The GitHub Action and the CI templates
install ^1.7, so they pick up 1.7.1 on their next run without changes.

Full changelog: v1.7.0...v1.7.1

v1.7.0

Choose a tag to compare

@Heyosseus Heyosseus released this 14 Oct 14:42
840ceec

Sloppy 1.7.0

Sloppy now checks agents beyond Claude Code. Gemini CLI and Codex get the same two hooks: findings an edit introduced are handed back right after the edit, and the agent is sent back once before it finishes.

Added

  • Hooks for Gemini CLI and Codex. sloppy agents install --host=gemini --host=codex (repeatable; php artisan sloppy:agents takes it too) writes .gemini/settings.json and .codex/hooks.json, plus each agent's ruleset (GEMINI.md, AGENTS.md). Where Laravel Boost is installed, every agent gets the Boost guideline instead.
  • A Codex patch that touches several files has each file's new findings reported.
  • Gemini CLI gets findings as context on the tool's result, so the model still knows its write went through.
  • sloppy rules --format=gemini writes GEMINI.md.
  • agents uninstall --host limits removal to the agents named. Without it, uninstall also cleans Sloppy out of .gemini/settings.json (hooks and MCP server), .codex/hooks.json, GEMINI.md and AGENTS.md.

Upgrading

  • Nothing to do. Without --host, install wires up Claude Code only, as before, and hooks written by 1.6 keep working unchanged.
  • Codex: after installing, run /hooks in Codex and trust the two Sloppy hooks. Start Codex from the project root, because its hooks run php vendor/bin/sloppy from the session's directory.
  • No --local for Gemini CLI and Codex. They have no personal settings file inside the project, so --local, or an install with no vendor/bin/sloppy, skips them with a warning.

See Coding agents for details.

v1.6.0

Choose a tag to compare

@github-actions github-actions released this 05 Oct 13:19
3b8252e

Sloppy 1.6.0

A correctness release. Fewer false positives, git handling that survives monorepos and unusual file names, a safer MCP server and sloppy fix, and a diff score that describes the whole tree.

⚠️ Before you upgrade

  • Configuration is now validated. A value of the wrong type or out of range stops the run with exit code 2 and lists every problem. An unknowkey only prints a warning, with a "did you mean" hint.
  • The standalone binary merges your config over the defaults, as Artisan always has. A sloppy.php that left out fail_on or exclude now the defaults for them.
  • More things exit with code 2: a --path that doesn't exist, an unknown option, a number option that isn't a whole number, and a file that doesn't parse in ci. Use --allow-parse-errors to keep t architecture no longer accept options they used to ignore.
  • SL501 fingerprints no longer contain a line number, so baselined SL501 entries reappear once. Run sloppy baseline again.
  • More code is analysed: top-level functions, closures,hat extend your own base model. A full scan may reportfindings it missed before; diff and ci still report only new ones.
  • sloppy fix runs Pint only on a Laravel project or one wn the files it changed. agents install --local writesCLAUDE.local.md instead of editing CLAUDE.md.
  • The CI templates and the GitHub Action now install ^1.6

✨ New

  • sloppy agents uninstall removes everything `agents r other settings exactly as they were.
  • diff --merge-base compares against where your branch forked. It's the default in ci.
  • diff accepts every --format, and diff and ci
  • SL303.layer_suffixes, sharing one list with SL301 in the shipped config.
  • CI now covers Windows and PHP 8.5, plus a --no-dev e test.

🐛 Fixed

Rules

  • SL204/SL210 no longer count the collection a loop iterates over as inside the loop.
  • Carbon and other static calls are no longer taken for que
  • SL203 no longer reports after load(), on with('relation:columns'), or on timestamp and cast attributes.
  • SL108/SL110 no longer treat "not null" as "truthy". SL110ed by foreach or destructuring.
  • SL105 accounts for dynamic calls, and SL303 counts enums and anonymous classes as implementations.
  • A class named Client is no longer assumed to be an HTTP
  • SL501 catches three more suppression forms. SL103 no longer counts else if as nesting.
  • No more duplicate SL111 findings. SL109 handles trailing methods, and SL112's stub patterns are tightened.
  • No crash on first-class callables (foo(...)), and anonymous classes are reported once.
  • The blast-radius off-by-one is fixed, and quadratic slowdmoved.

Git and diff

  • Works for a project in a subdirectory of its repository, and with quoted or non-ASCII file names.
  • Ignores your own diff settings: colour, external diff too
  • Handles files moved with plain mv, deleted files, and repositories with no commits yet.
  • The diff score now describes the whole tree instead of al
  • Claude Code hooks skip the score entirely, so they stay fast.

Output

  • Invalid UTF-8 no longer breaks JSON, SARIF or GitLab repo
  • Annotation and SARIF paths are relative to the repository root.
  • errors is always a JSON object.

MCP server

  • Stray output and PHP warnings stay off stdout.
  • ping answers {}, and the protocol version is negotiat
  • Batched and malformed requests are handled, tool arguments are validated, and a relative project path is resolved against the server's root.

Everything else

  • sloppy fix never overwrites a Rector config it didn't w--no-rector`, and exits 0 on a dry run with pending changes.
  • Shared agent hooks use ${CLAUDE_PROJECT_DIR} instead of a path from one machine, and settings files keep their formatting.
  • watch restores your terminal on Ctrl+C and polls less o.
  • The GitHub Action no longer pastes its inputs into its shell script.
  • The phar now includes resources/.

Full changelog: https://github.com/heyosseus/sloppy/com

v1.5.0

Choose a tag to compare

@github-actions github-actions released this 04 Oct 17:56

Sloppy 1.5.0: your architecture, taught to the agents writing your code

1.4.0 let a project describe its architecture. 1.5.0 makes sure the agents writing the code learn it in two places: before they write a file, and on the edit that breaks it. It also makes the architecture easier to write down: init drafts it from your code, import translates deptrac, and graph draws it.

For agents

  • Architecture in every ruleset. If your project declares an architecture, sloppy rules now adds an "Architecture of this project" section to CLAUDE.md, AGENTS.md, Cursor and the Boost guideline. It lists each role, where its classes live, what their names end in, and the policy that applies, written as instructions. Projects that declare nothing get the same file as before.

  • sloppy architecture place says where a new class belongs: the role, namespace, file, naming, and what it may depend on and do.

    vendor/bin/sloppy architecture place "an action that refunds an order" --name=RefundOrder
  • New MCP tools:

    • sloppy_architecture: the whole architecture, one class explained, or the graph.
    • sloppy_place: where a new class belongs.
    • sloppy_architecture_prompt: what an agent needs to write a profile.

    The server now tells agents to call sloppy_place before creating a class.

New checks

Rule Reports
SL307 Misplaced Class A class the change adds in a path listed under covers that matches no role. Runs in sloppy diff and the agent hooks only, so existing classes are never reported.
SL308 Role Shape A public method the role doesn't allow, or a class that isn't final when its role must be (public_methods, final). The laravel-actions preset now limits actions to handle() and the lorisleiva/laravel-actions hooks.
'architecture' => [
    'preset' => 'laravel-actions',
    'covers' => ['app/*'],
    'policies' => [
        'controller' => ['public_methods' => ['__invoke'], 'final' => true],
    ],
],

Writing it down

  • sloppy architecture init drafts a profile from your code:
    • It picks the closest preset.
    • It adds a role for each family of classes the preset doesn't cover (*Observer, *Presenter, …).
    • It asks about any namespace it can't place instead of guessing.
  • sloppy architecture import translates deptrac.yaml: layers become roles, collectors become matchers, and the ruleset becomes allow lists. Anything that can't be translated is named in the file's comments.
  • sloppy architecture prompt gives an agent the format, what the code shows and a draft, so it can turn your ARCHITECTURE.md into a profile. Sloppy itself never calls a model.
  • sloppy architecture graph draws which roles depend on which, as Mermaid, Graphviz or JSON. Forbidden edges are shown in red.

init and import write sloppy-architecture.php in the project root, which Sloppy reads instead of sloppy.architecture. Nothing is written unless you confirm at the terminal or pass --write.

Changed

  • symfony/yaml is now a runtime dependency, used to read deptrac configuration.
  • Evidence sources now receive the project index, so diff-only checks recognise classes exactly the way rules do.

Upgrading

Nothing changes unless you opt in. Projects without a declared architecture get the same rules, findings and rulesets as in 1.4.0.

📖 Describing your architecture · Coding agents · Full changelog

v1.4.0

Choose a tag to compare

@github-actions github-actions released this 04 Oct 14:01
4647fbb

Sloppy 1.4.0: describe your architecture, and Sloppy enforces it

Sloppy no longer has to guess what your classes are from their names. You tell it your project's layers, what each one may do, and where its module boundaries are. Three new rules then report any code that breaks them.

Roles

The new architecture setting gives each class a role: couest, middleware, service, or one of your own. A rolecan match a class by namespace, path, suffix, parent, ancestors, interfaces, traits, attributes or kind. SL201, SL202, SL206, SL207 and SL208 now
read these roles. So if your controllers live in `App\Ui\Htayer, you say so once and every rule uses it.

'architecture' => [
    'preset' => 'laravel',
    'policies' => [
        'controller' => ['may_not' => ['db'], 'may_not_depe
    ],
    'boundaries' => [
        'modules' => 'App\Modules\{module}\*',
        'public'  => ['Contracts\*'],
    ],
],

New rules (opt-in)

Rule Reports
SL304 Layer Violation A dependency a role may not have, named by role or by a glob such as Illuminate\*
SL305 Forbidden Capability A DB query or write, a d read, a view, or a container lookup in a role whose policyforbids it. It only reports what it can prove, so $order->save() on a variable is never a finding.
SL306 Boundary Violation A module that uses anotherf its public surface or the shared kernel

SL208 now also reports outbound HTTP in any role whose poli

These rules run only when your configuration declares a polheck. A project that declares nothing gets the same 26rules and agent rulesets as before.

Presets

The presets are laravel (the default, which works exactly as before), laravel-actions, service-repository, ddd, hexagonal and modular.
Each preset ships roles, policies or boundaries, and you ca a time.

Intended abstractions

Setting 'intended_abstraction' => true on a role tells SL and wrappers in that role are deliberate. A port with asingle adapter is then no longer reported as needless indirection.

sloppy architecture

  • sloppy architecture counts the classes in each role and lists every policy and boundary in force, with where each one came from. - sloppy architecture OrderController explains one class:hich roles it lost, and which policy it is held to.
  • The command can write console output or JSON. Laravel projects can also run it as php artisan sloppy:architecture. - Custom rules can check a class's role with $context->rolasRole($class, 'controller').
    ### Changed
    - Each class now has exactly one role. Where the old chiable signal wins. A FormRequest kept underHttp\Controllers is a form request. An Eloquent model whose name ends in Action, or that sits in App\Domain, is a model, not a service7,485 declarations in eight real applications, this changed findings.
    ### Upgrading
    You don't need to change anything. With no new configuratios in 1.3.1. To try the new rules, add a policies orboundaries entry, or pick a preset. Then run sloppy architecture to see what is in force.
    📖 Describing your architecture · [Full changelog](https://github.com/heyosseus/sloppy/compare/v1.3

v1.3.1

Choose a tag to compare

@github-actions github-actions released this 30 Sep 18:49
fix: lower SL107 when a comment explains the catch

v1.3.0

Choose a tag to compare

@github-actions github-actions released this 30 Sep 17:06
8b81e4d
Merge pull request #30 from Heyosseus/release/1.3.0

feat: add the stable API for phpstan-sloppy

v1.2.0

Choose a tag to compare

@github-actions github-actions released this 28 Sep 15:41
3b7a8aa

Triaged scan output

Once a run has more than 20 findings, sloppy groups the report into four sections:

  • Fix first: defects such as swallowed exceptions, queries in loops and unfinished method bodies. They're ranked by risk and grouped by file and rule.
  • Hotspots: maintainability findings, counted per file.
  • By rule: a count for every rule, so nothing is hidden.
  • Next: the commands that shorten the list without read

Use --all for the full list, --top=N to show more defece rule.

Clears the obvious findings for you

  • sloppy fix now deletes comments that only restate theomments to keep them.
  • A long first scan offers to baseline your existing findings, so later scans show only new ones. It only asks when you run it yourself at a terminal, never in CI.

Ranks by what changes

Findings in files that change often now rank higher. Slts, so the same checkout ranks the same way on any day.This affects the ranking, never the score.

Calibrated on real code

Tested against eight open-source Laravel apps, 782,578 lines in total:

  • Findings dropped from 5,097 to 4,075.
  • Scores now range from 25 to 90. Before, they ran from 0 to 87, and mature apps like Snipe-IT and Pixelfed scored 0.

What changed:

  • SL101: "many calls" and "many collaborators" now counrately, they were the only trigger for 41% of itsfindings.
  • Score: no single rule can take more than 30 points ofapping findings no longer count the same lines twice.
  • SL109: no longer flags comments at the end of a block, or single lines of a multi-line comment.

Agent guardrails

  • SL112 Placeholder Implementation catches method bodies left unwritten, such as // ... existing code ... or a "not implemented" throw.
  • SL503 Weakened Test catches tests made to pass by cheth assertions removed, or given assertTrue(true).
  • Claude Code hooks now work on Windows without Git Bash. Re-run sloppy agents install to update your settings.

Upgrade notes

  • Different scores: expect different numbers from 1.1.x, usually higher on large codebases. The score stored in an existing baseline was calculated with the old formula, so it won't match ne
  • JSON output: each finding gains a tier field.
  • New config keys: score.rule_cap, risk.churn_weight, rrule tier option.

The full list of changes is in CHANGELOG.md.

v1.1.1 — Windows hook fix, new docs, new look

Choose a tag to compare

@github-actions github-actions released this 26 Sep 17:08

A patch release: one bug fix for the Claude Code hooks, a cleaner feedback message, and a new home for the documentation.

Fixed

  • sloppy hook no longer misses a payload redirected from a file on Windows. Symfony Console measures the terminal before any command runs. On Windows, its mode CON probe inherited standard input and swallowed a redirected file, so the edit went unchecked. Piped input, which is what Claude Code sends, was not affected. The binary now sets a terminal width for hook runs, which skips the probe.

Changed

  • The hook feedback no longer tells the agent to explain a deliberate finding "rather than in a code comment". That contradicted SL107's own advice to leave a comment when a swallowed failure is intentional.

Documentation

  • The README is now a landing page. It is 208 lines, down from 1,417, and opens with real output of the Claude Code hook.
  • The reference material moved to docs/ word for word: