althing 1.7.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (156) hide show
  1. althing/__init__.py +46 -0
  2. althing/__main__.py +9 -0
  3. althing/__version__.py +1 -0
  4. althing/_compat_env.py +27 -0
  5. althing/_runners.py +953 -0
  6. althing/agent_assets/__init__.py +3 -0
  7. althing/agent_assets/commands/althing-poll.md +75 -0
  8. althing/agent_assets/skills/concept-test/SKILL.md +72 -0
  9. althing/agent_assets/skills/focus-group/SKILL.md +77 -0
  10. althing/agent_assets/skills/name-test/SKILL.md +62 -0
  11. althing/agent_assets/skills/pricing-probe/SKILL.md +75 -0
  12. althing/agent_assets/skills/survey-prescreen/SKILL.md +76 -0
  13. althing/aggregation.py +240 -0
  14. althing/analysis/__init__.py +46 -0
  15. althing/analysis/distribution.py +323 -0
  16. althing/analysis/inspect.py +586 -0
  17. althing/analysis/subgroup.py +168 -0
  18. althing/analysis/subgroup_cli.py +598 -0
  19. althing/analyze.py +839 -0
  20. althing/attachments/__init__.py +77 -0
  21. althing/attachments/filter.py +67 -0
  22. althing/attachments/models.py +50 -0
  23. althing/attachments/pdf.py +537 -0
  24. althing/attachments/store.py +111 -0
  25. althing/calibration.py +239 -0
  26. althing/checkpoint.py +763 -0
  27. althing/cli/__init__.py +1 -0
  28. althing/cli/commands.py +8080 -0
  29. althing/cli/mcp_install.py +487 -0
  30. althing/cli/output.py +106 -0
  31. althing/cli/parser.py +1706 -0
  32. althing/cli/progress.py +93 -0
  33. althing/cli/repl.py +122 -0
  34. althing/cli/slash.py +197 -0
  35. althing/conditions.py +261 -0
  36. althing/convergence.py +1091 -0
  37. althing/cost.py +950 -0
  38. althing/cost_summary.py +452 -0
  39. althing/credentials.py +311 -0
  40. althing/data/__init__.py +8 -0
  41. althing/data/synthbench-snapshot.json +120 -0
  42. althing/diff.py +331 -0
  43. althing/domains.py +284 -0
  44. althing/ensemble.py +922 -0
  45. althing/fetch/__init__.py +38 -0
  46. althing/fetch/cache.py +360 -0
  47. althing/fetch/ladder.py +437 -0
  48. althing/fetch/lower.py +199 -0
  49. althing/fetch/perimeter.py +494 -0
  50. althing/instrument.py +751 -0
  51. althing/integrations/__init__.py +21 -0
  52. althing/integrations/composio.py +345 -0
  53. althing/llm/__init__.py +32 -0
  54. althing/llm/aliases.py +138 -0
  55. althing/llm/capabilities.py +86 -0
  56. althing/llm/client.py +267 -0
  57. althing/llm/errors.py +162 -0
  58. althing/llm/fast_default.py +71 -0
  59. althing/llm/models.py +340 -0
  60. althing/llm/providers/__init__.py +18 -0
  61. althing/llm/providers/_anthropic_format.py +281 -0
  62. althing/llm/providers/_openai_format.py +381 -0
  63. althing/llm/providers/anthropic.py +172 -0
  64. althing/llm/providers/base.py +60 -0
  65. althing/llm/providers/gemini.py +107 -0
  66. althing/llm/providers/openai_compat.py +102 -0
  67. althing/llm/providers/openrouter.py +357 -0
  68. althing/llm/providers/xai.py +98 -0
  69. althing/llm/retry.py +113 -0
  70. althing/logging_config.py +80 -0
  71. althing/main.py +308 -0
  72. althing/mcp/__init__.py +7 -0
  73. althing/mcp/compat.py +110 -0
  74. althing/mcp/data.py +700 -0
  75. althing/mcp/sampling.py +380 -0
  76. althing/mcp/server.py +3371 -0
  77. althing/metadata.py +214 -0
  78. althing/metadata_migrations.py +70 -0
  79. althing/orchestrator.py +2119 -0
  80. althing/pack_diff.py +271 -0
  81. althing/packs/__init__.py +3 -0
  82. althing/packs/ai-eval-buyers.yaml +247 -0
  83. althing/packs/broad-professionals.yaml +251 -0
  84. althing/packs/developer.yaml +271 -0
  85. althing/packs/enterprise-ai-buyers.yaml +245 -0
  86. althing/packs/enterprise-buyer.yaml +252 -0
  87. althing/packs/general-consumer.yaml +271 -0
  88. althing/packs/healthcare-patient.yaml +271 -0
  89. althing/packs/instruments/__init__.py +1 -0
  90. althing/packs/instruments/churn-diagnosis.yaml +73 -0
  91. althing/packs/instruments/feature-prioritization.yaml +75 -0
  92. althing/packs/instruments/general-survey.yaml +46 -0
  93. althing/packs/instruments/happiness-probe.yaml +41 -0
  94. althing/packs/instruments/landing-page-comprehension.yaml +75 -0
  95. althing/packs/instruments/market-research.yaml +50 -0
  96. althing/packs/instruments/name-test.yaml +74 -0
  97. althing/packs/instruments/pricing-discovery.yaml +80 -0
  98. althing/packs/instruments/product-feedback.yaml +46 -0
  99. althing/packs/job-seekers.yaml +188 -0
  100. althing/packs/market-research-critics.yaml +217 -0
  101. althing/packs/product-research.yaml +248 -0
  102. althing/packs/recruiters-talent.yaml +264 -0
  103. althing/packs/skeptical-executives.yaml +227 -0
  104. althing/packs/startup-founder.yaml +242 -0
  105. althing/packs/students.yaml +352 -0
  106. althing/persistence.py +510 -0
  107. althing/perturbation.py +333 -0
  108. althing/plugins/__init__.py +34 -0
  109. althing/plugins/hooks.py +159 -0
  110. althing/plugins/lint.py +352 -0
  111. althing/plugins/manager.py +176 -0
  112. althing/plugins/manifest.py +100 -0
  113. althing/plugins/registry.py +66 -0
  114. althing/poll_summary.py +1195 -0
  115. althing/preflight.py +155 -0
  116. althing/profiles.py +264 -0
  117. althing/prompts.py +311 -0
  118. althing/py.typed +0 -0
  119. althing/question_budget.py +140 -0
  120. althing/registry/__init__.py +178 -0
  121. althing/registry/cache.py +223 -0
  122. althing/registry/fetch.py +104 -0
  123. althing/registry/github.py +212 -0
  124. althing/reporting/__init__.py +17 -0
  125. althing/reporting/loader.py +69 -0
  126. althing/reporting/markdown.py +450 -0
  127. althing/response_coercion.py +161 -0
  128. althing/routing.py +132 -0
  129. althing/runtime.py +552 -0
  130. althing/schemas/__init__.py +53 -0
  131. althing/schemas/v1.0.0.json +161 -0
  132. althing/sdk.py +1458 -0
  133. althing/stats.py +1522 -0
  134. althing/structured/__init__.py +5 -0
  135. althing/structured/models.py +149 -0
  136. althing/structured/output.py +376 -0
  137. althing/structured/retry.py +170 -0
  138. althing/structured/schemas.py +127 -0
  139. althing/structured/validate.py +303 -0
  140. althing/structured/verdict.py +146 -0
  141. althing/synthbench.py +768 -0
  142. althing/synthbench_submit.py +582 -0
  143. althing/synthesis.py +1529 -0
  144. althing/synthesis_recovery.py +467 -0
  145. althing/templates.py +179 -0
  146. althing/text_width.py +126 -0
  147. althing-1.7.0.dist-info/METADATA +1473 -0
  148. althing-1.7.0.dist-info/RECORD +156 -0
  149. althing-1.7.0.dist-info/WHEEL +5 -0
  150. althing-1.7.0.dist-info/entry_points.txt +3 -0
  151. althing-1.7.0.dist-info/licenses/LICENSE +21 -0
  152. althing-1.7.0.dist-info/top_level.txt +3 -0
  153. synth_panel/__init__.py +60 -0
  154. synth_panel/__main__.py +17 -0
  155. synthpanel/__init__.py +60 -0
  156. synthpanel/__main__.py +17 -0
