SPEC-STV-08-AI-Assistant
SPEC-STV-08 · Spec header. Spec ID: SPEC-STV-08 · Title: AI Writing Assistant · Version: 1.0.0 · Status: Planned · Authority: Specification · Priority: P0 · Owner role: AI workflow lead · Reviewers: Backend architect, Security lead, Frontend lead · Last reviewed: 2026-05-11 · Sync targets: app/Services/Ai/**, resources/js/ai-selection/**, docs/AI_ASSISTANT.md · Depends on: SPEC-STV-HUB, SPEC-STV-04, SPEC-STV-07 · Consumed by: SPEC-STV-03, SPEC-STV-10 · Conflict rule: Hub wins. · Change policy: AI workflow lead + Security lead; Registry bump.
Mobile select-to-edit flow → see SPEC-STV-13. This spec (SPEC-STV-08) is canonical for the 17 actions, prompt templates, preview gate, selection model, abilities, rate limits, models/providers, and safety. The mobile-specific selection UX, floating toolbar, AI preview bottom sheet (Compact / Half / Full + draft-on-navigate-away), haptics, and conflict-rule integration with native handles live in SPEC-STV-13 · Mobile Gestures & Text Selection Editor → SPEC-STV-13.
1 · Surface
A selection-scoped overlay that activates wherever text can be selected in the app — paragraphs, headings, list items, table cells, callouts, code blocks, comments, database text cells, page titles, share-page descriptions. Selecting text and pressing the AI button (or ⌘/Ctrl + J) opens the action menu.
2 · 17 canonical actions
| action | Prompt template (system) | Output mode |
|---|---|---|
improve | Improve the writing of the selection. Keep meaning and tone. Return only the rewritten text. | replace |
rewrite | Rewrite the selection in different words while keeping meaning. Return only the rewrite. | replace |
summarize | Summarize the selection in N sentences (default 3). Return only the summary. | insert_below |
expand | Expand the selection with more detail and examples. Return only the expanded text. | replace |
simplify | Simplify the selection for a non-expert reader. Return only the simplified text. | replace |
translate | Translate the selection to {target_language}. Return only the translation. | replace |
make_professional | Rewrite the selection in a professional, business-appropriate tone. | replace |
make_shorter | Rewrite the selection to be shorter while preserving meaning. | replace |
make_longer | Rewrite the selection longer with more depth and examples. | replace |
to_checklist | Convert the selection into a Markdown checklist • [ ] .... Return only the list. | replace_as_blocks |
to_table | Convert the selection into a Markdown table inferring columns. Return only the table. | replace_as_blocks |
generate_doc | Generate documentation for the topic in the prompt. Use RAG when available. Cite sources. | new_page |
generate_outline | Generate an outline (headings + bullets) for the topic in the prompt. | insert_below |
generate_api_docs | Generate API docs (endpoints, request/response, errors) for the topic in the prompt. | insert_below |
generate_product_spec | Generate a product spec (overview, goals, non-goals, requirements, success metrics) for the topic. | insert_below |
generate_meeting_summary | Summarize the meeting transcript / notes; output Decisions, Action items (owner, due), Open questions. | insert_below |
explain | Explain the selection plainly. Return only the explanation. | side_panel |
continue | Continue writing where the selection (or caret) ends, matching tone. | insert_after_selection |
3 · Preview gate (mandatory)
The AI never modifies content directly. The result lands in a Preview Panel with four actions:
- Replace — swap the selection with the result (replace, replace_as_blocks).
- Insert below — add a new paragraph or blocks after the selection.
- Copy — copy result to clipboard.
- Discard — close the panel; no write occurs.
A visible "AI suggestion" label persists on the preview until the user resolves it.
4 · Selection model
type Selection = {
page_uuid: string,
block_id?: number, // null when selection spans multiple blocks
text: string, // plain text of selection
range?: { start: number, end: number }, // intra-block character offsets
spans?: Array<{ block_id, start, end }> // multi-block selection
}The server validates that the caller can read the page and that the selection text matches the block content (defense in depth against prompt-injection bait).
5 · API
See SPEC-STV-03 §10. SSE stream events: delta (string chunk), final (full text + token usage), error. The client renders deltas live; the apply action is enabled only on final.
6 · RAG integration
For generate_* actions and any action with use_kb: true, AiTransformService calls RagService::query() first and injects top-K excerpts into the prompt with explicit citation IDs [1] [2]. Responses are post-processed to keep citation markers and resolve them client-side.
7 · Sanctum abilities & rate limits
Ability ai:transform for selection actions; ai:generate for generate_*. Rate limits live in SPEC-STV-03 §12. Per-workspace daily token budget enforced by RateLimiter (Redis::throttle('ai:ws:{id}', tokens_in + tokens_out, daily_cap)); exceeded budget returns ai.rate_limited.
8 · Audit
Every call writes one ai_text_transformations row with { action, model, input_text, output_text, applied, tokens_in, tokens_out, cost_usd }. applied = true only when the user clicks Replace / Insert below.
9 · Models & providers
Default: OpenAI gpt-4.1 (mini-tier when the action is simplify|make_shorter|to_checklist); Anthropic claude-3.7-sonnet available per-workspace. Per-workspace setting ai.default_model. Providers behind AiProviderContract; never called from the JS layer.
10 · Safety
- Input length capped per action (e.g.
improve8 KiB;translate32 KiB;generate_doc4 KiB prompt).
- Output capped at 16 KiB; truncated with a soft notice.
- Refuse to act on selections that include secret patterns (see SPEC-STV-07 §9).
- Refuse to act when the user lacks edit permission on the target page (selection-only read is OK; Apply is gated).