Survey Flow Audit
Audit a survey the way it will actually run, not the way its build files say it
should. Everything here reads the LIVE definition over the API and, optionally,
walks the respondent path in a real browser. The audit is read-only on the
survey definition: it produces findings, never fixes. The optional browser
walk (Phase H) does generate test responses — data-plane writes with their
own cleanup obligations, and possibly test hits on a vendor dashboard — so it
is opt-in and announced, never silent. Repairs are a separate, explicitly
authorized step (see the qualtrics-ops skill for how to make them without
new damage).
Fielding now happens in an environment where AI agents complete surveys at
scale and pass conventional attention checks (documented since 2025 in
peer-reviewed and platform validations), panel vendors bill on redirect
passbacks, and platforms silently stage rather than publish edits. Each of those failure classes is invisible in a casual preview
and cheap to catch here.
When to use
Immediately before a soft launch or full launch; after any live patch to a
fielding instrument; when a vendor reports a broken redirect or "different
content"; when handed an unfamiliar survey to take over. Inputs: API
credentials and the survey id; ideally also the pre-registration or PAP (for
the report-only-vs-terminating posture), the vendor's integration sheet
(redirect URLs, ID parameter name), and the quota targets. A browser MCP
(claude-in-chrome or Playwright) enables Phase H; without it, run A–G and say
so in the report.
Posture
- Read-only.
GET everything; PUT/POST nothing. If the platform offers a
no-op write check for token scope, that is the only write.
- Evidence or it didn't happen: every PASS cites the object read back (flow
element, option key, quota logic), never the absence of an error.
- The registered design wins. Where a PAP declares an item report-only, a live
branch that terminates on it is a blocking finding even if well-built.
Phase A — identity and publish state
Confirm the survey id, name, and active/inactive state match intent. An
inactive instrument scheduled for launch is fine; an active one nobody meant
to open is a finding.
Publish state: the working definition and the published version must match.
On Qualtrics, do not trust an in_sync flag alone — question- and
quota-level writes can leave it true while respondents see an older version.
The proof is the version list: a published entry, created by a publish call
someone can vouch for, with the published content read back where the API
exposes it (a description is provenance, not proof of content).
Staged-but-unpublished edits to a fielding survey are a blocking finding.
Response settings that shape the data: partial-response window, multiple-
submission prevention, anonymization/IP recording, link type, expiration —
and whether in-progress respondents stay pinned to the version they started.
Phase B — consent before anything
- The first substantive screen a respondent reaches is consent (or a language
selector whose every arm leads first to consent).
- Nothing evaluates or acts before affirmative consent: no terminating gates,
no quality branches, no telemetry collectors on or before the consent page.
(If the approved protocol places a minimal eligibility screener before
consent, audit that instead for authorization, minimization, and whether
pre-consent data are retained.)
Location/device capture nodes may write earlier (platforms populate them at
session start), but every branch that reads them must sit after consent.
- Decline path: declining consent must route to the vendor's screen-out (or the
study's stated exit), not dead-end or count as a complete.
- Consent text ↔ configuration consistency, both directions: if invisible
scoring or fingerprinting is enabled (reCAPTCHA, device checks), the text
discloses it; if the text promises skippable questions, optional questions
actually exist. A consent page describing a survey that isn't this one is a
finding whichever direction the drift runs.
Phase C — question integrity
- Force-response completeness: enumerate every question; classify descriptive
(no answer possible), forced, requested, and unvalidated. The check is
consistency, not a universal forced-by-default norm (optional is often the
right call for sensitive items): every unvalidated answerable item must be
one the design names optional, and if any exist, Phase B's
consent-consistency check must see them.
- Attention and manipulation checks: present where the design says, and their
consequence (terminate vs record-only) matches the registration. In the
current environment, terminating on an attention check screens out humans
while catching almost no agents — flag it as a design smell even when it
matches the PAP.
- Multilingual instruments: first identify the architecture. Qualtrics'
native translation layer keeps one block structure (audit translations for
coverage); a branch-per-language build duplicates every block per arm — there,
every item, choice set, validation setting, and embedded JS must exist
symmetrically in each arm. A check present in one arm only, or logic testing
"correct option NOT selected" on a twin build (the unanswered twin matches
trivially and ejects the whole other arm), is a blocking finding.
Phase D — flow structure
Walk the full flow tree, at every nesting depth:
- Block order matches the intended instrument; randomizers present with the
intended settings (even presentation, subset size).
- Every embedded-data field is written before the first element that reads it
(capture-before-gate). A guarded condition on a never-yet-written field is
silently dead — it fails safe, which is exactly why nobody notices.
- Terminating branches: condition logic decodes to the intended trigger; inner
flow sets the exit redirect before the End-of-Survey element; unique flow
IDs throughout; the terminal "completion" redirect node is the last element.
- On branched (language/arm) instruments, structural checks run per arm, not
once globally.
Phase E — vendor integration
- Redirect pattern: a pre-consent default carrying the screen-out URL, a
terminal overwrite carrying the complete URL, end-of-survey set to redirect
to the piped field. Early leavers must exit as screen-outs, completers as
completes, quota-fulls (if hard quotas exist) as quota-fulls — each URL
byte-exact against the vendor's sheet.
- The vendor's respondent-ID parameter is captured as embedded data and echoed
back on every exit path, including declines. Note: query parameters resolve
into piped references at session start regardless of where (or whether) the
field is declared — but declaration is what makes the value reliably saved
and exported, so treat a missing declaration as a minor finding and a wrong
parameter name as fatal.
- Enumerate which vendor endpoints can receive traffic and which are dead by
design, and check that against what the vendor was told in writing. A quality
or quota-full endpoint the vendor expects to fire, wired to nothing, is a
relationship problem waiting for fieldwork.
Phase F — quotas
- Decode every quota's logic against the live question's choices and audit it
against the RATIFIED grid, not an assumed one: marginal-family designs
should partition each frame exactly once with per-family targets summing to
the commissioned N; interlocked or deliberately overlapping designs have
their own intended structure (check the multiple-match setting). Screening
categories ("I don't live here") belong to no quota either way.
- Hard vs soft actions match the ratified design; group labels say which is
which truthfully.
- All counts are zero before fielding (test responses leave phantom counts even
after deletion-with-decrement — read the actual counters).
- Platform-specific: on Qualtrics, choice conditions need
ChoiceLocator as
well as LeftOperand — the engine evaluates the latter, the editor renders
from the former, and an editor save over a missing locator can blank live
logic. Read both. Follow pagination: quota lists truncate.
Phase G — anti-automation layer
- Platform toggles (bot-detection scoring, device fingerprinting, geo capture)
are on if the design says so — and disclosed per Phase B.
- Behavioral instrumentation (interaction paradata, honeypots, page timers) is
present on the pages the design instruments, in every language arm.
- The live-terminating set is restricted to signals that cannot plausibly be a
real person: ineligibility, duplicate device, machine signature. Anything
scored or graded (bot-score thresholds, fraud scores, speed cutoffs,
attention items) belongs to analysis, not to a live gate — a scored live gate
is a finding.
Phase H — browser walk (optional, needs a browser MCP)
- Use the LIVE distribution link, never the preview (preview banners change
rendering and skip embedded-data population). Append a test value for the
vendor ID parameter.
- Walk at minimum: one decline (assert the screen-out redirect fires with the
ID echoed), one complete per language arm (assert the complete redirect), one
mobile-viewport pass (conjoint tables and stacked layouts render; nothing
clips). Where feasible add: the quota-full path, one pass per experimental
arm, a missing-vendor-ID entry, and validation/back-button behavior on one
forced item.
- Confirm no screen precedes consent, and that the consent page renders in the
right language for each arm.
- Clean up: delete the test responses with quota decrement, then re-read quota
counts (Phase F) — and note that in-progress partials usually cannot be
deleted via API and must expire or be cleared in the UI.
Report
Rank findings blocking / major / minor, each with the evidence read back
and the phase that produced it. State explicitly: live version vs working
version; which phases ran (and that H was skipped, if it was); which findings
the registered design forces you to leave alone. End with the test-response
cleanup confirmation if Phase H ran. Hand fixes to a separate authorized
change — with its own backup, read-back, and publish-with-proof — rather than
folding them into the audit.
1---2name: survey-flow-audit3description: Pre-fielding audit of a live survey over the platform API, with an optional browser walk. Consent-before-anything gates, publish state, force-response completeness, quotas, vendor redirects, anti-bot instrumentation, language-arm symmetry.4---5
6# Survey Flow Audit
7
8Audit a survey the way it will actually run, not the way its build files say it
9should. Everything here reads the LIVE definition over the API and, optionally,
10walks the respondent path in a real browser. The audit is **read-only on the
11survey definition**: it produces findings, never fixes. The optional browser
12walk (Phase H) does generate test *responses* — data-plane writes with their
13own cleanup obligations, and possibly test hits on a vendor dashboard — so it
14is opt-in and announced, never silent. Repairs are a separate, explicitly
15authorized step (see the `qualtrics-ops` skill for how to make them without
16new damage).
17
18Fielding now happens in an environment where AI agents complete surveys at
19scale and pass conventional attention checks (documented since 2025 in
20peer-reviewed and platform validations), panel vendors bill on redirect
21passbacks, and platforms silently stage rather than publish edits. Each of those failure classes is invisible in a casual preview
22and cheap to catch here.
23
24## When to use
25
26Immediately before a soft launch or full launch; after any live patch to a
27fielding instrument; when a vendor reports a broken redirect or "different
28content"; when handed an unfamiliar survey to take over. Inputs: API
29credentials and the survey id; ideally also the pre-registration or PAP (for
30the report-only-vs-terminating posture), the vendor's integration sheet
31(redirect URLs, ID parameter name), and the quota targets. A browser MCP
32(claude-in-chrome or Playwright) enables Phase H; without it, run A–G and say
33so in the report.
34
35## Posture
36
37- Read-only. `GET` everything; `PUT`/`POST` nothing. If the platform offers a
38 no-op write check for token scope, that is the only write.
39- Evidence or it didn't happen: every PASS cites the object read back (flow
40 element, option key, quota logic), never the absence of an error.
41- The registered design wins. Where a PAP declares an item report-only, a live
42 branch that terminates on it is a **blocking** finding even if well-built.
43
44## Phase A — identity and publish state
45
46- Confirm the survey id, name, and active/inactive state match intent. An
47 inactive instrument scheduled for launch is fine; an active one nobody meant
48 to open is a finding.
49- Publish state: the working definition and the published version must match.
50 On Qualtrics, do not trust an `in_sync` flag alone — question- and
51 quota-level writes can leave it true while respondents see an older version.
52 The proof is the version list: a published entry, created by a publish call
53 someone can vouch for, with the published content read back where the API
54 exposes it (a description is provenance, not proof of content).
55 Staged-but-unpublished edits to a fielding survey are a **blocking** finding.
56
57- Response settings that shape the data: partial-response window, multiple-
58 submission prevention, anonymization/IP recording, link type, expiration —
59 and whether in-progress respondents stay pinned to the version they started.
60
61## Phase B — consent before anything
62
63- The first substantive screen a respondent reaches is consent (or a language
64 selector whose every arm leads first to consent).
65- Nothing evaluates or acts before affirmative consent: no terminating gates,
66 no quality branches, no telemetry collectors on or before the consent page.
67 (If the approved protocol places a minimal eligibility screener before
68 consent, audit that instead for authorization, minimization, and whether
69 pre-consent data are retained.)
70 Location/device capture nodes may *write* earlier (platforms populate them at
71 session start), but every branch that *reads* them must sit after consent.
72- Decline path: declining consent must route to the vendor's screen-out (or the
73 study's stated exit), not dead-end or count as a complete.
74- Consent text ↔ configuration consistency, both directions: if invisible
75 scoring or fingerprinting is enabled (reCAPTCHA, device checks), the text
76 discloses it; if the text promises skippable questions, optional questions
77 actually exist. A consent page describing a survey that isn't this one is a
78 finding whichever direction the drift runs.
79
80## Phase C — question integrity
81
82- Force-response completeness: enumerate every question; classify descriptive
83 (no answer possible), forced, requested, and unvalidated. The check is
84 consistency, not a universal forced-by-default norm (optional is often the
85 right call for sensitive items): every unvalidated answerable item must be
86 one the design *names* optional, and if any exist, Phase B's
87 consent-consistency check must see them.
88- Attention and manipulation checks: present where the design says, and their
89 *consequence* (terminate vs record-only) matches the registration. In the
90 current environment, terminating on an attention check screens out humans
91 while catching almost no agents — flag it as a design smell even when it
92 matches the PAP.
93- Multilingual instruments: first identify the architecture. Qualtrics'
94 native translation layer keeps one block structure (audit translations for
95 coverage); a branch-per-language build duplicates every block per arm — there,
96 every item, choice set, validation setting, and embedded JS must exist
97 symmetrically in each arm. A check present in one arm only, or logic testing
98 "correct option NOT selected" on a twin build (the unanswered twin matches
99 trivially and ejects the whole other arm), is a **blocking** finding.
100
101## Phase D — flow structure
102
103Walk the full flow tree, at every nesting depth:
104
105- Block order matches the intended instrument; randomizers present with the
106 intended settings (even presentation, subset size).
107- Every embedded-data field is written before the first element that reads it
108 (capture-before-gate). A guarded condition on a never-yet-written field is
109 silently dead — it fails safe, which is exactly why nobody notices.
110- Terminating branches: condition logic decodes to the intended trigger; inner
111 flow sets the exit redirect *before* the End-of-Survey element; unique flow
112 IDs throughout; the terminal "completion" redirect node is the last element.
113- On branched (language/arm) instruments, structural checks run per arm, not
114 once globally.
115
116## Phase E — vendor integration
117
118- Redirect pattern: a pre-consent default carrying the screen-out URL, a
119 terminal overwrite carrying the complete URL, end-of-survey set to redirect
120 to the piped field. Early leavers must exit as screen-outs, completers as
121 completes, quota-fulls (if hard quotas exist) as quota-fulls — each URL
122 byte-exact against the vendor's sheet.
123- The vendor's respondent-ID parameter is captured as embedded data and echoed
124 back on every exit path, including declines. Note: query parameters resolve
125 into piped references at session start regardless of where (or whether) the
126 field is declared — but declaration is what makes the value reliably saved
127 and exported, so treat a missing declaration as a minor finding and a wrong
128 parameter name as fatal.
129- Enumerate which vendor endpoints can receive traffic and which are dead by
130 design, and check that against what the vendor was told in writing. A quality
131 or quota-full endpoint the vendor expects to fire, wired to nothing, is a
132 relationship problem waiting for fieldwork.
133
134## Phase F — quotas
135
136- Decode every quota's logic against the live question's choices and audit it
137 against the RATIFIED grid, not an assumed one: marginal-family designs
138 should partition each frame exactly once with per-family targets summing to
139 the commissioned N; interlocked or deliberately overlapping designs have
140 their own intended structure (check the multiple-match setting). Screening
141 categories ("I don't live here") belong to no quota either way.
142- Hard vs soft actions match the ratified design; group labels say which is
143 which truthfully.
144- All counts are zero before fielding (test responses leave phantom counts even
145 after deletion-with-decrement — read the actual counters).
146- Platform-specific: on Qualtrics, choice conditions need `ChoiceLocator` as
147 well as `LeftOperand` — the engine evaluates the latter, the editor renders
148 from the former, and an editor save over a missing locator can blank live
149 logic. Read both. Follow pagination: quota lists truncate.
150
151## Phase G — anti-automation layer
152
153- Platform toggles (bot-detection scoring, device fingerprinting, geo capture)
154 are on if the design says so — and disclosed per Phase B.
155- Behavioral instrumentation (interaction paradata, honeypots, page timers) is
156 present on the pages the design instruments, in every language arm.
157- The live-terminating set is restricted to signals that cannot plausibly be a
158 real person: ineligibility, duplicate device, machine signature. Anything
159 scored or graded (bot-score thresholds, fraud scores, speed cutoffs,
160 attention items) belongs to analysis, not to a live gate — a scored live gate
161 is a finding.
162
163## Phase H — browser walk (optional, needs a browser MCP)
164
165- Use the LIVE distribution link, never the preview (preview banners change
166 rendering and skip embedded-data population). Append a test value for the
167 vendor ID parameter.
168- Walk at minimum: one decline (assert the screen-out redirect fires with the
169 ID echoed), one complete per language arm (assert the complete redirect), one
170 mobile-viewport pass (conjoint tables and stacked layouts render; nothing
171 clips). Where feasible add: the quota-full path, one pass per experimental
172 arm, a missing-vendor-ID entry, and validation/back-button behavior on one
173 forced item.
174- Confirm no screen precedes consent, and that the consent page renders in the
175 right language for each arm.
176- Clean up: delete the test responses with quota decrement, then re-read quota
177 counts (Phase F) — and note that in-progress partials usually cannot be
178 deleted via API and must expire or be cleared in the UI.
179
180## Report
181
182Rank findings **blocking / major / minor**, each with the evidence read back
183and the phase that produced it. State explicitly: live version vs working
184version; which phases ran (and that H was skipped, if it was); which findings
185the registered design forces you to leave alone. End with the test-response
186cleanup confirmation if Phase H ran. Hand fixes to a separate authorized
187change — with its own backup, read-back, and publish-with-proof — rather than
188folding them into the audit.