letmesplain

Generation (pro, bring-your-own model)

splain:generate drafts a guide for a resource by having a model read your app's code and produce guide JSON — then it runs that draft through the same validator splain:check uses, mechanically flags every anchor it couldn't verify, and lands the result as an unpublished draft. It is a drafting aid for a developer, never an autopilot: nothing it produces reaches your users until a human reviews it, signs off, and publishes.

Bring your own model

Splain ships no model, no API key, and no default endpoint. The one thing generation sends anywhere is your source (at dev time, never runtime data), and you own that crossing. You opt in one of two ways.

The quick way: the reference adapter (OpenAI-compatible, your endpoint)

Set all three and Splain binds its reference client to your endpoint — OpenAI, Azure, OpenRouter, or a fully-local Ollama / LM Studio / vLLM:

SPLAIN_GENERATION_ENDPOINT=https://api.openai.com/v1   # or http://localhost:11434/v1
SPLAIN_GENERATION_KEY=sk-…                             # local hosts: any non-empty string
SPLAIN_GENERATION_MODEL=gpt-4o                         # or llama3.1:70b, etc.

Leave any of them unset (the default) and nothing is bound — splain:generate refuses. The configuration is the consent: your source facts go only to the endpoint you chose (the confirmation prompt names the host and model, never the key), and a fully local endpoint means they never leave your machine at all. The reference prompt asks for the same discipline the pipeline enforces: anchor only to real markers — any non-marker or unverifiable selector is mechanically flagged by the AnchorFlagger for human review before publish — and describe what the user actually does, never a process the interface merely allows.

Two operational notes, said plainly:

The full-control way: bind your own adapter

// A service provider in your app
use Splain\Generation\Contracts\Generator;

public function register(): void
{
    $this->app->bind(Generator::class, YourGenerator::class);
}

Generator is one method:

use Splain\Generation\Contracts\Generator;

class YourGenerator implements Generator
{
    public function draft(array $context, array $feedback = []): array
    {
        // $context = the introspected surface facts (routes, anchors, model, label).
        // $feedback = validator errors from the previous attempt (empty on the first).
        // Call whatever you want — your OpenAI/Anthropic/Azure/Bedrock/local endpoint,
        // with YOUR key — and return a guide array (slug, title, genre, spans, steps).
        // You do NOT need to make it valid; the loop validates and asks you to fix.
        return $yourModel->draft($context, $feedback);
    }
}

Until a Generator is bound, splain:generate refuses to run and tells you so.

What Splain does around your model

You supply the drafting; Splain supplies the conscience, so a weak or careless model still can't ship something dangerous:

  1. Validator-in-the-loop. Each draft is run through ValidateGuide; its errors are fed back to your draft() verbatim, up to splain.generation.max_attempts times, until the guide has zero structural errors. Your model can be dumb — the loop keeps it honest. (It repairs errors only; it never feeds a needs_review flag back as something to "fix", so a model can't learn to delete a flag to pass.)
  2. Mechanical anchor-flagging. The only anchors Splain can verify are the data-splain markers splain:introspect actually found in your source. Every other anchor a model emits — a fabricated data-splain value, a bare .fi-* class, a proposed injection — gets a needs_review flag saying "confirm this on the live screen." A model cannot launder a guessed selector as a confident one.
  3. Lands as a draft. The result is created as an unpublished guide carrying its flags. It appears in the Studio hub; you resolve the flags on the live page, sign off (the publish attestation), and publish. The publish gate blocks on any open flag.

Usage

php artisan splain:suggest              # find a resource with no guide
php artisan splain:generate documents   # draft one (asks for confirmation first)
php artisan splain:generate documents --yes   # non-interactive (CI); explicit consent

Honest scope


Rendered from splain@b6ea439. The documentation is rendered from the package repository — the same files that ship with Splain — so the site can't drift from the code.