Prep structured agent output and implement agentFix() on free rules#35
Merged
Conversation
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
This PR lays the groundwork for the upcoming FilaCheck-Pro structured-output mode (where an AI coding agent runs
filacheckand consumes a single JSON document on stdout) and ships the free-package half of the contract end-to-end:src/Rules/now returns a structured, agent-actionable fix payload (instructions,next_steps,docs) so agents get a concrete plan instead of having to parse the humansuggestionstring.The default
vendor/bin/filacheckrun against a terminal is byte-for-byte unchanged — the new code paths are only exercised when Pro flips them on.The work is split across two commits.
Commit 1 —
Prep structured agent output for pro versionAdds the abstractions Pro needs to inject a structured reporter at runtime, plus a command-execution path in
CodeFixerso Pro rules can ship "runphp artisan make:filament-theme admin"-style fixes the same way the existing text-replacement rules do.New files
src/Rules/ProvidesAgentFix.phpsrc/Reporting/ReporterInterface.phpreport/reportWithFixes) so reporters are pluggable.src/Reporting/ReporterFactory.phpoverride(...)the default reporter at runtime — e.g. swap inJsonReporterwhen an agent is detected.src/Support/RunContext.phpmarkAgent/isAgent) Pro sets when it detects an AI agent. The free CLI reads this flag — no Pro dependency.Modified files
src/Rules/FixableRule.php— docblock now documents two flavours of fixable violation: the existing text replacement (byte-precise edit of the offending file) and the new command execution (run an external command from the project root).src/Support/Violation.php— adds two nullable fields:src/Fixer/CodeFixer.php— partitions violations into text-style and command-style at the start offix(), and gains afixCommands()path that:(fixCommand, fixCommandCwd)so the samephp artisan ...only runs once per scan even when many Blade files trigger it,artisanfile (guard against a misconfigured rule passing the wrong base path),--dry-run(marks statuswould-run),symfony/process(now a hard dependency incomposer.json),commandskey in thefix()result describing every command's status / output.bin/filacheck— three behavioural changes, all gated onRunContext::isAgent():$reporter = StandaloneReporter::new(...)is replaced withReporterFactory::make(...)so Pro can swap it out.RunContext::isAgent()is true,$fixis forced totruesoCodeFixerapplies all auto-fixable issues with byte precision before any structured reporter emits output. This avoids handing the agent ambiguous search/replace strings for fixes the tool can already apply itself.stderrand is silenced entirely in agent mode sostdoutstays clean for a single parseable JSON document.src/Reporting/ConsoleReporter.php+src/Reporting/StandaloneReporter.php— nowimplements ReporterInterface. Behaviour unchanged.composer.json— addssymfony/process: ^6.0|^7.0|^8.0for the command-execution path.resources/boost/guidelines/core.blade.php— new Boost guideline that tells Laravel Boost agents to runvendor/bin/filacheck --fixafter touching anything underapp/Filament.Worked example:
ProvidesAgentFixinterfaceWorked example:
RunContextWorked example: agent-mode forcing in
bin/filacheckCommit 2 —
Provide structured agent fix data on free rulesImplements
ProvidesAgentFixon all 16 rules insrc/Rules/so the JSON output Pro emits for a free-rule violation gets a concrete fix payload instead offix: null.Pattern
Every rule now
implements <existingInterface>, ProvidesAgentFix, gains theResolvesFilamentDocsUrltrait if it didn't already have it, and adds anagentFix(Violation $violation): mixedmethod that returns:[ 'instructions' => string, // 1-sentence imperative directive 'next_steps' => string[], // 2–5 concrete bullets, including edge cases 'docs' => string, // filamentDocsUrl(...) link ]This shape mirrors the convention already in use in
FilaCheck-Pro/src/Rules, so Pro'sJsonReporterconsumes free-rule and pro-rule fix payloads through a single code path.Worked example:
DeprecatedReactiveRuleRules updated
ActionInBulkActionGroupRuleAction::make()insidetoolbarActions()→BulkAction::make()DeprecatedActionFormRule->form([...])→->schema([...])DeprecatedBulkActionsRule->bulkActions([...])→->toolbarActions([...])DeprecatedEmptyLabelRule->label('')→->hiddenLabel()/->iconButton()DeprecatedFilterFormRule->form([...])→->schema([...])DeprecatedFormsGetRuleFilament\Forms\Get→Filament\Schemas\Components\Utilities\GetDeprecatedFormsSetRuleFilament\Forms\Set→Filament\Schemas\Components\Utilities\SetDeprecatedGetTableQueryRulegetTableQuery()→->query()insidetable()DeprecatedImageColumnSizeRuleImageColumn::size()→->imageSize()DeprecatedMutateFormDataUsingRulemutateFormDataUsing()→mutateDataUsing()DeprecatedPlaceholderRulePlaceholder::make()→TextEntry::make()->state(...)DeprecatedReactiveRule->reactive()→->live()DeprecatedTestMethodsRuleTestAction::make(...)wrappersDeprecatedUrlParametersRuleDeprecatedViewPropertyRule$view→protected string $viewWrongTabNamespaceRuleFilament\Tabs\Tab→Filament\Schemas\Components\Tabs\TabNew test:
tests/Rules/ProvidesAgentFixContractTest.phpA single dataset-driven contract test covers all 16 rules:
The test asserts the shape of the payload (and that it round-trips through
json_encode), not the exact wording — so future copy tweaks don't churn the suite.Backwards compatibility
RunContext::isAgent()is alwaysfalse, sobin/filacheckstill resolvesStandaloneReporterfromReporterFactory::make(...), still writes "Scanning: …" to the terminal, and still only runs--fixwhen the user passes the flag.ProvidesAgentFixis an optional interface; nothing in the free package's reporter chain callsagentFix(). Rules that don't implement it will continue to emitfix: nullonce Pro'sJsonReporterlands, exactly as today.Violationconstructor picks up two new optional fields at the end of the parameter list, so existing positional callers are unaffected.composer.jsongainssymfony/process. This is a new hard dependency but matches the existingsymfony/consoleconstraint, so Laravel apps already satisfy it transitively.Test results
That's the previous 240 tests plus 16 new contract tests (one per rule) — every existing test still passes, no fixture changes were needed.
Example agent payload (post-Pro)
Once the matching Pro PR lands and an AI agent runs
vendor/bin/filacheck, a single violation now serialises to JSON like:{ "rule": "deprecated-reactive", "file": "app/Filament/Resources/UserResource.php", "line": 87, "message": "The `reactive()` method is deprecated.", "fix": { "instructions": "Replace the deprecated `reactive()` modifier with `live()`.", "next_steps": [ "Rename `->reactive()` to `->live()` on the field.", "If you need debounced updates, use `->live(debounce: 500)`. If you only want to react on blur, use `->live(onBlur: true)`." ], "docs": "https://filamentphp.com/docs/4.x/forms/overview#the-basics-of-reactivity" } }instead of:
{ "rule": "deprecated-reactive", "fix": null }