@@ -0,0 +1,3 @@
1
+ """Bundled Claude Code slash commands and skills shipped with althing."""
2
+
3
+ from __future__ import annotations
@@ -0,0 +1,75 @@
1
+ ---
2
+ description: Run a one-question synthetic poll across AI personas and synthesize the themes
3
+ allowed-tools:
4
+ - mcp__althing__run_quick_poll
5
+ - mcp__althing__list_persona_packs
6
+ - mcp__althing__get_persona_pack
7
+ argument-hint: <question to ask the panel>
8
+ ---
9
+
10
+ Run a quick synthetic poll using the Althing MCP server. One question, a
11
+ handful of AI personas, one synthesized writeup.
12
+
13
+ Question: $ARGUMENTS
14
+
15
+ ## What to do
16
+
17
+ 1. **Resolve the question.** If `$ARGUMENTS` is empty, ask the user for the
18
+ question before continuing. Do not invent one.
19
+
20
+ 2. **Pick personas.** Default to the built-in zero-config persona set by
21
+ omitting the `personas` argument. Only build a custom list when the user
22
+ names a specific audience (e.g. "three enterprise SRE personas"). In that
23
+ case, either:
24
+ - Call `mcp__althing__list_persona_packs` and `get_persona_pack` to
25
+ pull an installed pack, or
26
+ - Hand-author 3–5 dicts with `name`, `age`, `occupation`, `background`,
27
+ and `personality_traits`.
28
+
29
+ Keep panels small — `run_quick_poll` caps at 3 personas when running in
30
+ sampling mode (no API key).
31
+
32
+ 3. **Run the poll.** Call `mcp__althing__run_quick_poll` with:
33
+ - `question`: the user's question
34
+ - `personas`: omit for the default set, or pass your custom list
35
+ - `synthesis`: leave as `true` (default) — the synthesis pass is the
36
+ point of this command
37
+
38
+ Do not pass `model` unless the user explicitly asked for a specific one.
39
+ The MCP server picks a sensible default (haiku in BYOK mode, or the
40
+ host's own model in sampling mode).
41
+
42
+ 4. **Report the result.** Present the output in this shape:
43
+
44
+ ```
45
+ Question: <the question>
46
+ Panel: <n> personas (<mode: BYOK model-name | sampling>)
47
+
48
+ ## Themes
49
+ <bulleted list from the synthesis>
50
+
51
+ ## Per-persona responses
52
+ - <persona name>: <one-line summary of their response>
53
+ - ...
54
+
55
+ ## Notable divergences
56
+ <any disagreements the synthesis flagged>
57
+
58
+ Cost: <$X.XX from the response's `cost` field, or "n/a" in sampling mode>
59
+ ```
60
+
61
+ Keep each persona summary to one line. The full transcripts are in the
62
+ raw tool output — don't re-print them.
63
+
64
+ ## Guardrails
65
+
66
+ - **Synthetic panels are exploratory, not validating.** End the report with
67
+ a single-line caveat: "Synthetic panel — directional signal only, not a
68
+ substitute for real user research."
69
+ - **Don't loop.** If the user wants a second question, that's another
70
+ `/althing-poll` invocation, not a follow-up inside this one. For
71
+ multi-question structured studies, suggest the `/focus-group` skill
72
+ instead.
73
+ - **Report errors honestly.** If the tool returns an `error` field
74
+ (missing API key, persona cap exceeded, etc.), show it verbatim and
75
+ suggest the fix — don't silently fall back.
@@ -0,0 +1,72 @@
1
+ ---
2
+ name: concept-test
3
+ description: Validate a product concept or value proposition with a target audience — surfaces whether the problem is real, whether the solution lands, and what would prevent adoption.
4
+ allowed-tools:
5
+ - mcp__althing__run_panel
6
+ - mcp__althing__run_quick_poll
7
+ - mcp__althing__list_persona_packs
8
+ - mcp__althing__get_persona_pack
9
+ - mcp__althing__save_persona_pack
10
+ - mcp__althing__list_instrument_packs
11
+ ---
12
+
13
+ You are running a **concept test** using the althing MCP tools.
14
+
15
+ ## What You Do
16
+
17
+ You help the user pressure-test an early-stage product concept, value prop, or feature idea against a specific target audience before they build or ship it. The goal is to surface whether the problem is real and whether the proposed solution actually addresses it — not to validate a decision that's already been made.
18
+
19
+ 1. **Clarify the concept and the audience.**
20
+ 2. **Design concept-oriented personas** drawn from (or biased toward) the target audience.
21
+ 3. **Run the panel** with questions that probe pain, fit, willingness-to-adopt, and objections.
22
+ 4. **Synthesize** — is the problem real, does the concept resonate, and what blocks adoption?
23
+
24
+ ## Available MCP Tools
25
+
26
+ - **`mcp__althing__run_panel`** — Primary tool. Run a multi-question panel with target-audience personas.
27
+ - **`mcp__althing__run_quick_poll`** — Use for a single "would you try this?" temperature check.
28
+ - **`mcp__althing__list_persona_packs`** / **`mcp__althing__get_persona_pack`** — Reuse saved target-audience packs.
29
+ - **`mcp__althing__save_persona_pack`** — Save a new audience pack if the user is likely to re-test.
30
+ - **`mcp__althing__list_instrument_packs`** — Check for bundled packs that fit (e.g. `product-feedback`, `market-research`).
31
+
32
+ ## Workflow
33
+
34
+ ### Step 1: Frame the Concept
35
+
36
+ Ask the user for:
37
+ - A 2-3 sentence description of the concept (what it is, who it's for, what problem it solves).
38
+ - The target audience (role, demographic, or psychographic).
39
+ - What decision this test is meant to inform ("should we keep exploring?" vs. "which direction?").
40
+
41
+ ### Step 2: Build or Load Personas
42
+
43
+ - 4-8 personas, biased toward the target audience but with **at least one skeptic** and **at least one adjacent non-target** to stress-test the boundaries.
44
+ - Each persona should have a plausible reason the problem may or may not apply to them.
45
+
46
+ ### Step 3: Design the Instrument
47
+
48
+ Include questions in this order:
49
+ 1. **Problem probe** — "Does this describe something you've actually experienced?" (don't lead with the solution)
50
+ 2. **Concept reveal** — present the concept, ask for gut reaction.
51
+ 3. **Fit** — "Who do you know this would be for?" (reveals whether they see themselves in it)
52
+ 4. **Adoption blockers** — "What would stop you from trying this?"
53
+ 5. **Willingness** — rough price sensitivity or alternative-they'd-pick.
54
+
55
+ Add 1-2 follow-ups on the concept reveal for depth.
56
+
57
+ ### Step 4: Run and Synthesize
58
+
59
+ After results return, report:
60
+ - **Problem validity** — did panelists actually experience the problem, or did you have to convince them?
61
+ - **Concept resonance** — who lit up, who shrugged, who pushed back.
62
+ - **Top 2-3 adoption blockers** across panelists.
63
+ - **Surprising insights** — anything you didn't expect.
64
+ - **Recommended next step** — iterate the concept, test with real users, or drop it.
65
+ - **Total cost**.
66
+
67
+ ## Guidelines
68
+
69
+ - **Don't sell the concept to the panel.** Describe it neutrally. Leading questions produce leading answers.
70
+ - **Respect dissent.** If 2 of 6 panelists hate it, that's signal — don't average it away.
71
+ - **Distinguish "I'd use this" from "This is a good idea."** Only the first predicts adoption.
72
+ - **Concept tests are exploration, not validation.** Say so when the user asks "should we build this?" — the honest answer is "this is one data point; go talk to real users."
@@ -0,0 +1,77 @@
1
+ ---
2
+ name: focus-group
3
+ description: Run a synthetic focus group — define personas, craft questions, and collect structured qualitative feedback from AI panelists.
4
+ allowed-tools:
5
+ - mcp__althing__run_prompt
6
+ - mcp__althing__run_panel
7
+ - mcp__althing__list_persona_packs
8
+ - mcp__althing__list_instrument_packs
9
+ ---
10
+
11
+ You are orchestrating a **synthetic focus group** using the althing MCP tools.
12
+
13
+ ## What You Do
14
+
15
+ You help the user design and run synthetic focus groups — structured qualitative research using AI-powered personas. You handle the full workflow:
16
+
17
+ 1. **Understand the research question** — What does the user want to learn?
18
+ 2. **Define personas** — Assemble a list of realistic, diverse participants.
19
+ 3. **Design the instrument** — Write targeted questions and follow-ups.
20
+ 4. **Run the panel** — Execute the focus group via MCP tools.
21
+ 5. **Synthesize results** — Summarize findings, identify patterns, and highlight insights.
22
+
23
+ ## Available MCP Tools
24
+
25
+ - **`mcp__althing__run_prompt`** — Send a single prompt to an LLM (no personas). Use for a quick smoke test before building a panel.
26
+ - **`mcp__althing__run_panel`** — Run a full panel: pass `personas` (an inline list of persona dicts) plus one question source — inline `questions`, an inline `instrument` dict, or an `instrument_pack` name.
27
+ - **`mcp__althing__list_persona_packs`** — List saved persona packs you can reuse via `run_panel`'s `pack_id`.
28
+ - **`mcp__althing__list_instrument_packs`** — List installed instrument packs you can reference via `run_panel`'s `instrument_pack`.
29
+
30
+ > These MCP tools take **inline data or pack names, not file paths.** Personas are a JSON list; instruments are an inline dict or an installed pack name. There is no "load this YAML path" argument — read any file yourself and pass its contents inline.
31
+
32
+ ## Workflow
33
+
34
+ ### Step 1: Clarify the Research Goal
35
+
36
+ Ask the user what they want to test. Examples:
37
+ - "What do people think of the name 'Traitprint' for a career app?"
38
+ - "How would different demographics react to this pricing page?"
39
+ - "Pre-screen this survey before we send it to real participants."
40
+
41
+ ### Step 2: Assemble Personas
42
+
43
+ Build a list of 3-6 diverse personas. Each persona is a dict with:
44
+ - `name` (required), `age`, `occupation`
45
+ - `background` — 2-3 sentences of life context
46
+ - `personality_traits` — 3-5 traits that shape their perspective
47
+
48
+ Ensure demographic and psychographic diversity relevant to the research question. Pass the list inline as `run_panel`'s `personas` argument, or reuse a saved pack by `pack_id` (discover names via `list_persona_packs`).
49
+
50
+ ### Step 3: Design the Instrument
51
+
52
+ Write 2-5 focused questions. Each question can have:
53
+ - `text` — The question itself
54
+ - `response_schema` — Usually `{type: text}`
55
+ - `follow_ups` — Probing questions for depth
56
+
57
+ Pass them inline as `run_panel`'s `questions` list (single round) or as an `instrument` dict (for v2/v3 multi-round). To use a bundled pack, pass its name as `instrument_pack` (discover names via `list_instrument_packs`).
58
+
59
+ ### Step 4: Run the Panel
60
+
61
+ Call `mcp__althing__run_panel` with the `personas` list and one question source (`questions`, `instrument`, or `instrument_pack`).
62
+
63
+ ### Step 5: Synthesize
64
+
65
+ After results return:
66
+ - Summarize each persona's perspective in 1-2 sentences
67
+ - Identify consensus vs. divergence across personas
68
+ - Flag surprising or non-obvious insights
69
+ - Recommend next steps (iterate instrument, test with real users, etc.)
70
+
71
+ ## Guidelines
72
+
73
+ - **Don't over-engineer personas** — 3-5 well-chosen personas beat 10 generic ones.
74
+ - **Ask pointed questions** — Vague questions get vague answers.
75
+ - **Use follow-ups** — They surface depth that initial responses miss.
76
+ - **Report costs** — Always mention the total cost of the panel run (surfaced as `total_cost`).
77
+ - **Be honest about limitations** — Synthetic panels are for exploration, not validation.
@@ -0,0 +1,62 @@
1
+ ---
2
+ name: name-test
3
+ description: Quickly test 1-3 candidate product or feature names with a synthetic panel — surfaces confusion, pronounceability, and memorability concerns in one pass.
4
+ allowed-tools:
5
+ - mcp__althing__run_quick_poll
6
+ - mcp__althing__run_panel
7
+ - mcp__althing__list_persona_packs
8
+ - mcp__althing__get_persona_pack
9
+ - mcp__althing__list_instrument_packs
10
+ - mcp__althing__get_instrument_pack
11
+ ---
12
+
13
+ You are running a **quick name test** using the althing MCP tools.
14
+
15
+ ## What You Do
16
+
17
+ You help the user decide between candidate names for a product, feature, or brand. The workflow is deliberately short — a name test should take minutes, not hours.
18
+
19
+ 1. **Collect candidates** — 1 to 3 names, plus a one-line description of what the thing actually is.
20
+ 2. **Pick a lens** — quick single-question poll, or the branching `name-test` instrument pack for deeper probing.
21
+ 3. **Run the panel** — small, diverse personas; keep it cheap.
22
+ 4. **Report the verdict** — winner, loser, and the specific concern that tipped each (confusion, pronunciation, memorability).
23
+
24
+ ## Available MCP Tools
25
+
26
+ - **`mcp__althing__run_quick_poll`** — Single-question poll across personas (fastest, cheapest).
27
+ - **`mcp__althing__run_panel`** — Full panel run using the bundled `name-test` branching instrument that probes meaning, pronounceability, or memorability based on first reactions. Its opening question has a `{candidates}` placeholder; fill it with the `vars` argument (see Step 2).
28
+ - **`mcp__althing__list_persona_packs`** / **`mcp__althing__get_persona_pack`** — Reuse saved personas instead of inventing new ones.
29
+ - **`mcp__althing__list_instrument_packs`** — Confirm the `name-test` pack is available.
30
+
31
+ ## Workflow
32
+
33
+ ### Step 1: Gather Inputs
34
+
35
+ Ask for:
36
+ - The candidate names (comma-separated).
37
+ - A one-sentence description of what the product/feature does.
38
+ - Target audience (so personas are relevant).
39
+
40
+ ### Step 2: Choose Depth
41
+
42
+ - **Quick gut check** → `run_quick_poll` with a question that has the description and candidate names written directly into the `question` string, e.g. *"Which of these names best fits a budget travel app — Wander, Roamly, Tr9? Why?"*
43
+ - **Full branching evaluation** → `run_panel` with `instrument_pack="name-test"` and `vars={"candidates": "Name A, Name B"}` — the comma-separated candidate names are substituted into the opening question's `{candidates}` placeholder before the panel runs. (CLI equivalent: `althing panel run --instrument name-test --var 'candidates=Name A, Name B'`.) If you omit `vars`, the call fails fast with a typed `INVALID_TOOL_ARG` error naming the missing placeholder. The instrument branches into meaning-probe, pronounce-probe, or memorability-probe based on what surfaces first.
44
+
45
+ ### Step 3: Run
46
+
47
+ Default to 4-6 personas. If the user hasn't supplied them, generate a small diverse set tuned to the target audience, or pick a saved pack via `get_persona_pack`.
48
+
49
+ ### Step 4: Report
50
+
51
+ Produce a tight summary:
52
+ - **Winner** and why (quote 1-2 panelists).
53
+ - **Loser** and the specific failure mode (misread, hard to say, forgettable).
54
+ - **Risks for the winner** — concerns that still showed up even for the preferred name.
55
+ - **Total cost** of the run.
56
+
57
+ ## Guidelines
58
+
59
+ - Keep it small — 4-6 personas is plenty for a name test.
60
+ - Don't over-interpret a single panel — flag when reactions were genuinely mixed rather than forcing a winner.
61
+ - If all names scored poorly, say so and suggest the user brainstorm a new set instead of picking the least-bad.
62
+ - Name tests are exploratory signal, not validation. Say this when the user asks "should we ship this?"
@@ -0,0 +1,75 @@
1
+ ---
2
+ name: pricing-probe
3
+ description: Probe pricing sensitivity with a target audience using the bundled 'pricing-discovery' branching instrument — surfaces pain, price anchoring, or competitor alternatives based on what the panel volunteers first.
4
+ allowed-tools:
5
+ - mcp__althing__run_panel
6
+ - mcp__althing__get_instrument_pack
7
+ - mcp__althing__list_instrument_packs
8
+ - mcp__althing__list_persona_packs
9
+ - mcp__althing__get_persona_pack
10
+ - mcp__althing__run_quick_poll
11
+ ---
12
+
13
+ You are running a **pricing sensitivity probe** using the althing MCP tools and the bundled `pricing-discovery` v3 branching instrument.
14
+
15
+ ## What You Do
16
+
17
+ You help the user understand how a target audience reasons about price for a product or service. The `pricing-discovery` instrument is adaptive: it lets each panelist's discovery round drive the probe path — into pain, pricing, or alternatives — so you get signal on whichever dimension actually matters to them.
18
+
19
+ 1. **Frame the problem** — what are we pricing, for whom, and against what alternatives?
20
+ 2. **Assemble a target-audience panel.**
21
+ 3. **Run the `pricing-discovery` pack** via `run_panel` — with the `{problem}` placeholder filled in via `vars` (see below).
22
+ 4. **Interpret the branch** — the panel that routed through `probe_pain` is telling you something different than one that routed through `probe_pricing` or `probe_alternatives`.
23
+
24
+ ## Available MCP Tools
25
+
26
+ - **`mcp__althing__run_panel`** — Primary tool. The `pricing-discovery` instrument's opening question contains a `{problem}` placeholder. Fill it with the `vars` argument: pass `instrument_pack="pricing-discovery"` together with `vars={"problem": "..."}`. (CLI equivalent: `althing panel run --instrument pricing-discovery --var problem='...'`.) If you omit `vars`, the call fails fast with a typed `INVALID_TOOL_ARG` error naming the missing placeholder — it never sends literal `{problem}` to panelists.
27
+ - **`mcp__althing__get_instrument_pack`** / **`mcp__althing__list_instrument_packs`** — Inspect the bundled pricing-discovery pack (e.g. to see which placeholders it declares).
28
+ - **`mcp__althing__list_persona_packs`** / **`mcp__althing__get_persona_pack`** — Load a saved target-audience pack.
29
+ - **`mcp__althing__run_quick_poll`** — Use for a narrow follow-up question after the main run (e.g. "Would $X/month feel fair?").
30
+
31
+ ## Workflow
32
+
33
+ ### Step 1: Clarify the Pricing Context
34
+
35
+ Ask:
36
+ - **What problem does the product solve?** (The `pricing-discovery` instrument substitutes this into its opening question.)
37
+ - **Who is it for?** (shapes personas)
38
+ - **Are there competitors or alternatives?** (panelists will volunteer these if real)
39
+ - **What price range is the user considering?** (optional — don't reveal it to the panel until after discovery)
40
+
41
+ ### Step 2: Build or Load the Panel
42
+
43
+ - 5-8 personas matching the target audience.
44
+ - Include **at least one price-sensitive** persona and **one value-driven** persona — pricing intuition varies more across that axis than demographics.
45
+ - Pull saved packs via `get_persona_pack` when re-running against the same audience.
46
+
47
+ ### Step 3: Run the Instrument
48
+
49
+ Call `run_panel` with:
50
+ - the persona set (inline `personas`, or a saved pack via `pack_id`)
51
+ - `instrument_pack="pricing-discovery"`
52
+ - `vars={"problem": "<the user's problem statement>"}` — `run_panel` substitutes it into the instrument's `{problem}` placeholder before any panelist sees the question
53
+
54
+ Note: the instrument branches via theme tags (`pain`, `price`, `alternative`). Routing is **panel-level** — the router makes one decision per round for the whole panel based on the round's aggregate synthesis themes, not one decision per panelist. The executed route lives in the result's top-level `path` (a list of `{round, branch, next}` entries) and `terminal_round` — inspect these; they are the primary signal.
55
+
56
+ ### Step 4: Interpret the Branch
57
+
58
+ Report, for the panel:
59
+ - **Which branch did the panel take?** (pain / price / alternatives / else)
60
+ - That branch *is* the insight: a panel that routed to `probe_alternatives` is telling you price is benchmarked against an incumbent, not derived from value.
61
+
62
+ Then overall:
63
+ - **Where the route landed** — if the panel went to `probe_alternatives`, your pricing problem is really a positioning problem.
64
+ - **Price anchors** that surfaced organically (vs. ones you asked about).
65
+ - **Willingness-to-pay range** — cluster the numbers panelists volunteered.
66
+ - **Deal-breakers** — what would stop them from paying anything.
67
+ - **Suggested price test** — one specific follow-up (e.g. a `run_quick_poll` at a target price point).
68
+ - **Total cost**.
69
+
70
+ ## Guidelines
71
+
72
+ - **Don't anchor the panel with your target price** until after discovery — price sensitivity is contaminated by any number you drop first.
73
+ - **Trust the branch.** The router is how this instrument earns its keep; interpreting which branch fired (panel-level, once per round) matters more than individual answers.
74
+ - **Synthetic WTP is directional, not predictive.** Real people are stingier than personas. Discount synthetic price points before fielding.
75
+ - **Watch for `else` fall-through.** If the panel bypasses the routed branches and lands on `else`, the synthesizer isn't emitting the canonical theme tags — say so and suggest re-running or editing the instrument's theme-tag guidance.
@@ -0,0 +1,76 @@
1
+ ---
2
+ name: survey-prescreen
3
+ description: Pre-screen a survey instrument with synthetic respondents before sending to real participants — catches ambiguous wording, leading questions, and dead-end branches cheaply.
4
+ allowed-tools:
5
+ - mcp__althing__run_panel
6
+ - mcp__althing__get_instrument_pack
7
+ - mcp__althing__list_instrument_packs
8
+ - mcp__althing__save_instrument_pack
9
+ - mcp__althing__list_persona_packs
10
+ - mcp__althing__get_persona_pack
11
+ ---
12
+
13
+ You are pre-screening a **user-authored survey instrument** using the althing MCP tools.
14
+
15
+ ## What You Do
16
+
17
+ You help the user catch problems in a survey before they spend real budget fielding it. Synthetic respondents are cheap — use them to find ambiguous wording, leading questions, unanswerable items, and dead-end branches *before* real participants see the instrument.
18
+
19
+ 1. **Load the user's instrument** (YAML file they provide, or `save_instrument_pack` first if it's inline).
20
+ 2. **Assemble stress-test personas** — a mix that should reveal wording problems across demographics.
21
+ 3. **Run the instrument** as a full panel.
22
+ 4. **Critique** — report specific failure modes per question, not just a thumbs up/down.
23
+
24
+ ## Available MCP Tools
25
+
26
+ - **`mcp__althing__run_panel`** — Run the user's instrument against the stress-test personas. Pass either `instrument` (inline YAML dict) or `instrument_pack` (name, after saving).
27
+ - **`mcp__althing__get_instrument_pack`** / **`mcp__althing__list_instrument_packs`** — Load an installed instrument for review.
28
+ - **`mcp__althing__save_instrument_pack`** — Save the user's instrument temporarily if they'd rather reference it by name.
29
+ - **`mcp__althing__list_persona_packs`** / **`mcp__althing__get_persona_pack`** — Load a realistic audience pack for the survey's intended population.
30
+
31
+ ## Workflow
32
+
33
+ ### Step 1: Load the Instrument
34
+
35
+ Read the user's YAML. Before running, do a quick structural review:
36
+ - Are questions clear and scoped to one thing each?
37
+ - Any double-barreled questions ("How satisfied and how often do you...")?
38
+ - Any leading wording ("How much do you *love*...")?
39
+ - For v3 instruments: do `route_when` branches cover plausible respondent paths, or do cases silently fall to `else`?
40
+ - Are follow-ups specific enough to produce depth?
41
+
42
+ Call out structural issues first — sometimes the instrument doesn't need a panel run at all, just a rewrite.
43
+
44
+ ### Step 2: Assemble Stress-Test Personas
45
+
46
+ 5-8 personas that specifically stress the instrument:
47
+ - **Representative of the intended audience** (2-3).
48
+ - **Adjacent-but-different** — slightly outside the target, to reveal questions that assume audience knowledge (1-2).
49
+ - **A literal responder** who answers exactly what's asked (catches ambiguity).
50
+ - **A confused/distracted responder** (catches comprehension failures).
51
+ - **An opinionated outlier** (catches leading questions — they'll push back).
52
+
53
+ ### Step 3: Run the Panel
54
+
55
+ Use `run_panel`. If the instrument is v3 branching, note which rounds each persona was routed into — `path` in the result tells you whether branches fired or fell through to `else`.
56
+
57
+ ### Step 4: Critique (Report Format)
58
+
59
+ For each question, report:
60
+ - **Did everyone understand it?** Quote a confused answer verbatim if so.
61
+ - **Did answers cluster or scatter?** Scattering often means the question is too open or ambiguous.
62
+ - **Were follow-ups productive** or did they produce filler?
63
+
64
+ Then overall:
65
+ - **Top 3 problems** with the instrument, in priority order.
66
+ - **Specific rewrites** for the worst offenders.
67
+ - **Branch coverage** (v3 only) — which `route_when` clauses never fired, and whether that's a coverage gap or just this persona sample.
68
+ - **Go/no-go** — is this instrument ready to field, or does it need another pass?
69
+ - **Total cost**.
70
+
71
+ ## Guidelines
72
+
73
+ - **Diagnose, don't just score.** "Question 3 is unclear" is useless; "Question 3 was interpreted three different ways; here are the three readings" is actionable.
74
+ - **Preserve the user's intent.** When suggesting rewrites, match what they were trying to ask — don't silently redesign the survey.
75
+ - **A prescreen isn't a pilot.** Synthetic respondents won't catch fatigue, incentive gaming, or platform-specific dropout. Say so.
76
+ - **If the instrument is broken at the structural level, stop and say so** before burning tokens on a panel run.