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 EditorSPEC-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

actionPrompt template (system)Output mode
improveImprove the writing of the selection. Keep meaning and tone. Return only the rewritten text.replace
rewriteRewrite the selection in different words while keeping meaning. Return only the rewrite.replace
summarizeSummarize the selection in N sentences (default 3). Return only the summary.insert_below
expandExpand the selection with more detail and examples. Return only the expanded text.replace
simplifySimplify the selection for a non-expert reader. Return only the simplified text.replace
translateTranslate the selection to {target_language}. Return only the translation.replace
make_professionalRewrite the selection in a professional, business-appropriate tone.replace
make_shorterRewrite the selection to be shorter while preserving meaning.replace
make_longerRewrite the selection longer with more depth and examples.replace
to_checklistConvert the selection into a Markdown checklist • [ ] .... Return only the list.replace_as_blocks
to_tableConvert the selection into a Markdown table inferring columns. Return only the table.replace_as_blocks
generate_docGenerate documentation for the topic in the prompt. Use RAG when available. Cite sources.new_page
generate_outlineGenerate an outline (headings + bullets) for the topic in the prompt.insert_below
generate_api_docsGenerate API docs (endpoints, request/response, errors) for the topic in the prompt.insert_below
generate_product_specGenerate a product spec (overview, goals, non-goals, requirements, success metrics) for the topic.insert_below
generate_meeting_summarySummarize the meeting transcript / notes; output Decisions, Action items (owner, due), Open questions.insert_below
explainExplain the selection plainly. Return only the explanation.side_panel
continueContinue 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. improve 8 KiB; translate 32 KiB; generate_doc 4 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).