Diagnosing Your Feed
Introduction
The doctor checks your definitions, schema, and recorded activities and reports how to fix gaps. By default, publishing without a headline definition throws UnauthoredActivity in local and testing environments. When storyfeed.grammar.strict is disabled, the activity can publish with a null headline; the doctor can find these gaps in already-recorded activities.
Running the Doctor
php artisan storyfeed:doctorFor an order-placement activity recorded with strict grammar disabled and no headline definition, the report shows:
No headline resolves for `order.place` — headlines will be null.
No icon resolves for `order.place`.
Note: verb `place` has no AS2.0 mapping — will serialize as base `Activity`.
2 finding(s) — see above.
Run with --stubs to print the registrations these imply.The count excludes notes. If no errors or warnings are found, the command prints Storyfeed looks healthy.
Most checks query recorded activities, so use a database with traffic, such as staging or a production copy. With no activities, only configuration and schema checks can report findings.
Running Selected Checks
--list prints the check names, and --only runs the ones you name:
php artisan storyfeed:doctor --list
php artisan storyfeed:doctor --only=grammar --only=verbsEvery check is listed in Doctor Checks.
Reading a Finding
Each finding includes a code, severity, and message. The text report colours messages by severity. Use --json to return the full report:
php artisan storyfeed:doctor --json{
"healthy": false,
"count": 2,
"severity": "error",
"findings": [
{
"code": "grammar.missing",
"severity": "error",
"message": "No headline resolves for `order.place` — headlines will be null.",
"subject": {
"type": "order",
"verb": "place"
},
"fix": {
"registry": "grammar",
"key": "order.place",
"tokens": [":actor", ":object", ":target", ":context", ":origin", ":result", ":instrument"],
"snippet": "Story::for(Order::class)->verb('place')->headline(':actor placed :object');",
"definition": "Story::for(Order::class)->verb('place')->headline(':actor placed :object');"
}
}
]
}The other findings use the same structure. Findings without a generated fix have "fix": null. The code's first segment identifies the check; subject identifies what it checked. definition contains the line printed by --stubs.
| Severity | Meaning |
|---|---|
error | the feed displays incorrect content, or publication will throw |
warning | something is missing or inconsistent, but the feed still displays correctly |
info | additional information that may not require a change |
Fixing Common Findings
| Finding | Means | Fix |
|---|---|---|
grammar.missing | a recorded type and verb has no headline | write it in routes/feed.php, or print it with --stubs |
grammar.icon_missing | a recorded type and verb has no icon | add ->icon() |
aggregates.missing | activities group, and the group has no headline | add a group headline, or print it with --stubs |
verbs.undeclared | a recorded verb is not in your vocabulary, usually a typo | fix the call site, or register the verb |
feeds.unclassified | no restricted named feed includes or excludes a verb | add the verb to a feed's only() or except() |
surface.unaliased | a Feedable model has no morph alias, so publishing about it throws | give it an alias, or return its parent's from getMorphClass() (Surface) |
entities.unfeedable | activities name a model that does not implement Feedable | implement Feedable, then run storyfeed:trickle |
backlog.uncached | entities have uncached labels and links | schedule storyfeed:trickle |
tables.missing | a package table does not exist | run the migrations |
See Doctor Checks for all findings.
Generating Missing Definitions
Use --stubs to print suggested definitions for routes/feed.php:
php artisan storyfeed:doctor --stubsuse App\Models\Order;
use Storyfeed\Facades\Story;
Story::for(Order::class)->verb('place')->headline(':actor placed :object');
// order.place: an icon from your app's own set; doctor cannot choose one.
// Story::for(Order::class)->verb('place')->icon('…');Review each stub before adding it. Incomplete stubs, such as icons, are commented out with an explanation. The finding remains until you supply the missing definition. See Doctor Checks for the definitions --stubs generates.
To write Story classes instead, run make:story --from-doctor.
Running the Doctor in CI
By default, findings leave the exit status at 0. Use --fail-on to fail the command at a chosen severity:
php artisan storyfeed:doctor --fail-on=warning # Fails on a warning or an error.
php artisan storyfeed:doctor --fail-on=error # Fails on an error only.Coverage assertions check headlines in your test suite before traffic exists. The doctor checks recorded activities.