The follow-up ask for document-grade run artifacts (memos, summaries, redlines) as real downloadable deliverables, beyond findings-as-text. Proposes an emit_artifact chokepoint during the drafting phase, storing artifacts as KB documents (preferred) or a dedicated table, a paginated GET /sessions/{id}/artifacts endpoint, an artifact_count on the notification payload, and clear deletion semantics (documents outlive sessions). Open at the time of writing; later landed as lq-ai #138 per the pin log. When rendering downloadable artifacts on an automation receipt.
LQ-AI ask — document-grade artifacts from autonomous runs (in ADDITION to findings)
Filed: 2026-06-06 · From: Donna (consumer) · For: the Automations "Results" surface, follow-up to the resolved findings ask (lq-ai-autonomous-run-output.md, shipped as lq-ai #135 / pin 0097b01). The LQ-AI session works in /Users/kevinkeller/Code/lq-ai (absolute paths below; it can't see Donna branches).
Product gap (user-confirmed, 2026-06-06)
Findings-as-text shipped and is surfaced (Donna renders a run's findings + proposed memories in a "Results" section on the receipt page — built on #135). Keep that exactly as is. But the user expectation for watch/schedule runs goes further: "if a workflow ran when a new document were dropped into a knowledge base — where would the resulting document/work-product generated by the skill or playbook be found?" Today the answer is "nowhere — there is no document": the drafting phase drafts findings text, and nothing document-shaped is persisted or linkable. The user explicitly wants both: findings-as-text (✅ shipped) and document-grade artifacts (this ask) — e.g. a generated review memo, summary doc, or redline report the user can open/download/keep where they work.
Current state (verified against 0097b01 source)
- The run's only persisted work-products are findings (
/Users/kevinkeller/Code/lq-ai/api/app/models/autonomous.py:426AutonomousFinding, written by theemit_findingchokepoint handler at/Users/kevinkeller/Code/lq-ai/api/app/autonomous/guard.py:299), proposed memories, and recurrence-aggregated precedents. - Phases: intake → analysis → drafting → ethicsreview → notify (
/Users/kevinkeller/Code/lq-ai/api/app/autonomous/enums.py). "Drafting" currently means drafting _findings, not files. - No
document_id/ file / artifact reference exists anywhere in the autonomous output model, session detail, or notification payload. Real documents are created only via the ingest pipeline (/Users/kevinkeller/Code/lq-ai/api/app/pipeline/ingest.py:325). - Sessions/schedules/watches already carry
target_kb_idandproject_id— i.e. the natural destination for an artifact is already on the run.
Ask
1. Let a run persist document-grade artifacts
During drafting (and/or ethics_review), allow the run to produce one or more named artifacts — markdown/plain-text is fully sufficient for v1 (PDF/DOCX rendering NOT requested). Plumbing presumably mirrors emit_finding: a new chokepoint intent (e.g. emit_artifact) so cost/audit accounting flows through the existing guard machinery.
Two storage shapes — LQ-AI's choice; Donna's preference is (a):
- (a) Write the artifact into the run's
target_kb_idas a real Document (ingest-path or direct), attributed to the session. This makes the artifact first-class where the user already works: visible in the KB, chat/RAG-queryable, openable in Donna's existing document panel, downloadable via the existing/files/{id}/content. (If the run has no target KB, fall back to (b) or skip artifact persistence with a finding noting why.) - (b) A dedicated
autonomous_artifactstable + object storage, with a download endpoint. Acceptable, but the artifact then lives outside the user's KB/matter world and Donna needs a new viewer path.
2. Expose artifact references on the read model
- Either fold into session detail or add
GET /api/v1/autonomous/sessions/{id}/artifacts→{ artifacts: [{ id, name, mime, size_bytes, file_id?/document_id? (shape (a)), created_at }], total_count, … }. - Same authz posture as findings: owner-gated via the parent session, 404 id-probing-safe, paginated with the [1,200] clamp convention.
- Notification payload: an
artifact_countnext tofinding_countwould let the inbox say "completed — 2 findings, 1 document". - Deletion semantics: please specify. If shape (a), the document presumably OUTLIVES the session (it's the user's deliverable — cascade-deleting it with the session would surprise); a session deletion should drop the reference, not the KB document. If shape (b), cascade like findings is fine.
3. Keep the established conventions
- No backfill needed (same as findings).
- Free-text-tolerant fields where LLM-emitted (mirror the no-CHECK severity precedent and document it).
created_atASC emission order if multiple artifacts.
What Donna builds on top (so the contract fits)
The receipt's Results section gains a "Documents" block above the findings list: one row per artifact — name, size, and (shape (a)) an "Open" action into the existing doc panel via document_id/file_id + a Download link; (shape (b)) Download only. Notification copy upgraded when artifact_count is present. We already render findings/memories from the widened receipt payload, so wiring artifacts in is a small additive slice once the SHA lands.
Out of scope (explicitly not asked)
PDF/DOCX rendering; artifact editing/versioning; per-position redline file formats (the interactive Playbooks Apply flow already renders redlines on screen); artifacts for the interactive chat/playbook paths (autonomous runs only).