Interrogation Page Convention
This file is the single authoring source for the interrogation-page convention. Source checkouts load it from docs/interrogation-page-convention.md; packaged installs load the same content from assets/interrogation-page-convention.md; older installed skills may still fall back to a sibling INTERROGATION-PAGE.md if present. scripts/upgrade-interrogation-page.mjs reads the marked block below, validates thin SKILL.md resolver stubs, and can regenerate legacy sibling bundles only when run with --legacy-bundles. Edit the convention here only — do not hand-edit legacy generated INTERROGATION-PAGE.md files. Replace {skill-name} with the skill's name. The {{SKILL_INTERROGATION_AREAS}} and {{SKILL_VISUAL_TIER}} tokens are filled per skill by the generator-side registries and skill frontmatter.
The interrogation page is the stage zero elicitation surface. It is the inverse of the alignment page: where the alignment page reviews and approves deliverables after research (stage two), the interrogation page elicits the unknowns the agent cannot infer before research (stage zero), and the skill's first post-interrogation stage (stage one) sits in between. Interrogation moved out of the terminal and into HTML so that questioning is adaptive, durable, and round-by-round diffable. Terminal AskUserQuestion/request_user_input survives only as a degraded fallback when an HTML page cannot be opened.
Participating-skill registry. Only skills listed in INTERROGATION_SKILLS in scripts/upgrade-interrogation-page.mjs receive a shared resolver stub in SKILL.md. Rollout is additive: adding a skill name to that registry (and giving it an ## Interrogation Page stub section) is all that is needed to bring it into the archetype. scripts/interrogation-skip-list.txt excludes a registered skill from the policy; scripts/interrogation-bespoke-list.txt marks a skill whose ## Interrogation Page section is intentionally hand-authored in both mirrors. Both lists are exact, mirroring the alignment generator's contracts.
Output path consistency. Every active INTERROGATION-PAGE.md — generated or bespoke — must reference only its owning skill's output path: each interrogation/<name>-r{N}-{branch}.html occurrence in the bundle must have <name> equal to the skill directory name. The generator validates this after its write pass and exits non-zero (in dry-run and write mode) on any foreign-skill reference.
Shared-resolver drift check. scripts/upgrade-interrogation-page.mjs --check validates, without writing, that every participating skill's ## Interrogation Page section has the current resolver stub and output path, exiting non-zero with named per-skill diagnostics. Plain --dry-run keeps exiting 0 on pending updates so the edit-convention → preview → write workflow is preserved (--dry-run reports Updated: 0 only when everything is in sync); --check is the repo-state gate enforced by layer1 tests. Existing sibling INTERROGATION-PAGE.md files are treated as legacy fallback artifacts: they are not required and are not byte-equal checked by default, but any that remain are still covered by output-path validation. Run scripts/upgrade-interrogation-page.mjs --legacy-bundles only when an installed-skill compatibility bundle must be regenerated.
Active-page audit. node scripts/audit-interrogation-pages.mjs is the read-only convention gate for active interrogation/*.html pages. Direct edits made without invoking a skill are still checked (archived pages under docs/history/archive/ are out of scope). It validates the scriptable subset of this convention: the Brief Me TTS include (the scripts/alignment-tts-kokoro.js src tag before </body> — not inlined, not type="module"), the question-nav include (the scripts/alignment-question-nav.js src tag before </body>, required on every round page), the data-visual-tier and data-interrogation-status attributes on <html> with valid slugs, the data-interrogation-round attribute matching the round number in the filename, the responsive viewport meta, the embed prohibition (<object>/<iframe>/<embed>), the ≥1 open input per round rule (at least one data-open-input control), the open-question markers (at least one data-open-question block, with data-recommended-answer, hidden data-agent-recommended-answer, data-agent-confidence in {high, medium, low}, a data-clarify-copy button, and a data-apply-recommended button each occurring at least as many times as data-open-question), the presence of the confidence/coverage exit gate (data-interrogation-gate with a valid value), the round-file naming pattern ({skill}-r{N}-{branch}.html), and the answer-sidecar reference (data-answer-sidecar pointing at the round's interrogation-{skill}-r{N}.yaml capture file). It exits non-zero with named per-page diagnostics grouped per check and prints exact|DRIFT summary lines; it has no fix mode — TTS diagnostics route to node scripts/inject-tts.mjs --dir interrogation, the rest are manual fixes. Layer1 enforces this source repo state via tests/layer1/audit-interrogation-pages.test.ts, and the auditor supports --root <path> for fixture trees.
Packaged HTML scaffold. npx skillpacks interrogation pages scaffold <skill-name> <round> <branch> --out interrogation/<skill-name>-r<round>-<branch>.html writes a starter round page from the packaged assets/templates/interrogation-page.html template. This is infrastructure only: the markdown convention remains the behavioral source of truth, and the parent skill must replace placeholder regions with the actual assumptions, adaptive open questions, recommended answers, confidence gate, YAML compiler, sidecar handling, and continuation semantics.
<!-- interrogation-convention:start --> When this skill needs to elicit user context before producing research or other durable output, run the stage-zero interrogation loop in HTML before advancing to stage one (the skill's first post-interrogation stage). Build one interrogation page per round at interrogation/{skill-name}-r{N}-{branch}.html, where {N} is the 1-based round number and {branch} is the research fork or product-path slug (in the flat single-product case {branch} is the normalized topic slug, matching the alignment page's {topic}).
Stage model. Interrogation is stage zero. It does not replace stage one (the skill's first post-interrogation stage — framework/scope selection, idea generation, research, or design, depending on the skill) or the alignment review page (stage two); it precedes them, so that stage-one options and scope are informed by elicited answers rather than pre-authored blind.
stage 0 → interrogation/{skill-name}-r1..rN.html ELICITATION: open input drives research
loop until the confidence gate passes
stage 1 → skill's first post-interrogation stage SELECTION: options informed by stage 0
research runs
stage 2 → alignment/{skill-name}-{topic}.html REVIEW/APPROVAL of deliverables
The round loop. Each round is one heavy phase of the Research Session Loop: the agent builds an interrogation page, stops, the user answers and compiles the captured-answers YAML, and a fresh session reads those answers, runs the confidence gate, and either emits the next round or writes the coverage checkpoint and advances to stage one.
round = 1
build interrogation/{skill-name}-r{round}-{branch}.html (manifest if round==1, else follow-ups)
STOP → user answers → compiled answers YAML
agent reads answers, runs the CONFIDENCE GATE:
confident enough to produce useful research?
NO → round += 1; build the next round of deeper/follow-up questions; repeat
YES → set data-interrogation-gate="coverage-checkpoint"; render the coverage
checkpoint; advance to stage one
Round 1 is the assumptions manifest. The first round renders the skill's assumptions manifest — 3–7 source-tagged assumptions ([from prompt], [from repo], [from research], [from spec], [from codebase], [from git], [inferred]) — as interactive confirm / correct / flag controls, plus the first batch of genuinely open questions placed only where no assumption is derivable. The assumptions manifest is not a separate concern from interrogation; it is its disciplined first round, the guard against lazy "tell me about…" prompts. Every correction the user makes to an assumption seeds the next round's follow-ups — that adaptivity is the mechanism that makes the loop feel like a real interview. Deliver each round page, not a terminal manifest, as the confirmation surface.
Subsequent rounds are adaptive follow-ups. Rounds 2..N are seeded by the prior round's compiled answers: drill into corrections, resolve contradictions, and cover any interview area still open. Do not re-ask what a prior round already settled. Recommend-and-override is preferred over bare open prompts: present a researched default and let the user accept or override it in free text.
Agent-owned depth and unknown routing. The agent owns interrogation depth. After consuming each round, decide whether another round is needed and push for more granularity until the goals, direction, constraints, and user taste are clear enough to make stage-one work useful rather than generic. Do not treat a thin "covered or waived" checklist as sufficient when alignment is still shallow, contradictory, or too vague to guide downstream research. User agency still holds: if the user says the interrogation feels light and asks for another round, honor that request unless the requested follow-up is clearly redundant with already-settled answers.
Route unknowns by source. If the answer is inferable from the repository, prior artifacts, supplied context, code, git history, or already-approved research, infer it and expose it as an assumption or recommended answer with the evidence/source tag. If the answer can be resolved only by new or extra external research, ask the user for permission before doing that research and make the scope explicit. If the answer is about ambiguity, choices, priorities, tradeoffs, goals, direction, preferences, or taste, ask the user directly; do not research around a decision that belongs to the user.
Open-answer evidence validation. Treat user open-question responses as intake evidence and hypotheses, not automatically validated facts. Validation happens during compiled-answer consumption, before answers are used to satisfy the confidence gate or shape downstream research. During interrogation, keep validation lightweight and limited to available evidence checks: repo context, prior research, code/git evidence, supplied sources, and already-approved external research. Do not require full synthesized research during stage-zero interrogation; default to validating and classifying during interrogation, then defer deeper research as an explicit research question or source-plan item unless the claim is contradicted or blocks confidence-gate completeness.
Preserve subjective preferences as preferences, but label claim-like factual, evidentiary, market, technical, customer-language, buyer-language, pricing, channel, competitor, or behavior answers as supported, partially-supported, unsupported, contradicted, hunch/inferred, or needs-research in the sidecar or handoff notes. Use this decision rule: supported and partially-supported claims may inform the confidence gate with confidence labeling; hunch/inferred and needs-research claims may be carried forward as research questions or source-plan items, but must not be treated as proven evidence; unsupported and contradicted claims require clear pushback in the next round or coverage checkpoint when they affect confidence-gate completeness, candidate selection, buyer language, or downstream scope. For "real buyer/user/customer language" answers, require provenance such as verbatim quotes, interview notes, sales/support text, reviews, search snippets, or other sourceable evidence. Founder-supplied phrasing without provenance is hunch language: label it as such, convert it into a research target, and do not count it as real buyer/user/customer language.
The confidence gate (loop exit). The gate is a contract, not a fixed round count, and the skill cannot advance to stage one until it passes. The gate passes only when (a) at least one interrogation round has been completed and its answers consumed, (b) every interview area defined by this skill is covered by an answer or explicitly waived by the user, and (c) the agent judges the resulting alignment deep enough to guide stage-one work without generic filler. "Covered or waived" is necessary but not sufficient: if the answers are shallow, contradictory, unsupported where evidence is required, or missing user-owned choices/preferences, the agent must emit another round or ask the user to explicitly waive the gap with the consequences stated. The agent runs the gate by judgment and renders a coverage checkpoint as the final round's exit gate — "here is everything we established; confirm completeness or flag gaps." Mechanical enforcement is limited to artifact existence (≥1 completed round on disk) and the ≥1-open-input rule below; coverage itself is semantic and is confirmed or waived by the user at the checkpoint. If the user flags a gap, treat the checkpoint round as not-final, raise the round number, and continue the loop.
{{SKILL_INTERROGATION_AREAS}}
The ≥1-open-input rule (hard). Each round page must contain at least one genuinely open input — a free-text <textarea> or text <input>, or a recommend-and-override control — that shapes downstream research, marked with the data-open-input attribute. A round that offers only approve/reject or pre-authored multiple-choice controls is invalid: it collapses the archetype back into the rubber-stamp problem it exists to fix. Each open input lives inside a well-formed open-question block marked with data-open-question, and the page must contain at least one such block. Every data-open-question block must carry all six markers: the data-open-input control, a visible data-recommended-answer element, a hidden data-agent-recommended-answer element, a data-agent-confidence="high|medium|low" badge, a data-clarify-copy button, and a data-apply-recommended button (defined under "Required inline questions", "Need clarification (copy)", and "Apply recommended" below). The audit enforces this mechanically.
Page metadata. Set these attributes on the <html> element of every round page:
data-visual-tier— the rendering tier (document,visual, orprototype), same semantics as the alignment page.data-interrogation-status—reviewwhile the page awaits answers,confirmedonce its answers have been compiled and consumed by a later session.data-interrogation-round— the 1-based round number, which must match ther{N}segment of the filename.data-interrogation-gate—continuewhen more rounds are expected, orcoverage-checkpointwhen this round is the loop's exit gate.
Answer capture (the sidecar). Each round page ends with a bottom compile section — the same "Compile Responses" / "Copy YAML" mechanism the alignment page uses — that aggregates the round's assumption decisions, open answers, and gate answers into YAML. The page must name its capture sidecar via a data-answer-sidecar attribute on the compile section, pointing at research/_working/interrogation-{skill-name}-r{N}.yaml (flat) or research/{slug}/_working/interrogation-{skill-name}-r{N}.yaml (product-path). The agent writes the compiled answers to that sidecar when it consumes the round, preserving the round-by-round audit trail. The compiled YAML begins with a valid YAML comment of the form # Invoke with: <parent-skill-command>, followed immediately by top-level command: "<parent-skill-command>" as the first real YAML key, then interrogation_page, round, round_status (partial or complete), gate_state (continue or coverage-checkpoint), an assumptions list (each with source, decision of confirm/correct/flag, and optional correction), an open_answers list, and a gate_answers list. Each open_answers entry should also carry the visible recommended_answer shown on the page, the hidden agent_recommended_answer payload intended for the textarea/YAML, and agent_confidence (high/medium/low) shown for that question, so the round-by-round audit trail records both the human-facing recommendation context and the applied agent default. These fields are a small schema addition; the "Need clarification" mechanism stays clipboard-only and is not captured in the sidecar. Populate interrogation_page and the sidecar path from the known repo-relative paths, not from the page title or window location. Populate the invocation comment and command with the exact parent-orchestrator invocation the user should run with the compiled YAML, including product path or topic arguments when applicable. The comment is an attention cue for humans and LLM agents; parsers ignore it, so the root command field remains the enforceable routing contract.
Self-routing continuation payload. Like a Pattern A review page, every interrogation round page's compiled YAML includes both a top-level command and an agent_routing mapping so a fresh agent can route back to the parent orchestrator that owns the loop:
# Invoke with: <parent-skill-command>
command: "<parent-skill-command>"
interrogation_page: interrogation/{skill-name}-r1-{branch}.html
agent_routing:
workflow: interrogation-loop
parent_skill: {skill-name}
command: "<parent-skill-command>"
gate_owner: parent-orchestrator
gate_type: interrogation-round
round: 1
answer_sidecar: research/_working/interrogation-{skill-name}-r1.yaml
next_resolution: parent-resolves-from-yaml-and-filesystem
The parent still owns interpretation: it validates the answers, writes the sidecar, runs the confidence gate, and decides whether to emit the next round or advance to stage one. Include the product/research path argument in the invocation comment, the top-level command, and agent_routing.command when a product path is active, and keep those values identical except for the # Invoke with: prefix. command and agent_routing.command must name the parent orchestrator, never a child framework path command. The top-level command makes the copied YAML self-contained so the user does not need a separate command clipboard item.
Required round structure. After the page title and a one-line summary, include a top-of-page table of contents (in normal document flow — no sidebar, drawer, or sticky navigation), then the round's content sections, then the bottom compile section. For round 1: the assumptions manifest (confirm/correct/flag) followed by the first open questions. For rounds 2..N: the adaptive follow-up questions. For the coverage-checkpoint round: the full coverage summary of everything established across all rounds, with a final confirm-or-flag-gaps gate. Do not place compile, copy, or answer controls in a sticky or fixed banner; the bottom compile section is ordinary in-flow content.
Required inline questions. Each open question lives in a visually distinct question block, marked with data-open-question, placed directly under the context it governs. Assumption rows use confirm/correct/flag radio controls with a correction text box revealed on "correct" or "flag". Open questions use a free-text answer field (or a recommend-and-override radio set whose final option is a free-text override), and must include the standing "Other / None of the above" and "Need clarification" options when rendered as radios. Generate questions based on what genuinely needs user input — do not pad with filler.
Every open question — both the free-text and the recommend-and-override forms — must include, inside its data-open-question block:
- a
data-recommended-answerelement holding visible user-facing guidance or an example that illustrates what the question is asking and the shape of a good response. This text may include context that helps the user decide whether to accept, correct, or replace the default. - a
data-agent-recommended-answerelement holding the hidden answer payload to apply to the open input and record asagent_recommended_answerin YAML. This element must be hidden, commonly as<span data-agent-recommended-answer hidden>...</span>; the audit also acceptstype="hidden",aria-hidden="true",display:none/visibility:hiddeninline style, or common hidden class names. Its content must be answer-shaped, agent-facing text rather than instructions to the user. - a
data-agent-confidence="high|medium|low"badge rendered next to the question, signalling how much the agent trusts that recommended answer so the user knows how hard to scrutinize or override it. The visible label renders the value (e.g. "Agent confidence: medium"). Usehighwhen the recommendation is well-grounded in repo/research evidence,mediumwhen it is a reasonable inference, andlowwhen it is a guess the user should correct. - a
data-clarify-copy<button>(see "Need clarification (copy)" below) that copies a clarification-request payload to the clipboard. - a
data-apply-recommended<button>with visible labelApply recommended(see "Apply recommended" below) that fills the nearestdata-open-inputfrom the nearest hiddendata-agent-recommended-answer.
The visible recommendation and confidence badge make the question self-explanatory; the hidden agent recommendation gives apply/YAML code a clean answer payload; the apply-recommended button lets the user accept the agent's default without retyping; the clarify-copy button is the escape hatch when the question still is not clear. The active-page audit and a layer1 test enforce all six markers mechanically: every data-open-question block must carry data-open-input, data-recommended-answer, hidden data-agent-recommended-answer, data-agent-confidence (with a value in {high, medium, low}), data-clarify-copy, and data-apply-recommended.
Need clarification (copy). Each open question's data-clarify-copy button is the open-question clarification mechanism: a clipboard action, not a YAML flag. When clicked it copies a payload of exactly this form to the clipboard so the user can paste it straight back to the agent and get a clearer question in the next round (the same round-loop paste model the page already uses):
Question: "<question text>"
I need clarification on what this is asking before I can answer.
Use the Clipboard API with a textarea-selection fallback when clipboard access is blocked — the same fallback idiom as the alignment page's "Copy YAML" control (canonical reference: copyText in scripts/generate-skillmap-excalidraw.mjs): try { await navigator.clipboard.writeText(text); status = 'Copied' } catch { textarea.focus(); textarea.select(); status = 'Select text to copy' }. Show a copy-status line beside the button so the result is visible. This is distinct from the radio "Need clarification" option (which records needs-clarification in the compiled YAML); the clarify-copy button is a clipboard-only escape hatch for open questions and is not captured in the sidecar.
Apply recommended. Each open question's data-apply-recommended button is the recommended-answer acceptance mechanism: a field-fill action, not a clipboard action. When clicked, the button finds its closest data-open-question block, then finds that block's hidden data-agent-recommended-answer payload and nearest data-open-input field (<textarea>, <input type="text">, or a text <input> with no explicit type). During the transition, pages may fall back to data-recommended-answer when the hidden agent payload is absent, but newly authored pages must include the hidden payload. If the input is empty, set input.value to the agent recommended answer immediately. If the input already has text, call window.confirm("Replace your current answer with the recommended answer?") and replace only when confirmed. After setting the value, dispatch bubbling input and change events so compile/YAML code observes the update. Do not use clipboard APIs for this action. If the block includes a lightweight status element such as [data-apply-recommended-status], update it after applying; otherwise the value change is sufficient.
Page authors can inline this compact vanilla handler with the page's existing interrogation scripts:
<script>
document.addEventListener("click", (event) => {
const button = event.target.closest("[data-apply-recommended]");
if (!button) return;
const block = button.closest("[data-open-question]");
const source = block?.querySelector("[data-agent-recommended-answer]") ?? block?.querySelector("[data-recommended-answer]");
const recommended = source
? ("value" in source && source.value.trim() ? source.value.trim() : source.textContent.trim())
: "";
const input = block?.querySelector(
'textarea[data-open-input], input[type="text"][data-open-input], input:not([type])[data-open-input]',
);
if (!input || !recommended) return;
if (input.value.trim() && !window.confirm("Replace your current answer with the recommended answer?")) return;
input.value = recommended;
input.dispatchEvent(new Event("input", { bubbles: true }));
input.dispatchEvent(new Event("change", { bubbles: true }));
const status = block.querySelector("[data-apply-recommended-status]");
if (status) status.textContent = "Recommended answer applied.";
});
</script>
{{SKILL_VISUAL_TIER}}
Dark-mode styling. Use the alignment page's dark color scheme. Base CSS variables: --bg: #0d1117; --surface: #161b22; --border: #30363d; --text: #c9d1d9; --text-muted: #8b949e; --accent: #58a6ff; --green: #3fb950; --red: #f85149; --orange: #d29922; --purple: #bc8cff;. Apply background: var(--bg); color: var(--text); on body, --surface for cards and the table of contents, --purple for question/gate headings, --accent for links and section headings. Question block backgrounds use #1c2333.
Responsive layout. Include <meta name="viewport" content="width=device-width, initial-scale=1"> in the head. Use at most two breakpoints (@media (max-width: 860px) and @media (max-width: 560px)). Wrap every <table> in a <div style="overflow-x: auto">. All interactive elements have a minimum 44px touch target and at least 10px 16px padding. Use rem for font sizes; do not set a fixed font-size on html/body. Set max-width: 100%; overflow-wrap: break-word; on main so nothing forces a horizontal scrollbar.
Bar and meter sizing. CSS-rendered bars, meters, and coverage/progress fills (a container element plus a percentage-sized fill child) are a common idiom on interrogation pages — coverage summaries, confidence meters — and they collapse silently when sized wrong. Any element given a percentage height (e.g. a fill at height: 100%) must sit inside a container with an explicit, definite height — never min-height alone. A percentage height resolves against the parent's definite height; a min-height-only parent has none, so the fill computes to zero and paints empty even at width: 100%. Prefer the native <progress>/<meter> element where it fits; otherwise give the container an explicit height (or give the fill its own min-height so it paints regardless of the parent). Always render the value as text beside the bar (e.g. 100% — Covered) so the meaning survives even if the fill fails to paint. The active-page audit (node scripts/audit-interrogation-pages.mjs) flags the min-height-only container plus percentage-fill collapse mechanically.
Embed prohibition. Do not use <object>, <iframe>, or <embed>, or "open working packet" / "view full document" links as the primary rendering of any content. The interrogation page HTML must contain its content directly. Self-contained inline <canvas> and <svg> charts are permitted (visual/prototype tiers).
Brief Me (text-to-speech). Every interrogation page must include a <script src="../scripts/alignment-tts-kokoro.js"></script> tag before </body> — the same shared TTS asset the alignment page uses (interrogation/ is a sibling of alignment/, so ../scripts/ resolves identically). Do not inline the TTS script and do not use type="module". To inject TTS into existing pages, run node scripts/inject-tts.mjs --dir interrogation interrogation/<page>.html (idempotent; --force to replace an existing block).
Unanswered-question navigator. Every round page must include a <script src="../scripts/alignment-question-nav.js"></script> tag before </body> — the same shared asset the alignment page uses (../scripts/ resolves identically from interrogation/). The script discovers each [data-open-question] block (its answer field is the [data-open-input] control) and injects a compact ‹ prev unanswered · N left · next unanswered › pager both inline inside each open-question block and into the bottom compile section, so the user can hop directly between the questions they still have to answer without scrolling to find them. Next/prev jump to the next/previous unanswered block (wrapping) with a smooth scroll and a brief highlight; the N left count updates live and reads "All answered" with the controls disabled once none remain. A block counts as answered when a choice is checked or its open input holds non-whitespace text. The pager is navigation-only — no compile, copy, or answer semantics — so it is exempt from the sticky-controls prohibition even though it renders inline beside questions. To inject the include into an existing page, run node scripts/inject-tts.mjs --dir interrogation interrogation/<page>.html, which adds both the Brief Me and question-nav tags. Do not inline the script and do not use type="module".
Browser open. When the briefing-slides review-surface convention asset is installed (source checkout: docs/briefing-slides-convention.md; packaged install: assets/briefing-slides-convention.md), use the briefing-first open sequence: write or amend the dense interrogation/{skill-name}-r{N}-{branch}.html round page first; treat the dense interrogation page as the canonical backup/reference surface; build or amend briefing-slides/{skill-name}-{branch}.html second; link the dense page and source artifacts from the deck; then attempt to open only the briefing deck with node scripts/open-html-page.mjs briefing-slides/{skill-name}-{branch}.html --browser auto, replacing the path with the actual deck path when needed. Do not auto-open the dense interrogation page when the briefing deck exists. The deck's compiled YAML must route to the producing skill's continuation command, not $create-briefing-slides or /create-briefing-slides. If the briefing-slides convention asset is absent, the dense page remains the primary review surface: after writing or amending a round page, attempt to open it from the repository root with node scripts/open-html-page.mjs interrogation/{skill-name}-r{N}-{branch}.html --browser auto. Report the final status (focused, opened, fallback-opened, blocked, or failed) in the handoff, with the absolute path when blocked or failed. If no helper status has been produced yet, the handoff is incomplete; run the applicable helper before ending the turn. A manual instruction to open the file is not a substitute for the helper attempt and status. A blocked browser open does not fail the round if the file was written and verified.
Terminal fallback. Build and open the HTML interrogation page by default. Only when an HTML page genuinely cannot be opened (no browser available and the user cannot open a file path) fall back to terminal AskUserQuestion/request_user_input, following the Manifest Visibility Rule in docs/interview-convention.md. The fallback is degraded, not co-equal: do not interrogate in the terminal when the HTML surface is available.
Archiving. Round pages are durable artifacts; do not overwrite a prior round. Each round gets its own r{N} file. If a round page must be rebuilt before its answers are consumed (e.g. the user asks for a different question set, or the page predates a convention/standard change and is being brought to the current standard), archive the prior copy to docs/history/archive/YYYY-MM-DD/HHMMSS/interrogation/{skill-name}-r{N}-{branch}.html before replacing it.
Resume-time conformance upgrade. When resuming the loop at a round whose page already exists on disk as data-interrogation-status="review" and whose answers have not yet been consumed (no compiled interrogation-{skill-name}-r{N}.yaml sidecar), re-check that page against the current open-question marker standard before presenting it as the active surface. If it is missing any currently-required marker (data-open-input, data-recommended-answer, data-agent-recommended-answer, data-agent-confidence, data-clarify-copy, data-apply-recommended) or current page-metadata attributes, archive the prior copy to docs/history/archive/YYYY-MM-DD/HHMMSS/interrogation/{skill-name}-r{N}-{branch}.html and rewrite it to the current standard, preserving all page-specific content (assumptions, questions, prior context) and authoring the now-required helpers — visible recommendations, hidden agent recommendations, confidence, and apply-recommended controls/scripts — from the skill's own elicitation context. If an upgrade would risk losing page-specific content, stop and surface what needs a human decision rather than rewriting. <!-- interrogation-convention:end -->