Skip to content

feat: AI survey draft generation from a creator brief (#15) - #59

Open
ganjasan wants to merge 6 commits into
masterfrom
feature/ai-survey-generator
Open

feat: AI survey draft generation from a creator brief (#15)#59
ganjasan wants to merge 6 commits into
masterfrom
feature/ai-survey-generator

Conversation

@ganjasan

Copy link
Copy Markdown
Owner

Implements backlog #15 — AI agent that creates surveys from chat description (MVP: one-shot brief, mockup variant B). OpenSpec change: openspec/changes/ai-survey-generator/.

What this does

The Create New Survey page gains an optional AI brief (goal, audience, what to map, use-case chips). "Generate draft" runs a Celery task that calls an LLM, validates the output, and materializes a fully populated multilingual survey through the existing serialization import path; the page shows a game-style loading overlay and lands the creator in the editor with a working draft. Creators whose org has no surveys are routed from /editor/ straight to the create page (?dashboard=1 escapes).

Rationale: of 222 real registrations only 53% ever create a survey — the empty editor is the funnel's biggest leak.

Design highlights

  • Structural fields are computed, never generated. The model produces content only; code, is_head, section links and order_number come from list order, so the import path's silent gotchas (stuck-in-draft, broken navigation, code collisions) are unreachable by construction.
  • Provider-agnostic client (survey/ai/client.py): Anthropic (official SDK, default claude-opus-5) and Gemini (plain requests, free-tier testing; schema adapted to its JSON-Schema dialect). Adding an EU-hosted or local provider is one class — proven by the Gemini addition touching only client.py.
  • PPGIS-grounded prompt. The system prompt is an operative summary of docs/research/survey-design-rules.md (Brown & Kyttä 2014; Seebauer et al. 2024; Lehnert et al. 2023; Alderton et al. 2026) plus a description of the respondent-facing interface. Marker color + curated-enum icon are part of the schema.
  • Validation gate before any DB write, one retry with the error list fed back; twice-invalid drafts store the rejected blob for prompt iteration.
  • AIGenerationEvent = async task state + hypothesis telemetry: brief, generated-blob snapshot (baseline for the generated-vs-published diff), tokens/latency/outcome, and server-side last_polled_at/redirected_at (waited-or-left, no client JS). Quota seam (check_quota) documented for #87.
  • Celery worker enabled on PR previews so this feature is verifiable exactly where changes are reviewed.

Verified

  • Full suite: 1101 tests OK (54 new). Two pre-existing dashboard tests updated to pass ?dashboard=1 (their orgs have no live surveys, so the new redirect correctly fires).
  • Live end-to-end with Gemini (gemini-3.6-flash): two-language (en+it) drafts generated in 19–44s; exactly one point question with styled marker (#D9480F, fas fa-exclamation-triangle) and popup sub-questions; translations complete; coping-behaviour question present (the PPGIS rule visibly changed the output).
  • Browser-tested on the dev stand: panel rendering, overlay (no flicker — poller is a separate hx-swap="none" element, pending answers 204), HX-Redirect into the populated editor, one-screen layout.

Known gaps

  • Anthropic path is untested live (billing blocked); it shares everything but the client with the verified Gemini path. Smoke-test on a preview once a key is available.
  • Follow-up backlog item #124 (AI activation analytics): funnel dashboard section, generated-vs-published diff metric, client events, fork-friendly replay/experiments stack.

Deploy notes

  • One additive migration (0048, new table only).
  • Set ANTHROPIC_API_KEY (or AI_PROVIDER=gemini + GEMINI_API_KEY) in the Render dashboard on web and worker; unset = the panel simply doesn't render.
  • render.yaml now creates worker instances for PR previews (small prorated cost).

🤖 Generated with Claude Code

ganjasan and others added 6 commits August 14, 2026 23:44
One tracked file carries the design rules with citations (Brown & Kyttä 2014;
Seebauer 2024; Lehnert 2023; Alderton 2026; Laborgne & Klöcker 2023) plus a
description of what a respondent actually sees. The AI generator prompt and
the newsurvey skill are both operative summaries of it — change a rule there
and here together. Source papers and heat-domain notes stay untracked: the
repo is public, the notes carry client context and the PDFs are third-party
copyright.

The newsurvey skill gains the same design guidance: it previously knew how to
assemble a valid ZIP but nothing about what makes a survey collect.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
New survey/ai/ package: LLMProvider interface (Anthropic via the official SDK,
Gemini over plain requests for free-tier testing), a PPGIS-grounded prompt, a
pure validator that gates model output before any DB write, and a materializer
that computes every structural field (codes, is_head, section links, order)
from list order — the model only ever produces content, so the serialization
import's silent gotchas are unreachable by construction. Marker color and a
curated-enum icon are part of the schema: an all-black-marker draft reads as
unfinished, and a free-text icon field would let the model hallucinate FA
classes that silently render nothing.

AIGenerationEvent doubles as async task state and the hypothesis-telemetry
record: brief, generated blob snapshot (baseline for the generated-vs-published
diff), token usage, latency, outcome, last_polled_at/redirected_at
(waited-or-left, measured server-side). check_quota() is the documented no-op
seam for plans & entitlements (#87).

Pipfile.lock regenerated: adds anthropic; also picks up nh3, which was in
Pipfile but missing from the lock.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The create page gains an optional brief (goal, audience, map target, use-case
chips) rendered only when a provider is configured. Generate enqueues a Celery
task and shows a fixed overlay with rotating game-style quips; the page polls
a status endpoint that answers 204 while pending (swapping the overlay every
tick made the screen flicker) and HX-Redirects into the populated editor on
success. Validation failures return a fragment, never the full page — swapping
survey_create.html into the HTMX slot would duplicate every id and re-run the
Leaflet setup.

/editor/ now redirects creators whose org has no surveys to the create page
(?dashboard=1 escapes; viewers exempt — they cannot create). Layout compacted
so the whole form, map and actions fit one desktop screen; Generate sits on
its own row above Create empty and Cancel.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…b+worker

Worker previews were off as pure cost; AI draft generation runs in the worker,
and a preview without one would leave the feature untestable exactly where
changes are reviewed. The key is sync:false on both services (web only gates
the UI on its presence; the worker makes the calls). Ports registry records
offset 70 for this worktree.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
54 tests over the generation pipeline: validator rules (languages, geo policy,
codes, styling), computed structure and rollback, provider config gating and
error normalization (incl. Gemini schema dialect and truncation usage), the
retry-once loop, view gating and the 204-pending/HX-Redirect contract, the
zero-survey redirect, task crash-survivability, and the waited-or-left stamps.
Two pre-existing dashboard tests now pass ?dashboard=1 — their orgs have no
live surveys, so a bare /editor/ correctly redirects to the create page.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…low-up

Full artifact set (proposal, design with 10 decisions, delta specs for
ai-survey-generation / survey-editor / render-deployment, tasks) plus the
interaction-mode mockups that drove the variant-B decision. Backlog: #15
marked promoted; new #124 'AI activation analytics' captures the hypothesis
instrument's second half (funnel dashboard section, generated-vs-published
diff, client events, fork-friendly replay/experiments stack).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@ganjasan
ganjasan deployed to feature/ai-survey-generator - mapsurvey-db PR #59 August 14, 2026 18:01 — with Render Active
@ganjasan
ganjasan deployed to feature/ai-survey-generator - mapsurvey-celery PR #59 August 14, 2026 18:02 — with Render Active
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant