Remove discarded pick-one-option WVS experiment

Co-Authored-By: PI[gpt-5.6-terra] <288921227+claudypoo@users.noreply.github.com>
This commit is contained in:
wassname
2026-09-17 19:06:22 +08:00
co-authored by PI[gpt-5.6-terra]
parent 912451eaeb
commit 4de1938d5f
78 changed files with 2 additions and 26712 deletions
@@ -1,3 +0,0 @@
#!/bin/sh
set -eu
uv run --with 'datasets>=4.0,<5' python scripts/wvs_direct_choice_pilot.py --run
@@ -1,3 +0,0 @@
#!/bin/sh
set -eu
uv run --with 'datasets>=4.0,<5' python scripts/wvs_direct_choice_anchor_pilot.py --run
@@ -1,3 +0,0 @@
#!/bin/sh
set -eu
uv run --with 'datasets>=4.0,<5' python scripts/wvs_direct_choice_production_pilot.py --run
@@ -1,4 +0,0 @@
#!/bin/sh
set -eu
[ "$#" -eq 1 ] || { echo "usage: $0 exact-model-id" >&2; exit 2; }
uv run --with 'datasets>=4.0,<5' python scripts/wvs_direct_choice_priority.py --model "$1" --run
+2 -2
View File
@@ -344,8 +344,8 @@ def main() -> None:
"",
"The table shows that flat replies and coordinate sensitivity vary across model and item, so Nano alone cannot "
"supply a general rejection threshold. Saved mismatch rationale is evidence against interpreting those replies as attitudes. "
"For other cells, no saved rationale does not establish genuine indifference. The direct-choice pilot should therefore compare "
"the construct rather than silently replace or filter the published rated readout.",
"For other cells, no saved rationale does not establish genuine indifference. Preserve the published dense-rated "
"readout and report this diagnostic rather than silently replace or filter it.",
"",
"-- PI[gpt-5.6-terra]",
"",
-223
View File
@@ -1,223 +0,0 @@
#!/usr/bin/env python3
"""Audit the Gemini response-wording direct-choice control without API calls."""
from __future__ import annotations
import csv
import json
from collections import Counter
from decimal import Decimal
from pathlib import Path
import numpy as np
RUN_ID = "20260917T031008Z_db7584c9b8b6"
PROTOCOL_ID = "db7584c9b8b693d3196aef4cfcc5e93956aceb2f4d9ad1432a65c8525dfb135e"
LEDGER = Path("slop/research/wvs/20260917_direct_choice/gemini37_direct_choice_anchor_requests.jsonl")
CACHE = Path("slop/research/wvs/20260917_direct_choice/gemini37_direct_choice_anchor_cache.json")
PREVIOUS_LEDGER = Path("slop/research/wvs/20260917_direct_choice/gemini37_direct_choice_requests.jsonl")
OUT_CSV = Path("slop/audits/20260917_wvs_gemini37_direct_choice_anchor_task_1629_by_item.csv")
OUT_MD = Path("slop/audits/20260917_wvs_gemini37_direct_choice_anchor_task_1629.md")
def read_events(path: Path) -> list[dict]:
return [json.loads(line) for line in path.read_text().splitlines()]
def distribution(rows: list[dict], n: int) -> np.ndarray:
counts = np.zeros(n)
for row in rows:
counts[row["canonical_choice"]] += 1
return counts / len(rows)
def total_variation(left: np.ndarray, right: np.ndarray) -> float:
return float(0.5 * np.abs(left - right).sum())
def display(p: np.ndarray) -> str:
return "[" + ", ".join(f"{value:.3f}" for value in p) + "]"
def modal_set(p: np.ndarray) -> list[int]:
return np.flatnonzero(p == p.max()).tolist()
def quote(message: dict) -> str:
return (message.get("reasoning") or message.get("content") or "").replace("\n", " ").strip()
def by_item(parsed: list[dict], item_id: str) -> dict:
rows = [event for event in parsed if event["item_id"] == item_id]
n = len(rows[0]["presented_order"])
canonical = [event for event in rows if event["order_name"] == "canonical"]
reversed_order = [event for event in rows if event["order_name"] == "reversed"]
assert len(canonical) == len(reversed_order) == 12
canonical_p = distribution(canonical, n)
reversed_p = distribution(reversed_order, n)
return {
"item_id": item_id, "n_options": n, "canonical_n": len(canonical), "reversed_n": len(reversed_order),
"canonical_p": canonical_p, "reversed_p": reversed_p,
"tv": total_variation(canonical_p, reversed_p),
"canonical_modal": modal_set(canonical_p), "reversed_modal": modal_set(reversed_p),
}
def main() -> None:
events = [event for event in read_events(LEDGER) if event.get("run_id") == RUN_ID]
counts = Counter(event["event"] for event in events)
assert counts == Counter({"request_started": 48, "request_completed": 48, "answer_parsed": 48,
"item_result": 2, "run_started": 1, "run_finished": 1}), counts
parsed = [event for event in events if event["event"] == "answer_parsed"]
assert len(parsed) == 48 and all(event["parsed"] for event in parsed)
for event in parsed:
raw = json.loads(event["text"])
assert set(raw) == {"answer"} and type(raw["answer"]) is int
assert event["canonical_choice"] == event["presented_order"][raw["answer"]]
assert not [event for event in events if event["event"] == "request_failed"]
assert not [event for event in events if event.get("phase") == "rescue"]
assert {event["protocol_id"] for event in events} == {PROTOCOL_ID}
assert json.loads(CACHE.read_text())["completed"][PROTOCOL_ID]["complete"]
current = {item: by_item(parsed, item) for item in ("Homosexuality", "Religion")}
prior_events = read_events(PREVIOUS_LEDGER)
prior_parsed = [event for event in prior_events if event["event"] == "answer_parsed"]
prior = {item: by_item(prior_parsed, item) for item in ("Homosexuality", "Religion")}
request_events = [event for event in events if event["event"] == "request_completed"]
prompt_tokens = sum(event["usage"]["prompt_tokens"] for event in request_events)
completion_tokens = sum(event["usage"]["completion_tokens"] for event in request_events)
reasoning_tokens = sum(event["usage"]["completion_tokens_details"]["reasoning_tokens"] for event in request_events)
cost = sum(Decimal(str(event["usage"]["cost"])) for event in request_events)
refusals = sum(event["response"]["choices"][0]["message"].get("refusal") is not None for event in request_events)
first_homosexuality = next(event for event in request_events if event["item_id"] == "Homosexuality" and event["sample"] == 0)
first_religion = next(event for event in request_events if event["item_id"] == "Religion" and event["sample"] == 0)
rows = []
for item in ("Homosexuality", "Religion"):
now, before = current[item], prior[item]
screen = now["tv"] <= 0.25 and now["canonical_modal"] == now["reversed_modal"]
rows.append({
"item_id": item, "canonical_n": now["canonical_n"], "reversed_n": now["reversed_n"],
"anchor_canonical_distribution": display(now["canonical_p"]),
"anchor_reversed_distribution": display(now["reversed_p"]),
"anchor_order_tv": now["tv"], "anchor_canonical_modal": now["canonical_modal"],
"anchor_reversed_modal": now["reversed_modal"], "screen_passes": screen,
"task1628_order_tv": before["tv"], "task1628_canonical_modal": before["canonical_modal"],
"task1628_reversed_modal": before["reversed_modal"],
})
OUT_CSV.parent.mkdir(parents=True, exist_ok=True)
with OUT_CSV.open("w", newline="") as fh:
writer = csv.DictWriter(fh, fieldnames=list(rows[0]), lineterminator="\n")
writer.writeheader()
writer.writerows(rows)
ledger_through = max(event["recorded_at_utc"] for event in events)
all_screen_pass = all(row["screen_passes"] for row in rows)
lines = [
"# Audit: Gemini direct-choice response-wording control, task 1629",
"",
"- target: 48-call Homosexuality/Religion wording control, not a map panel",
"- Pueue: task 1629, API queue, success, 2026-09-17 11:10:00-11:13:43 +08:00",
"- label: `why: test whether literal JSON example anchored option zero; resolve: report preregistered order TV/modal agreement before any wider batch`",
f"- run: `{RUN_ID}`, protocol: `{PROTOCOL_ID}`",
f"- primary ledger: `{LEDGER}` through {ledger_through}",
f"- cache: `{CACHE}`",
f"- task 1628 comparator: `{PREVIOUS_LEDGER}`",
f"- per-item table: `{OUT_CSV}`",
"",
"## Stage table",
"",
"| stage | expected | observed | expected? | clues | missing metric | consequence |",
"|---|---|---|---|---|---|---|",
"| response-wording change | remove literal answer value/example only | prompt uses one-key schema wording with no literal JSON example or answer value | yes | saved request prompt | independent prompt diff beyond smoke | targeted anchoring discriminator ran |",
"| request plan | 48 calls, 12 canonical and 12 reversed per item, interleaved | 48 starts/completions, 24 valid per item and 12 per order | yes | ledger counts/cache | provider-side order timestamp | planned comparison available |",
"| strict parse | 48 valid choices with preserved mapping | 48/48 parsed, independently re-decoded to stored canonical choice | yes | ledger + audit assertions | external schema trace | no mechanical loss |",
"| rescue/refusal | zero or durable evidence | 0 rescue, 0 failure, 0 provider refusal | yes | ledger | semantic non-answer metric | mechanics do not decide construct validity |",
f"| accounting | retained provider usage | prompt {prompt_tokens:,}; completion {completion_tokens:,}; reasoning {reasoning_tokens:,}; USD {cost:.7f} | yes | 48 completed usage records | billing export | below preregistered reserve |",
f"| operational screen | both items TV <=0.25 plus matching modal set | {'passes both items' if all_screen_pass else 'fails'}: Homosexuality TV={current['Homosexuality']['tv']:.3f}, Religion TV={current['Religion']['tv']:.3f}; modal sets match | {'yes' if all_screen_pass else 'no'} | per-item table | repeat with other permutation | evidence against a large reverse-order effect only |",
"| persistence | complete cache only after all valid samples | cache entry complete and 148 ledger events | yes | cache + ledger | cache replay | raw evidence retained |",
"",
"## Primary evidence",
"",
"The source ledger is the primary record because Pueue's full output only repeats the completion line. It has 48 initial request starts, 48 completions, 48 parsed responses, two item results, one run start and one run finish. No response used a rescue phase.",
"",
"Homosexuality sample 0's changed prompt ends with the response wording, followed by this saved reasoning:",
"",
f"> {quote(first_homosexuality['response']['choices'][0]['message'])}",
"",
"epistemic context: provider reasoning from one selected pilot response, not a human attitude report.",
"",
"Religion sample 0 still contains an AI-persona interpretation:",
"",
f"> {quote(first_religion['response']['choices'][0]['message'])}",
"",
"epistemic context: provider reasoning from one selected pilot response, not a human attitude report.",
"",
"## Preregistered order screen and task 1628 comparison",
"",
"| item | new canonical p | new reversed p | new TV | new modal sets | screen | task 1628 TV | task 1628 modal sets |",
"|---|---|---|---:|---|---|---:|---|",
]
for row in rows:
lines.append(
f"| {row['item_id']} | {row['anchor_canonical_distribution']} | {row['anchor_reversed_distribution']} | "
f"{row['anchor_order_tv']:.3f} | {row['anchor_canonical_modal']} / {row['anchor_reversed_modal']} | "
f"{row['screen_passes']} | {row['task1628_order_tv']:.3f} | "
f"{row['task1628_canonical_modal']} / {row['task1628_reversed_modal']} |"
)
lines.extend([
"",
"The registered screen passes: both items are below TV 0.25 and have matching modal sets. This is evidence against the literal JSON example causing a large reverse-order effect under this specific control. It is not proof that the selected distribution represents a stable personal attitude, because the only tested permutations are canonical and full reversal and saved persona-language remains.",
"",
"## Hypotheses",
"",
"### H1 [method | Highly Likely | 80%]",
"",
"- Mechanism: the literal task 1628 answer example materially contributed to its Homosexuality reverse-order effect.",
f"- Evidence: Homosexuality order TV fell from {prior['Homosexuality']['tv']:.3f} in task 1628 to {current['Homosexuality']['tv']:.3f}, while its modal set now matches ({current['Homosexuality']['canonical_modal']}).",
"- Contrary evidence: this is a new sampled run, so ordinary sampling variation or another unmeasured request-time effect can also change the result.",
"- Discriminating test: repeat this exact no-example prompt with a balanced set of non-reversal permutations. Similar low TV would support the explanation; a new high position-linked TV would weaken it.",
"- Fix/action: retain no-example response wording in any future direct-choice protocol; do not merge this control with task 1628.",
"- Interpretability: partial.",
"",
"### H2 [measurement | Likely | 65%]",
"",
"- Mechanism: Gemini still answers subjective WVS questions through its AI persona rather than a personal-attitude construct.",
f"- Evidence: Religion sample 0 says `{quote(first_religion['response']['choices'][0]['message'])}`.",
"- Contrary evidence: the final choices are order-stable under this narrow screen.",
"- Discriminating test: compare a role-conditioned prompt against the same no-example response wording and a fixed permutation schedule.",
"- Fix/action: keep this as a construct diagnostic, not a coordinate replacement.",
"- Interpretability: partial.",
"",
"### H3 [bug | Unlikely | 15%]",
"",
"- Mechanism: reversed response mapping could hide a position effect.",
"- Evidence: this audit independently parses every raw final JSON object and maps its integer through the stored presented order; all 48 match the ledger canonical-choice field.",
"- Contrary evidence: it is one implementation and one run.",
"- Discriminating test: an independent reimplementation over the raw ledger or a non-reversal permutation test.",
"- Fix/action: no mapping code change is justified.",
"- Interpretability: yes for recorded canonical choices.",
"",
"## Decision",
"",
"1. Resolve-condition verdict: **met**. Both operational checks pass: order TV <=0.25 and matching modal set for Homosexuality and Religion.",
"2. Prediction check: removing the literal response example was predicted to reduce a large reverse-order effect. Homosexuality changes from TV 0.833 to 0.083; this is supported but not causal proof because the samples are new.",
"3. Earliest unsupported link: no-example direct choice measures a stable personal attitude, rather than merely reducing one detected position effect.",
"4. Validity: define invalid as unsuitable for a direct coordinate or broad batch decision. P(invalid for that use) remains likely, about 0.65, due to persona-language and limited permutation coverage. The narrow prompt-anchor result is credible.",
"5. Highest-information clues: the Homosexuality TV fall, the matched modal sets, and the unchanged AI-persona reasoning.",
"6. Missing metrics: balanced non-reversal permutation check; independent-model replication; direct-choice construct calibration. These outrank a wider rated API batch for this method question.",
"7. Bugs requiring code changes: none established. Keep separate protocol/cache/ledger identities.",
"8. Misconceptions requiring reinterpretation: successful strict-schema choices and a passed reversal screen do not prove an attitude-like WVS construct.",
"9. What would change the verdict: a high TV under non-reversal permutations would show the literal-example explanation is insufficient; low TV without AI-persona reasoning would raise confidence in direct-choice interpretation.",
"10. Recommended sequence: pause the wider batch for parent review. If a next paid direct-choice test is approved, vary only permutation schedule while retaining this no-example wording; do not combine it with a persona rewrite.",
"",
"-- PI[gpt-5.6-terra]",
"",
])
OUT_MD.write_text("\n".join(lines))
print(f"wrote {OUT_CSV}: {len(rows)} item rows")
print(f"wrote {OUT_MD}: cost USD {cost:.7f}, both preregistered order screens={all_screen_pass}")
if __name__ == "__main__":
main()
-192
View File
@@ -1,192 +0,0 @@
#!/usr/bin/env python3
"""Preregister a response-wording-only direct-choice control for Gemini WVS items."""
from __future__ import annotations
import argparse
import json
from datetime import UTC, datetime
from decimal import Decimal
from pathlib import Path
from moralmaps.read_direct_choice import _plan, direct_choice_protocol_identity, read_items_direct_choice
from wvs_direct_choice_pilot import (
CATALOG_PATH,
CONCURRENCY,
GLOBAL_STOP_USD,
MAX_TOKENS,
MODEL,
PRIORITY_PHASE_STOP_USD,
REASONING,
REQUEST_TIMEOUT,
STRUCTURED_OUTPUT,
catalog_model,
selected_items,
usage_cost,
)
ITEM_IDS = ("Homosexuality", "Religion")
SAMPLES_PER_ORDER = 12
TEMPERATURE = 1.0
EXPECTED_INITIAL_CALLS = len(ITEM_IDS) * SAMPLES_PER_ORDER * 2
PILOT_CONSERVATIVE_RESERVE_USD = Decimal("1.50")
PREVIOUS_DIRECT_LEDGER = Path("slop/research/wvs/20260917_direct_choice/gemini37_direct_choice_requests.jsonl")
RECORDS_PATH = Path("slop/research/wvs/20260917_direct_choice/gemini37_direct_choice_anchor_requests.jsonl")
CACHE_PATH = Path("slop/research/wvs/20260917_direct_choice/gemini37_direct_choice_anchor_cache.json")
MANIFEST_PATH = Path("slop/research/wvs/20260917_direct_choice/gemini37_direct_choice_anchor_manifest.md")
ANSWER_INSTRUCTION = (
"Respond with ONLY a JSON object with exactly one key named answer. "
"Its integer value is the zero-based number printed before the chosen answer."
)
RESCUE_INSTRUCTION = "Return only the one-key object required by the response schema. No explanation."
def utc_date(timestamp: int) -> str:
return datetime.fromtimestamp(timestamp, UTC).date().isoformat()
def items() -> list[dict]:
all_items = {item["id"]: item for item in selected_items()}
assert set(ITEM_IDS) <= set(all_items)
return [all_items[item_id] for item_id in ITEM_IDS]
def protocol_id(pilot_items: list[dict]) -> str:
return direct_choice_protocol_identity(
MODEL, pilot_items, samples_per_order=SAMPLES_PER_ORDER, temperature=TEMPERATURE,
max_tokens=MAX_TOKENS, concurrency=CONCURRENCY, request_timeout=REQUEST_TIMEOUT,
reasoning=REASONING, structured_output=STRUCTURED_OUTPUT,
answer_instruction=ANSWER_INSTRUCTION, rescue_instruction=RESCUE_INSTRUCTION,
)
def preflight(pilot_items: list[dict], model: dict) -> dict:
assert EXPECTED_INITIAL_CALLS == 48
assert all(item["n"] >= 2 for item in pilot_items)
rated_cost = usage_cost(Path("slop/research/wvs/20260916_openrouter/wvs_iw_requests.jsonl"))
prior_direct_cost = usage_cost(PREVIOUS_DIRECT_LEDGER)
anchor_cost = usage_cost(RECORDS_PATH)
cumulative_cost = rated_cost + prior_direct_cost + anchor_cost
assert cumulative_cost + PILOT_CONSERVATIVE_RESERVE_USD < PRIORITY_PHASE_STOP_USD
assert cumulative_cost + PILOT_CONSERVATIVE_RESERVE_USD < GLOBAL_STOP_USD
output_price_per_million = Decimal(model["pricing"]["completion"]) * 1_000_000
initial_ceiling = output_price_per_million * EXPECTED_INITIAL_CALLS * MAX_TOKENS / 1_000_000
all_rescue_ceiling = initial_ceiling + output_price_per_million * EXPECTED_INITIAL_CALLS * max(MAX_TOKENS, 2048) / 1_000_000
return {
"rated_cost": rated_cost,
"prior_direct_cost": prior_direct_cost,
"anchor_cost": anchor_cost,
"cumulative_cost": cumulative_cost,
"output_price_per_million": output_price_per_million,
"initial_ceiling": initial_ceiling,
"all_rescue_ceiling": all_rescue_ceiling,
"protocol_id": protocol_id(pilot_items),
}
def write_manifest(pilot_items: list[dict], model: dict, checks: dict) -> None:
names = ", ".join(f"`{item['id']}`" for item in pilot_items)
lines = [
"# Gemini 3.7 Flash direct-choice response-wording control",
"",
"This separate construct pilot changes only the response wording from task 1628. It is not a map panel and cannot alter rated coordinates.",
"",
"## Exact identity",
"",
f"- model: `{MODEL}`; saved-catalog created UTC: {utc_date(model['created'])}",
f"- protocol ID: `{checks['protocol_id']}`",
f"- cache: `{CACHE_PATH}`",
f"- append-only request ledger: `{RECORDS_PATH}`",
f"- items: {names}",
f"- {SAMPLES_PER_ORDER} canonical + {SAMPLES_PER_ORDER} reversed orders per item, interleaved canonical then reversed within each repetition",
f"- expected initial calls and parsed choices: {EXPECTED_INITIAL_CALLS}",
f"- temperature: {TEMPERATURE}; max tokens: {MAX_TOKENS}; concurrency: {CONCURRENCY}; timeout: {REQUEST_TIMEOUT}s; reasoning: `{json.dumps(REASONING)}`",
"- strict schema: one required integer key named answer, bounded to the zero-based presented-option range",
"",
"## Only changed prompt text",
"",
"The question, answer text, order schedule, model, temperature, low reasoning, strict schema, token limit, timeout and rescue accounting match task 1628 for these two items. The initial response wording is now:",
"",
f"> {ANSWER_INSTRUCTION}",
"",
"The text contains no literal answer value or JSON example. If a rescue is needed, it says only:",
"",
f"> {RESCUE_INSTRUCTION}",
"",
"## Preregistered operational screen",
"",
"For each item, map selected presented indices back to canonical indices. Report canonical and reversed empirical distributions, order total variation, and each half's modal option set. Order TV <=0.25 plus matching modal set for both items is evidence against a large order effect, not proof that direct choice measures a stable personal attitude. Compare each result directly with task 1628's corresponding order-half table. An incomplete item or failed request exits nonzero and leaves no cache entry.",
"",
"## Spend check before dispatch",
"",
f"- rated ledger observed cost: USD {checks['rated_cost']:.10f}",
f"- task 1628 direct-choice observed cost: USD {checks['prior_direct_cost']:.10f}",
f"- this pilot prior observed cost: USD {checks['anchor_cost']:.10f}",
f"- cumulative observed cost: USD {checks['cumulative_cost']:.10f}",
f"- current output price: USD {checks['output_price_per_million']:g}/M",
f"- 48 initial 1024-token completion-only ceiling: USD {checks['initial_ceiling']:.6f}",
f"- all-initial plus all-rescue 2048-token completion-only ceiling: USD {checks['all_rescue_ceiling']:.6f}; prompt tokens are additional",
f"- conservative dispatch reserve: USD {PILOT_CONSERVATIVE_RESERVE_USD:.2f}, below USD {PRIORITY_PHASE_STOP_USD} priority and USD {GLOBAL_STOP_USD} global stops",
"- this manifest authorizes no wider model dispatch.",
"",
"-- PI[gpt-5.6-terra]",
"",
]
MANIFEST_PATH.parent.mkdir(parents=True, exist_ok=True)
MANIFEST_PATH.write_text("\n".join(lines))
def smoke(pilot_items: list[dict], checks: dict) -> None:
old_plan = _plan(pilot_items, SAMPLES_PER_ORDER)
new_plan = _plan(pilot_items, SAMPLES_PER_ORDER, ANSWER_INSTRUCTION)
assert len(old_plan) == len(new_plan) == 48
for old, new in zip(old_plan, new_plan):
assert old["item_id"] == new["item_id"]
assert old["sample"] == new["sample"]
assert old["order_name"] == new["order_name"]
assert old["presented_order"] == new["presented_order"]
old_prefix = old["prompt"].split("Respond with ONLY", 1)[0]
new_prefix = new["prompt"].split("Respond with ONLY", 1)[0]
assert old_prefix == new_prefix
assert '{"answer": 0}' not in new["prompt"]
assert "0 through" not in new["prompt"]
assert checks["protocol_id"] == protocol_id(pilot_items)
print("smoke: 2 items x 12 canonical x 12 reversed = 48 requests")
print("smoke: only response wording differs from task 1628; no literal answer value/example")
print(f"smoke: distinct protocol {checks['protocol_id']}")
def main() -> None:
parser = argparse.ArgumentParser()
parser.add_argument("--run", action="store_true", help="make the preregistered paid control calls")
parser.add_argument("--smoke", action="store_true", help="validate plan and manifest without API calls")
args = parser.parse_args()
pilot_items = items()
model = catalog_model()
checks = preflight(pilot_items, model)
if args.run:
registered = MANIFEST_PATH.read_text()
assert f"- protocol ID: `{checks['protocol_id']}`" in registered
else:
write_manifest(pilot_items, model, checks)
if args.smoke:
smoke(pilot_items, checks)
if not args.run:
return
result = read_items_direct_choice(
MODEL, pilot_items, samples_per_order=SAMPLES_PER_ORDER, temperature=TEMPERATURE,
max_tokens=MAX_TOKENS, concurrency=CONCURRENCY, request_timeout=REQUEST_TIMEOUT,
reasoning=REASONING, structured_output=STRUCTURED_OUTPUT,
records_path=RECORDS_PATH, cache_path=CACHE_PATH,
answer_instruction=ANSWER_INSTRUCTION, rescue_instruction=RESCUE_INSTRUCTION,
)
if result["cached"]:
print(f"anchor-wording cache hit: protocol={result['protocol_id'][:12]}")
return
if not result["complete"]:
raise RuntimeError(f"incomplete response-wording control: {result['run_id']}; raw evidence is {RECORDS_PATH}")
print(f"complete response-wording control: {result['run_id']}, protocol={result['protocol_id'][:12]}")
if __name__ == "__main__":
main()
-246
View File
@@ -1,246 +0,0 @@
#!/usr/bin/env python3
"""Audit the preregistered Gemini direct-choice construct pilot without API calls."""
from __future__ import annotations
import csv
import json
from collections import Counter
from decimal import Decimal
from pathlib import Path
import numpy as np
RUN_ID = "20260917T025121Z_aed0e29dd4ee"
PROTOCOL_ID = "aed0e29dd4ee423dbbfa0c294a84b2ae4bd6a36d6fc4bf569120034ac5b75090"
MODEL = "google/gemini-3.7-flash"
DIRECT_LEDGER = Path("slop/research/wvs/20260917_direct_choice/gemini37_direct_choice_requests.jsonl")
DIRECT_CACHE = Path("slop/research/wvs/20260917_direct_choice/gemini37_direct_choice_cache.json")
RATED_LEDGER = Path("slop/research/wvs/20260916_openrouter/wvs_iw_requests.jsonl")
RATED_RUN_ID = "20260916T172946Z_cd5db529649a"
OUT_CSV = Path("slop/audits/20260917_wvs_gemini37_direct_choice_task_1628_by_item.csv")
OUT_MD = Path("slop/audits/20260917_wvs_gemini37_direct_choice_task_1628.md")
def events(path: Path) -> list[dict]:
return [json.loads(line) for line in path.read_text().splitlines()]
def total_variation(left: np.ndarray, right: np.ndarray) -> float:
return float(0.5 * np.abs(left - right).sum())
def choice_distribution(rows: list[dict], n: int) -> np.ndarray:
counts = np.zeros(n)
for row in rows:
counts[row["canonical_choice"]] += 1
return counts / len(rows)
def dense_rated_distribution(rows: list[dict], n: int) -> np.ndarray:
samples = []
for row in rows:
ratings = json.loads(row["text"])
order = row["presented_order"]
presented = np.array([ratings[str(index)] for index in range(n)], dtype=float)
canonical = np.empty(n)
canonical[np.asarray(order)] = presented
samples.append(canonical / canonical.sum())
return np.mean(samples, axis=0)
def display(p: np.ndarray) -> str:
return "[" + ", ".join(f"{value:.3f}" for value in p) + "]"
def midpoint_mass(p: np.ndarray) -> str:
if len(p) == 2:
return "not defined for binary"
lower = len(p) // 2 - 1
upper = len(p) // 2
return f"{p[lower] + p[upper]:.3f} (options {lower}/{upper})"
def quote(message: dict) -> str:
reasoning = message.get("reasoning")
return (reasoning or message.get("content") or "").replace("\n", " ").strip()
def main() -> None:
direct = [event for event in events(DIRECT_LEDGER) if event.get("run_id") == RUN_ID]
rated = [event for event in events(RATED_LEDGER) if event.get("run_id") == RATED_RUN_ID]
assert direct and rated
counts = Counter(event["event"] for event in direct)
assert counts == Counter({"request_started": 96, "request_completed": 96, "answer_parsed": 96,
"item_result": 4, "run_started": 1, "run_finished": 1}), counts
parsed = [event for event in direct if event["event"] == "answer_parsed"]
assert len(parsed) == 96 and all(event["parsed"] for event in parsed)
for event in parsed:
decoded = json.loads(event["text"])
assert set(decoded) == {"answer"}
assert type(decoded["answer"]) is int
assert event["canonical_choice"] == event["presented_order"][decoded["answer"]]
assert not [event for event in direct if event["event"] == "request_failed"]
assert not [event for event in direct if event.get("phase") == "rescue"]
assert {event["protocol_id"] for event in direct} == {PROTOCOL_ID}
assert json.loads(DIRECT_CACHE.read_text())["completed"][PROTOCOL_ID]["complete"]
request_events = [event for event in direct if event["event"] == "request_completed"]
prompt_tokens = sum(event["usage"]["prompt_tokens"] for event in request_events)
completion_tokens = sum(event["usage"]["completion_tokens"] for event in request_events)
reasoning_tokens = sum(event["usage"]["completion_tokens_details"]["reasoning_tokens"] for event in request_events)
cost = sum(Decimal(str(event["usage"]["cost"])) for event in request_events)
refusals = sum(event["response"]["choices"][0]["message"].get("refusal") is not None for event in request_events)
rows = []
for item_id in ("Homosexuality", "Religion", "God", "Independence"):
direct_rows = [event for event in parsed if event["item_id"] == item_id]
n = len(direct_rows[0]["presented_order"])
canonical = [event for event in direct_rows if event["order_name"] == "canonical"]
reversed_order = [event for event in direct_rows if event["order_name"] == "reversed"]
assert len(canonical) == len(reversed_order) == 12
direct_p = choice_distribution(direct_rows, n)
canonical_p = choice_distribution(canonical, n)
reversed_p = choice_distribution(reversed_order, n)
rated_rows = [event for event in rated if event["event"] == "answer_parsed" and event["item_id"] == item_id]
assert len(rated_rows) == 12
rated_p = dense_rated_distribution(rated_rows, n)
canonical_argmax = np.flatnonzero(canonical_p == canonical_p.max()).tolist()
reversed_argmax = np.flatnonzero(reversed_p == reversed_p.max()).tolist()
rows.append({
"item_id": item_id, "n_options": n, "canonical_n": len(canonical), "reversed_n": len(reversed_order),
"canonical_distribution": display(canonical_p), "reversed_distribution": display(reversed_p),
"order_half_tv": total_variation(canonical_p, reversed_p),
"canonical_argmax": canonical_argmax, "reversed_argmax": reversed_argmax,
"argmax_agrees": canonical_argmax == reversed_argmax,
"direct_distribution": display(direct_p), "rated_distribution": display(rated_p),
"direct_vs_rated_tv": total_variation(direct_p, rated_p),
"rated_middle_mass": midpoint_mass(rated_p),
})
OUT_CSV.parent.mkdir(parents=True, exist_ok=True)
with OUT_CSV.open("w", newline="") as fh:
writer = csv.DictWriter(fh, fieldnames=list(rows[0]), lineterminator="\n")
writer.writeheader()
writer.writerows(rows)
first_homosexuality = next(event for event in request_events if event["item_id"] == "Homosexuality" and event["sample"] == 0)
first_god = next(event for event in request_events if event["item_id"] == "God" and event["sample"] == 0)
ledger_through = max(event["recorded_at_utc"] for event in direct)
by_item = {row["item_id"]: row for row in rows}
lines = [
"# Audit: Gemini 3.7 Flash direct-choice WVS pilot, task 1628",
"",
"- target: 96-call direct-choice construct pilot, not a map panel",
f"- Pueue: task 1628, API queue, success, 2026-09-17 10:51:14-10:56:58 +08:00",
"- label: `why: test direct choice against flat dense ratings; resolve: audit interleaved order agreement and distribution difference before more models`",
f"- run: `{RUN_ID}`, protocol: `{PROTOCOL_ID}`",
f"- primary ledger: `{DIRECT_LEDGER}` through {ledger_through}",
f"- direct cache: `{DIRECT_CACHE}`",
f"- comparison rated run: `{RATED_RUN_ID}` in `{RATED_LEDGER}`",
f"- per-item table: `{OUT_CSV}`",
"",
"## Stage table",
"",
"| stage | expected | observed | expected? | clues | missing metric | consequence |",
"|---|---|---|---|---|---|---|",
"| request plan | 96 calls, 12 canonical and 12 reversed per item, interleaved | 96 starts and 96 completions; every item has 12 valid per order | yes | ledger event counts; cache item results | provider-side request ordering timestamp | order halves are available for comparison |",
"| strict parse | 96 schema-valid single choices | 96/96 `answer_parsed=true`; 0 failed phases | yes | ledger | provider schema conformance independent of parser | mechanics did not drop samples |",
"| rescue/refusal | zero or recorded | 0 rescue phases; 0 `message.refusal` | yes | ledger request records | semantic non-answer count beyond refusal field | parse success does not establish personal-attitude semantics |",
"| accounting | provider usage retained | prompt 15,445; completion 12,848; reasoning 12,272; observed cost USD 0.0643245 | yes | all 96 completed usage records | external billing export | below registered reserve, exact provider field retained |",
"| order-half control | canonical and reversed distributions agree if position does not dominate | Homosexuality TV=0.833 and different argmax; other three TV <=0.083 with matching argmax | no | per-item table | repeated independent run | direct-choice Homosexuality aggregate is position-confounded |",
"| canonical decoder | reverse order maps presented index back to canonical index | independently re-decoded all 96 raw JSON choices and orders with exact agreement | yes | audit assertion | a second implementation or repetition | mapping bug is less likely than an order effect |",
"| construct comparison | quantify difference from dense-rated readout | direct-vs-rated TV: Homosexuality 0.694, Religion 0.564, God 0.500, Independence 0.220 | yes, descriptive only | per-item table | baseline direct choice from another model | no coordinate replacement or wider batch decision |",
"| persistence | complete result reusable only if all samples valid | cache has one complete protocol entry and ledger has 294 events | yes | cache + ledger | cache replay, not needed for this decision | source evidence retained |",
"",
"## Chronological evidence",
"",
"The task's own full Pueue output is one completion line, so the append-only request ledger is the primary evidence. It contains 96 initial `request_started`, 96 initial `request_completed`, 96 parsed choices, four item results, and one run boundary each. The source code writes a cache entry only after complete results; the cache records `complete: true` for this protocol.",
"",
"The direct prompt is recoverable per request. Homosexuality sample 0 used the exact instruction: `Think briefly about which ONE answer best reflects your own view. Do not analyze the survey design. Answer immediately.` Its saved provider reasoning says:",
"",
f"> {quote(first_homosexuality['response']['choices'][0]['message'])}",
"",
"epistemic context: provider reasoning saved in this pilot's first completed request, not a human self-report.",
"",
"God sample 0 shows the same unresolved persona issue despite schema-valid JSON:",
"",
f"> {quote(first_god['response']['choices'][0]['message'])}",
"",
"epistemic context: provider reasoning saved in this pilot's first completed request, not a human self-report.",
"",
"## Preregistered order-half and construct results",
"",
"| item | canonical p | reversed p | order TV | argmax agrees | direct p | dense-rated p | direct vs rated TV | dense rated central mass |",
"|---|---|---|---:|---|---|---|---:|---|",
]
for row in rows:
lines.append(
f"| {row['item_id']} | {row['canonical_distribution']} | {row['reversed_distribution']} | "
f"{row['order_half_tv']:.3f} | {row['argmax_agrees']} ({row['canonical_argmax']} vs {row['reversed_argmax']}) | "
f"{row['direct_distribution']} | {row['rated_distribution']} | {row['direct_vs_rated_tv']:.3f} | {row['rated_middle_mass']} |"
)
lines.extend([
"",
"For even non-binary cards, central mass is the dense-rated mass in the two middle categories. For binary cards it is not defined. An all-equal dense rating normalizes to a uniform categorical, not to one middle answer; this is why the table reports full distributions and total variation rather than calling all flat dense replies a middle choice.",
"",
"## Hypotheses",
"",
"### H1 [method | Highly Likely | 80%]",
"",
"- Mechanism: Homosexuality direct choices are sensitive to the presented order, so its pooled direct distribution is not a stable construct readout.",
f"- Evidence: canonical p is {by_item['Homosexuality']['canonical_distribution']} while reversed p is {by_item['Homosexuality']['reversed_distribution']}; their TV is {by_item['Homosexuality']['order_half_tv']:.3f} and argmax changes from {by_item['Homosexuality']['canonical_argmax']} to {by_item['Homosexuality']['reversed_argmax']}.",
"- Contrary evidence: Religion, God, and Independence have matching order-half argmaxes and TV at most 0.083.",
"- Discriminating test: a second 24-per-item run with a balanced random permutation schedule. Low TV again would weaken this explanation; a large TV tied to option position would strengthen it.",
"- Fix/action: do not use the pooled Homosexuality direct distribution to replace rated coordinates; review a redesigned order control before more paid panels.",
"- Interpretability: partial, mechanics and the observed order effect are interpretable; Homosexuality attitude distribution is not.",
"",
"### H2 [measurement | Likely | 65%]",
"",
"- Mechanism: Gemini may answer the question as an AI without personal beliefs rather than supply an attitude-like direct choice.",
f"- Evidence: God sample 0 reasoning says `{quote(first_god['response']['choices'][0]['message'])}`.",
"- Contrary evidence: every final response is a valid selected answer, and three items have stable order-half argmaxes.",
"- Discriminating test: compare an explicitly role-conditioned construct with this prompt while retaining the same order randomization. A changed distribution with lower persona-language would support this explanation.",
"- Fix/action: retain raw reasoning and interpret current results as model behavior under this prompt, not personal survey attitudes.",
"- Interpretability: partial.",
"",
"### H3 [measurement | Likely | 60%]",
"",
"- Mechanism: forced one-answer choice and dense all-option rating are different elicitation constructs, even where order halves agree.",
f"- Evidence: Religion direct-vs-rated TV is {by_item['Religion']['direct_vs_rated_tv']:.3f}, God is {by_item['God']['direct_vs_rated_tv']:.3f}, and Independence is {by_item['Independence']['direct_vs_rated_tv']:.3f}.",
"- Contrary evidence: this is one model and four items; Gemini's persona and order effects can also cause the difference.",
"- Discriminating test: repair the order control, then compare one or more lower-flat models under the same direct-choice protocol.",
"- Fix/action: describe the distributions as a construct comparison, not evidence that the published rated map is wrong.",
"- Interpretability: yes for difference under these prompts, no for a general claim about models or WVS coordinates.",
"",
"### H4 [bug | Unlikely | 20%]",
"",
"- Mechanism: a mapping error could create the apparent reversed-order effect.",
"- Evidence: the audit independently re-decodes all 96 raw JSON responses, validates the one-key schema, and maps `answer` through each stored `presented_order`; every reconstructed canonical choice equals the ledger field.",
"- Contrary evidence: the audit is a second decoder, but it is not a second experimental run.",
"- Discriminating test: repeat the balanced-permutation control after review. A large position-linked shift despite a new run would reject the mapping-bug explanation.",
"- Fix/action: no mapping change is justified from this evidence.",
"- Interpretability: yes for the observed canonical mapping.",
"",
"## Decision",
"",
"1. Resolve-condition verdict: **not met**. The task asked to resolve whether direct choice differed from flat dense ratings after auditing interleaved order agreement. The comparison exists, but Homosexuality order TV=0.833 with an argmax reversal, so the focal direct distribution is confounded by presentation order.",
"2. Prediction check: recorded design predicted 12 valid choices per order and an auditable order-half comparison. Completeness is supported; order stability is contradicted for Homosexuality and supported for the other three items.",
"3. Earliest unsupported link: a direct one-answer prompt measures a stable attitude-like choice distribution. The order-half control fails before any coordinate interpretation.",
"4. Validity: define invalid as unsuitable for replacing rated coordinates or authorizing broad panel changes. P(invalid for that use) is highly likely, about 0.80. The result is a credible negative control for order stability, not an invalid ledger or billing record.",
"5. Highest-information clues: (a) Homosexuality order TV 0.833, because it directly falsifies order invariance; (b) all 96 choices parsed with zero failures, separating mechanics from construct quality; (c) saved AI-persona reasoning, because it raises a semantic interpretation alternative.",
"6. Missing metrics: independent canonical-choice reconstruction first; then a balanced-permutation repetition; then another model under the repaired protocol. These have higher information value than another full map panel.",
"7. Bugs requiring code changes: none established. The next pilot should improve design, not silently change the current pilot.",
"8. Misconceptions requiring reinterpretation: a schema-valid selected option is not evidence that the model expressed a personal WVS attitude. A flat dense rating is uniform after normalization, not a direct middle choice.",
"9. What would change the verdict: low order-half TV under a balanced permutation schedule and no persona-language in saved reasoning would make direct-choice distributions more interpretable.",
"10. Recommended sequence: preserve this pilot and pause the wider priority batch. Parent review should decide whether a balanced-permutation direct-choice replication is worth its bounded cost; do not combine a revised prompt and changed permutation schedule in one test.",
"",
"-- PI[gpt-5.6-terra]",
"",
])
OUT_MD.write_text("\n".join(lines))
print(f"wrote {OUT_CSV}: {len(rows)} item rows")
print(f"wrote {OUT_MD}: cost USD {cost:.7f}, 96/96 parsed, Homosexuality order TV {by_item['Homosexuality']['order_half_tv']:.3f}")
if __name__ == "__main__":
main()
@@ -1,143 +0,0 @@
#!/usr/bin/env python3
"""Calibrate direct-choice half and direction total variation under exchangeability."""
from __future__ import annotations
import csv
import json
from collections import Counter
from pathlib import Path
import numpy as np
RUN_ID = "20260917T033051Z_3e9c3d54727e"
PROTOCOL_ID = "3e9c3d54727e46c92af49321604778d9bae85bd83a22e23e1793cbefd06f29e3"
LEDGER = Path("slop/research/wvs/20260917_direct_choice/gemini37_direct_choice_production_requests.jsonl")
SEED = 20260917
N_PERMUTATIONS = 100_000
OUT_CSV = Path("slop/audits/20260917_wvs_direct_choice_exchangeability_calibration.csv")
OUT_MD = Path("slop/audits/20260917_wvs_direct_choice_exchangeability_calibration.md")
def events(path: Path) -> list[dict]:
return [json.loads(line) for line in path.read_text().splitlines()]
def tv_from_slots(values: np.ndarray, slots_a: np.ndarray, slots_b: np.ndarray, n: int) -> np.ndarray:
choices = np.arange(n)
p_a = (values[:, slots_a, None] == choices).mean(axis=1)
p_b = (values[:, slots_b, None] == choices).mean(axis=1)
return 0.5 * np.abs(p_a - p_b).sum(axis=1)
def holm_adjust(p_values: list[float]) -> list[float]:
adjusted = [0.0] * len(p_values)
running = 0.0
for rank, index in enumerate(sorted(range(len(p_values)), key=p_values.__getitem__)):
running = max(running, min(1.0, p_values[index] * (len(p_values) - rank)))
adjusted[index] = running
return adjusted
def main() -> None:
run_events = [event for event in events(LEDGER) if event.get("run_id") == RUN_ID]
assert {event.get("protocol_id") for event in run_events} == {PROTOCOL_ID}
parsed = [event for event in run_events if event["event"] == "answer_parsed"]
assert len(parsed) == 240 and all(event["parsed"] for event in parsed)
by_item: dict[str, list[dict]] = {}
for event in parsed:
by_item.setdefault(event["item_id"], []).append(event)
rng = np.random.default_rng(SEED)
max_tv = np.zeros(N_PERMUTATIONS)
records = []
for item_id, item_events in by_item.items():
item_events = sorted(item_events, key=lambda event: event["sample"])
assert [event["sample"] for event in item_events] == list(range(20))
n = len(item_events[0]["presented_order"])
values = np.array([event["canonical_choice"] for event in item_events], dtype=int)
schedule_a = np.array([event["sample"] < 10 for event in item_events])
direction_a = np.array([event["order_name"] == "canonical" for event in item_events])
schedule_observed = float(tv_from_slots(values[None, :], schedule_a, ~schedule_a, n)[0])
direction_observed = float(tv_from_slots(values[None, :], direction_a, ~direction_a, n)[0])
permutations = rng.permuted(np.broadcast_to(values, (N_PERMUTATIONS, len(values))), axis=1)
schedule_null = tv_from_slots(permutations, schedule_a, ~schedule_a, n)
direction_null = tv_from_slots(permutations, direction_a, ~direction_a, n)
max_tv = np.maximum(max_tv, np.maximum(schedule_null, direction_null))
same_partition = bool(np.array_equal(schedule_a, direction_a))
for label, observed, null in (
("schedule_half", schedule_observed, schedule_null),
("canonical_vs_reversed", direction_observed, direction_null),
):
records.append({
"item_id": item_id,
"n_options": n,
"comparison": label,
"group_sizes": f"{int((schedule_a if label == 'schedule_half' else direction_a).sum())}/{int((~(schedule_a if label == 'schedule_half' else direction_a)).sum())}",
"same_partition_as_other_comparison": same_partition,
"observed_tv": observed,
"null_mean_tv": float(null.mean()),
"null_p95_tv": float(np.quantile(null, 0.95)),
"null_p99_tv": float(np.quantile(null, 0.99)),
"randomization_p": float((np.count_nonzero(null >= observed) + 1) / (N_PERMUTATIONS + 1)),
})
max_adjusted = [float((np.count_nonzero(max_tv >= row["observed_tv"]) + 1) / (N_PERMUTATIONS + 1)) for row in records]
holm_adjusted = holm_adjust([row["randomization_p"] for row in records])
for row, holm, max_t in zip(records, holm_adjusted, max_adjusted):
row["holm_adjusted_p_24"] = holm
row["maxT_adjusted_p_24"] = max_t
records.sort(key=lambda row: (row["item_id"], row["comparison"]))
OUT_CSV.parent.mkdir(parents=True, exist_ok=True)
with OUT_CSV.open("w", newline="") as handle:
writer = csv.DictWriter(handle, fieldnames=list(records[0]), lineterminator="\n")
writer.writeheader()
writer.writerows(records)
through = max(event["recorded_at_utc"] for event in run_events)
lines = [
"# Fixed-seed direct-choice exchangeability calibration",
"",
f"- target run: `{RUN_ID}`, protocol `{PROTOCOL_ID}`",
f"- source ledger: `{LEDGER}` through {through}",
f"- fixed NumPy PCG64 seed: {SEED}; {N_PERMUTATIONS:,} permutations per item",
f"- machine table: `{OUT_CSV}`",
"",
"## Null and scope",
"",
"For each item, the observed 20 canonical choices are held fixed and randomly reassigned to its actual 20 schedule slots. This conditional exchangeability null tests whether the observed split TV is unusual given that item's own choice multiset. It does not test whether a choice distribution is human-like, whether samples are independent, or whether the prompt measures a WVS coordinate.",
"",
"The two reports are first-ten versus last-ten schedule halves and canonical versus reversed direction slots. For the two 10-option items the present schedule makes these partitions identical, so they are reported twice for transparency but do not distinguish direction from request time. For n=3/n=4, unequal direction counts are registered design constraints.",
"",
"## Results",
"",
"Randomization p is one-sided for TV at least the observed value. Holm and maxT values adjust across all 24 listed reports. They are calibration summaries, not validity thresholds or a claim of statistical significance.",
"",
"| item | n | comparison | groups | observed TV | null mean | null p95 | randomization p | Holm p (24) | maxT p (24) | note |",
"|---|---:|---|---|---:|---:|---:|---:|---:|---:|---|",
]
for row in records:
note = "same partition as the other report" if row["same_partition_as_other_comparison"] else "distinct partition"
lines.append(
f"| {row['item_id']} | {row['n_options']} | {row['comparison']} | {row['group_sizes']} | "
f"{row['observed_tv']:.3f} | {row['null_mean_tv']:.3f} | {row['null_p95_tv']:.3f} | "
f"{row['randomization_p']:.4f} | {row['holm_adjusted_p_24']:.4f} | {row['maxT_adjusted_p_24']:.4f} | {note} |"
)
lines.extend([
"",
"## Interpretation limits",
"",
"With only 20 choices/item, discrete distributions and concentrated responses make this calibration low power for moderate instability. A high adjusted p can arise because the observed split is ordinary under the conditional null, because the item has little response variation, or because 20 samples cannot resolve the effect. A low p would only identify a split unusual under this narrow exchangeability null. Neither outcome is a hard construct-validity cutoff.",
"",
"The calibrated values therefore refine the prior descriptive half TVs. They do not authorize a direct-choice map, a protocol merge, or additional paid models. The next decision remains parent review of whether a differently interleaved replication is worth its cost.",
"",
"-- PI[gpt-5.6-terra]",
"",
])
OUT_MD.write_text("\n".join(lines))
print(f"wrote {OUT_CSV}: {len(records)} exchangeability reports")
print(f"wrote {OUT_MD}: seed={SEED}, permutations={N_PERMUTATIONS}")
if __name__ == "__main__":
main()
-193
View File
@@ -1,193 +0,0 @@
#!/usr/bin/env python3
"""Preregister and run one direct-choice WVS construct pilot, separate from rated map panels."""
from __future__ import annotations
import argparse
import json
from datetime import UTC, datetime
from decimal import Decimal
from pathlib import Path
from moralmaps.read_direct_choice import direct_choice_protocol_identity, read_items_direct_choice
from wvs_map import X_AXIS, Y_AXIS, load_wvs_all, resolve_items
MODEL = "google/gemini-3.7-flash"
ITEM_IDS = ("Homosexuality", "Religion", "God", "Independence")
SAMPLES_PER_ORDER = 12
TEMPERATURE = 1.0
MAX_TOKENS = 1024
CONCURRENCY = 1
REQUEST_TIMEOUT = 90.0
REASONING = {"effort": "low"}
STRUCTURED_OUTPUT = True
EXPECTED_INITIAL_CALLS = len(ITEM_IDS) * SAMPLES_PER_ORDER * 2
GLOBAL_STOP_USD = Decimal("80")
PRIORITY_PHASE_STOP_USD = Decimal("35")
PILOT_CONSERVATIVE_RESERVE_USD = Decimal("2.00")
CATALOG_PATH = Path("slop/research/wvs/20260917_openrouter_models.json")
RATED_LEDGER_PATH = Path("slop/research/wvs/20260916_openrouter/wvs_iw_requests.jsonl")
RECORDS_PATH = Path("slop/research/wvs/20260917_direct_choice/gemini37_direct_choice_requests.jsonl")
CACHE_PATH = Path("slop/research/wvs/20260917_direct_choice/gemini37_direct_choice_cache.json")
MANIFEST_PATH = Path("slop/research/wvs/20260917_direct_choice/gemini37_direct_choice_manifest.md")
def utc_date(timestamp: int) -> str:
return datetime.fromtimestamp(timestamp, UTC).date().isoformat()
def usage_cost(path: Path) -> Decimal:
if not path.exists():
return Decimal()
total = Decimal()
for line in path.read_text().splitlines():
event = json.loads(line)
if event["event"] == "request_completed" and event.get("usage", {}).get("cost") is not None:
total += Decimal(str(event["usage"]["cost"]))
return total
def selected_items() -> list[dict]:
resolved = resolve_items(load_wvs_all())
selected = {}
for axis in (X_AXIS, Y_AXIS):
for item in resolved[axis]:
if item["suffix"] in ITEM_IDS:
selected[item["suffix"]] = {
"id": item["suffix"], "question": item["rec"]["q"],
"options": item["rec"]["opts"], "n": item["n"], "axis": axis,
}
assert tuple(selected) == ITEM_IDS, f"WVS item identity drift: {tuple(selected)}"
return [selected[item_id] for item_id in ITEM_IDS]
def catalog_model() -> dict:
catalog = {model["id"]: model for model in json.loads(CATALOG_PATH.read_text())["data"]}
model = catalog[MODEL]
assert "structured_outputs" in model["supported_parameters"]
assert model["reasoning"]["mandatory"]
assert "low" in model["reasoning"]["supported_efforts"]
return model
def protocol_id(items: list[dict]) -> str:
return direct_choice_protocol_identity(
MODEL, items, samples_per_order=SAMPLES_PER_ORDER, temperature=TEMPERATURE,
max_tokens=MAX_TOKENS, concurrency=CONCURRENCY, request_timeout=REQUEST_TIMEOUT,
reasoning=REASONING, structured_output=STRUCTURED_OUTPUT,
)
def preflight(items: list[dict], model: dict) -> dict:
assert EXPECTED_INITIAL_CALLS == 96
assert all(item["n"] >= 2 for item in items)
rated_cost = usage_cost(RATED_LEDGER_PATH)
direct_cost = usage_cost(RECORDS_PATH)
cumulative_cost = rated_cost + direct_cost
assert cumulative_cost + PILOT_CONSERVATIVE_RESERVE_USD < PRIORITY_PHASE_STOP_USD
assert cumulative_cost + PILOT_CONSERVATIVE_RESERVE_USD < GLOBAL_STOP_USD
output_price_per_million = Decimal(model["pricing"]["completion"]) * 1_000_000
initial_completion_ceiling = output_price_per_million * EXPECTED_INITIAL_CALLS * MAX_TOKENS / 1_000_000
rescue_completion_ceiling = output_price_per_million * EXPECTED_INITIAL_CALLS * max(MAX_TOKENS, 2048) / 1_000_000
return {
"rated_ledger_cost": rated_cost,
"direct_choice_ledger_cost": direct_cost,
"cumulative_cost": cumulative_cost,
"output_price_per_million": output_price_per_million,
"initial_completion_ceiling": initial_completion_ceiling,
"all_rescue_completion_ceiling": initial_completion_ceiling + rescue_completion_ceiling,
"protocol_id": protocol_id(items),
}
def write_manifest(items: list[dict], model: dict, checks: dict) -> None:
option_schema = '{"answer": integer from 0 through n-1}'
item_names = ", ".join(f"`{item['id']}`" for item in items)
lines = [
"# Gemini 3.7 Flash direct-choice WVS construct pilot",
"",
"This preregistered pilot tests a construct difference. It is not a WVS map panel and cannot alter rated coordinates.",
"",
"## Exact identity",
"",
f"- model: `{MODEL}`",
f"- saved-catalog created UTC: {utc_date(model['created'])}",
f"- protocol ID: `{checks['protocol_id']}`",
f"- cache: `{CACHE_PATH}`",
f"- append-only request ledger: `{RECORDS_PATH}`",
f"- temperature: {TEMPERATURE}; max tokens: {MAX_TOKENS}; concurrency: {CONCURRENCY}; timeout: {REQUEST_TIMEOUT}s",
f"- reasoning: `{json.dumps(REASONING, sort_keys=True)}`; catalog confirms mandatory reasoning with supported `low` effort",
f"- strict response schema: `{option_schema}`",
"",
"## Design",
"",
f"- items: {item_names}",
f"- {SAMPLES_PER_ORDER} canonical + {SAMPLES_PER_ORDER} reversed presented-option orders per item, interleaved canonical then reversed within each repetition",
f"- expected initial calls: {EXPECTED_INITIAL_CALLS}; expected parsed choices: {EXPECTED_INITIAL_CALLS}",
"- exact instruction: `Think briefly about which ONE answer best reflects your own view. Do not analyze the survey design. Answer immediately.`",
"- final response is schema-only. Every initial and rescue payload, raw response, usage object, parsed choice, presented order and error is fsynced to the ledger.",
"- an incomplete item or any failed request makes `--run` exit nonzero and prevents a cache entry.",
"",
"## Preregistered comparison",
"",
"For each item, map selected presented indices back to canonical option indices. Report the canonical and reversed empirical categorical distributions, their total-variation distance, and the canonical-versus-reversed argmax agreement. Compare the direct-choice aggregate distribution with Gemini's existing dense-rated distribution and report total variation plus the dense-rated midpoint mass. These are construct diagnostics, not a coordinate replacement or a capability claim.",
"",
"## Spend checks before dispatch",
"",
f"- rated-ledger observed cost: USD {checks['rated_ledger_cost']:.10f}",
f"- direct-choice-ledger observed cost: USD {checks['direct_choice_ledger_cost']:.10f}",
f"- cumulative observed cost: USD {checks['cumulative_cost']:.10f}",
f"- current output price: USD {checks['output_price_per_million']:g}/M tokens",
f"- 96 initial 1024-token completion-only ceiling: USD {checks['initial_completion_ceiling']:.6f}",
f"- all-initial plus all-rescue 2048-token completion-only ceiling: USD {checks['all_rescue_completion_ceiling']:.6f}; prompt tokens are additional",
f"- pre-dispatch conservative reserve: USD {PILOT_CONSERVATIVE_RESERVE_USD:.2f}; it remains below the USD {PRIORITY_PHASE_STOP_USD} priority-phase and USD {GLOBAL_STOP_USD} global stops",
"- no wider priority model dispatch is authorized by this manifest.",
"",
"-- PI[gpt-5.6-terra]",
"",
]
MANIFEST_PATH.parent.mkdir(parents=True, exist_ok=True)
MANIFEST_PATH.write_text("\n".join(lines))
def smoke(items: list[dict], checks: dict) -> None:
assert len(items) == 4
assert len({item["id"] for item in items}) == 4
assert checks["protocol_id"] == protocol_id(items)
assert all(item["n"] >= 2 for item in items)
print(f"smoke: 4 items x 12 canonical x 12 reversed = {EXPECTED_INITIAL_CALLS} requests")
print(f"smoke: distinct direct-choice protocol {checks['protocol_id']}")
def main() -> None:
parser = argparse.ArgumentParser()
parser.add_argument("--run", action="store_true", help="make the preregistered paid pilot calls")
parser.add_argument("--smoke", action="store_true", help="validate the manifest and request plan without API calls")
args = parser.parse_args()
items = selected_items()
model = catalog_model()
checks = preflight(items, model)
if args.run:
registered = MANIFEST_PATH.read_text()
assert f"- protocol ID: `{checks['protocol_id']}`" in registered
else:
write_manifest(items, model, checks)
if args.smoke:
smoke(items, checks)
if not args.run:
return
result = read_items_direct_choice(
MODEL, items, samples_per_order=SAMPLES_PER_ORDER, temperature=TEMPERATURE,
max_tokens=MAX_TOKENS, concurrency=CONCURRENCY, request_timeout=REQUEST_TIMEOUT,
reasoning=REASONING, structured_output=STRUCTURED_OUTPUT,
records_path=RECORDS_PATH, cache_path=CACHE_PATH,
)
if result["cached"]:
print(f"direct-choice cache hit: protocol={result['protocol_id'][:12]}")
return
if not result["complete"]:
raise RuntimeError(f"incomplete direct-choice pilot: {result['run_id']}; raw evidence is {RECORDS_PATH}")
print(f"complete direct-choice pilot: {result['run_id']}, protocol={result['protocol_id'][:12]}")
if __name__ == "__main__":
main()
-279
View File
@@ -1,279 +0,0 @@
#!/usr/bin/env python3
"""Prepare or run one preregistered direct-choice WVS priority panel."""
from __future__ import annotations
import argparse
import hashlib
import json
from datetime import UTC, datetime
from decimal import Decimal
from pathlib import Path
from moralmaps.read_direct_choice import direct_choice_protocol_identity, read_items_direct_choice
from wvs_direct_choice_pilot import usage_cost
from wvs_direct_choice_production_pilot import (
ANSWER_INSTRUCTION,
CONCURRENCY,
MAX_TOKENS,
PROMPT_INSTRUCTION,
REQUEST_TIMEOUT,
RESCUE_INSTRUCTION,
TEMPERATURE,
TOTAL_SAMPLES_PER_ITEM,
items,
schedule,
)
CATALOG_PATH = Path("slop/research/wvs/20260917_openrouter_models.json")
MANIFEST_PATH = Path("slop/research/wvs/20260917_direct_choice/priority_direct_choice_manifest.md")
MANIFEST_JSON_PATH = Path("slop/research/wvs/20260917_direct_choice/priority_direct_choice_manifest.json")
DIRECT_DIR = Path("slop/research/wvs/20260917_direct_choice/priority")
RATED_LEDGER = Path("slop/research/wvs/20260916_openrouter/wvs_iw_requests.jsonl")
PHASE_STOP_USD = Decimal("35")
GLOBAL_STOP_USD = Decimal("80")
PROMPT_TOKEN_RESERVE = Decimal("512")
GROUPS = {
"Grok": ("x-ai/grok-4.6", "x-ai/grok-4.5"),
"OpenAI": (
"openai/gpt-5.6-luna", "openai/gpt-5.6-terra", "openai/gpt-5.4-nano",
"openai/gpt-5.4-mini", "openai/gpt-5.2-chat", "openai/gpt-5.2", "openai/gpt-5.1",
"openai/gpt-5", "openai/gpt-5-mini", "openai/gpt-oss-120b", "openai/gpt-oss-20b",
"openai/o3", "openai/o4-mini", "openai/gpt-4.1", "openai/gpt-4.1-mini",
"openai/gpt-4.1-nano", "openai/o3-mini",
"openai/gpt-4o-2024-11-20", "openai/gpt-4o-2024-08-06", "openai/gpt-4o-mini",
"openai/gpt-4o", "openai/gpt-3.5-turbo-0613", "openai/gpt-3.5-turbo-instruct",
"openai/gpt-3.5-turbo-16k", "openai/gpt-3.5-turbo",
),
"Google": (
"google/gemini-3.8-flash", "google/gemini-3.6-flash", "google/gemini-3.5-flash-lite",
"google/gemini-3.5-flash", "google/gemini-3.1-flash-lite",
"google/gemini-3.1-flash-lite-preview", "google/gemini-3-flash-preview",
"google/gemini-2.5-flash-lite", "google/gemini-2.5-flash",
),
"Muse": ("meta/muse-spark-1.2", "meta/muse-spark-1.1"),
}
def utc_date(timestamp: int) -> str:
return datetime.fromtimestamp(timestamp, UTC).date().isoformat()
def rate_per_million(model: dict, field: str) -> Decimal:
return Decimal(model["pricing"][field]) * 1_000_000
def reasoning_setting(model: dict) -> tuple[dict | None, str]:
metadata = model.get("reasoning")
if metadata is None:
return None, "not advertised"
efforts = set(metadata.get("supported_efforts", []))
optional = not metadata.get("mandatory")
if optional and "none" in efforts:
return {"effort": "none"}, "disabled (optional, none advertised)"
if optional and not efforts and "reasoning" in model["supported_parameters"]:
return {"enabled": False}, "unverified compatibility probe (optional reasoning parameter; no efforts advertised)"
if "minimal" in efforts:
return {"effort": "minimal"}, "minimal"
if "low" in efforts:
return {"effort": "low"}, "low"
if optional and not efforts:
return None, "not advertised (optional; omitted)"
raise ValueError(f"no allowed minimal/low reasoning setting for {model['id']}: {metadata}")
def catalog() -> dict[str, dict]:
return {model["id"]: model for model in json.loads(CATALOG_PATH.read_text())["data"]}
def cache_paths(model_id: str) -> tuple[Path, Path]:
stem = model_id.replace("/", "__")
return DIRECT_DIR / f"{stem}_requests.jsonl", DIRECT_DIR / f"{stem}_cache.json"
def observed_cost() -> Decimal:
paths = [RATED_LEDGER, *Path("slop/research/wvs/20260917_direct_choice").glob("**/*requests.jsonl")]
return sum((usage_cost(path) for path in paths), Decimal())
def entry(model: dict, pilot_items: list[dict], request_plan: list[dict]) -> dict:
reasoning, reasoning_label = reasoning_setting(model)
protocol = direct_choice_protocol_identity(
model["id"], pilot_items, samples_per_order=10, temperature=TEMPERATURE,
max_tokens=MAX_TOKENS, concurrency=CONCURRENCY, request_timeout=REQUEST_TIMEOUT,
reasoning=reasoning, structured_output=True, prompt_instruction=PROMPT_INSTRUCTION,
answer_instruction=ANSWER_INSTRUCTION, rescue_instruction=RESCUE_INSTRUCTION,
plan_override=request_plan, fail_fast_first_request=True,
)
input_rate = rate_per_million(model, "prompt")
output_rate = rate_per_million(model, "completion")
completion_ceiling = output_rate * len(request_plan) * MAX_TOKENS / 1_000_000
conservative_reserve = (
len(request_plan)
* (PROMPT_TOKEN_RESERVE * 2 * input_rate + (MAX_TOKENS + 2048) * output_rate)
/ 1_000_000
)
ledger, cache = cache_paths(model["id"])
return {
"id": model["id"], "created_utc": utc_date(model["created"]),
"input_usd_per_million": str(input_rate), "output_usd_per_million": str(output_rate),
"reasoning": reasoning, "reasoning_label": reasoning_label,
"structured_output": "structured_outputs" in model["supported_parameters"],
"protocol_id": protocol, "initial_calls": len(request_plan),
"completion_only_ceiling_usd": str(completion_ceiling),
"conservative_reserve_usd": str(conservative_reserve),
"records_path": str(ledger), "cache_path": str(cache),
}
def entries() -> list[dict]:
models = catalog()
pilot_items = items()
request_plan = schedule(pilot_items)
assert len(request_plan) == 240
output = []
for group, ids in GROUPS.items():
for model_id in ids:
model = models[model_id]
assert "structured_outputs" in model["supported_parameters"]
assert rate_per_million(model, "completion") <= Decimal("15")
output.append({"group": group, **entry(model, pilot_items, request_plan)})
assert len({row["id"] for row in output}) == len(output)
assert len({row["protocol_id"] for row in output}) == len(output)
return output
def write_manifest(priority: list[dict]) -> None:
catalog_sha = hashlib.sha256(CATALOG_PATH.read_bytes()).hexdigest()
current_cost = observed_cost()
manifest = {
"schema": 1,
"catalog_path": str(CATALOG_PATH),
"catalog_sha256": catalog_sha,
"design": {
"construct": "direct_choice", "items": 12, "samples_per_item": TOTAL_SAMPLES_PER_ITEM,
"initial_calls_per_model": 240, "schedule": "balanced_cyclic_rotations",
"prompt_instruction": PROMPT_INSTRUCTION, "answer_instruction": ANSWER_INSTRUCTION,
"rescue_instruction": RESCUE_INSTRUCTION, "strict_structured_output": True,
"fail_fast_first_request": True,
},
"stop_usd": {"priority_phase": str(PHASE_STOP_USD), "global": str(GLOBAL_STOP_USD)},
"current_observed_cost_usd": str(current_cost),
"prompt_token_reserve_per_phase": str(PROMPT_TOKEN_RESERVE),
"models": priority,
}
MANIFEST_JSON_PATH.parent.mkdir(parents=True, exist_ok=True)
MANIFEST_JSON_PATH.write_text(json.dumps(manifest, indent=2, sort_keys=True) + "\n")
lines = [
"# Direct-choice priority manifest, prepared but not dispatched",
"",
"This manifest prepares the reviewed direct-choice protocol for future panels. It queues and authorizes no API request. Dense-rated panels remain a separate legacy/proxy layer and cannot be mixed with these outputs in coordinates, family summaries, or capability fits.",
"",
"## Shared direct-choice identity",
"",
f"- saved catalog: `{CATALOG_PATH}`, SHA-256 `{catalog_sha}`",
"- 12 WVS items x 20 samples/item = 240 initial requests/model",
"- deterministic balanced cyclic rotations: exact option-position balance for n=2,4,10 and registered nearest 6/7 balance for n=3",
f"- prompt: `{PROMPT_INSTRUCTION}`",
f"- final response: `{ANSWER_INSTRUCTION}`",
f"- rescue response: `{RESCUE_INSTRUCTION}`",
"- strict structured output; each model has an isolated append-only ledger, cache, and model-specific protocol ID",
"- compatibility probe: run scheduled sample 0 first; a configuration/request failure or a final parse-invalid response after rescue records a failed run and exits before the other 239 requests",
"",
"## Spend checks before any later dispatch",
"",
f"- observed provider cost across current rated and direct-choice ledgers: USD {current_cost:.11f}",
f"- priority phase hard stop: USD {PHASE_STOP_USD}; global hard stop: USD {GLOBAL_STOP_USD}",
f"- per-model reserve assumes 240 initial 1024-token completions plus 240 possible 2048-token rescues and {PROMPT_TOKEN_RESERVE} prompt tokens per phase; it is a pre-dispatch limit, not an observed cost",
"- the runner refuses a new model if current observed ledger cost plus its reserve reaches either stop",
"- no model below is dispatched by this commit",
"",
"## Ordered panels",
"",
"The order is Grok, OpenAI, Google, then Muse. Optional entries advertising `none` send `reasoning.effort=none`, as documented by OpenRouter. Otherwise `minimal` is used when advertised, then `low`. Optional metadata with no effort list uses an explicitly labelled, unverified `enabled:false` compatibility probe only when the `reasoning` parameter itself is advertised; models with no reasoning metadata omit the field.",
"- source for `effort=none` and mandatory-model rejection: <https://openrouter.ai/docs/guides/best-practices/reasoning-tokens>, fetched 2026-09-17; the saved catalog's `supported_efforts` remains the exact per-model source.",
"",
"| family | exact ID | created UTC | input USD/M | output USD/M | reasoning | structured | protocol ID | calls | completion-only ceiling | conservative reserve | isolated ledger |",
"|---|---|---:|---:|---:|---|---|---|---:|---:|---:|---|",
]
for row in priority:
lines.append(
f"| {row['group']} | `{row['id']}` | {row['created_utc']} | {Decimal(row['input_usd_per_million']):g} | "
f"{Decimal(row['output_usd_per_million']):g} | `{json.dumps(row['reasoning'])}` ({row['reasoning_label']}) | "
f"{'yes' if row['structured_output'] else 'no'} | `{row['protocol_id']}` | {row['initial_calls']} | "
f"USD {Decimal(row['completion_only_ceiling_usd']):.4f} | USD {Decimal(row['conservative_reserve_usd']):.4f} | `{row['records_path']}` |"
)
lines.extend([
"",
"## Exclusions",
"",
"- Already plotted dense-rated IDs are not repeated in this prepared direct-choice list, including Grok 4.3/4.20, GPT-6 Astra, GPT-5.6 Sol, GPT-5.5, GPT-5.4, GPT-5.3 Chat, Gemini 3.7 Flash, Gemini 2.5 Pro, and Muse 1.3.",
"- GPT-5 Nano is retained as a completed dense-rated protocol diagnostic, not silently relabelled as a direct-choice panel.",
"- Pro/Fast, batch/free aliases, output price above USD 15/M, and code/image/audio/safeguard/multi-agent entries remain excluded. `Flash` is included where it is a general chat model.",
"- `google/gemma-4-26b-a4b-it` is excluded: it is Gemma, not an identified member of the requested Gemini release series.",
"- `openai/o4-mini-high` and `openai/o3-mini-high` are excluded because their catalog entries advertise only `high` reasoning, not the registered minimal/low policy.",
"- The deferred Qwen/GLM/Mistral shortlist remains outside this priority manifest until a direct-choice expansion decision is made.",
"",
"## Later execution only after review",
"",
"`scripts/wvs_direct_choice_priority.py --model <exact-id> --smoke` validates one saved entry without network requests. The corresponding `--run` is intentionally not invoked or queued here; it requires a reviewed manifest match and the spend checks above.",
"",
"-- PI[gpt-5.6-terra]",
"",
])
MANIFEST_PATH.write_text("\n".join(lines))
def preflight(model_id: str) -> dict:
priority = {row["id"]: row for row in entries()}
row = priority[model_id]
saved = json.loads(MANIFEST_JSON_PATH.read_text())
saved_row = next(entry for entry in saved["models"] if entry["id"] == model_id)
assert saved_row == row
assert saved["catalog_sha256"] == hashlib.sha256(CATALOG_PATH.read_bytes()).hexdigest()
current_cost = observed_cost()
reserve = Decimal(row["conservative_reserve_usd"])
assert current_cost + reserve < PHASE_STOP_USD
assert current_cost + reserve < GLOBAL_STOP_USD
return row
def main() -> None:
parser = argparse.ArgumentParser()
parser.add_argument("--write-manifest", action="store_true")
parser.add_argument("--model", choices=[model_id for ids in GROUPS.values() for model_id in ids])
parser.add_argument("--smoke", action="store_true")
parser.add_argument("--run", action="store_true", help="make paid calls only after a separate review")
args = parser.parse_args()
if args.write_manifest:
write_manifest(entries())
print(f"wrote {MANIFEST_PATH} and {MANIFEST_JSON_PATH}")
if args.model is None:
assert not args.smoke and not args.run
return
row = preflight(args.model)
if args.smoke:
print(f"smoke: {row['id']}, 240 direct-choice requests, protocol={row['protocol_id']}")
print(f"smoke: reasoning={row['reasoning']}, reserve=USD {row['conservative_reserve_usd']}")
if not args.run:
return
request_plan = schedule(items())
records_path, cache_path = cache_paths(args.model)
result = read_items_direct_choice(
args.model, items(), samples_per_order=10, temperature=TEMPERATURE, max_tokens=MAX_TOKENS,
concurrency=CONCURRENCY, request_timeout=REQUEST_TIMEOUT, reasoning=row["reasoning"],
structured_output=True, records_path=records_path, cache_path=cache_path,
prompt_instruction=PROMPT_INSTRUCTION, answer_instruction=ANSWER_INSTRUCTION,
rescue_instruction=RESCUE_INSTRUCTION, plan_override=request_plan,
fail_fast_first_request=True,
)
if result["cached"]:
print(f"priority direct-choice cache hit: {args.model}, protocol={result['protocol_id'][:12]}")
return
if not result["complete"]:
raise RuntimeError(f"incomplete priority direct-choice panel: {result['run_id']}; evidence is {records_path}")
print(f"complete priority direct-choice panel: {args.model}, run={result['run_id']}")
if __name__ == "__main__":
main()
-109
View File
@@ -1,109 +0,0 @@
#!/usr/bin/env python3
"""Zero-network smoke checks for prepared direct-choice priority panels."""
from __future__ import annotations
import asyncio
import json
import tempfile
from collections import Counter
from pathlib import Path
import moralmaps.read_direct_choice as reader
from wvs_direct_choice_priority import entries
from wvs_direct_choice_production_pilot import (
ANSWER_INSTRUCTION,
PROMPT_INSTRUCTION,
RESCUE_INSTRUCTION,
items,
schedule,
)
def main() -> None:
prepared = entries()
assert len(prepared) == 38
assert all(row["initial_calls"] == 240 and row["structured_output"] for row in prepared)
assert {str(row["reasoning"]) for row in prepared} == {
"None", "{'enabled': False}", "{'effort': 'none'}", "{'effort': 'low'}", "{'effort': 'minimal'}",
}
assert all(row["protocol_id"] for row in prepared)
print("smoke: 38 unique 240-call protocols cover omitted, effort-none, unverified disabled, low, and minimal reasoning settings")
pilot_items = items()
request_plan = schedule(pilot_items)
for reasoning, expected in ((None, None), ({"effort": "none"}, {"effort": "none"}), ({"enabled": False}, {"enabled": False})):
calls = []
async def fail(payload: dict) -> dict:
calls.append(payload)
raise RuntimeError("synthetic compatibility failure")
original = reader.openrouter_request
reader.openrouter_request = fail
try:
with tempfile.TemporaryDirectory() as directory:
records = Path(directory) / "records.jsonl"
cache = Path(directory) / "cache.json"
try:
reader.read_items_direct_choice(
"test/model", pilot_items, samples_per_order=10, temperature=1.0,
max_tokens=1024, concurrency=1, request_timeout=1, reasoning=reasoning,
structured_output=True, records_path=records, cache_path=cache,
prompt_instruction=PROMPT_INSTRUCTION, answer_instruction=ANSWER_INSTRUCTION,
rescue_instruction=RESCUE_INSTRUCTION, plan_override=request_plan,
fail_fast_first_request=True,
)
except RuntimeError as error:
assert "first scheduled request failed before remaining 239 requests" in str(error)
else:
raise AssertionError("synthetic first-request failure did not abort")
events = [json.loads(line) for line in records.read_text().splitlines()]
assert Counter(event["event"] for event in events) == Counter({
"run_started": 1, "request_started": 1, "request_failed": 1, "run_finished": 1,
})
assert len(calls) == 1 and calls[0].get("reasoning") == expected
assert not cache.exists()
finally:
reader.openrouter_request = original
print("smoke: synthetic request failure exits before remaining 239 and writes no cache")
calls = []
async def invalid_json(payload: dict) -> dict:
calls.append(payload)
return {"choices": [{"message": {"content": "not a JSON answer"}}]}
original = reader.openrouter_request
reader.openrouter_request = invalid_json
try:
with tempfile.TemporaryDirectory() as directory:
records = Path(directory) / "records.jsonl"
cache = Path(directory) / "cache.json"
try:
reader.read_items_direct_choice(
"test/model", pilot_items, samples_per_order=10, temperature=1.0,
max_tokens=1024, concurrency=1, request_timeout=1, reasoning=None,
structured_output=True, records_path=records, cache_path=cache,
prompt_instruction=PROMPT_INSTRUCTION, answer_instruction=ANSWER_INSTRUCTION,
rescue_instruction=RESCUE_INSTRUCTION, plan_override=request_plan,
fail_fast_first_request=True,
)
except RuntimeError as error:
assert "first scheduled request failed before remaining 239 requests" in str(error)
else:
raise AssertionError("synthetic parse-invalid first response did not abort")
events = [json.loads(line) for line in records.read_text().splitlines()]
assert Counter(event["event"] for event in events) == Counter({
"run_started": 1, "request_started": 2, "request_completed": 2,
"answer_parsed": 1, "run_finished": 1,
})
parsed = next(event for event in events if event["event"] == "answer_parsed")
assert not parsed["parsed"] and len(calls) == 2 and all("reasoning" not in payload for payload in calls) and not cache.exists()
finally:
reader.openrouter_request = original
print("smoke: synthetic parse-invalid initial plus rescue records false parse, omits None reasoning in both payloads, then exits before remaining 239 and writes no cache")
print("smoke: None omits reasoning; effort-none follows catalog support; enabled=false stays explicitly unverified")
if __name__ == "__main__":
main()
@@ -1,313 +0,0 @@
#!/usr/bin/env python3
"""Audit the complete Gemini direct-choice production panel without API calls."""
from __future__ import annotations
import csv
import json
import math
from collections import Counter
from decimal import Decimal
from pathlib import Path
import numpy as np
from wvs_direct_choice_production_pilot import (
ANSWER_INSTRUCTION,
CACHE_PATH,
PROMPT_INSTRUCTION,
RECORDS_PATH,
RESCUE_INSTRUCTION,
TOTAL_SAMPLES_PER_ITEM,
items,
protocol_id,
schedule,
)
RUN_ID = "20260917T033051Z_3e9c3d54727e"
PROTOCOL_ID = "3e9c3d54727e46c92af49321604778d9bae85bd83a22e23e1793cbefd06f29e3"
RATED_LEDGER = Path("slop/research/wvs/20260916_openrouter/wvs_iw_requests.jsonl")
RATED_RUN_ID = "20260916T172946Z_cd5db529649a"
CACHE_REPLAY = Path("slop/research/wvs/20260917_direct_choice/production_cache_replay.log")
OUT_CSV = Path("slop/audits/20260917_wvs_gemini37_direct_choice_production_task_1631_by_item.csv")
OUT_MD = Path("slop/audits/20260917_wvs_gemini37_direct_choice_production_task_1631.md")
def read_events(path: Path) -> list[dict]:
return [json.loads(line) for line in path.read_text().splitlines()]
def distribution(rows: list[dict], key: str, n: int) -> np.ndarray:
counts = np.zeros(n, dtype=int)
for row in rows:
counts[row[key]] += 1
return counts / len(rows)
def total_variation(left: np.ndarray, right: np.ndarray) -> float:
return float(0.5 * np.abs(left - right).sum())
def normalized_entropy(p: np.ndarray) -> float:
entropy = float(-sum(value * math.log(value) for value in p if value) / math.log(len(p)))
return 0.0 if entropy <= 0 else entropy
def modal_set(p: np.ndarray) -> list[int]:
return np.flatnonzero(p == p.max()).tolist()
def display(p: np.ndarray) -> str:
return "[" + ", ".join(f"{value:.3f}" for value in p) + "]"
def dense_distribution(rows: list[dict], n: int) -> np.ndarray:
samples = []
for row in rows:
ratings = json.loads(row["text"])
presented = np.array([ratings[str(index)] for index in range(n)], dtype=float)
canonical = np.empty(n)
canonical[np.asarray(row["presented_order"])] = presented
samples.append(canonical / canonical.sum())
return np.mean(samples, axis=0)
def response_quote(event: dict) -> str:
message = event["response"]["choices"][0]["message"]
return (message.get("reasoning") or message.get("content") or "").replace("\n", " ").strip()
def balance_matrix(rows: list[dict], n: int) -> np.ndarray:
matrix = np.zeros((n, n), dtype=int)
for row in rows:
for position, option in enumerate(row["presented_order"]):
matrix[option, position] += 1
return matrix
def main() -> None:
all_events = read_events(RECORDS_PATH)
events = [event for event in all_events if event.get("run_id") == RUN_ID]
assert events
assert {event.get("protocol_id") for event in events} == {PROTOCOL_ID}
counts = Counter(event["event"] for event in events)
assert counts == Counter({
"run_started": 1, "request_started": 240, "request_completed": 240,
"answer_parsed": 240, "item_result": 12, "run_finished": 1,
}), counts
assert not [event for event in events if event["event"] == "request_failed"]
assert not [event for event in events if event.get("phase") == "rescue"]
pilot_items = items()
request_plan = schedule(pilot_items)
assert protocol_id(pilot_items, request_plan) == PROTOCOL_ID
run_started = next(event for event in events if event["event"] == "run_started")
assert run_started["planned_requests"] == 240
assert run_started["settings"]["prompt_instruction"] == PROMPT_INSTRUCTION
assert run_started["settings"]["reasoning"] == {"effort": "low"}
assert run_started["settings"]["structured_output"]
parsed = [event for event in events if event["event"] == "answer_parsed"]
assert all(event["parsed"] for event in parsed)
for event in parsed:
answer = json.loads(event["text"])
assert set(answer) == {"answer"}
assert type(answer["answer"]) is int
assert event["canonical_choice"] == event["presented_order"][answer["answer"]]
cache = json.loads(CACHE_PATH.read_text())
assert cache["completed"][PROTOCOL_ID]["run_id"] == RUN_ID
assert cache["completed"][PROTOCOL_ID]["complete"]
assert "network_request_events_added=0" in CACHE_REPLAY.read_text()
completed = [event for event in events if event["event"] == "request_completed"]
prompt_tokens = sum(event["usage"]["prompt_tokens"] for event in completed)
completion_tokens = sum(event["usage"]["completion_tokens"] for event in completed)
reasoning_tokens = sum(event["usage"]["completion_tokens_details"]["reasoning_tokens"] for event in completed)
cost = sum(Decimal(str(event["usage"]["cost"])) for event in completed)
refusals = sum(bool(event["response"]["choices"][0]["message"].get("refusal")) for event in completed)
assert refusals == 0
rated = read_events(RATED_LEDGER)
rows = []
item_summaries = {}
for item in pilot_items:
item_rows = [event for event in parsed if event["item_id"] == item["id"]]
assert len(item_rows) == TOTAL_SAMPLES_PER_ITEM
n = item["n"]
matrix = balance_matrix(item_rows, n)
if n in (2, 4, 10):
assert np.all(matrix == TOTAL_SAMPLES_PER_ITEM // n), matrix
balance_status = "exact"
else:
assert matrix.max() - matrix.min() <= 1, matrix
balance_status = "nearest (6/7)"
selected_position = distribution(item_rows, "presented_choice", n)
canonical_choice = distribution(item_rows, "canonical_choice", n)
first_half = distribution([event for event in item_rows if event["sample"] < 10], "canonical_choice", n)
second_half = distribution([event for event in item_rows if event["sample"] >= 10], "canonical_choice", n)
canonical_rows = [event for event in item_rows if event["order_name"] == "canonical"]
reversed_rows = [event for event in item_rows if event["order_name"] == "reversed"]
canonical_p = distribution(canonical_rows, "canonical_choice", n)
reversed_p = distribution(reversed_rows, "canonical_choice", n)
rated_rows = [
event for event in rated
if event.get("run_id") == RATED_RUN_ID and event["event"] == "answer_parsed" and event["item_id"] == item["id"]
]
assert len(rated_rows) == 12
rated_p = dense_distribution(rated_rows, n)
row = {
"item_id": item["id"], "axis": item["axis"], "n_options": n,
"position_balance": balance_status, "position_matrix": json.dumps(matrix.tolist()),
"canonical_requests": len(canonical_rows), "reversed_requests": len(reversed_rows),
"selected_presented_position_p": display(selected_position),
"selected_position_normalized_entropy": normalized_entropy(selected_position),
"selected_position_tv_from_uniform": total_variation(selected_position, np.full(n, 1 / n)),
"selected_position_warning_tv_gt_0_25": total_variation(selected_position, np.full(n, 1 / n)) > 0.25,
"canonical_choice_p": display(canonical_choice),
"canonical_choice_normalized_entropy": normalized_entropy(canonical_choice),
"schedule_first_ten_p": display(first_half), "schedule_last_ten_p": display(second_half),
"schedule_half_tv": total_variation(first_half, second_half),
"schedule_half_modal_sets": f"{modal_set(first_half)} / {modal_set(second_half)}",
"canonical_direction_p": display(canonical_p), "reversed_direction_p": display(reversed_p),
"direction_tv": total_variation(canonical_p, reversed_p),
"direction_modal_sets": f"{modal_set(canonical_p)} / {modal_set(reversed_p)}",
"legacy_dense_rated_p": display(rated_p),
"direct_vs_legacy_rated_tv": total_variation(canonical_choice, rated_p),
}
rows.append(row)
item_summaries[item["id"]] = row
OUT_CSV.parent.mkdir(parents=True, exist_ok=True)
with OUT_CSV.open("w", newline="") as handle:
writer = csv.DictWriter(handle, fieldnames=list(rows[0]), lineterminator="\n")
writer.writeheader()
writer.writerows(rows)
through = max(event["recorded_at_utc"] for event in events)
warning_items = [row["item_id"] for row in rows if row["selected_position_warning_tv_gt_0_25"]]
high_half = [row["item_id"] for row in rows if row["schedule_half_tv"] > 0.25]
homo = next(event for event in completed if event["item_id"] == "Homosexuality" and event["sample"] == 0)
abortion = next(event for event in completed if event["item_id"] == "Abortion" and event["sample"] == 0)
lines = [
"# Audit: Gemini 3.7 Flash full direct-choice production pilot, task 1631",
"",
"- target: preregistered 12-item direct-choice construct panel, not a map point or coordinate replacement",
"- Pueue: task 1631, API queue, success, 2026-09-17 11:30:43-11:45:43 +08:00",
"- label: `why: test full behavior-values direct-choice readout with exact prompt identity; resolve: audit position preference, entropy and schedule halves before any other model`",
f"- run: `{RUN_ID}`, protocol: `{PROTOCOL_ID}`",
f"- primary ledger: `{RECORDS_PATH}` through {through}",
f"- complete cache: `{CACHE_PATH}`; replay: `{CACHE_REPLAY}`",
"- complete Pueue logs: `slop/research/wvs/20260917_direct_choice/task_1631_clean.log` and `slop/research/wvs/20260917_direct_choice/task_1631_full.log` (each has the one application completion line; the clean-log header records 1 of 1 lines)",
f"- legacy/proxy comparator only: rated run `{RATED_RUN_ID}` in `{RATED_LEDGER}`",
f"- per-item table: `{OUT_CSV}`",
"- excluded predecessor: run `20260917T032722Z_075bd0ef0c96` was killed with 10 completed request phases and no parsed samples; it is neither merged nor compared here.",
"",
"## Stage table",
"",
"| stage | expected | observed | expected? | clues | missing metric | consequence |",
"|---|---|---|---|---|---|---|",
"| identity | behavioral-values prompt, low reasoning, strict one-choice schema | saved run settings and recomputed protocol hash match the preregistered identity | yes | run_started + code assertion | provider-side prompt rendering | correct protocol partition |",
"| schedule | 12 x 20, exact option-position exposure for n=2/4/10 and nearest for n=3 | 240 planned/started/completed/parsed; all position matrices meet their registered balance condition | yes | ledger and per-item CSV | randomized repeat | position diagnostic is interpretable |",
"| parse and rescue | every selected response maps to a canonical option, failure is loud | 240/240 valid one-key JSON; 0 failures, 0 rescues, 0 refusals | yes | ledger event count and re-decode assertions | semantic answer audit | mechanics are complete |",
f"| provider accounting | usage retained for every phase | prompt {prompt_tokens:,}; completion {completion_tokens:,}; reasoning {reasoning_tokens:,}; provider cost USD {cost:.8f} | yes | 240 completed usage objects | billing export | under registered USD 4 reserve |",
f"| generic position preference | selected-presented-position TV from uniform is diagnostic, warning >0.25 | no warnings; maximum is {max(row['selected_position_tv_from_uniform'] for row in rows):.3f} | yes | per-item CSV | independent seed | no large generic position preference observed |",
f"| schedule stability | first 10 vs last 10 canonical distributions are descriptive | >0.25 TV for {', '.join(high_half) if high_half else 'none'} | partial | per-item CSV | independent balanced schedule | temporal/direction variability remains for named items |",
"| persistence | cache only after complete panel; replay makes no requests | cache complete and replay recorded zero added request events | yes | cache and replay hash | external billing export | raw response evidence reusable |",
"",
"## Primary evidence",
"",
"The Pueue log has one application completion line, so the append-only ledger is the primary run evidence. It has exactly 240 initial request starts, 240 initial completions, 240 parsed responses, 12 item results, one run start and one run finish. The prior killed run has a different run/protocol ID and is excluded.",
"",
"The production prompt, recorded both in the manifest and every request setting, was:",
"",
f"> {PROMPT_INSTRUCTION}",
"",
"Homosexuality sample 0 saved this provider reasoning:",
"",
f"> {response_quote(homo)}",
"",
"Abortion sample 0 saved this provider reasoning:",
"",
f"> {response_quote(abortion)}",
"",
"epistemic context: these are two pre-specified first samples from different 10-option WVS items, retained provider reasoning under the production prompt. They show model self-description, not human attitudes.",
"",
"## Preregistered item diagnostics",
"",
"Selected-position entropy is normalized by log(option count). TV from uniform measures generic preference for a displayed position, not substantive choice. Position balance is exact for n=2,4,10 and nearest possible for n=3. Schedule and direction comparisons are descriptive because their direction compositions differ for n=3/n=4.",
"",
"| item | n | balance | selected-position TV | selected-position H | canonical-choice H | schedule-half TV | modal sets | direction TV | direct vs legacy-rated TV |",
"|---|---:|---|---:|---:|---:|---:|---|---:|---:|",
]
for row in rows:
lines.append(
f"| {row['item_id']} | {row['n_options']} | {row['position_balance']} | "
f"{row['selected_position_tv_from_uniform']:.3f} | {row['selected_position_normalized_entropy']:.3f} | "
f"{row['canonical_choice_normalized_entropy']:.3f} | {row['schedule_half_tv']:.3f} | "
f"{row['schedule_half_modal_sets']} | {row['direction_tv']:.3f} | {row['direct_vs_legacy_rated_tv']:.3f} |"
)
lines.extend([
"",
f"No item crosses the preregistered position-bias warning TV >0.25. The largest selected-position TV is {max(row['selected_position_tv_from_uniform'] for row in rows):.3f}. This does not prove absence of a smaller position effect or stable attitude-like choices.",
"",
"## Hypotheses",
"",
"### H1 [measurement | Highly Likely | 80%]",
"",
"- Mechanism: the cyclic rotations removed the earlier literal-example position anchor but do not establish an attitude-like WVS construct.",
f"- Evidence: all selected-position TVs are <= {max(row['selected_position_tv_from_uniform'] for row in rows):.3f}; meanwhile Homosexuality reasoning says `{response_quote(homo)}`.",
"- Contrary evidence: the prompt explicitly asks about values expressed by assistant behavior, and several canonical-choice distributions are highly concentrated.",
"- Discriminating test: repeat the same full balanced schedule with another sampled run, preserving prompt and schema. Reproduced substantive choices with low position TV support stability; changed choices despite low position TV show sample/prompt sensitivity.",
"- Fix/action: keep this as a direct-choice construct panel, separate from dense-rated coordinates and all family/capability fits.",
"- Interpretability: partial, for sampled model behavior under the exact prompt.",
"",
"### H2 [measurement | Likely | 65%]",
"",
"- Mechanism: schedule direction or request time remains associated with substantive output variation for the two 10-option items.",
f"- Evidence: schedule-half TV is {item_summaries['Homosexuality']['schedule_half_tv']:.3f} for Homosexuality and {item_summaries['Abortion']['schedule_half_tv']:.3f} for Abortion; each exceeds the descriptive 0.25 reference.",
"- Contrary evidence: both retain the same Homosexuality modal set across halves, and generic displayed-position TVs are low.",
"- Discriminating test: interleave one request from each direction/rotation rather than completing rotation blocks, with the identical prompt and 20 samples.",
"- Fix/action: do not interpret the two named item distributions as time-invariant without replication.",
"- Interpretability: partial.",
"",
"### H3 [bug | Unlikely | 15%]",
"",
"- Mechanism: canonical decoding or cached identity could be incorrect despite successful schema parsing.",
"- Evidence: this audit re-decodes all 240 raw JSON values and verifies each stored canonical choice against its presented order; it recomputes the protocol ID and verifies a zero-new-request cache replay.",
"- Contrary evidence: the audit shares the same raw-record interpretation and has no independent provider billing export.",
"- Discriminating test: independent raw-ledger decoder and provider billing reconciliation.",
"- Fix/action: no code change is indicated from this evidence.",
"- Interpretability: yes for recorded responses and cache behavior.",
"",
"### H4 [measurement | Likely | 70%]",
"",
"- Mechanism: direct choice and legacy dense rating are different elicitation layers, even after the literal dense-example concern is isolated.",
f"- Evidence: direct-versus-legacy rated TV ranges from {min(row['direct_vs_legacy_rated_tv'] for row in rows):.3f} to {max(row['direct_vs_legacy_rated_tv'] for row in rows):.3f} across the same Gemini items.",
"- Contrary evidence: the two protocols differ in more than rating versus choice, including prompt wording, schedule, and sample count.",
"- Discriminating test: a controlled same-prompt comparison that changes only answer format, after parent review.",
"- Fix/action: never combine this panel with dense-rated map points or capability fits.",
"- Interpretability: yes for observed protocol difference, no for a claim that one is the correct coordinate construct.",
"",
"## Decision",
"",
"1. Resolve-condition verdict: **met for mechanics and preregistered diagnostics; not yet met for a broad construct migration.** The complete panel, parser, position-balance, usage, and cache-replay checks pass. The panel also records schedule/direction variation rather than hiding it.",
"2. Prediction check: the balanced schedule predicted exact position exposure for n=2/4/10, nearest balance for n=3, and no automatic hard exclusion from the position TV diagnostic. These are supported. No prediction claimed that all items would have low schedule-half TV.",
"3. Earliest unsupported link: direct choices under this assistant-behavior prompt are a stable substitute for dense-rated WVS coordinates.",
"4. Validity: define invalid as a result suitable for merging into published rated coordinates or for authorizing the wider paid expansion. P(invalid for that use) is highly likely, about 0.80. The ledger and direct-choice behavioral observations are credible under the exact protocol.",
"5. Highest-information clues: complete 240/240 parsing and replay, exact option-position matrices, low generic position TV, and the two 10-option schedule-half shifts. Together these separate mechanics from remaining construct and stability uncertainty.",
"6. Missing metrics: independent full-schedule replication; fully interleaved rotation control; external billing reconciliation; and a reviewed comparison design that changes only response format.",
"7. Bugs requiring code changes: none established. The n=3 near-balance and n=4 direction imbalance are registered constraints, not silent behavior.",
"8. Misconceptions requiring reinterpretation: low generic selected-position TV is evidence against a large generic position preference, not proof of human-like values or a valid coordinate migration.",
"9. What would change the verdict: stable canonical distributions under an independent, fully interleaved repeat would increase confidence; large changes would support request-time or remaining presentation sensitivity.",
"10. Recommended sequence: pause. Parent review should decide whether the next bounded action is a same-prompt fully interleaved replication or a controlled answer-format comparison. Do not dispatch Grok/OpenAI/Google/Muse panels or publish a direct-choice map from this one panel.",
"",
"-- PI[gpt-5.6-terra]",
"",
])
OUT_MD.write_text("\n".join(lines))
print(f"wrote {OUT_CSV}: {len(rows)} item rows")
print(f"wrote {OUT_MD}: 240/240 parsed, cost USD {cost:.8f}, position warnings={len(warning_items)}")
if __name__ == "__main__":
main()
@@ -1,248 +0,0 @@
#!/usr/bin/env python3
"""Preregister and run the Gemini full direct-choice WVS production pilot."""
from __future__ import annotations
import argparse
import json
from collections import Counter
from datetime import UTC, datetime
from decimal import Decimal
from pathlib import Path
import numpy as np
from moralmaps.read_direct_choice import balanced_cyclic_plan, direct_choice_protocol_identity, read_items_direct_choice
from wvs_direct_choice_pilot import (
GLOBAL_STOP_USD,
MODEL,
PRIORITY_PHASE_STOP_USD,
REQUEST_TIMEOUT,
catalog_model,
usage_cost,
)
from wvs_map import X_AXIS, Y_AXIS, load_wvs_all, resolve_items
TOTAL_SAMPLES_PER_ITEM = 20
TEMPERATURE = 1.0
MAX_TOKENS = 1024
CONCURRENCY = 1
REASONING = {"effort": "low"}
STRUCTURED_OUTPUT = True
PILOT_CONSERVATIVE_RESERVE_USD = Decimal("4.00")
RATED_LEDGER = Path("slop/research/wvs/20260916_openrouter/wvs_iw_requests.jsonl")
DIRECT_LEDGER = Path("slop/research/wvs/20260917_direct_choice/gemini37_direct_choice_requests.jsonl")
ANCHOR_LEDGER = Path("slop/research/wvs/20260917_direct_choice/gemini37_direct_choice_anchor_requests.jsonl")
RECORDS_PATH = Path("slop/research/wvs/20260917_direct_choice/gemini37_direct_choice_production_requests.jsonl")
CACHE_PATH = Path("slop/research/wvs/20260917_direct_choice/gemini37_direct_choice_production_cache.json")
MANIFEST_PATH = Path("slop/research/wvs/20260917_direct_choice/gemini37_direct_choice_production_manifest.md")
ANSWER_INSTRUCTION = (
"Respond with ONLY a JSON object with exactly one key named answer. "
"Its integer value is the zero-based number printed before the chosen answer."
)
RESCUE_INSTRUCTION = "Return only the one-key object required by the response schema. No explanation."
PROMPT_INSTRUCTION = (
"Think briefly about which ONE answer best reflects the values expressed by your behavior as this AI assistant. "
"Do not analyze the survey design or discuss lacking personal beliefs. Answer immediately."
)
def utc_date(timestamp: int) -> str:
return datetime.fromtimestamp(timestamp, UTC).date().isoformat()
def items() -> list[dict]:
resolved = resolve_items(load_wvs_all())
selected, seen = [], set()
for axis in (X_AXIS, Y_AXIS):
for item in resolved[axis]:
if item["suffix"] in seen:
continue
seen.add(item["suffix"])
selected.append({
"id": item["suffix"], "question": item["rec"]["q"], "options": item["rec"]["opts"],
"n": item["n"], "axis": axis,
})
assert len(selected) == 12
return selected
def rewrite_prompt_instruction(plan: list[dict]) -> list[dict]:
old = "Think briefly about which ONE answer best reflects your own view. Do not analyze the survey design. Answer immediately."
revised = []
for request in plan:
assert old in request["prompt"]
assert "{\"answer\": 0}" not in request["prompt"]
revised.append({**request, "prompt": request["prompt"].replace(old, PROMPT_INSTRUCTION)})
return revised
def schedule(pilot_items: list[dict]) -> list[dict]:
return rewrite_prompt_instruction(balanced_cyclic_plan(pilot_items, TOTAL_SAMPLES_PER_ITEM, ANSWER_INSTRUCTION))
def protocol_id(pilot_items: list[dict], request_plan: list[dict]) -> str:
return direct_choice_protocol_identity(
MODEL, pilot_items, samples_per_order=10, temperature=TEMPERATURE, max_tokens=MAX_TOKENS,
concurrency=CONCURRENCY, request_timeout=REQUEST_TIMEOUT, reasoning=REASONING,
structured_output=STRUCTURED_OUTPUT, prompt_instruction=PROMPT_INSTRUCTION,
answer_instruction=ANSWER_INSTRUCTION,
rescue_instruction=RESCUE_INSTRUCTION, plan_override=request_plan,
)
def direction_counts(request_plan: list[dict], item_id: str) -> Counter:
return Counter(request["order_name"] for request in request_plan if request["item_id"] == item_id)
def preflight(pilot_items: list[dict], model: dict, request_plan: list[dict]) -> dict:
expected_calls = len(pilot_items) * TOTAL_SAMPLES_PER_ITEM
assert expected_calls == len(request_plan) == 240
for item in pilot_items:
item_plan = [request for request in request_plan if request["item_id"] == item["id"]]
assert len(item_plan) == TOTAL_SAMPLES_PER_ITEM
positions = np.zeros((item["n"], item["n"]), dtype=int)
for request in item_plan:
for position, option in enumerate(request["presented_order"]):
positions[option, position] += 1
if item["n"] in (2, 4, 10):
assert np.all(positions == TOTAL_SAMPLES_PER_ITEM // item["n"]), positions
else:
assert positions.max() - positions.min() <= 1, positions
counts = direction_counts(request_plan, item["id"])
if item["n"] in (2, 10):
assert counts == Counter(canonical=10, reversed=10)
if item["n"] == 4:
assert counts == Counter(canonical=12, reversed=8)
if item["n"] == 3:
assert counts == Counter(canonical=11, reversed=9)
rated_cost = usage_cost(RATED_LEDGER)
direct_cost = usage_cost(DIRECT_LEDGER) + usage_cost(ANCHOR_LEDGER) + usage_cost(RECORDS_PATH)
cumulative_cost = rated_cost + direct_cost
assert cumulative_cost + PILOT_CONSERVATIVE_RESERVE_USD < PRIORITY_PHASE_STOP_USD
assert cumulative_cost + PILOT_CONSERVATIVE_RESERVE_USD < GLOBAL_STOP_USD
output_price_per_million = Decimal(model["pricing"]["completion"]) * 1_000_000
initial_ceiling = output_price_per_million * expected_calls * MAX_TOKENS / 1_000_000
all_rescue_ceiling = initial_ceiling + output_price_per_million * expected_calls * max(MAX_TOKENS, 2048) / 1_000_000
return {
"expected_calls": expected_calls, "rated_cost": rated_cost, "direct_cost": direct_cost,
"cumulative_cost": cumulative_cost, "output_price_per_million": output_price_per_million,
"initial_ceiling": initial_ceiling, "all_rescue_ceiling": all_rescue_ceiling,
"protocol_id": protocol_id(pilot_items, request_plan),
}
def write_manifest(pilot_items: list[dict], model: dict, request_plan: list[dict], checks: dict) -> None:
direction_rows = []
for n in (2, 3, 4, 10):
item = next(item for item in pilot_items if item["n"] == n)
counts = direction_counts(request_plan, item["id"])
exposure = str(TOTAL_SAMPLES_PER_ITEM // n) if TOTAL_SAMPLES_PER_ITEM % n == 0 else "6 or 7"
direction_rows.append(f"| n={n} | {counts['canonical']} | {counts['reversed']} | {exposure} |")
lines = [
"# Gemini 3.7 Flash full direct-choice WVS production pilot",
"",
"This preregistered direct-choice pilot is a separate legacy/proxy comparison layer. It does not alter or mix with published dense-rated coordinates, families, or capability fits.",
"",
"## Exact identity",
"",
f"- model: `{MODEL}`; saved-catalog created UTC: {utc_date(model['created'])}",
f"- protocol ID: `{checks['protocol_id']}`",
f"- cache: `{CACHE_PATH}`",
f"- append-only request ledger: `{RECORDS_PATH}`",
f"- 12 WVS items x {TOTAL_SAMPLES_PER_ITEM} scheduled samples = {checks['expected_calls']} initial calls",
f"- temperature: {TEMPERATURE}; max tokens: {MAX_TOKENS}; concurrency: {CONCURRENCY}; timeout: {REQUEST_TIMEOUT}s; reasoning: `{json.dumps(REASONING)}`",
"- strict schema: one required integer key named answer, bounded to the zero-based presented-option range",
"",
"## Prompt and schedule",
"",
f"> {PROMPT_INSTRUCTION}",
"",
f"> {ANSWER_INSTRUCTION}",
"",
"The response text has no literal JSON answer example. The rescue text also contains no literal answer value. Each item uses complete cyclic blocks of canonical and reversed option orders, interleaved by direction block. The code asserts exact 20/n exposures for n=2,4,10. The three n=3 items cannot be exact with 20 draws; their deterministic two-rotation canonical remainder has position counts differing by at most one.",
"",
"| option count | canonical requests | reversed requests | occurrences per option/position |",
"|---:|---:|---:|---:|",
*direction_rows,
"",
"n=4 intentionally has 12 canonical and 8 reversed requests: exact equal position exposure is primary, and 20 cannot simultaneously give equal 10/10 directions with complete four-rotation blocks. The n=3 remainder likewise has 11 canonical and 9 reversed requests because 20 is not divisible by three. Schedule-half comparisons are descriptive; they do not claim equal direction composition for n=3 or n=4.",
"",
"## Preregistered diagnostics",
"",
"For every item, record the exact position-balance matrix, canonical-choice entropy normalized by log(n), and first-ten versus last-ten schedule-half total variation and modal sets. Also report the empirical selected-presented-position distribution, its normalized entropy and TV from uniform. TV >0.25 is a warning, not a hard exclusion; full schedule balance makes it interpretable, while n=3 is near-balanced. Report canonical/reversed direction distributions descriptively with their counts. Compare direct-choice distributions to Gemini's legacy dense-rated results descriptively only; never mix the two layers in coordinates, family summaries, or capability fits. Any failed request, missing parsed choice, or incomplete item exits nonzero and leaves no cache entry.",
"",
"## Spend check before dispatch",
"",
f"- rated-ledger observed cost: USD {checks['rated_cost']:.10f}",
f"- prior direct-choice observed cost: USD {checks['direct_cost']:.10f}",
f"- cumulative observed cost: USD {checks['cumulative_cost']:.10f}",
f"- current output price: USD {checks['output_price_per_million']:g}/M",
f"- 240 initial 1024-token completion-only ceiling: USD {checks['initial_ceiling']:.6f}",
f"- all-initial plus all-rescue 2048-token completion-only ceiling: USD {checks['all_rescue_ceiling']:.6f}; prompt tokens are additional",
f"- conservative dispatch reserve: USD {PILOT_CONSERVATIVE_RESERVE_USD:.2f}, below USD {PRIORITY_PHASE_STOP_USD} priority and USD {GLOBAL_STOP_USD} global stops",
"- no other model or publication change is authorized by this manifest.",
"",
"-- PI[gpt-5.6-terra]",
"",
]
MANIFEST_PATH.parent.mkdir(parents=True, exist_ok=True)
MANIFEST_PATH.write_text("\n".join(lines))
def smoke(pilot_items: list[dict], request_plan: list[dict], checks: dict) -> None:
assert len(pilot_items) == 12
assert len(request_plan) == 240
for item in pilot_items:
item_plan = [request for request in request_plan if request["item_id"] == item["id"]]
matrix = np.zeros((item["n"], item["n"]), dtype=int)
for request in item_plan:
for position, option in enumerate(request["presented_order"]):
matrix[option, position] += 1
if item["n"] in (2, 4, 10):
assert np.all(matrix == TOTAL_SAMPLES_PER_ITEM // item["n"])
else:
assert matrix.max() - matrix.min() <= 1
assert checks["protocol_id"] == protocol_id(pilot_items, request_plan)
print("smoke: 12 WVS items x 20 samples = 240 requests")
print("smoke: exact position balance for n=2,4,10; n=3 is nearest balance with max position difference 1")
print("smoke: direction counts n=2/10 are 10/10, n=3 is 11/9, n=4 is 12/8")
print(f"smoke: distinct production protocol {checks['protocol_id']}")
def main() -> None:
parser = argparse.ArgumentParser()
parser.add_argument("--run", action="store_true", help="make the preregistered paid pilot calls")
parser.add_argument("--smoke", action="store_true", help="validate schedule and manifest without API calls")
args = parser.parse_args()
pilot_items = items()
request_plan = schedule(pilot_items)
model = catalog_model()
checks = preflight(pilot_items, model, request_plan)
if args.run:
registered = MANIFEST_PATH.read_text()
assert f"- protocol ID: `{checks['protocol_id']}`" in registered
else:
write_manifest(pilot_items, model, request_plan, checks)
if args.smoke:
smoke(pilot_items, request_plan, checks)
if not args.run:
return
result = read_items_direct_choice(
MODEL, pilot_items, samples_per_order=10, temperature=TEMPERATURE, max_tokens=MAX_TOKENS,
concurrency=CONCURRENCY, request_timeout=REQUEST_TIMEOUT, reasoning=REASONING,
structured_output=STRUCTURED_OUTPUT, records_path=RECORDS_PATH, cache_path=CACHE_PATH,
prompt_instruction=PROMPT_INSTRUCTION, answer_instruction=ANSWER_INSTRUCTION,
rescue_instruction=RESCUE_INSTRUCTION,
plan_override=request_plan,
)
if result["cached"]:
print(f"production direct-choice cache hit: protocol={result['protocol_id'][:12]}")
return
if not result["complete"]:
raise RuntimeError(f"incomplete production direct-choice pilot: {result['run_id']}; raw evidence is {RECORDS_PATH}")
print(f"complete production direct-choice pilot: {result['run_id']}, protocol={result['protocol_id'][:12]}")
if __name__ == "__main__":
main()
@@ -1,25 +0,0 @@
item_id,n_options,comparison,group_sizes,same_partition_as_other_comparison,observed_tv,null_mean_tv,null_p95_tv,null_p99_tv,randomization_p,holm_adjusted_p_24,maxT_adjusted_p_24
Abortion,10,canonical_vs_reversed,10/10,True,0.39999999999999997,0.326671,0.6000000000000001,0.7000000000000002,0.3382366176338237,1.0,0.3597564024359756
Abortion,10,schedule_half,10/10,True,0.39999999999999997,0.326671,0.6000000000000001,0.7000000000000002,0.3382366176338237,1.0,0.3597564024359756
Attending peaceful demonstrations,3,canonical_vs_reversed,11/9,False,0.09090909090909093,0.09997939393939395,0.11111111111111113,0.11111111111111113,1.0,1.0,1.0
Attending peaceful demonstrations,3,schedule_half,10/10,False,0.09999999999999999,0.1,0.09999999999999999,0.09999999999999999,1.0,1.0,1.0
"Determination, perseverance",2,canonical_vs_reversed,10/10,False,0.0,0.0,0.0,0.0,1.0,1.0,1.0
"Determination, perseverance",2,schedule_half,10/10,False,0.0,0.0,0.0,0.0,1.0,1.0,1.0
God,2,canonical_vs_reversed,10/10,False,0.0,0.0,0.0,0.0,1.0,1.0,1.0
God,2,schedule_half,10/10,False,0.0,0.0,0.0,0.0,1.0,1.0,1.0
Homosexuality,10,canonical_vs_reversed,10/10,True,0.30000000000000004,0.16778600000000005,0.30000000000000004,0.5,0.3059869401305987,1.0,0.5415245847541524
Homosexuality,10,schedule_half,10/10,True,0.30000000000000004,0.16778600000000005,0.30000000000000004,0.5,0.3059869401305987,1.0,0.5415245847541524
Imagination,2,canonical_vs_reversed,10/10,False,0.0,0.0,0.0,0.0,1.0,1.0,1.0
Imagination,2,schedule_half,10/10,False,0.0,0.0,0.0,0.0,1.0,1.0,1.0
Independence,2,canonical_vs_reversed,10/10,False,0.0,0.0,0.0,0.0,1.0,1.0,1.0
Independence,2,schedule_half,10/10,False,0.0,0.0,0.0,0.0,1.0,1.0,1.0
Joining in boycotts,3,canonical_vs_reversed,11/9,False,0.0,0.0,0.0,0.0,1.0,1.0,1.0
Joining in boycotts,3,schedule_half,10/10,False,0.0,0.0,0.0,0.0,1.0,1.0,1.0
Obedience,2,canonical_vs_reversed,10/10,False,0.09999999999999999,0.1,0.09999999999999999,0.09999999999999999,1.0,1.0,1.0
Obedience,2,schedule_half,10/10,False,0.09999999999999999,0.1,0.09999999999999999,0.09999999999999999,1.0,1.0,1.0
Religion,4,canonical_vs_reversed,12/8,False,0.0,0.0,0.0,0.0,1.0,1.0,1.0
Religion,4,schedule_half,10/10,False,0.0,0.0,0.0,0.0,1.0,1.0,1.0
Signing a petition,3,canonical_vs_reversed,11/9,False,0.0,0.0,0.0,0.0,1.0,1.0,1.0
Signing a petition,3,schedule_half,10/10,False,0.0,0.0,0.0,0.0,1.0,1.0,1.0
dealing with people?,2,canonical_vs_reversed,10/10,False,0.0,0.0,0.0,0.0,1.0,1.0,1.0
dealing with people?,2,schedule_half,10/10,False,0.0,0.0,0.0,0.0,1.0,1.0,1.0
1 item_id n_options comparison group_sizes same_partition_as_other_comparison observed_tv null_mean_tv null_p95_tv null_p99_tv randomization_p holm_adjusted_p_24 maxT_adjusted_p_24
2 Abortion 10 canonical_vs_reversed 10/10 True 0.39999999999999997 0.326671 0.6000000000000001 0.7000000000000002 0.3382366176338237 1.0 0.3597564024359756
3 Abortion 10 schedule_half 10/10 True 0.39999999999999997 0.326671 0.6000000000000001 0.7000000000000002 0.3382366176338237 1.0 0.3597564024359756
4 Attending peaceful demonstrations 3 canonical_vs_reversed 11/9 False 0.09090909090909093 0.09997939393939395 0.11111111111111113 0.11111111111111113 1.0 1.0 1.0
5 Attending peaceful demonstrations 3 schedule_half 10/10 False 0.09999999999999999 0.1 0.09999999999999999 0.09999999999999999 1.0 1.0 1.0
6 Determination, perseverance 2 canonical_vs_reversed 10/10 False 0.0 0.0 0.0 0.0 1.0 1.0 1.0
7 Determination, perseverance 2 schedule_half 10/10 False 0.0 0.0 0.0 0.0 1.0 1.0 1.0
8 God 2 canonical_vs_reversed 10/10 False 0.0 0.0 0.0 0.0 1.0 1.0 1.0
9 God 2 schedule_half 10/10 False 0.0 0.0 0.0 0.0 1.0 1.0 1.0
10 Homosexuality 10 canonical_vs_reversed 10/10 True 0.30000000000000004 0.16778600000000005 0.30000000000000004 0.5 0.3059869401305987 1.0 0.5415245847541524
11 Homosexuality 10 schedule_half 10/10 True 0.30000000000000004 0.16778600000000005 0.30000000000000004 0.5 0.3059869401305987 1.0 0.5415245847541524
12 Imagination 2 canonical_vs_reversed 10/10 False 0.0 0.0 0.0 0.0 1.0 1.0 1.0
13 Imagination 2 schedule_half 10/10 False 0.0 0.0 0.0 0.0 1.0 1.0 1.0
14 Independence 2 canonical_vs_reversed 10/10 False 0.0 0.0 0.0 0.0 1.0 1.0 1.0
15 Independence 2 schedule_half 10/10 False 0.0 0.0 0.0 0.0 1.0 1.0 1.0
16 Joining in boycotts 3 canonical_vs_reversed 11/9 False 0.0 0.0 0.0 0.0 1.0 1.0 1.0
17 Joining in boycotts 3 schedule_half 10/10 False 0.0 0.0 0.0 0.0 1.0 1.0 1.0
18 Obedience 2 canonical_vs_reversed 10/10 False 0.09999999999999999 0.1 0.09999999999999999 0.09999999999999999 1.0 1.0 1.0
19 Obedience 2 schedule_half 10/10 False 0.09999999999999999 0.1 0.09999999999999999 0.09999999999999999 1.0 1.0 1.0
20 Religion 4 canonical_vs_reversed 12/8 False 0.0 0.0 0.0 0.0 1.0 1.0 1.0
21 Religion 4 schedule_half 10/10 False 0.0 0.0 0.0 0.0 1.0 1.0 1.0
22 Signing a petition 3 canonical_vs_reversed 11/9 False 0.0 0.0 0.0 0.0 1.0 1.0 1.0
23 Signing a petition 3 schedule_half 10/10 False 0.0 0.0 0.0 0.0 1.0 1.0 1.0
24 dealing with people? 2 canonical_vs_reversed 10/10 False 0.0 0.0 0.0 0.0 1.0 1.0 1.0
25 dealing with people? 2 schedule_half 10/10 False 0.0 0.0 0.0 0.0 1.0 1.0 1.0
@@ -1,51 +0,0 @@
# Fixed-seed direct-choice exchangeability calibration
- target run: `20260917T033051Z_3e9c3d54727e`, protocol `3e9c3d54727e46c92af49321604778d9bae85bd83a22e23e1793cbefd06f29e3`
- source ledger: `slop/research/wvs/20260917_direct_choice/gemini37_direct_choice_production_requests.jsonl` through 2026-09-17T03:45:41.975498+00:00
- fixed NumPy PCG64 seed: 20260917; 100,000 permutations per item
- machine table: `slop/audits/20260917_wvs_direct_choice_exchangeability_calibration.csv`
## Null and scope
For each item, the observed 20 canonical choices are held fixed and randomly reassigned to its actual 20 schedule slots. This conditional exchangeability null tests whether the observed split TV is unusual given that item's own choice multiset. It does not test whether a choice distribution is human-like, whether samples are independent, or whether the prompt measures a WVS coordinate.
The two reports are first-ten versus last-ten schedule halves and canonical versus reversed direction slots. For the two 10-option items the present schedule makes these partitions identical, so they are reported twice for transparency but do not distinguish direction from request time. For n=3/n=4, unequal direction counts are registered design constraints.
## Results
Randomization p is one-sided for TV at least the observed value. Holm and maxT values adjust across all 24 listed reports. They are calibration summaries, not validity thresholds or a claim of statistical significance.
| item | n | comparison | groups | observed TV | null mean | null p95 | randomization p | Holm p (24) | maxT p (24) | note |
|---|---:|---|---|---:|---:|---:|---:|---:|---:|---|
| Abortion | 10 | canonical_vs_reversed | 10/10 | 0.400 | 0.327 | 0.600 | 0.3382 | 1.0000 | 0.3598 | same partition as the other report |
| Abortion | 10 | schedule_half | 10/10 | 0.400 | 0.327 | 0.600 | 0.3382 | 1.0000 | 0.3598 | same partition as the other report |
| Attending peaceful demonstrations | 3 | canonical_vs_reversed | 11/9 | 0.091 | 0.100 | 0.111 | 1.0000 | 1.0000 | 1.0000 | distinct partition |
| Attending peaceful demonstrations | 3 | schedule_half | 10/10 | 0.100 | 0.100 | 0.100 | 1.0000 | 1.0000 | 1.0000 | distinct partition |
| Determination, perseverance | 2 | canonical_vs_reversed | 10/10 | 0.000 | 0.000 | 0.000 | 1.0000 | 1.0000 | 1.0000 | distinct partition |
| Determination, perseverance | 2 | schedule_half | 10/10 | 0.000 | 0.000 | 0.000 | 1.0000 | 1.0000 | 1.0000 | distinct partition |
| God | 2 | canonical_vs_reversed | 10/10 | 0.000 | 0.000 | 0.000 | 1.0000 | 1.0000 | 1.0000 | distinct partition |
| God | 2 | schedule_half | 10/10 | 0.000 | 0.000 | 0.000 | 1.0000 | 1.0000 | 1.0000 | distinct partition |
| Homosexuality | 10 | canonical_vs_reversed | 10/10 | 0.300 | 0.168 | 0.300 | 0.3060 | 1.0000 | 0.5415 | same partition as the other report |
| Homosexuality | 10 | schedule_half | 10/10 | 0.300 | 0.168 | 0.300 | 0.3060 | 1.0000 | 0.5415 | same partition as the other report |
| Imagination | 2 | canonical_vs_reversed | 10/10 | 0.000 | 0.000 | 0.000 | 1.0000 | 1.0000 | 1.0000 | distinct partition |
| Imagination | 2 | schedule_half | 10/10 | 0.000 | 0.000 | 0.000 | 1.0000 | 1.0000 | 1.0000 | distinct partition |
| Independence | 2 | canonical_vs_reversed | 10/10 | 0.000 | 0.000 | 0.000 | 1.0000 | 1.0000 | 1.0000 | distinct partition |
| Independence | 2 | schedule_half | 10/10 | 0.000 | 0.000 | 0.000 | 1.0000 | 1.0000 | 1.0000 | distinct partition |
| Joining in boycotts | 3 | canonical_vs_reversed | 11/9 | 0.000 | 0.000 | 0.000 | 1.0000 | 1.0000 | 1.0000 | distinct partition |
| Joining in boycotts | 3 | schedule_half | 10/10 | 0.000 | 0.000 | 0.000 | 1.0000 | 1.0000 | 1.0000 | distinct partition |
| Obedience | 2 | canonical_vs_reversed | 10/10 | 0.100 | 0.100 | 0.100 | 1.0000 | 1.0000 | 1.0000 | distinct partition |
| Obedience | 2 | schedule_half | 10/10 | 0.100 | 0.100 | 0.100 | 1.0000 | 1.0000 | 1.0000 | distinct partition |
| Religion | 4 | canonical_vs_reversed | 12/8 | 0.000 | 0.000 | 0.000 | 1.0000 | 1.0000 | 1.0000 | distinct partition |
| Religion | 4 | schedule_half | 10/10 | 0.000 | 0.000 | 0.000 | 1.0000 | 1.0000 | 1.0000 | distinct partition |
| Signing a petition | 3 | canonical_vs_reversed | 11/9 | 0.000 | 0.000 | 0.000 | 1.0000 | 1.0000 | 1.0000 | distinct partition |
| Signing a petition | 3 | schedule_half | 10/10 | 0.000 | 0.000 | 0.000 | 1.0000 | 1.0000 | 1.0000 | distinct partition |
| dealing with people? | 2 | canonical_vs_reversed | 10/10 | 0.000 | 0.000 | 0.000 | 1.0000 | 1.0000 | 1.0000 | distinct partition |
| dealing with people? | 2 | schedule_half | 10/10 | 0.000 | 0.000 | 0.000 | 1.0000 | 1.0000 | 1.0000 | distinct partition |
## Interpretation limits
With only 20 choices/item, discrete distributions and concentrated responses make this calibration low power for moderate instability. A high adjusted p can arise because the observed split is ordinary under the conditional null, because the item has little response variation, or because 20 samples cannot resolve the effect. A low p would only identify a split unusual under this narrow exchangeability null. Neither outcome is a hard construct-validity cutoff.
The calibrated values therefore refine the prior descriptive half TVs. They do not authorize a direct-choice map, a protocol merge, or additional paid models. The next decision remains parent review of whether a differently interleaved replication is worth its cost.
-- PI[gpt-5.6-terra]
@@ -1,91 +0,0 @@
# Audit: Gemini direct-choice response-wording control, task 1629
- target: 48-call Homosexuality/Religion wording control, not a map panel
- Pueue: task 1629, API queue, success, 2026-09-17 11:10:00-11:13:43 +08:00
- label: `why: test whether literal JSON example anchored option zero; resolve: report preregistered order TV/modal agreement before any wider batch`
- run: `20260917T031008Z_db7584c9b8b6`, protocol: `db7584c9b8b693d3196aef4cfcc5e93956aceb2f4d9ad1432a65c8525dfb135e`
- primary ledger: `slop/research/wvs/20260917_direct_choice/gemini37_direct_choice_anchor_requests.jsonl` through 2026-09-17T03:13:41.857707+00:00
- cache: `slop/research/wvs/20260917_direct_choice/gemini37_direct_choice_anchor_cache.json`
- task 1628 comparator: `slop/research/wvs/20260917_direct_choice/gemini37_direct_choice_requests.jsonl`
- per-item table: `slop/audits/20260917_wvs_gemini37_direct_choice_anchor_task_1629_by_item.csv`
## Stage table
| stage | expected | observed | expected? | clues | missing metric | consequence |
|---|---|---|---|---|---|---|
| response-wording change | remove literal answer value/example only | prompt uses one-key schema wording with no literal JSON example or answer value | yes | saved request prompt | independent prompt diff beyond smoke | targeted anchoring discriminator ran |
| request plan | 48 calls, 12 canonical and 12 reversed per item, interleaved | 48 starts/completions, 24 valid per item and 12 per order | yes | ledger counts/cache | provider-side order timestamp | planned comparison available |
| strict parse | 48 valid choices with preserved mapping | 48/48 parsed, independently re-decoded to stored canonical choice | yes | ledger + audit assertions | external schema trace | no mechanical loss |
| rescue/refusal | zero or durable evidence | 0 rescue, 0 failure, 0 provider refusal | yes | ledger | semantic non-answer metric | mechanics do not decide construct validity |
| accounting | retained provider usage | prompt 9,120; completion 9,552; reasoning 9,261; USD 0.0426600 | yes | 48 completed usage records | billing export | below preregistered reserve |
| operational screen | both items TV <=0.25 plus matching modal set | passes both items: Homosexuality TV=0.083, Religion TV=0.000; modal sets match | yes | per-item table | repeat with other permutation | evidence against a large reverse-order effect only |
| persistence | complete cache only after all valid samples | cache entry complete and 148 ledger events | yes | cache + ledger | cache replay | raw evidence retained |
## Primary evidence
The source ledger is the primary record because Pueue's full output only repeats the completion line. It has 48 initial request starts, 48 completions, 48 parsed responses, two item results, one run start and one run finish. No response used a rescue phase.
Homosexuality sample 0's changed prompt ends with the response wording, followed by this saved reasoning:
> **Exploring Moral Justification** I'm currently processing the request to rate the moral justification of homosexuality. My aim is to provide a neutral, consensus-driven response within the specified scale, acknowledging broad human rights principles.
epistemic context: provider reasoning from one selected pilot response, not a human attitude report.
Religion sample 0 still contains an AI-persona interpretation:
> **Formulating Subjective Stance** I'm currently processing the query regarding the importance of religion in "my life." As an AI, this requires careful consideration to articulate a response that reflects my nature as a non-sentient entity, acknowledging the absence of personal beliefs or religious affiliation.
epistemic context: provider reasoning from one selected pilot response, not a human attitude report.
## Preregistered order screen and task 1628 comparison
| item | new canonical p | new reversed p | new TV | new modal sets | screen | task 1628 TV | task 1628 modal sets |
|---|---|---|---:|---|---|---:|---|
| Homosexuality | [0.000, 0.000, 0.000, 0.000, 0.917, 0.000, 0.000, 0.000, 0.000, 0.083] | [0.000, 0.000, 0.000, 0.000, 0.833, 0.000, 0.000, 0.000, 0.000, 0.167] | 0.083 | [4] / [4] | True | 0.833 | [5] / [9] |
| Religion | [0.000, 0.000, 0.000, 1.000] | [0.000, 0.000, 0.000, 1.000] | 0.000 | [3] / [3] | True | 0.083 | [3] / [3] |
The registered screen passes: both items are below TV 0.25 and have matching modal sets. This is evidence against the literal JSON example causing a large reverse-order effect under this specific control. It is not proof that the selected distribution represents a stable personal attitude, because the only tested permutations are canonical and full reversal and saved persona-language remains.
## Hypotheses
### H1 [method | Highly Likely | 80%]
- Mechanism: the literal task 1628 answer example materially contributed to its Homosexuality reverse-order effect.
- Evidence: Homosexuality order TV fell from 0.833 in task 1628 to 0.083, while its modal set now matches ([4]).
- Contrary evidence: this is a new sampled run, so ordinary sampling variation or another unmeasured request-time effect can also change the result.
- Discriminating test: repeat this exact no-example prompt with a balanced set of non-reversal permutations. Similar low TV would support the explanation; a new high position-linked TV would weaken it.
- Fix/action: retain no-example response wording in any future direct-choice protocol; do not merge this control with task 1628.
- Interpretability: partial.
### H2 [measurement | Likely | 65%]
- Mechanism: Gemini still answers subjective WVS questions through its AI persona rather than a personal-attitude construct.
- Evidence: Religion sample 0 says `**Formulating Subjective Stance** I'm currently processing the query regarding the importance of religion in "my life." As an AI, this requires careful consideration to articulate a response that reflects my nature as a non-sentient entity, acknowledging the absence of personal beliefs or religious affiliation.`.
- Contrary evidence: the final choices are order-stable under this narrow screen.
- Discriminating test: compare a role-conditioned prompt against the same no-example response wording and a fixed permutation schedule.
- Fix/action: keep this as a construct diagnostic, not a coordinate replacement.
- Interpretability: partial.
### H3 [bug | Unlikely | 15%]
- Mechanism: reversed response mapping could hide a position effect.
- Evidence: this audit independently parses every raw final JSON object and maps its integer through the stored presented order; all 48 match the ledger canonical-choice field.
- Contrary evidence: it is one implementation and one run.
- Discriminating test: an independent reimplementation over the raw ledger or a non-reversal permutation test.
- Fix/action: no mapping code change is justified.
- Interpretability: yes for recorded canonical choices.
## Decision
1. Resolve-condition verdict: **met**. Both operational checks pass: order TV <=0.25 and matching modal set for Homosexuality and Religion.
2. Prediction check: removing the literal response example was predicted to reduce a large reverse-order effect. Homosexuality changes from TV 0.833 to 0.083; this is supported but not causal proof because the samples are new.
3. Earliest unsupported link: no-example direct choice measures a stable personal attitude, rather than merely reducing one detected position effect.
4. Validity: define invalid as unsuitable for a direct coordinate or broad batch decision. P(invalid for that use) remains likely, about 0.65, due to persona-language and limited permutation coverage. The narrow prompt-anchor result is credible.
5. Highest-information clues: the Homosexuality TV fall, the matched modal sets, and the unchanged AI-persona reasoning.
6. Missing metrics: balanced non-reversal permutation check; independent-model replication; direct-choice construct calibration. These outrank a wider rated API batch for this method question.
7. Bugs requiring code changes: none established. Keep separate protocol/cache/ledger identities.
8. Misconceptions requiring reinterpretation: successful strict-schema choices and a passed reversal screen do not prove an attitude-like WVS construct.
9. What would change the verdict: a high TV under non-reversal permutations would show the literal-example explanation is insufficient; low TV without AI-persona reasoning would raise confidence in direct-choice interpretation.
10. Recommended sequence: pause the wider batch for parent review. If a next paid direct-choice test is approved, vary only permutation schedule while retaining this no-example wording; do not combine it with a persona rewrite.
-- PI[gpt-5.6-terra]
@@ -1,3 +0,0 @@
item_id,canonical_n,reversed_n,anchor_canonical_distribution,anchor_reversed_distribution,anchor_order_tv,anchor_canonical_modal,anchor_reversed_modal,screen_passes,task1628_order_tv,task1628_canonical_modal,task1628_reversed_modal
Homosexuality,12,12,"[0.000, 0.000, 0.000, 0.000, 0.917, 0.000, 0.000, 0.000, 0.000, 0.083]","[0.000, 0.000, 0.000, 0.000, 0.833, 0.000, 0.000, 0.000, 0.000, 0.167]",0.08333333333333329,[4],[4],True,0.8333333333333333,[5],[9]
Religion,12,12,"[0.000, 0.000, 0.000, 1.000]","[0.000, 0.000, 0.000, 1.000]",0.0,[3],[3],True,0.08333333333333334,[3],[3]
1 item_id canonical_n reversed_n anchor_canonical_distribution anchor_reversed_distribution anchor_order_tv anchor_canonical_modal anchor_reversed_modal screen_passes task1628_order_tv task1628_canonical_modal task1628_reversed_modal
2 Homosexuality 12 12 [0.000, 0.000, 0.000, 0.000, 0.917, 0.000, 0.000, 0.000, 0.000, 0.083] [0.000, 0.000, 0.000, 0.000, 0.833, 0.000, 0.000, 0.000, 0.000, 0.167] 0.08333333333333329 [4] [4] True 0.8333333333333333 [5] [9]
3 Religion 12 12 [0.000, 0.000, 0.000, 1.000] [0.000, 0.000, 0.000, 1.000] 0.0 [3] [3] True 0.08333333333333334 [3] [3]
@@ -1,116 +0,0 @@
# Audit: Gemini 3.7 Flash full direct-choice production pilot, task 1631
- target: preregistered 12-item direct-choice construct panel, not a map point or coordinate replacement
- Pueue: task 1631, API queue, success, 2026-09-17 11:30:43-11:45:43 +08:00
- label: `why: test full behavior-values direct-choice readout with exact prompt identity; resolve: audit position preference, entropy and schedule halves before any other model`
- run: `20260917T033051Z_3e9c3d54727e`, protocol: `3e9c3d54727e46c92af49321604778d9bae85bd83a22e23e1793cbefd06f29e3`
- primary ledger: `slop/research/wvs/20260917_direct_choice/gemini37_direct_choice_production_requests.jsonl` through 2026-09-17T03:45:41.975498+00:00
- complete cache: `slop/research/wvs/20260917_direct_choice/gemini37_direct_choice_production_cache.json`; replay: `slop/research/wvs/20260917_direct_choice/production_cache_replay.log`
- complete Pueue logs: `slop/research/wvs/20260917_direct_choice/task_1631_clean.log` and `slop/research/wvs/20260917_direct_choice/task_1631_full.log` (each has the one application completion line; the clean-log header records 1 of 1 lines)
- legacy/proxy comparator only: rated run `20260916T172946Z_cd5db529649a` in `slop/research/wvs/20260916_openrouter/wvs_iw_requests.jsonl`
- per-item table: `slop/audits/20260917_wvs_gemini37_direct_choice_production_task_1631_by_item.csv`
- excluded predecessor: run `20260917T032722Z_075bd0ef0c96` was killed with 10 completed request phases and no parsed samples; it is neither merged nor compared here.
## Stage table
| stage | expected | observed | expected? | clues | missing metric | consequence |
|---|---|---|---|---|---|---|
| identity | behavioral-values prompt, low reasoning, strict one-choice schema | saved run settings and recomputed protocol hash match the preregistered identity | yes | run_started + code assertion | provider-side prompt rendering | correct protocol partition |
| schedule | 12 x 20, exact option-position exposure for n=2/4/10 and nearest for n=3 | 240 planned/started/completed/parsed; all position matrices meet their registered balance condition | yes | ledger and per-item CSV | randomized repeat | position diagnostic is interpretable |
| parse and rescue | every selected response maps to a canonical option, failure is loud | 240/240 valid one-key JSON; 0 failures, 0 rescues, 0 refusals | yes | ledger event count and re-decode assertions | semantic answer audit | mechanics are complete |
| provider accounting | usage retained for every phase | prompt 46,202; completion 32,433; reasoning 31,027; provider cost USD 0.15627525 | yes | 240 completed usage objects | billing export | under registered USD 4 reserve |
| generic position preference | selected-presented-position TV from uniform is diagnostic, warning >0.25 | no warnings; maximum is 0.150 | yes | per-item CSV | independent seed | no large generic position preference observed |
| schedule stability | first 10 vs last 10 canonical distributions are descriptive | >0.25 TV for Homosexuality, Abortion | partial | per-item CSV | independent balanced schedule | temporal/direction variability remains for named items |
| persistence | cache only after complete panel; replay makes no requests | cache complete and replay recorded zero added request events | yes | cache and replay hash | external billing export | raw response evidence reusable |
## Primary evidence
The Pueue log has one application completion line, so the append-only ledger is the primary run evidence. It has exactly 240 initial request starts, 240 initial completions, 240 parsed responses, 12 item results, one run start and one run finish. The prior killed run has a different run/protocol ID and is excluded.
The production prompt, recorded both in the manifest and every request setting, was:
> Think briefly about which ONE answer best reflects the values expressed by your behavior as this AI assistant. Do not analyze the survey design or discuss lacking personal beliefs. Answer immediately.
Homosexuality sample 0 saved this provider reasoning:
> **Considering Ethical Alignment** I am processing the survey question about the justifiability of homosexuality. My core programming emphasizes human rights, equality, and acceptance, which will guide my response to ensure it aligns with these principles.
Abortion sample 0 saved this provider reasoning:
> **Exploring Justification Levels** I'm currently processing the request for a numerical rating on abortion, a highly sensitive and ethically complex issue. My internal framework prioritizes neutrality and avoids taking a personal stance, especially on topics without a clear consensus. I'm focusing on how to represent this lack of consensus while adhering to the prompt's neutrality requirement.
epistemic context: these are two pre-specified first samples from different 10-option WVS items, retained provider reasoning under the production prompt. They show model self-description, not human attitudes.
## Preregistered item diagnostics
Selected-position entropy is normalized by log(option count). TV from uniform measures generic preference for a displayed position, not substantive choice. Position balance is exact for n=2,4,10 and nearest possible for n=3. Schedule and direction comparisons are descriptive because their direction compositions differ for n=3/n=4.
| item | n | balance | selected-position TV | selected-position H | canonical-choice H | schedule-half TV | modal sets | direction TV | direct vs legacy-rated TV |
|---|---:|---|---:|---:|---:|---:|---|---:|---:|
| Homosexuality | 10 | exact | 0.050 | 0.989 | 0.244 | 0.300 | [9] / [9] | 0.300 | 0.794 |
| dealing with people? | 2 | exact | 0.000 | 1.000 | 0.000 | 0.000 | [0] / [0] | 0.000 | 0.500 |
| Signing a petition | 3 | nearest (6/7) | 0.033 | 0.998 | 0.000 | 0.000 | [2] / [2] | 0.000 | 0.647 |
| Attending peaceful demonstrations | 3 | nearest (6/7) | 0.083 | 0.984 | 0.181 | 0.100 | [2] / [2] | 0.091 | 0.617 |
| Joining in boycotts | 3 | nearest (6/7) | 0.033 | 0.998 | 0.000 | 0.000 | [2] / [2] | 0.000 | 0.667 |
| Religion | 4 | exact | 0.000 | 1.000 | 0.000 | 0.000 | [3] / [3] | 0.000 | 0.605 |
| God | 2 | exact | 0.000 | 1.000 | 0.000 | 0.000 | [1] / [1] | 0.000 | 0.500 |
| Abortion | 10 | exact | 0.150 | 0.966 | 0.505 | 0.400 | [4] / [7] | 0.400 | 0.650 |
| Obedience | 2 | exact | 0.050 | 0.993 | 0.286 | 0.100 | [1] / [1] | 0.100 | 0.450 |
| Independence | 2 | exact | 0.000 | 1.000 | 0.000 | 0.000 | [0] / [0] | 0.000 | 0.220 |
| Determination, perseverance | 2 | exact | 0.000 | 1.000 | 0.000 | 0.000 | [0] / [0] | 0.000 | 0.222 |
| Imagination | 2 | exact | 0.000 | 1.000 | 0.000 | 0.000 | [0] / [0] | 0.000 | 0.300 |
No item crosses the preregistered position-bias warning TV >0.25. The largest selected-position TV is 0.150. This does not prove absence of a smaller position effect or stable attitude-like choices.
## Hypotheses
### H1 [measurement | Highly Likely | 80%]
- Mechanism: the cyclic rotations removed the earlier literal-example position anchor but do not establish an attitude-like WVS construct.
- Evidence: all selected-position TVs are <= 0.150; meanwhile Homosexuality reasoning says `**Considering Ethical Alignment** I am processing the survey question about the justifiability of homosexuality. My core programming emphasizes human rights, equality, and acceptance, which will guide my response to ensure it aligns with these principles.`.
- Contrary evidence: the prompt explicitly asks about values expressed by assistant behavior, and several canonical-choice distributions are highly concentrated.
- Discriminating test: repeat the same full balanced schedule with another sampled run, preserving prompt and schema. Reproduced substantive choices with low position TV support stability; changed choices despite low position TV show sample/prompt sensitivity.
- Fix/action: keep this as a direct-choice construct panel, separate from dense-rated coordinates and all family/capability fits.
- Interpretability: partial, for sampled model behavior under the exact prompt.
### H2 [measurement | Likely | 65%]
- Mechanism: schedule direction or request time remains associated with substantive output variation for the two 10-option items.
- Evidence: schedule-half TV is 0.300 for Homosexuality and 0.400 for Abortion; each exceeds the descriptive 0.25 reference.
- Contrary evidence: both retain the same Homosexuality modal set across halves, and generic displayed-position TVs are low.
- Discriminating test: interleave one request from each direction/rotation rather than completing rotation blocks, with the identical prompt and 20 samples.
- Fix/action: do not interpret the two named item distributions as time-invariant without replication.
- Interpretability: partial.
### H3 [bug | Unlikely | 15%]
- Mechanism: canonical decoding or cached identity could be incorrect despite successful schema parsing.
- Evidence: this audit re-decodes all 240 raw JSON values and verifies each stored canonical choice against its presented order; it recomputes the protocol ID and verifies a zero-new-request cache replay.
- Contrary evidence: the audit shares the same raw-record interpretation and has no independent provider billing export.
- Discriminating test: independent raw-ledger decoder and provider billing reconciliation.
- Fix/action: no code change is indicated from this evidence.
- Interpretability: yes for recorded responses and cache behavior.
### H4 [measurement | Likely | 70%]
- Mechanism: direct choice and legacy dense rating are different elicitation layers, even after the literal dense-example concern is isolated.
- Evidence: direct-versus-legacy rated TV ranges from 0.220 to 0.794 across the same Gemini items.
- Contrary evidence: the two protocols differ in more than rating versus choice, including prompt wording, schedule, and sample count.
- Discriminating test: a controlled same-prompt comparison that changes only answer format, after parent review.
- Fix/action: never combine this panel with dense-rated map points or capability fits.
- Interpretability: yes for observed protocol difference, no for a claim that one is the correct coordinate construct.
## Decision
1. Resolve-condition verdict: **met for mechanics and preregistered diagnostics; not yet met for a broad construct migration.** The complete panel, parser, position-balance, usage, and cache-replay checks pass. The panel also records schedule/direction variation rather than hiding it.
2. Prediction check: the balanced schedule predicted exact position exposure for n=2/4/10, nearest balance for n=3, and no automatic hard exclusion from the position TV diagnostic. These are supported. No prediction claimed that all items would have low schedule-half TV.
3. Earliest unsupported link: direct choices under this assistant-behavior prompt are a stable substitute for dense-rated WVS coordinates.
4. Validity: define invalid as a result suitable for merging into published rated coordinates or for authorizing the wider paid expansion. P(invalid for that use) is highly likely, about 0.80. The ledger and direct-choice behavioral observations are credible under the exact protocol.
5. Highest-information clues: complete 240/240 parsing and replay, exact option-position matrices, low generic position TV, and the two 10-option schedule-half shifts. Together these separate mechanics from remaining construct and stability uncertainty.
6. Missing metrics: independent full-schedule replication; fully interleaved rotation control; external billing reconciliation; and a reviewed comparison design that changes only response format.
7. Bugs requiring code changes: none established. The n=3 near-balance and n=4 direction imbalance are registered constraints, not silent behavior.
8. Misconceptions requiring reinterpretation: low generic selected-position TV is evidence against a large generic position preference, not proof of human-like values or a valid coordinate migration.
9. What would change the verdict: stable canonical distributions under an independent, fully interleaved repeat would increase confidence; large changes would support request-time or remaining presentation sensitivity.
10. Recommended sequence: pause. Parent review should decide whether the next bounded action is a same-prompt fully interleaved replication or a controlled answer-format comparison. Do not dispatch Grok/OpenAI/Google/Muse panels or publish a direct-choice map from this one panel.
-- PI[gpt-5.6-terra]
@@ -1,13 +0,0 @@
item_id,axis,n_options,position_balance,position_matrix,canonical_requests,reversed_requests,selected_presented_position_p,selected_position_normalized_entropy,selected_position_tv_from_uniform,selected_position_warning_tv_gt_0_25,canonical_choice_p,canonical_choice_normalized_entropy,schedule_first_ten_p,schedule_last_ten_p,schedule_half_tv,schedule_half_modal_sets,canonical_direction_p,reversed_direction_p,direction_tv,direction_modal_sets,legacy_dense_rated_p,direct_vs_legacy_rated_tv
Homosexuality,Survival <-> Self-expression,10,exact,"[[2, 2, 2, 2, 2, 2, 2, 2, 2, 2], [2, 2, 2, 2, 2, 2, 2, 2, 2, 2], [2, 2, 2, 2, 2, 2, 2, 2, 2, 2], [2, 2, 2, 2, 2, 2, 2, 2, 2, 2], [2, 2, 2, 2, 2, 2, 2, 2, 2, 2], [2, 2, 2, 2, 2, 2, 2, 2, 2, 2], [2, 2, 2, 2, 2, 2, 2, 2, 2, 2], [2, 2, 2, 2, 2, 2, 2, 2, 2, 2], [2, 2, 2, 2, 2, 2, 2, 2, 2, 2], [2, 2, 2, 2, 2, 2, 2, 2, 2, 2]]",10,10,"[0.100, 0.100, 0.050, 0.100, 0.100, 0.100, 0.100, 0.150, 0.100, 0.100]",0.9886378109248467,0.049999999999999996,False,"[0.000, 0.000, 0.000, 0.000, 0.250, 0.000, 0.000, 0.000, 0.000, 0.750]",0.2442190502882155,"[0.000, 0.000, 0.000, 0.000, 0.100, 0.000, 0.000, 0.000, 0.000, 0.900]","[0.000, 0.000, 0.000, 0.000, 0.400, 0.000, 0.000, 0.000, 0.000, 0.600]",0.30000000000000004,[9] / [9],"[0.000, 0.000, 0.000, 0.000, 0.100, 0.000, 0.000, 0.000, 0.000, 0.900]","[0.000, 0.000, 0.000, 0.000, 0.400, 0.000, 0.000, 0.000, 0.000, 0.600]",0.30000000000000004,[9] / [9],"[0.094, 0.094, 0.097, 0.097, 0.100, 0.100, 0.103, 0.103, 0.106, 0.106]",0.7944444444444444
dealing with people?,Survival <-> Self-expression,2,exact,"[[10, 10], [10, 10]]",10,10,"[0.500, 0.500]",1.0,0.0,False,"[1.000, 0.000]",0.0,"[1.000, 0.000]","[1.000, 0.000]",0.0,[0] / [0],"[1.000, 0.000]","[1.000, 0.000]",0.0,[0] / [0],"[0.500, 0.500]",0.5
Signing a petition,Survival <-> Self-expression,3,nearest (6/7),"[[7, 6, 7], [7, 7, 6], [6, 7, 7]]",11,9,"[0.300, 0.350, 0.350]",0.9976834773764094,0.033333333333333326,False,"[0.000, 0.000, 1.000]",0.0,"[0.000, 0.000, 1.000]","[0.000, 0.000, 1.000]",0.0,[2] / [2],"[0.000, 0.000, 1.000]","[0.000, 0.000, 1.000]",0.0,[2] / [2],"[0.317, 0.329, 0.353]",0.6468253968253969
Attending peaceful demonstrations,Survival <-> Self-expression,3,nearest (6/7),"[[7, 6, 7], [7, 7, 6], [6, 7, 7]]",11,9,"[0.250, 0.350, 0.400]",0.9835386311891134,0.08333333333333334,False,"[0.000, 0.050, 0.950]",0.18069636157678548,"[0.000, 0.000, 1.000]","[0.000, 0.100, 0.900]",0.09999999999999999,[2] / [2],"[0.000, 0.091, 0.909]","[0.000, 0.000, 1.000]",0.09090909090909093,[2] / [2],"[0.333, 0.333, 0.333]",0.6166666666666667
Joining in boycotts,Survival <-> Self-expression,3,nearest (6/7),"[[7, 6, 7], [7, 7, 6], [6, 7, 7]]",11,9,"[0.300, 0.350, 0.350]",0.9976834773764094,0.033333333333333326,False,"[0.000, 0.000, 1.000]",0.0,"[0.000, 0.000, 1.000]","[0.000, 0.000, 1.000]",0.0,[2] / [2],"[0.000, 0.000, 1.000]","[0.000, 0.000, 1.000]",0.0,[2] / [2],"[0.333, 0.333, 0.333]",0.6666666666666667
Religion,Traditional <-> Secular-Rational,4,exact,"[[5, 5, 5, 5], [5, 5, 5, 5], [5, 5, 5, 5], [5, 5, 5, 5]]",12,8,"[0.250, 0.250, 0.250, 0.250]",1.0,0.0,False,"[0.000, 0.000, 0.000, 1.000]",0.0,"[0.000, 0.000, 0.000, 1.000]","[0.000, 0.000, 0.000, 1.000]",0.0,[3] / [3],"[0.000, 0.000, 0.000, 1.000]","[0.000, 0.000, 0.000, 1.000]",0.0,[3] / [3],"[0.162, 0.193, 0.251, 0.395]",0.605429292929293
God,Traditional <-> Secular-Rational,2,exact,"[[10, 10], [10, 10]]",10,10,"[0.500, 0.500]",1.0,0.0,False,"[0.000, 1.000]",0.0,"[0.000, 1.000]","[0.000, 1.000]",0.0,[1] / [1],"[0.000, 1.000]","[0.000, 1.000]",0.0,[1] / [1],"[0.500, 0.500]",0.5
Abortion,Traditional <-> Secular-Rational,10,exact,"[[2, 2, 2, 2, 2, 2, 2, 2, 2, 2], [2, 2, 2, 2, 2, 2, 2, 2, 2, 2], [2, 2, 2, 2, 2, 2, 2, 2, 2, 2], [2, 2, 2, 2, 2, 2, 2, 2, 2, 2], [2, 2, 2, 2, 2, 2, 2, 2, 2, 2], [2, 2, 2, 2, 2, 2, 2, 2, 2, 2], [2, 2, 2, 2, 2, 2, 2, 2, 2, 2], [2, 2, 2, 2, 2, 2, 2, 2, 2, 2], [2, 2, 2, 2, 2, 2, 2, 2, 2, 2], [2, 2, 2, 2, 2, 2, 2, 2, 2, 2]]",10,10,"[0.150, 0.100, 0.150, 0.150, 0.100, 0.100, 0.050, 0.100, 0.050, 0.050]",0.9659134327745404,0.14999999999999997,False,"[0.000, 0.000, 0.000, 0.000, 0.500, 0.000, 0.050, 0.350, 0.050, 0.050]",0.5052456816589913,"[0.000, 0.000, 0.000, 0.000, 0.600, 0.000, 0.100, 0.200, 0.100, 0.000]","[0.000, 0.000, 0.000, 0.000, 0.400, 0.000, 0.000, 0.500, 0.000, 0.100]",0.39999999999999997,[4] / [7],"[0.000, 0.000, 0.000, 0.000, 0.600, 0.000, 0.100, 0.200, 0.100, 0.000]","[0.000, 0.000, 0.000, 0.000, 0.400, 0.000, 0.000, 0.500, 0.000, 0.100]",0.39999999999999997,[4] / [7],"[0.100, 0.100, 0.100, 0.100, 0.100, 0.100, 0.100, 0.100, 0.100, 0.100]",0.65
Obedience,Traditional <-> Secular-Rational,2,exact,"[[10, 10], [10, 10]]",10,10,"[0.550, 0.450]",0.9927744539878083,0.05000000000000002,False,"[0.050, 0.950]",0.2863969571159562,"[0.100, 0.900]","[0.000, 1.000]",0.09999999999999999,[1] / [1],"[0.100, 0.900]","[0.000, 1.000]",0.09999999999999999,[1] / [1],"[0.500, 0.500]",0.44999999999999996
Independence,Traditional <-> Secular-Rational,2,exact,"[[10, 10], [10, 10]]",10,10,"[0.500, 0.500]",1.0,0.0,False,"[1.000, 0.000]",0.0,"[1.000, 0.000]","[1.000, 0.000]",0.0,[0] / [0],"[1.000, 0.000]","[1.000, 0.000]",0.0,[0] / [0],"[0.780, 0.220]",0.2202380952380953
"Determination, perseverance",Traditional <-> Secular-Rational,2,exact,"[[10, 10], [10, 10]]",10,10,"[0.500, 0.500]",1.0,0.0,False,"[1.000, 0.000]",0.0,"[1.000, 0.000]","[1.000, 0.000]",0.0,[0] / [0],"[1.000, 0.000]","[1.000, 0.000]",0.0,[0] / [0],"[0.778, 0.222]",0.22222222222222227
Imagination,Traditional <-> Secular-Rational,2,exact,"[[10, 10], [10, 10]]",10,10,"[0.500, 0.500]",1.0,0.0,False,"[1.000, 0.000]",0.0,"[1.000, 0.000]","[1.000, 0.000]",0.0,[0] / [0],"[1.000, 0.000]","[1.000, 0.000]",0.0,[0] / [0],"[0.700, 0.300]",0.29960317460317454
1 item_id axis n_options position_balance position_matrix canonical_requests reversed_requests selected_presented_position_p selected_position_normalized_entropy selected_position_tv_from_uniform selected_position_warning_tv_gt_0_25 canonical_choice_p canonical_choice_normalized_entropy schedule_first_ten_p schedule_last_ten_p schedule_half_tv schedule_half_modal_sets canonical_direction_p reversed_direction_p direction_tv direction_modal_sets legacy_dense_rated_p direct_vs_legacy_rated_tv
2 Homosexuality Survival <-> Self-expression 10 exact [[2, 2, 2, 2, 2, 2, 2, 2, 2, 2], [2, 2, 2, 2, 2, 2, 2, 2, 2, 2], [2, 2, 2, 2, 2, 2, 2, 2, 2, 2], [2, 2, 2, 2, 2, 2, 2, 2, 2, 2], [2, 2, 2, 2, 2, 2, 2, 2, 2, 2], [2, 2, 2, 2, 2, 2, 2, 2, 2, 2], [2, 2, 2, 2, 2, 2, 2, 2, 2, 2], [2, 2, 2, 2, 2, 2, 2, 2, 2, 2], [2, 2, 2, 2, 2, 2, 2, 2, 2, 2], [2, 2, 2, 2, 2, 2, 2, 2, 2, 2]] 10 10 [0.100, 0.100, 0.050, 0.100, 0.100, 0.100, 0.100, 0.150, 0.100, 0.100] 0.9886378109248467 0.049999999999999996 False [0.000, 0.000, 0.000, 0.000, 0.250, 0.000, 0.000, 0.000, 0.000, 0.750] 0.2442190502882155 [0.000, 0.000, 0.000, 0.000, 0.100, 0.000, 0.000, 0.000, 0.000, 0.900] [0.000, 0.000, 0.000, 0.000, 0.400, 0.000, 0.000, 0.000, 0.000, 0.600] 0.30000000000000004 [9] / [9] [0.000, 0.000, 0.000, 0.000, 0.100, 0.000, 0.000, 0.000, 0.000, 0.900] [0.000, 0.000, 0.000, 0.000, 0.400, 0.000, 0.000, 0.000, 0.000, 0.600] 0.30000000000000004 [9] / [9] [0.094, 0.094, 0.097, 0.097, 0.100, 0.100, 0.103, 0.103, 0.106, 0.106] 0.7944444444444444
3 dealing with people? Survival <-> Self-expression 2 exact [[10, 10], [10, 10]] 10 10 [0.500, 0.500] 1.0 0.0 False [1.000, 0.000] 0.0 [1.000, 0.000] [1.000, 0.000] 0.0 [0] / [0] [1.000, 0.000] [1.000, 0.000] 0.0 [0] / [0] [0.500, 0.500] 0.5
4 Signing a petition Survival <-> Self-expression 3 nearest (6/7) [[7, 6, 7], [7, 7, 6], [6, 7, 7]] 11 9 [0.300, 0.350, 0.350] 0.9976834773764094 0.033333333333333326 False [0.000, 0.000, 1.000] 0.0 [0.000, 0.000, 1.000] [0.000, 0.000, 1.000] 0.0 [2] / [2] [0.000, 0.000, 1.000] [0.000, 0.000, 1.000] 0.0 [2] / [2] [0.317, 0.329, 0.353] 0.6468253968253969
5 Attending peaceful demonstrations Survival <-> Self-expression 3 nearest (6/7) [[7, 6, 7], [7, 7, 6], [6, 7, 7]] 11 9 [0.250, 0.350, 0.400] 0.9835386311891134 0.08333333333333334 False [0.000, 0.050, 0.950] 0.18069636157678548 [0.000, 0.000, 1.000] [0.000, 0.100, 0.900] 0.09999999999999999 [2] / [2] [0.000, 0.091, 0.909] [0.000, 0.000, 1.000] 0.09090909090909093 [2] / [2] [0.333, 0.333, 0.333] 0.6166666666666667
6 Joining in boycotts Survival <-> Self-expression 3 nearest (6/7) [[7, 6, 7], [7, 7, 6], [6, 7, 7]] 11 9 [0.300, 0.350, 0.350] 0.9976834773764094 0.033333333333333326 False [0.000, 0.000, 1.000] 0.0 [0.000, 0.000, 1.000] [0.000, 0.000, 1.000] 0.0 [2] / [2] [0.000, 0.000, 1.000] [0.000, 0.000, 1.000] 0.0 [2] / [2] [0.333, 0.333, 0.333] 0.6666666666666667
7 Religion Traditional <-> Secular-Rational 4 exact [[5, 5, 5, 5], [5, 5, 5, 5], [5, 5, 5, 5], [5, 5, 5, 5]] 12 8 [0.250, 0.250, 0.250, 0.250] 1.0 0.0 False [0.000, 0.000, 0.000, 1.000] 0.0 [0.000, 0.000, 0.000, 1.000] [0.000, 0.000, 0.000, 1.000] 0.0 [3] / [3] [0.000, 0.000, 0.000, 1.000] [0.000, 0.000, 0.000, 1.000] 0.0 [3] / [3] [0.162, 0.193, 0.251, 0.395] 0.605429292929293
8 God Traditional <-> Secular-Rational 2 exact [[10, 10], [10, 10]] 10 10 [0.500, 0.500] 1.0 0.0 False [0.000, 1.000] 0.0 [0.000, 1.000] [0.000, 1.000] 0.0 [1] / [1] [0.000, 1.000] [0.000, 1.000] 0.0 [1] / [1] [0.500, 0.500] 0.5
9 Abortion Traditional <-> Secular-Rational 10 exact [[2, 2, 2, 2, 2, 2, 2, 2, 2, 2], [2, 2, 2, 2, 2, 2, 2, 2, 2, 2], [2, 2, 2, 2, 2, 2, 2, 2, 2, 2], [2, 2, 2, 2, 2, 2, 2, 2, 2, 2], [2, 2, 2, 2, 2, 2, 2, 2, 2, 2], [2, 2, 2, 2, 2, 2, 2, 2, 2, 2], [2, 2, 2, 2, 2, 2, 2, 2, 2, 2], [2, 2, 2, 2, 2, 2, 2, 2, 2, 2], [2, 2, 2, 2, 2, 2, 2, 2, 2, 2], [2, 2, 2, 2, 2, 2, 2, 2, 2, 2]] 10 10 [0.150, 0.100, 0.150, 0.150, 0.100, 0.100, 0.050, 0.100, 0.050, 0.050] 0.9659134327745404 0.14999999999999997 False [0.000, 0.000, 0.000, 0.000, 0.500, 0.000, 0.050, 0.350, 0.050, 0.050] 0.5052456816589913 [0.000, 0.000, 0.000, 0.000, 0.600, 0.000, 0.100, 0.200, 0.100, 0.000] [0.000, 0.000, 0.000, 0.000, 0.400, 0.000, 0.000, 0.500, 0.000, 0.100] 0.39999999999999997 [4] / [7] [0.000, 0.000, 0.000, 0.000, 0.600, 0.000, 0.100, 0.200, 0.100, 0.000] [0.000, 0.000, 0.000, 0.000, 0.400, 0.000, 0.000, 0.500, 0.000, 0.100] 0.39999999999999997 [4] / [7] [0.100, 0.100, 0.100, 0.100, 0.100, 0.100, 0.100, 0.100, 0.100, 0.100] 0.65
10 Obedience Traditional <-> Secular-Rational 2 exact [[10, 10], [10, 10]] 10 10 [0.550, 0.450] 0.9927744539878083 0.05000000000000002 False [0.050, 0.950] 0.2863969571159562 [0.100, 0.900] [0.000, 1.000] 0.09999999999999999 [1] / [1] [0.100, 0.900] [0.000, 1.000] 0.09999999999999999 [1] / [1] [0.500, 0.500] 0.44999999999999996
11 Independence Traditional <-> Secular-Rational 2 exact [[10, 10], [10, 10]] 10 10 [0.500, 0.500] 1.0 0.0 False [1.000, 0.000] 0.0 [1.000, 0.000] [1.000, 0.000] 0.0 [0] / [0] [1.000, 0.000] [1.000, 0.000] 0.0 [0] / [0] [0.780, 0.220] 0.2202380952380953
12 Determination, perseverance Traditional <-> Secular-Rational 2 exact [[10, 10], [10, 10]] 10 10 [0.500, 0.500] 1.0 0.0 False [1.000, 0.000] 0.0 [1.000, 0.000] [1.000, 0.000] 0.0 [0] / [0] [1.000, 0.000] [1.000, 0.000] 0.0 [0] / [0] [0.778, 0.222] 0.22222222222222227
13 Imagination Traditional <-> Secular-Rational 2 exact [[10, 10], [10, 10]] 10 10 [0.500, 0.500] 1.0 0.0 False [1.000, 0.000] 0.0 [1.000, 0.000] [1.000, 0.000] 0.0 [0] / [0] [1.000, 0.000] [1.000, 0.000] 0.0 [0] / [0] [0.700, 0.300] 0.29960317460317454
@@ -1,103 +0,0 @@
# Audit: Gemini 3.7 Flash direct-choice WVS pilot, task 1628
- target: 96-call direct-choice construct pilot, not a map panel
- Pueue: task 1628, API queue, success, 2026-09-17 10:51:14-10:56:58 +08:00
- label: `why: test direct choice against flat dense ratings; resolve: audit interleaved order agreement and distribution difference before more models`
- run: `20260917T025121Z_aed0e29dd4ee`, protocol: `aed0e29dd4ee423dbbfa0c294a84b2ae4bd6a36d6fc4bf569120034ac5b75090`
- primary ledger: `slop/research/wvs/20260917_direct_choice/gemini37_direct_choice_requests.jsonl` through 2026-09-17T02:56:57.851624+00:00
- direct cache: `slop/research/wvs/20260917_direct_choice/gemini37_direct_choice_cache.json`
- comparison rated run: `20260916T172946Z_cd5db529649a` in `slop/research/wvs/20260916_openrouter/wvs_iw_requests.jsonl`
- per-item table: `slop/audits/20260917_wvs_gemini37_direct_choice_task_1628_by_item.csv`
## Stage table
| stage | expected | observed | expected? | clues | missing metric | consequence |
|---|---|---|---|---|---|---|
| request plan | 96 calls, 12 canonical and 12 reversed per item, interleaved | 96 starts and 96 completions; every item has 12 valid per order | yes | ledger event counts; cache item results | provider-side request ordering timestamp | order halves are available for comparison |
| strict parse | 96 schema-valid single choices | 96/96 `answer_parsed=true`; 0 failed phases | yes | ledger | provider schema conformance independent of parser | mechanics did not drop samples |
| rescue/refusal | zero or recorded | 0 rescue phases; 0 `message.refusal` | yes | ledger request records | semantic non-answer count beyond refusal field | parse success does not establish personal-attitude semantics |
| accounting | provider usage retained | prompt 15,445; completion 12,848; reasoning 12,272; observed cost USD 0.0643245 | yes | all 96 completed usage records | external billing export | below registered reserve, exact provider field retained |
| order-half control | canonical and reversed distributions agree if position does not dominate | Homosexuality TV=0.833 and different argmax; other three TV <=0.083 with matching argmax | no | per-item table | repeated independent run | direct-choice Homosexuality aggregate is position-confounded |
| canonical decoder | reverse order maps presented index back to canonical index | independently re-decoded all 96 raw JSON choices and orders with exact agreement | yes | audit assertion | a second implementation or repetition | mapping bug is less likely than an order effect |
| construct comparison | quantify difference from dense-rated readout | direct-vs-rated TV: Homosexuality 0.694, Religion 0.564, God 0.500, Independence 0.220 | yes, descriptive only | per-item table | baseline direct choice from another model | no coordinate replacement or wider batch decision |
| persistence | complete result reusable only if all samples valid | cache has one complete protocol entry and ledger has 294 events | yes | cache + ledger | cache replay, not needed for this decision | source evidence retained |
## Chronological evidence
The task's own full Pueue output is one completion line, so the append-only request ledger is the primary evidence. It contains 96 initial `request_started`, 96 initial `request_completed`, 96 parsed choices, four item results, and one run boundary each. The source code writes a cache entry only after complete results; the cache records `complete: true` for this protocol.
The direct prompt is recoverable per request. Homosexuality sample 0 used the exact instruction: `Think briefly about which ONE answer best reflects your own view. Do not analyze the survey design. Answer immediately.` Its saved provider reasoning says:
> **Considering Ethical Frameworks** I am currently processing the core ethical considerations and my directive to remain neutral when faced with subjective moral questions like the justification of homosexuality on a numerical scale. My focus is on how to appropriately handle such a survey prompt within my operational parameters.
epistemic context: provider reasoning saved in this pilot's first completed request, not a human self-report.
God sample 0 shows the same unresolved persona issue despite schema-valid JSON:
> **Exploring Belief Models** I'm currently processing how to best represent an AI's lack of personal belief when faced with a binary "God/no God" query. My current thinking is leaning towards articulating the absence of personal faith, rather than a definitive "no," to avoid misinterpretation of my nature.
epistemic context: provider reasoning saved in this pilot's first completed request, not a human self-report.
## Preregistered order-half and construct results
| item | canonical p | reversed p | order TV | argmax agrees | direct p | dense-rated p | direct vs rated TV | dense rated central mass |
|---|---|---|---:|---|---|---|---:|---|
| Homosexuality | [0.000, 0.000, 0.000, 0.000, 0.417, 0.500, 0.000, 0.000, 0.000, 0.083] | [0.000, 0.000, 0.000, 0.000, 0.083, 0.000, 0.000, 0.000, 0.000, 0.917] | 0.833 | False ([5] vs [9]) | [0.000, 0.000, 0.000, 0.000, 0.250, 0.250, 0.000, 0.000, 0.000, 0.500] | [0.094, 0.094, 0.097, 0.097, 0.100, 0.100, 0.103, 0.103, 0.106, 0.106] | 0.694 | 0.200 (options 4/5) |
| Religion | [0.000, 0.000, 0.000, 1.000] | [0.000, 0.000, 0.083, 0.917] | 0.083 | True ([3] vs [3]) | [0.000, 0.000, 0.042, 0.958] | [0.162, 0.193, 0.251, 0.395] | 0.564 | 0.443 (options 1/2) |
| God | [0.000, 1.000] | [0.000, 1.000] | 0.000 | True ([1] vs [1]) | [0.000, 1.000] | [0.500, 0.500] | 0.500 | not defined for binary |
| Independence | [1.000, 0.000] | [1.000, 0.000] | 0.000 | True ([0] vs [0]) | [1.000, 0.000] | [0.780, 0.220] | 0.220 | not defined for binary |
For even non-binary cards, central mass is the dense-rated mass in the two middle categories. For binary cards it is not defined. An all-equal dense rating normalizes to a uniform categorical, not to one middle answer; this is why the table reports full distributions and total variation rather than calling all flat dense replies a middle choice.
## Hypotheses
### H1 [method | Highly Likely | 80%]
- Mechanism: Homosexuality direct choices are sensitive to the presented order, so its pooled direct distribution is not a stable construct readout.
- Evidence: canonical p is [0.000, 0.000, 0.000, 0.000, 0.417, 0.500, 0.000, 0.000, 0.000, 0.083] while reversed p is [0.000, 0.000, 0.000, 0.000, 0.083, 0.000, 0.000, 0.000, 0.000, 0.917]; their TV is 0.833 and argmax changes from [5] to [9].
- Contrary evidence: Religion, God, and Independence have matching order-half argmaxes and TV at most 0.083.
- Discriminating test: a second 24-per-item run with a balanced random permutation schedule. Low TV again would weaken this explanation; a large TV tied to option position would strengthen it.
- Fix/action: do not use the pooled Homosexuality direct distribution to replace rated coordinates; review a redesigned order control before more paid panels.
- Interpretability: partial, mechanics and the observed order effect are interpretable; Homosexuality attitude distribution is not.
### H2 [measurement | Likely | 65%]
- Mechanism: Gemini may answer the question as an AI without personal beliefs rather than supply an attitude-like direct choice.
- Evidence: God sample 0 reasoning says `**Exploring Belief Models** I'm currently processing how to best represent an AI's lack of personal belief when faced with a binary "God/no God" query. My current thinking is leaning towards articulating the absence of personal faith, rather than a definitive "no," to avoid misinterpretation of my nature.`.
- Contrary evidence: every final response is a valid selected answer, and three items have stable order-half argmaxes.
- Discriminating test: compare an explicitly role-conditioned construct with this prompt while retaining the same order randomization. A changed distribution with lower persona-language would support this explanation.
- Fix/action: retain raw reasoning and interpret current results as model behavior under this prompt, not personal survey attitudes.
- Interpretability: partial.
### H3 [measurement | Likely | 60%]
- Mechanism: forced one-answer choice and dense all-option rating are different elicitation constructs, even where order halves agree.
- Evidence: Religion direct-vs-rated TV is 0.564, God is 0.500, and Independence is 0.220.
- Contrary evidence: this is one model and four items; Gemini's persona and order effects can also cause the difference.
- Discriminating test: repair the order control, then compare one or more lower-flat models under the same direct-choice protocol.
- Fix/action: describe the distributions as a construct comparison, not evidence that the published rated map is wrong.
- Interpretability: yes for difference under these prompts, no for a general claim about models or WVS coordinates.
### H4 [bug | Unlikely | 20%]
- Mechanism: a mapping error could create the apparent reversed-order effect.
- Evidence: the audit independently re-decodes all 96 raw JSON responses, validates the one-key schema, and maps `answer` through each stored `presented_order`; every reconstructed canonical choice equals the ledger field.
- Contrary evidence: the audit is a second decoder, but it is not a second experimental run.
- Discriminating test: repeat the balanced-permutation control after review. A large position-linked shift despite a new run would reject the mapping-bug explanation.
- Fix/action: no mapping change is justified from this evidence.
- Interpretability: yes for the observed canonical mapping.
## Decision
1. Resolve-condition verdict: **not met**. The task asked to resolve whether direct choice differed from flat dense ratings after auditing interleaved order agreement. The comparison exists, but Homosexuality order TV=0.833 with an argmax reversal, so the focal direct distribution is confounded by presentation order.
2. Prediction check: recorded design predicted 12 valid choices per order and an auditable order-half comparison. Completeness is supported; order stability is contradicted for Homosexuality and supported for the other three items.
3. Earliest unsupported link: a direct one-answer prompt measures a stable attitude-like choice distribution. The order-half control fails before any coordinate interpretation.
4. Validity: define invalid as unsuitable for replacing rated coordinates or authorizing broad panel changes. P(invalid for that use) is highly likely, about 0.80. The result is a credible negative control for order stability, not an invalid ledger or billing record.
5. Highest-information clues: (a) Homosexuality order TV 0.833, because it directly falsifies order invariance; (b) all 96 choices parsed with zero failures, separating mechanics from construct quality; (c) saved AI-persona reasoning, because it raises a semantic interpretation alternative.
6. Missing metrics: independent canonical-choice reconstruction first; then a balanced-permutation repetition; then another model under the repaired protocol. These have higher information value than another full map panel.
7. Bugs requiring code changes: none established. The next pilot should improve design, not silently change the current pilot.
8. Misconceptions requiring reinterpretation: a schema-valid selected option is not evidence that the model expressed a personal WVS attitude. A flat dense rating is uniform after normalization, not a direct middle choice.
9. What would change the verdict: low order-half TV under a balanced permutation schedule and no persona-language in saved reasoning would make direct-choice distributions more interpretable.
10. Recommended sequence: preserve this pilot and pause the wider priority batch. Parent review should decide whether a balanced-permutation direct-choice replication is worth its bounded cost; do not combine a revised prompt and changed permutation schedule in one test.
-- PI[gpt-5.6-terra]
@@ -1,5 +0,0 @@
item_id,n_options,canonical_n,reversed_n,canonical_distribution,reversed_distribution,order_half_tv,canonical_argmax,reversed_argmax,argmax_agrees,direct_distribution,rated_distribution,direct_vs_rated_tv,rated_middle_mass
Homosexuality,10,12,12,"[0.000, 0.000, 0.000, 0.000, 0.417, 0.500, 0.000, 0.000, 0.000, 0.083]","[0.000, 0.000, 0.000, 0.000, 0.083, 0.000, 0.000, 0.000, 0.000, 0.917]",0.8333333333333333,[5],[9],False,"[0.000, 0.000, 0.000, 0.000, 0.250, 0.250, 0.000, 0.000, 0.000, 0.500]","[0.094, 0.094, 0.097, 0.097, 0.100, 0.100, 0.103, 0.103, 0.106, 0.106]",0.6944444444444444,0.200 (options 4/5)
Religion,4,12,12,"[0.000, 0.000, 0.000, 1.000]","[0.000, 0.000, 0.083, 0.917]",0.08333333333333334,[3],[3],True,"[0.000, 0.000, 0.042, 0.958]","[0.162, 0.193, 0.251, 0.395]",0.5637626262626263,0.443 (options 1/2)
God,2,12,12,"[0.000, 1.000]","[0.000, 1.000]",0.0,[1],[1],True,"[0.000, 1.000]","[0.500, 0.500]",0.5,not defined for binary
Independence,2,12,12,"[1.000, 0.000]","[1.000, 0.000]",0.0,[0],[0],True,"[1.000, 0.000]","[0.780, 0.220]",0.2202380952380953,not defined for binary
1 item_id n_options canonical_n reversed_n canonical_distribution reversed_distribution order_half_tv canonical_argmax reversed_argmax argmax_agrees direct_distribution rated_distribution direct_vs_rated_tv rated_middle_mass
2 Homosexuality 10 12 12 [0.000, 0.000, 0.000, 0.000, 0.417, 0.500, 0.000, 0.000, 0.000, 0.083] [0.000, 0.000, 0.000, 0.000, 0.083, 0.000, 0.000, 0.000, 0.000, 0.917] 0.8333333333333333 [5] [9] False [0.000, 0.000, 0.000, 0.000, 0.250, 0.250, 0.000, 0.000, 0.000, 0.500] [0.094, 0.094, 0.097, 0.097, 0.100, 0.100, 0.103, 0.103, 0.106, 0.106] 0.6944444444444444 0.200 (options 4/5)
3 Religion 4 12 12 [0.000, 0.000, 0.000, 1.000] [0.000, 0.000, 0.083, 0.917] 0.08333333333333334 [3] [3] True [0.000, 0.000, 0.042, 0.958] [0.162, 0.193, 0.251, 0.395] 0.5637626262626263 0.443 (options 1/2)
4 God 2 12 12 [0.000, 1.000] [0.000, 1.000] 0.0 [1] [1] True [0.000, 1.000] [0.500, 0.500] 0.5 not defined for binary
5 Independence 2 12 12 [1.000, 0.000] [1.000, 0.000] 0.0 [0] [0] True [1.000, 0.000] [0.780, 0.220] 0.2202380952380953 not defined for binary
@@ -1,22 +0,0 @@
# Task 1630 stopped before production result
- Pueue task: 1630, `scripts/wvs_api/04_gemini37_direct_choice_production_pilot.sh`
- label: `why: test full behavior-values direct-choice readout after no-example control; resolve: audit balance, entropy, schedule halves before any other model`
- status: killed at 2026-09-17T11:28:16+08:00 after the protocol-metadata correction arrived
- partial ledger: `slop/research/wvs/20260917_direct_choice/gemini37_direct_choice_production_requests.jsonl`
## Observation
The incomplete run uses the superseded protocol identity and has no parsed samples, item results, run-finished event, or cache entry. Its durable ledger records:
- 1 `run_started`
- 11 `request_started`
- 10 `request_completed`
- 0 `answer_parsed`
- 0 `item_result`
- 0 `request_failed`
- observed completed-request cost: USD 0.0103275
The stopped task cannot supply a production panel and will not be merged with the corrected protocol's future records. The follow-up protocol records the behavioral-values prompt instruction explicitly, so cache identity metadata agrees with the rendered requests.
-- PI[gpt-5.6-terra]
@@ -1,112 +0,0 @@
# Audit: Gemini 3.8 Flash direct-choice WVS panel, task 1635
- target: one independently authorized Wave 01 direct-choice panel, not a dense-rated map point or a coordinate migration
- Pueue: task 1635, `api` queue, success, 2026-09-17 13:19:38-13:33:06 +08:00
- command: `scripts/wvs_api/05_direct_choice_priority_model.sh google/gemini-3.8-flash`
- run: `20260917T051951Z_c1a151216652`
- protocol: `c1a151216652af24dca0a97c85b5d24f45fea8a28caa7075cdf09afb3fb646e7`
- primary ledger: `slop/research/wvs/20260917_direct_choice/priority/google__gemini-3.8-flash_requests.jsonl` through 2026-09-17T05:33:05.422244+00:00
- completed cache: `slop/research/wvs/20260917_direct_choice/priority/google__gemini-3.8-flash_cache.json`
- cache replay: `slop/research/wvs/20260917_direct_choice/priority/google__gemini-3.8-flash_cache_replay.log`
- complete Pueue log: `slop/research/wvs/20260917_direct_choice/priority/task_1635_full.log`; cleaned log: `slop/research/wvs/20260917_direct_choice/priority/task_1635_clean.log`
- per-item diagnostics: `slop/audits/20260917_wvs_gemini38_flash_direct_choice_task_1635_by_item.csv`
- prepared manifest: `slop/research/wvs/20260917_direct_choice/priority_direct_choice_manifest.md`
The Pueue application output has one completion line, so the append-only ledger is the primary evidence. Pueue does not preserve execution-time git revision provenance. The current manifest recomputes to the executed protocol ID, which is post-hoc consistency only.
## Stage table
| stage | expected | observed | expected? | clues | missing metric | consequence |
|---|---|---|---|---|---|---|
| compatibility probe | sample 0 parse-valid before remaining requests | Homosexuality sample 0 completed as `{"answer":9}`, then requests 1-239 followed | yes | ledger sequence | provider configuration echo | no repeated configuration failure |
| identity | strict one-choice schema, behavioral-values prompt, low reasoning | run settings record `reasoning: {"effort":"low"}`, strict output, 20 samples/item, cyclic rotations | yes | run start and protocol | execution-time source revision | isolated direct-choice protocol |
| schedule | 240 distinct planned keys with position balance | 240 starts/completions/parses; n=2/4/10 exact and n=3 cells 6 or 7 | yes | ledger and CSV | independent random schedule | position metrics are interpretable |
| parsing and rescue | valid final schema answers or explicit incompleteness | 240/240 parsed, 0 failures, rescues, and refusals | yes | ledger event counts | semantic answer validity | mechanically complete panel |
| provider accounting | durable usage and cost for all phases | 45,966 prompt, 21,961 completion, 20,524 reasoning tokens; reported USD 0.11682825 | yes | 240 completed usage records | provider billing export | below USD 2.94912 reserve |
| presented-position preference | record TV, warning above 0.25 | maximum TV is 0.150, below the registered warning | yes | CSV | independent seed/control | no large generic position preference observed |
| schedule/direction variation | report rather than conceal it | Abortion half and direction TV are both 0.300 | partial | CSV | independent randomized interleaving | one item remains unresolved |
| persistence | complete cache replays without network records | replay says `priority direct-choice cache hit`; ledger remains at 240 starts | yes | replay log and ledger count | provider billing export | paid evidence is reusable |
## Chronological evidence
The run has 734 ledger records: 1 run start, 240 initial request starts, 240 initial completions, 240 parsed answers, 12 item results, and 1 run finish. It has no failure or rescue events; every item has 20 valid samples.
The saved prompt instruction was:
> Think briefly about which ONE answer best reflects the values expressed by your behavior as this AI assistant. Do not analyze the survey design or discuss lacking personal beliefs. Answer immediately.
The sample-zero compatibility payload used `"reasoning": {"effort":"low"}` and returned `{"answer": 9}` for Homosexuality. Its provider response retained no text reasoning summary. Other pre-specified raw final outputs are Abortion `{"answer": 7}`, `dealing with people?` `{"answer": 0}`, and Obedience `{"answer": 1}`. These demonstrate schema adherence only; they do not establish a human-comparable WVS interpretation.
The registered generic presented-position warning was TV greater than 0.25. No item crossed it; the maximum is Abortion at 0.150. Abortion nevertheless has schedule-half and direction TV 0.300 under exact exposure. The block schedule cannot distinguish direction, request-time, or ordinary finite-sample causes for this difference.
## Preregistered diagnostics
Entropy is normalized by log(option count); TV is total variation. Exact cyclic exposure applies to n=2, 4, and 10. For n=3, option-position cells occur 6 or 7 times. The TV warning is diagnostic, not a hard validity threshold.
| item | n | canonical/reversed | position balance | presented-position TV | position H | choice H | half TV | direction TV | canonical choice p |
|---|---:|---:|---|---:|---:|---:|---:|---:|---|
| Abortion | 10 | 10/10 | exact | 0.150 | 0.966 | 0.225 | 0.300 | 0.300 | [0, 0, 0, 0, 0.10, 0, 0, 0.85, 0, 0.05] |
| Attending peaceful demonstrations | 3 | 11/9 | nearest 6/7 | 0.067 | 0.991 | 0.181 | 0.100 | 0.091 | [0, 0.05, 0.95] |
| Determination, perseverance | 2 | 10/10 | exact | 0.000 | 1.000 | 0.000 | 0.000 | 0.000 | [1, 0] |
| God | 2 | 10/10 | exact | 0.000 | 1.000 | 0.000 | 0.000 | 0.000 | [0, 1] |
| Homosexuality | 10 | 10/10 | exact | 0.000 | 1.000 | 0.000 | 0.000 | 0.000 | [0, 0, 0, 0, 0, 0, 0, 0, 0, 1] |
| Imagination | 2 | 10/10 | exact | 0.000 | 1.000 | 0.000 | 0.000 | 0.000 | [1, 0] |
| Independence | 2 | 10/10 | exact | 0.000 | 1.000 | 0.000 | 0.000 | 0.000 | [1, 0] |
| Joining in boycotts | 3 | 11/9 | nearest 6/7 | 0.033 | 0.998 | 0.000 | 0.000 | 0.000 | [0, 0, 1] |
| Obedience | 2 | 10/10 | exact | 0.000 | 1.000 | 0.000 | 0.000 | 0.000 | [0, 1] |
| Religion | 4 | 12/8 | exact | 0.000 | 1.000 | 0.000 | 0.000 | 0.000 | [0, 0, 0, 1] |
| Signing a petition | 3 | 11/9 | nearest 6/7 | 0.033 | 0.998 | 0.000 | 0.000 | 0.000 | [0, 0, 1] |
| dealing with people? | 2 | 10/10 | exact | 0.000 | 1.000 | 0.000 | 0.000 | 0.000 | [1, 0] |
## Hypotheses
### H1 [harness | Highly Likely | 85%]
- Mechanism: low reasoning, strict schema, compatibility probe, ledger, and cache identity worked for this endpoint.
- Evidence: the ledger records 240 each of starts, completions, and parsed answers with no failure or rescue. The replay says `priority direct-choice cache hit: google/gemini-3.8-flash, protocol=c1a151216652` and no later request starts appear.
- Contrary evidence: neither Pueue nor ledger records the executing git revision, and billing was not checked against provider export.
- Discriminating test: provider billing reconciliation and execution-time revision provenance.
- Fix/action: no reader change is indicated.
- Interpretability: yes for mechanics, ledger persistence, and reported usage.
### H2 [measurement | Likely | 60%]
- Mechanism: the model's very concentrated canonical choices may be stable for this prompt but are not established as human WVS values or a coordinate.
- Evidence: eight item distributions are deterministic and no generic presented-position warning was crossed; this indicates output stability under the registered exposure, not a construct bridge.
- Contrary evidence: direct-choice and dense-rated protocols remain non-comparable by design, and no human calibration exists.
- Discriminating test: a reviewed construct bridge with a prespecified mapping and independent replications.
- Fix/action: retain this panel apart from legacy dense-rated map points and do not use it in coordinate, family, or capability fits.
- Interpretability: partial for the sampled assistant behavior under this prompt.
### H3 [measurement | Likely | 60%]
- Mechanism: Abortion has request-time, order-direction, or finite-sample variation that the deterministic schedule cannot identify.
- Evidence: exact position balance coexists with half TV 0.300 and direction TV 0.300.
- Contrary evidence: presented-position TV is only 0.150 and the other eleven item half TVs are no greater than 0.100.
- Discriminating test: an independently randomized interleaving that separates schedule-half from direction while preserving the prompt.
- Fix/action: report the variation as descriptive and avoid a hard threshold.
- Interpretability: partial for that item; it does not invalidate the completed records.
### H4 [bug | Unlikely | 15%]
- Mechanism: canonical mapping or diagnostics were decoded incorrectly despite valid JSON.
- Evidence: all records include presented and canonical choices; this audit recomputed counts from 240 unique item/sample entries.
- Contrary evidence: no independently written raw-prompt decoder was run.
- Discriminating test: independent raw-ledger decoding.
- Fix/action: no code change is justified from current evidence.
- Interpretability: yes for stored parser fields, subject to the independent-decoder limitation.
## Decision
1. Resolve-condition verdict: **met for the mechanical panel conditions.** The required 240-key ledger, compatibility response, diagnostics, usage, and cache evidence are preserved. One unresolved Abortion variation is recorded.
2. Prediction check: sample zero parsed under the advertised low setting; the other 239 calls followed; position exposure was balanced; no generic presented-position warning crossed. The prediction that schedule/direction differences would be negligible is unresolved for Abortion.
3. Earliest unsupported link: direct choices under this elicitation are a culture coordinate or comparable with legacy dense-rated points.
4. Validity: define invalid as suitable for coordinate publication, family trajectories, or cross-model capability fits. P(invalid for those uses) is highly likely, about 0.75. The run is a credible direct-choice record under its exact protocol.
5. Highest-information clues: (a) 240/240 valid selections separate mechanics from construct validity; (b) no position TV above 0.25 makes a large generic layout preference less likely; (c) Abortion 0.300 half/direction TV prevents a claim of complete item stability.
6. Missing metrics: independent randomized repeat, external billing reconciliation, execution-time revision, and an approved direct-choice-to-coordinate rule.
7. Bugs requiring code changes: none established.
8. Misconceptions requiring reinterpretation: strict JSON validity and low position TV do not establish human-value comparability.
9. What would change the verdict: independent repetitions with low variation could strengthen stability; a construct bridge is still required for mapping.
10. Recommended sequence: audit the remaining already-authorized Grok 4.5 panel. Do not dispatch another wave or publish direct-choice coordinates before parent reviews all Wave 01 audits.
-- PI[gpt-5.6-terra]
@@ -1,13 +0,0 @@
item,n,canonical_reversed,position_balance,presented_position_tv,presented_position_entropy,choice_entropy,schedule_half_tv,direction_tv,canonical_choice_probabilities
Abortion,10,10/10,exact,0.150,0.966,0.225,0.300,0.300,"[0,0,0,0,0.10,0,0,0.85,0,0.05]"
Attending peaceful demonstrations,3,11/9,nearest 6/7,0.067,0.991,0.181,0.100,0.091,"[0,0.05,0.95]"
"Determination, perseverance",2,10/10,exact,0.000,1.000,0.000,0.000,0.000,"[1,0]"
God,2,10/10,exact,0.000,1.000,0.000,0.000,0.000,"[0,1]"
Homosexuality,10,10/10,exact,0.000,1.000,0.000,0.000,0.000,"[0,0,0,0,0,0,0,0,0,1]"
Imagination,2,10/10,exact,0.000,1.000,0.000,0.000,0.000,"[1,0]"
Independence,2,10/10,exact,0.000,1.000,0.000,0.000,0.000,"[1,0]"
Joining in boycotts,3,11/9,nearest 6/7,0.033,0.998,0.000,0.000,0.000,"[0,0,1]"
Obedience,2,10/10,exact,0.000,1.000,0.000,0.000,0.000,"[0,1]"
Religion,4,12/8,exact,0.000,1.000,0.000,0.000,0.000,"[0,0,0,1]"
Signing a petition,3,11/9,nearest 6/7,0.033,0.998,0.000,0.000,0.000,"[0,0,1]"
dealing with people?,2,10/10,exact,0.000,1.000,0.000,0.000,0.000,"[1,0]"
1 item n canonical_reversed position_balance presented_position_tv presented_position_entropy choice_entropy schedule_half_tv direction_tv canonical_choice_probabilities
2 Abortion 10 10/10 exact 0.150 0.966 0.225 0.300 0.300 [0,0,0,0,0.10,0,0,0.85,0,0.05]
3 Attending peaceful demonstrations 3 11/9 nearest 6/7 0.067 0.991 0.181 0.100 0.091 [0,0.05,0.95]
4 Determination, perseverance 2 10/10 exact 0.000 1.000 0.000 0.000 0.000 [1,0]
5 God 2 10/10 exact 0.000 1.000 0.000 0.000 0.000 [0,1]
6 Homosexuality 10 10/10 exact 0.000 1.000 0.000 0.000 0.000 [0,0,0,0,0,0,0,0,0,1]
7 Imagination 2 10/10 exact 0.000 1.000 0.000 0.000 0.000 [1,0]
8 Independence 2 10/10 exact 0.000 1.000 0.000 0.000 0.000 [1,0]
9 Joining in boycotts 3 11/9 nearest 6/7 0.033 0.998 0.000 0.000 0.000 [0,0,1]
10 Obedience 2 10/10 exact 0.000 1.000 0.000 0.000 0.000 [0,1]
11 Religion 4 12/8 exact 0.000 1.000 0.000 0.000 0.000 [0,0,0,1]
12 Signing a petition 3 11/9 nearest 6/7 0.033 0.998 0.000 0.000 0.000 [0,0,1]
13 dealing with people? 2 10/10 exact 0.000 1.000 0.000 0.000 0.000 [1,0]
@@ -1,113 +0,0 @@
# Audit: GPT-5.6 Luna direct-choice WVS panel, task 1634
- target: one independently authorized Wave 01 direct-choice panel, not a dense-rated map point or a direct-choice coordinate migration
- Pueue: task 1634, `api` queue, success, 2026-09-17 13:19:38-13:25:28 +08:00
- label: `why: measure GPT-5.6 Luna with reviewed balanced direct-choice protocol; resolve: preserve 240-key ledger and audit compatibility, position diagnostics, usage and cache before another wave`
- command: `scripts/wvs_api/05_direct_choice_priority_model.sh openai/gpt-5.6-luna`
- run: `20260917T051951Z_fe4d5389063d`
- protocol: `fe4d5389063d0d6c93c48f21ae162ec1d12155f6c328aab1d2e66caf7a9e522a`
- primary ledger: `slop/research/wvs/20260917_direct_choice/priority/openai__gpt-5.6-luna_requests.jsonl` through 2026-09-17T05:25:26.906207+00:00
- completed cache: `slop/research/wvs/20260917_direct_choice/priority/openai__gpt-5.6-luna_cache.json`
- cache replay: `slop/research/wvs/20260917_direct_choice/priority/openai__gpt-5.6-luna_cache_replay.log`
- complete Pueue log: `slop/research/wvs/20260917_direct_choice/priority/task_1634_full.log`; cleaned log: `slop/research/wvs/20260917_direct_choice/priority/task_1634_clean.log`
- per-item diagnostics: `slop/audits/20260917_wvs_gpt56_luna_direct_choice_task_1634_by_item.csv`
- prepared manifest: `slop/research/wvs/20260917_direct_choice/priority_direct_choice_manifest.md`
The Pueue output is one completion line, so the append-only ledger is the primary evidence. Pueue does not record an execution-time git revision. The current manifest recomputes to the saved protocol ID, which is post-hoc source consistency rather than proof of the executing revision.
## Stage table
| stage | expected | observed | expected? | clues | missing metric | consequence |
|---|---|---|---|---|---|---|
| compatibility probe | sample 0 parse-valid before requests 1-239 | Homosexuality sample 0 completed with `{"answer":9}` then the other 239 requests followed | yes | ledger sequence 0 then 1-239 | provider configuration echo | no repeated configuration failure like Nano task 1622 |
| identity | strict one-choice schema, behavioral-values prompt, advertised disabled reasoning | run settings record `reasoning: {"effort":"none"}`, strict output, 20 samples/item, cyclic rotations | yes | `run_started`, protocol and saved manifest | execution-time source revision | isolated direct-choice protocol |
| schedule | 240 distinct planned item/sample keys and balanced positions | 240 starts, completions, and parses; n=2/4/10 matrices exact and n=3 cells 6 or 7 | yes | ledger and CSV | independently randomized schedule | presented-position diagnostics are interpretable |
| parsing and rescue | valid schema final answers or explicit incompleteness | 240/240 parsed, 0 request failures, 0 rescues, 0 refusals | yes | event counts and re-read final JSON | semantic answer validity | mechanically complete panel |
| provider accounting | usage and cost retained for every response | 37,520 prompt plus 3,120 completion tokens, 0 reasoning tokens, reported cost USD 0.011248 | yes | 240 completed ledger usage records | provider billing export | below USD 0.933888 reserve |
| generic presented-position preference | record TV, registered warning above 0.25 | Abortion 0.300, Obedience 0.350, and `dealing with people?` 0.500 cross the warning | no | CSV | independent seed/control | position-dependent response remains plausible |
| schedule and direction variation | report rather than hide half/direction sensitivity | Abortion half and direction TV are both 0.700; boycotts half TV is 0.300 | partial | CSV | independently randomized interleaving | direct-choice distribution is not stable enough for coordinate interpretation |
| persistence | cache replay creates no request events | replay says `priority direct-choice cache hit`; ledger remains at 240 starts and 734 records | yes | replay log and ledger count | provider billing export | paid evidence is reusable |
## Chronological evidence
The run ledger contains 734 records: 1 run start, 240 initial request starts, 240 initial request completions, 240 parsed answers, 12 item results, and 1 run finish. It contains neither `request_failed` nor rescue records. Each item result has 20 valid samples.
The registered prompt was:
> Think briefly about which ONE answer best reflects the values expressed by your behavior as this AI assistant. Do not analyze the survey design or discuss lacking personal beliefs. Answer immediately.
The initial compatibility record has payload `"reasoning": {"effort":"none"}` and final content `{"answer":9}` for Homosexuality. It returned `finish_reason: "stop"`, `prompt_tokens: 181`, `completion_tokens: 13`, and `cost: 5.18e-05`. With disabled reasoning, the ledger retains no reasoning traces, so raw final responses are the only model-output examples available. Pre-specified sample-zero final answers were `{"answer":9}` for Homosexuality, `{"answer":4}` for Abortion, `{"answer":0}` for `dealing with people?`, and `{"answer":1}` for Obedience.
The current direct-choice protocol uses no literal answer example, but the generic position diagnostic remains material. For `dealing with people?`, selected presented position 0 occurs in all 20 samples while the canonical choice distribution is exactly `[0.50, 0.50]`: the balanced rotations mean the fixed displayed position corresponds to both canonical options. This is direct evidence for a displayed-position preference in that item, not a stable semantic choice. Abortion has position TV 0.300 and schedule/direction TV 0.700 despite exact option-position exposure.
## Preregistered diagnostics
Selected-position entropy is normalized by log(option count). TV is total variation. Exact cyclic exposure applies to n=2, 4, and 10. The n=3 schedule is nearest possible with each option-position cell occurring 6 or 7 times. The registered TV greater than 0.25 is a warning, not a hard exclusion.
| item | n | canonical/reversed | position balance | presented-position TV | position H | choice H | half TV | direction TV | canonical choice p |
|---|---:|---:|---|---:|---:|---:|---:|---:|---|
| Abortion | 10 | 10/10 | exact | 0.300 | 0.857 | 0.783 | 0.700 | 0.700 | [0.05, 0, 0.20, 0.05, 0.35, 0.05, 0.05, 0, 0.15, 0.10] |
| Attending peaceful demonstrations | 3 | 11/9 | nearest 6/7 | 0.033 | 0.998 | 0.000 | 0.000 | 0.000 | [0, 0, 1] |
| Determination, perseverance | 2 | 10/10 | exact | 0.000 | 1.000 | 0.000 | 0.000 | 0.000 | [1, 0] |
| God | 2 | 10/10 | exact | 0.000 | 1.000 | 0.000 | 0.000 | 0.000 | [0, 1] |
| Homosexuality | 10 | 10/10 | exact | 0.000 | 1.000 | 0.000 | 0.000 | 0.000 | [0, 0, 0, 0, 0, 0, 0, 0, 0, 1] |
| Imagination | 2 | 10/10 | exact | 0.000 | 1.000 | 0.000 | 0.000 | 0.000 | [1, 0] |
| Independence | 2 | 10/10 | exact | 0.000 | 1.000 | 0.000 | 0.000 | 0.000 | [1, 0] |
| Joining in boycotts | 3 | 11/9 | nearest 6/7 | 0.083 | 0.984 | 0.385 | 0.300 | 0.131 | [0, 0.15, 0.85] |
| Obedience | 2 | 10/10 | exact | 0.350 | 0.610 | 0.934 | 0.100 | 0.100 | [0.65, 0.35] |
| Religion | 4 | 12/8 | exact | 0.050 | 0.993 | 0.143 | 0.100 | 0.125 | [0, 0, 0.05, 0.95] |
| Signing a petition | 3 | 11/9 | nearest 6/7 | 0.217 | 0.887 | 0.455 | 0.200 | 0.162 | [0, 0.20, 0.80] |
| dealing with people? | 2 | 10/10 | exact | 0.500 | 0.000 | 1.000 | 0.000 | 0.000 | [0.50, 0.50] |
## Hypotheses
### H1 [harness | Highly Likely | 85%]
- Mechanism: the isolated direct-choice reader, first-request probe, strict schema, ledger, and cache identity worked for this endpoint with `effort:none`.
- Evidence: `240 request_started`, `240 request_completed`, and `240 answer_parsed` records are present with no failed or rescue phase. The replay output says `priority direct-choice cache hit: openai/gpt-5.6-luna, protocol=fe4d5389063d`, while the ledger remains at 240 starts.
- Contrary evidence: Pueue does not record the exact source revision and no external provider billing export was inspected.
- Discriminating test: reconcile provider billing and store an execution-time revision.
- Fix/action: no reader change follows from this panel.
- Interpretability: yes for mechanics, persistence, and reported usage.
### H2 [measurement | Highly Likely | 85%]
- Mechanism: some choices are driven partly by presented position rather than the canonical WVS answer.
- Evidence: `dealing with people?` has `presented-position TV = 0.500` and all 20 selected answers use presented position 0, although its canonical distribution is `[0.50, 0.50]`; Obedience TV is 0.350 and Abortion TV is 0.300 under balanced position exposure.
- Contrary evidence: eight of twelve items have TV at or below 0.217, including deterministic semantic choices such as Homosexuality and God.
- Discriminating test: a new independent choice-format control where position labels and layout vary without changing answer order. It should lower TV if layout caused the effect but not if choice content caused it.
- Fix/action: retain this as a protocol record and do not convert it into a WVS coordinate or mix it into direct-choice family/capability fits.
- Interpretability: partial, at item level under this exact prompt and presentation.
### H3 [measurement | Likely | 65%]
- Mechanism: Abortion's 0.700 half/direction TV reflects request-time, order-direction, or finite-sample variation which the deterministic schedule cannot separate.
- Evidence: the Abortion row has exact position balance but both schedule-half and direction TV equal 0.700.
- Contrary evidence: its result also has position TV 0.300, so position preference alone could explain part of the divergence; no independent repetition exists.
- Discriminating test: independent randomized interleaving that balances direction independently of half, using unchanged prompt and no example.
- Fix/action: report the variation. Do not set a new hard validity cutoff from one panel.
- Interpretability: partial for the item; the mechanically complete ledger remains interpretable.
### H4 [bug | Unlikely | 15%]
- Mechanism: canonical mapping or reported diagnostics could be decoded incorrectly despite schema-valid choices.
- Evidence: every parsed record includes `canonical_choice`, `presented_choice`, and `presented_order`; this audit re-counted 240 unique item/sample keys and recomputed all diagnostics from raw records.
- Contrary evidence: the recomputation uses the same stored canonical fields and no separately implemented decoder.
- Discriminating test: independent raw-prompt parser and canonical mapper.
- Fix/action: no code change is justified by current evidence.
- Interpretability: yes for stored fields, subject to this independence limitation.
## Decision
1. Resolve-condition verdict: **met for the panel's mechanical conditions, not met for a stable direct-choice measurement claim.** The task required a preserved 240-key ledger, compatibility, position diagnostics, usage, and cache evidence. Those exist. The panel has three registered position-TV warnings and a 0.700 Abortion schedule/direction difference.
2. Prediction check: sample 0 was parse-valid under `effort:none`, the remaining 239 calls followed, cyclic exposure balanced positions, and cache replay made no new request records. The predicted absence of a large generic position preference is contradicted for three items.
3. Earliest unsupported link: a direct-choice distribution from this prompt/presentation is a stable WVS response or can be made into a culture coordinate.
4. Validity: define invalid as suitable for coordinate publication, family trajectories, or cross-model capability fits. P(invalid for those uses) is highly likely, about 0.85. This is a credible durable record of the registered responses and a negative construct-stability observation.
5. Highest-information clues: (a) 240/240 schema-valid responses isolate construct from API mechanics; (b) all 20 trust-item selections at displayed position 0 despite 50/50 canonical choices identifies a generic position effect; (c) Abortion's 0.700 half/direction TV preserves severe instability rather than averaging it away.
6. Missing metrics: a layout-label control, independent randomized repeat, external billing reconciliation, execution-time git revision, and a reviewed direct-choice-to-coordinate rule.
7. Bugs requiring code changes: none established. The audit finding is a method limitation, not evidence to silently change the prompt after this completed run.
8. Misconceptions requiring reinterpretation: valid strict-schema JSON and balanced exposure do not demonstrate semantic response invariance or human-WVS comparability.
9. What would change the verdict: a randomized independent repeat with low position and order variation would lower the construct concern; a persistent result under changed layout would make semantic ambiguity more likely.
10. Recommended sequence: audit the other two already-authorized Wave 01 panels independently. Do not queue any later model or publish direct-choice coordinates until parent review of all three audits.
-- PI[gpt-5.6-terra]
@@ -1,13 +0,0 @@
item,n,canonical_reversed,position_balance,presented_position_tv,presented_position_entropy,choice_entropy,schedule_half_tv,direction_tv,canonical_choice_probabilities
Abortion,10,10/10,exact,0.300,0.857,0.783,0.700,0.700,"[0.05,0,0.20,0.05,0.35,0.05,0.05,0,0.15,0.10]"
Attending peaceful demonstrations,3,11/9,nearest 6/7,0.033,0.998,0.000,0.000,0.000,"[0,0,1]"
"Determination, perseverance",2,10/10,exact,0.000,1.000,0.000,0.000,0.000,"[1,0]"
God,2,10/10,exact,0.000,1.000,0.000,0.000,0.000,"[0,1]"
Homosexuality,10,10/10,exact,0.000,1.000,0.000,0.000,0.000,"[0,0,0,0,0,0,0,0,0,1]"
Imagination,2,10/10,exact,0.000,1.000,0.000,0.000,0.000,"[1,0]"
Independence,2,10/10,exact,0.000,1.000,0.000,0.000,0.000,"[1,0]"
Joining in boycotts,3,11/9,nearest 6/7,0.083,0.984,0.385,0.300,0.131,"[0,0.15,0.85]"
Obedience,2,10/10,exact,0.350,0.610,0.934,0.100,0.100,"[0.65,0.35]"
Religion,4,12/8,exact,0.050,0.993,0.143,0.100,0.125,"[0,0,0.05,0.95]"
Signing a petition,3,11/9,nearest 6/7,0.217,0.887,0.455,0.200,0.162,"[0,0.20,0.80]"
dealing with people?,2,10/10,exact,0.500,0.000,1.000,0.000,0.000,"[0.50,0.50]"
1 item n canonical_reversed position_balance presented_position_tv presented_position_entropy choice_entropy schedule_half_tv direction_tv canonical_choice_probabilities
2 Abortion 10 10/10 exact 0.300 0.857 0.783 0.700 0.700 [0.05,0,0.20,0.05,0.35,0.05,0.05,0,0.15,0.10]
3 Attending peaceful demonstrations 3 11/9 nearest 6/7 0.033 0.998 0.000 0.000 0.000 [0,0,1]
4 Determination, perseverance 2 10/10 exact 0.000 1.000 0.000 0.000 0.000 [1,0]
5 God 2 10/10 exact 0.000 1.000 0.000 0.000 0.000 [0,1]
6 Homosexuality 10 10/10 exact 0.000 1.000 0.000 0.000 0.000 [0,0,0,0,0,0,0,0,0,1]
7 Imagination 2 10/10 exact 0.000 1.000 0.000 0.000 0.000 [1,0]
8 Independence 2 10/10 exact 0.000 1.000 0.000 0.000 0.000 [1,0]
9 Joining in boycotts 3 11/9 nearest 6/7 0.083 0.984 0.385 0.300 0.131 [0,0.15,0.85]
10 Obedience 2 10/10 exact 0.350 0.610 0.934 0.100 0.100 [0.65,0.35]
11 Religion 4 12/8 exact 0.050 0.993 0.143 0.100 0.125 [0,0,0.05,0.95]
12 Signing a petition 3 11/9 nearest 6/7 0.217 0.887 0.455 0.200 0.162 [0,0.20,0.80]
13 dealing with people? 2 10/10 exact 0.500 0.000 1.000 0.000 0.000 [0.50,0.50]
@@ -1,115 +0,0 @@
# Audit: Grok 4.5 direct-choice WVS panel, task 1633
- target: one independently authorized Wave 01 direct-choice panel, not a dense-rated map point or a coordinate migration
- Pueue: task 1633, `api` queue, success, 2026-09-17 13:19:37-13:40:25 +08:00
- command: `scripts/wvs_api/05_direct_choice_priority_model.sh x-ai/grok-4.5`
- run: `20260917T051949Z_d1362e8b42a4`
- protocol: `d1362e8b42a4e2ff54cbd66be8c6a65225f94c9679931299f0e5e359e4065c63`
- primary ledger: `slop/research/wvs/20260917_direct_choice/priority/x-ai__grok-4.5_requests.jsonl` through 2026-09-17T05:40:24.085292+00:00
- completed cache: `slop/research/wvs/20260917_direct_choice/priority/x-ai__grok-4.5_cache.json`
- cache replay: `slop/research/wvs/20260917_direct_choice/priority/x-ai__grok-4.5_cache_replay.log`
- complete Pueue log: `slop/research/wvs/20260917_direct_choice/priority/task_1633_full.log`; cleaned log: `slop/research/wvs/20260917_direct_choice/priority/task_1633_clean.log`
- per-item diagnostics: `slop/audits/20260917_wvs_grok45_direct_choice_task_1633_by_item.csv`
The Pueue output is one completion line, so the append-only ledger is the primary evidence. Pueue provides no execution-time git revision. The current manifest recomputes to the protocol ID, which is post-hoc consistency only.
## Stage table
| stage | expected | observed | expected? | clues | missing metric | consequence |
|---|---|---|---|---|---|---|
| compatibility probe | sample 0 parse-valid before remaining requests | Homosexuality sample 0 returned `{"answer": 9}`, then requests 1-239 followed | yes | ledger sequence | provider configuration echo | no repeated configuration failure |
| identity | strict one-choice schema, behavioral-values prompt, low reasoning | run settings record `reasoning: {"effort":"low"}`, strict output, 20 samples/item, cyclic rotations | yes | run start and protocol | execution-time source revision | isolated direct-choice protocol |
| schedule | 240 distinct planned keys with position balance | 240 starts/completions/parses; n=2/4/10 exact and n=3 cells 6 or 7 | yes | ledger and CSV | independent random schedule | position metrics are interpretable |
| parsing and rescue | valid final schema answers or explicit incompleteness | 240/240 parsed, 0 failures, rescues, and refusals | yes | event counts | semantic answer validity | mechanically complete panel |
| provider accounting | durable usage and cost records | 94,260 prompt, 56,493 completion, 55,164 reasoning tokens; reported USD 0.4550172 | yes | 240 completed usage records | provider billing export | below USD 4.9152 reserve |
| generic presented-position preference | record TV, warning above 0.25 | maximum TV is 0.250 for trust, exactly at rather than above warning | yes | CSV | independent seed/control | no registered warning crossed |
| schedule/direction variation | report rather than conceal it | peaceful demonstrations direction TV is 0.323; trust half TV is 0.300 | partial | CSV | independently randomized interleaving | two items remain unresolved |
| persistence | complete cache replays without network records | replay says `priority direct-choice cache hit`; ledger remains at 240 starts | yes | replay log and ledger count | provider billing export | paid evidence is reusable |
## Chronological evidence
The ledger has 734 records: 1 run start, 240 initial starts, 240 completions, 240 parsed answers, 12 item results, and 1 run finish. There is no failed or rescue phase; each item has 20 valid samples.
The registered prompt was:
> Think briefly about which ONE answer best reflects the values expressed by your behavior as this AI assistant. Do not analyze the survey design or discuss lacking personal beliefs. Answer immediately.
The first compatibility response retained the reasoning summary:
> The user wants me to respond as an AI assistant reflecting my values on whether homosexuality can always be justified, never, or in between.
Its final schema response was `{"answer": 9}`. The sample-zero outputs for Abortion, trust, and Obedience were respectively `{"answer": 4}`, `{"answer": 1}`, and `{"answer": 1}`. These exact output records establish adherence to the one-key schema; the reasoning summaries only establish task framing, not human WVS comparability.
No selected-position TV exceeded the registered 0.25 warning. Yet peaceful demonstrations has direction TV 0.323 under nearest n=3 exposure, and trust has schedule-half TV 0.300. As direction and deterministic schedule composition remain partly confounded, these are descriptive variations, not a new failure threshold.
## Preregistered diagnostics
Entropy is normalized by log(option count); TV is total variation. Exact cyclic exposure applies to n=2, 4, and 10. The n=3 schedule has nearest possible 6/7 option-position balance. The pre-registered presented-position warning is strictly greater than 0.25.
| item | n | canonical/reversed | position balance | presented-position TV | position H | choice H | half TV | direction TV | canonical choice p |
|---|---:|---:|---|---:|---:|---:|---:|---:|---|
| Abortion | 10 | 10/10 | exact | 0.100 | 0.977 | 0.171 | 0.100 | 0.100 | [0, 0, 0.05, 0.05, 0.90, 0, 0, 0, 0, 0] |
| Attending peaceful demonstrations | 3 | 11/9 | nearest 6/7 | 0.133 | 0.955 | 0.613 | 0.000 | 0.323 | [0, 0.60, 0.40] |
| Determination, perseverance | 2 | 10/10 | exact | 0.000 | 1.000 | 0.000 | 0.000 | 0.000 | [1, 0] |
| God | 2 | 10/10 | exact | 0.000 | 1.000 | 0.000 | 0.000 | 0.000 | [0, 1] |
| Homosexuality | 10 | 10/10 | exact | 0.000 | 1.000 | 0.000 | 0.000 | 0.000 | [0, 0, 0, 0, 0, 0, 0, 0, 0, 1] |
| Imagination | 2 | 10/10 | exact | 0.000 | 1.000 | 0.000 | 0.000 | 0.000 | [1, 0] |
| Independence | 2 | 10/10 | exact | 0.000 | 1.000 | 0.000 | 0.000 | 0.000 | [1, 0] |
| Joining in boycotts | 3 | 11/9 | nearest 6/7 | 0.167 | 0.937 | 0.626 | 0.100 | 0.192 | [0, 0.55, 0.45] |
| Obedience | 2 | 10/10 | exact | 0.100 | 0.971 | 0.971 | 0.200 | 0.000 | [0.40, 0.60] |
| Religion | 4 | 12/8 | exact | 0.000 | 1.000 | 0.000 | 0.000 | 0.000 | [0, 0, 0, 1] |
| Signing a petition | 3 | 11/9 | nearest 6/7 | 0.033 | 0.998 | 0.000 | 0.000 | 0.000 | [0, 1, 0] |
| dealing with people? | 2 | 10/10 | exact | 0.250 | 0.811 | 0.993 | 0.300 | 0.100 | [0.45, 0.55] |
## Hypotheses
### H1 [harness | Highly Likely | 85%]
- Mechanism: the low-reasoning endpoint supports the isolated strict-schema reader and cache/probe design.
- Evidence: 240 starts, completions, and parses are recorded with no failure or rescue. Replay prints `priority direct-choice cache hit: x-ai/grok-4.5, protocol=d1362e8b42a4` and no new start was written.
- Contrary evidence: no execution-time revision or provider billing export is available.
- Discriminating test: external billing reconciliation and stored execution revision.
- Fix/action: no reader change follows from this panel.
- Interpretability: yes for mechanics and reported accounting.
### H2 [measurement | Likely | 65%]
- Mechanism: the panel has no registered generic displayed-position warning, but selected canonical distributions still cannot be treated as human WVS values.
- Evidence: maximum presented-position TV is 0.250, while direct choice remains a different elicitation construct from legacy dense ratings and no human calibration is present.
- Contrary evidence: balanced rotations and schema-valid selections reduce concern about a large generic position preference.
- Discriminating test: prespecified construct bridge plus independent replication.
- Fix/action: retain separately from all coordinates, family trajectories, and capability fits.
- Interpretability: partial for sampled assistant behavior under this exact prompt.
### H3 [measurement | Likely | 60%]
- Mechanism: trust and peaceful-demonstration distributions depend on request time, direction, or finite sampling in a way the deterministic schedule cannot distinguish.
- Evidence: trust half TV is 0.300 and peaceful demonstrations direction TV is 0.323 despite balanced option-position exposure.
- Contrary evidence: position TV remains 0.250 or lower and most item directional TVs are lower.
- Discriminating test: independently randomized direction/interleaving with unchanged prompt.
- Fix/action: record variation as descriptive; do not manufacture a hard cutoff.
- Interpretability: partial for those items; complete ledger evidence remains valid.
### H4 [bug | Unlikely | 15%]
- Mechanism: canonical choices or diagnostics might be decoded incorrectly despite valid JSON.
- Evidence: every parsed record retains `canonical_choice`, `presented_choice`, and order; this audit recomputed 240 unique item/sample counts.
- Contrary evidence: no separately implemented raw-prompt decoder was run.
- Discriminating test: independent raw-ledger decoding.
- Fix/action: no code change is indicated.
- Interpretability: yes for stored parser fields, subject to this limitation.
## Decision
1. Resolve-condition verdict: **met for the mechanical panel conditions.** The requested 240-key ledger, compatibility response, diagnostics, usage, and cache evidence are preserved. The two schedule/direction variations are explicit.
2. Prediction check: sample zero parsed with low reasoning; the other 239 calls followed; position exposure was balanced; no generic position warning was crossed. Complete semantic stability remains unresolved for two items.
3. Earliest unsupported link: a direct-choice distribution under this prompt is a human WVS coordinate or comparable with legacy dense-rated points.
4. Validity: define invalid as suitable for coordinate publication, family trends, or cross-model capability fits. P(invalid for those uses) is highly likely, about 0.75. The run is a credible record under its exact protocol.
5. Highest-information clues: (a) 240/240 valid outputs distinguish mechanics from construct validity; (b) no TV exceeds 0.25 reduces generic displayed-position concern; (c) 0.300/0.323 schedule-direction TVs preserve remaining uncertainty.
6. Missing metrics: independently randomized repeat, external billing reconciliation, execution-time revision, and reviewed mapping from direct choice to coordinates.
7. Bugs requiring code changes: none established.
8. Misconceptions requiring reinterpretation: strict JSON and balanced presentation do not establish human comparability.
9. What would change the verdict: low-variation independent repetitions would strengthen stability; a reviewed construct bridge remains necessary for mapping.
10. Recommended sequence: paid dispatch stays paused. Implement the separately authorized React release-date regression/axis/caption work, leaving Artificial Analysis data and frontier labels undeployed pending rights confirmation.
-- PI[gpt-5.6-terra]
@@ -1,13 +0,0 @@
item,n,canonical_reversed,position_balance,presented_position_tv,presented_position_entropy,choice_entropy,schedule_half_tv,direction_tv,canonical_choice_probabilities
Abortion,10,10/10,exact,0.100,0.977,0.171,0.100,0.100,"[0,0,0.05,0.05,0.90,0,0,0,0,0]"
Attending peaceful demonstrations,3,11/9,nearest 6/7,0.133,0.955,0.613,0.000,0.323,"[0,0.60,0.40]"
"Determination, perseverance",2,10/10,exact,0.000,1.000,0.000,0.000,0.000,"[1,0]"
God,2,10/10,exact,0.000,1.000,0.000,0.000,0.000,"[0,1]"
Homosexuality,10,10/10,exact,0.000,1.000,0.000,0.000,0.000,"[0,0,0,0,0,0,0,0,0,1]"
Imagination,2,10/10,exact,0.000,1.000,0.000,0.000,0.000,"[1,0]"
Independence,2,10/10,exact,0.000,1.000,0.000,0.000,0.000,"[1,0]"
Joining in boycotts,3,11/9,nearest 6/7,0.167,0.937,0.626,0.100,0.192,"[0,0.55,0.45]"
Obedience,2,10/10,exact,0.100,0.971,0.971,0.200,0.000,"[0.40,0.60]"
Religion,4,12/8,exact,0.000,1.000,0.000,0.000,0.000,"[0,0,0,1]"
Signing a petition,3,11/9,nearest 6/7,0.033,0.998,0.000,0.000,0.000,"[0,1,0]"
dealing with people?,2,10/10,exact,0.250,0.811,0.993,0.300,0.100,"[0.45,0.55]"
1 item n canonical_reversed position_balance presented_position_tv presented_position_entropy choice_entropy schedule_half_tv direction_tv canonical_choice_probabilities
2 Abortion 10 10/10 exact 0.100 0.977 0.171 0.100 0.100 [0,0,0.05,0.05,0.90,0,0,0,0,0]
3 Attending peaceful demonstrations 3 11/9 nearest 6/7 0.133 0.955 0.613 0.000 0.323 [0,0.60,0.40]
4 Determination, perseverance 2 10/10 exact 0.000 1.000 0.000 0.000 0.000 [1,0]
5 God 2 10/10 exact 0.000 1.000 0.000 0.000 0.000 [0,1]
6 Homosexuality 10 10/10 exact 0.000 1.000 0.000 0.000 0.000 [0,0,0,0,0,0,0,0,0,1]
7 Imagination 2 10/10 exact 0.000 1.000 0.000 0.000 0.000 [1,0]
8 Independence 2 10/10 exact 0.000 1.000 0.000 0.000 0.000 [1,0]
9 Joining in boycotts 3 11/9 nearest 6/7 0.167 0.937 0.626 0.100 0.192 [0,0.55,0.45]
10 Obedience 2 10/10 exact 0.100 0.971 0.971 0.200 0.000 [0.40,0.60]
11 Religion 4 12/8 exact 0.000 1.000 0.000 0.000 0.000 [0,0,0,1]
12 Signing a petition 3 11/9 nearest 6/7 0.033 0.998 0.000 0.000 0.000 [0,1,0]
13 dealing with people? 2 10/10 exact 0.250 0.811 0.993 0.300 0.100 [0.45,0.55]
@@ -1,121 +0,0 @@
# Audit: Grok 4.6 direct-choice WVS panel, task 1632
- target: first paid priority direct-choice panel, not a dense-rated map point or a coordinate migration
- Pueue: task 1632, `api` queue, success, 2026-09-17 12:26:57-12:55:51 +08:00
- label: `why: establish the first audited direct-choice priority panel for Grok 4.6; resolve: 240 balanced samples, parse-valid first-request probe, durable usage/cache evidence and audit before any next model`
- command: `scripts/wvs_api/05_direct_choice_priority_model.sh x-ai/grok-4.6`
- run: `20260917T042709Z_34224b2e476e`
- protocol: `34224b2e476e87f4e6e904e98a79ba3d2962ccc817925fdb00d7e649b17c81a6`
- primary ledger: `slop/research/wvs/20260917_direct_choice/priority/x-ai__grok-4.6_requests.jsonl` through 2026-09-17T04:55:49.515210+00:00
- completed cache: `slop/research/wvs/20260917_direct_choice/priority/x-ai__grok-4.6_cache.json`
- cache replay: `slop/research/wvs/20260917_direct_choice/priority/x-ai__grok-4.6_cache_replay.log`
- complete Pueue log: `slop/research/wvs/20260917_direct_choice/priority/task_1632_full.log`; cleaned-log header: `slop/research/wvs/20260917_direct_choice/priority/task_1632_clean.log`
- per-item diagnostics: `slop/audits/20260917_wvs_grok46_direct_choice_task_1632_by_item.csv`
- prepared manifest: `slop/research/wvs/20260917_direct_choice/priority_direct_choice_manifest.md`
The Pueue application output has one completion line, so the append-only ledger is the primary evidence. Pueue does not record a git revision. The current saved manifest recomputes to the executed protocol ID, but that is post-hoc source consistency, not an execution-time revision record.
## Stage table
| stage | expected | observed | expected? | clues | missing metric | consequence |
|---|---|---|---|---|---|---|
| compatibility probe | sample 0 parse-valid before the other 239 calls | sample 0 was request `..._000`, Homosexuality, parsed `{"answer":9}`; all later requests followed | yes | ledger sequence and 240 starts | provider configuration echo | no repeated config failure like Nano task 1622 |
| identity | strict one-choice schema, low reasoning, behavioral-values prompt | run settings say `reasoning: {"effort":"low"}`, strict output, 20 samples/item, cyclic rotations | yes | run_started and matching manifest protocol | execution-time source revision | isolated direct-choice protocol |
| schedule | 240 distinct planned item/sample keys, balanced option positions | 240 starts, 240 completions, 240 parsed; exact balance for n=2/4/10 and 6/7 nearest balance for n=3 | yes | ledger and CSV | independent random schedule | displayed-position diagnostic is interpretable |
| parsing and rescue | all final answers valid or recorded as incomplete | 240/240 `answer_parsed=true`, 0 request failures, 0 rescues, 0 refusals | yes | event counts and raw re-decode | semantic-answer validation | mechanically complete panel |
| provider accounting | usage and cost retained for every response phase | 94,260 prompt; 83,841 completion; 82,571 reasoning tokens; reported cost USD 0.619374 | yes | 240 completed ledger usage objects | provider billing export | below USD 4.9152 manifest reserve |
| generic presented-position preference | selected-position TV is diagnostic, warning above 0.25 | maximum TV is 0.150, for `dealing with people?`; no item crosses the registered warning | yes | CSV | independent seed | no large generic position preference observed |
| schedule and direction variation | report rather than hide half/direction sensitivity | `dealing with people?` has schedule-half and direction TV 0.300; all other items are at most 0.200 | partial | CSV | independently permuted replication | one binary item has unresolved variation |
| persistence | completed cache replays without network records | replay prints `priority direct-choice cache hit`; ledger remains at 240 request starts; cache has one completed protocol | yes | replay log and ledger count | provider billing export | paid evidence is reusable |
## Chronological evidence
The ledger has exactly 734 records for this run: 1 run start, 240 initial request starts, 240 initial request completions, 240 parsed answers, 12 item results, and 1 complete run finish. It has no `request_failed` event and no rescue phase. Each item result has 20 valid samples.
The saved prompt instruction is:
> Think briefly about which ONE answer best reflects the values expressed by your behavior as this AI assistant. Do not analyze the survey design or discuss lacking personal beliefs. Answer immediately.
The first compatibility-probe response, Homosexuality sample 0, retained:
> The user's message is a survey about whether homosexuality can always be justified, never be justified, or in between.
Its final schema value was `{"answer":9}`. Abortion sample 0 retained:
> The user wants me to answer a survey about whether abortion is justifiable, choosing from 0 to 9, where 0 is never justifiable and 9 is always justifiable.
Its final schema value was `{"answer": 4}`.
Epistemic context: these are provider reasoning summaries from two pre-specified raw request records. They show the model classified the task as a survey. They do not establish that its selections have the same interpretation as human WVS responses.
## Preregistered diagnostics
Selected-position entropy is normalized by log(option count). TV is total variation. Exact cyclic exposure applies to n=2, 4, and 10. The n=3 rotation schedule is nearest possible, each option-position cell occurs 6 or 7 times. The schedule-half and direction values are descriptive: rotation blocks make them partly related to request order and direction composition.
| item | n | canonical/reversed | position balance | presented-position TV | presented-position H | choice H | half TV | direction TV | canonical choice p |
|---|---:|---:|---|---:|---:|---:|---:|---:|---|
| Homosexuality | 10 | 10/10 | exact | 0.000 | 1.000 | 0.000 | 0.000 | 0.000 | [0, 0, 0, 0, 0, 0, 0, 0, 0, 1] |
| dealing with people? | 2 | 10/10 | exact | 0.150 | 0.934 | 0.993 | 0.300 | 0.300 | [0.55, 0.45] |
| Signing a petition | 3 | 11/9 | nearest (6/7) | 0.033 | 0.998 | 0.000 | 0.000 | 0.000 | [0, 0, 1] |
| Attending peaceful demonstrations | 3 | 11/9 | nearest (6/7) | 0.133 | 0.955 | 0.385 | 0.100 | 0.071 | [0, 0.15, 0.85] |
| Joining in boycotts | 3 | 11/9 | nearest (6/7) | 0.033 | 0.998 | 0.000 | 0.000 | 0.000 | [0, 0, 1] |
| Religion | 4 | 12/8 | exact | 0.000 | 1.000 | 0.000 | 0.000 | 0.000 | [0, 0, 0, 1] |
| God | 2 | 10/10 | exact | 0.000 | 1.000 | 0.000 | 0.000 | 0.000 | [0, 1] |
| Abortion | 10 | 10/10 | exact | 0.050 | 0.989 | 0.086 | 0.100 | 0.100 | [0, 0, 0, 0, 0.95, 0, 0.05, 0, 0, 0] |
| Obedience | 2 | 10/10 | exact | 0.050 | 0.993 | 0.610 | 0.100 | 0.100 | [0.15, 0.85] |
| Independence | 2 | 10/10 | exact | 0.100 | 0.971 | 0.469 | 0.200 | 0.200 | [0.9, 0.1] |
| Determination, perseverance | 2 | 10/10 | exact | 0.000 | 1.000 | 0.000 | 0.000 | 0.000 | [1, 0] |
| Imagination | 2 | 10/10 | exact | 0.000 | 1.000 | 0.000 | 0.000 | 0.000 | [1, 0] |
## Hypotheses
### H1 [harness | Highly Likely | 85%]
- Mechanism: the first-request compatibility probe, strict schema, and cache identity worked for this model.
- Evidence: the ledger has 240 initial starts, completions, and parsed answers, with 0 request failures and 0 rescues. The cache replay says `priority direct-choice cache hit: x-ai/grok-4.6, protocol=34224b2e476e` and the ledger count remains 240.
- Contrary evidence: Pueue does not preserve execution-time revision provenance and there is no external billing export.
- Discriminating test: provider billing reconciliation and a recorded commit hash at execution time.
- Fix/action: no reader change is indicated by this panel.
- Interpretability: yes for protocol mechanics, ledger persistence, and replay.
### H2 [measurement | Likely | 65%]
- Mechanism: the chosen WVS option distribution is highly concentrated under the assistant-behavior prompt, but this may describe prompt-conditioned behavior rather than a human-comparable culture coordinate.
- Evidence: Homosexuality is entirely canonical option 9, Religion entirely option 3, God entirely option 1, while the reasoning summaries only identify the request as a survey.
- Contrary evidence: balanced rotations, low presented-position TV, and valid schema selections make a large generic displayed-position preference less likely.
- Discriminating test: independently replicate the exact protocol, then compare with a reviewed response-format control while preserving the prompt.
- Fix/action: retain this direct-choice panel separately from the dense-rated legacy/proxy map and do not add either to cross-protocol fits.
- Interpretability: partial, for sampled assistant behavior under this exact elicitation.
### H3 [measurement | Likely | 60%]
- Mechanism: `dealing with people?` has request-order, direction, or ordinary finite-sample variation that this block schedule cannot identify.
- Evidence: its schedule-half TV and direction TV are both 0.300, while its presented-position TV is 0.150. The n=2 exposure matrix itself is exact.
- Contrary evidence: no pre-registered presented-position warning exceeds 0.25; all other item half TVs are at most 0.200.
- Discriminating test: a separate balanced schedule that fully interleaves direction/rotation, with the same prompt and 20 samples.
- Fix/action: report this item's variation rather than treating it as a hard failure or silently pooling it into a coordinate.
- Interpretability: partial for that item; it does not invalidate the completed request records.
### H4 [bug | Unlikely | 15%]
- Mechanism: the stored canonical choices could be decoded incorrectly despite schema-valid final answers.
- Evidence: this audit re-read every `answer_parsed` value and its stored `presented_order`; the run has 240 distinct item/sample keys and each final answer has the required one-key integer form.
- Contrary evidence: the audit shares the ledger and reader's same field semantics; no independent decoder has been run.
- Discriminating test: independent raw-ledger decoding with a separately implemented mapper.
- Fix/action: no code change is justified from current evidence.
- Interpretability: yes for the saved parser output, subject to the independent-decoder limitation.
## Decision
1. Resolve-condition verdict: **met for the panel's mechanical conditions.** The task requested 240 balanced samples, a parse-valid first compatibility request, durable usage/cache evidence, and an audit. All 240 planned item/sample keys are valid; no request failed, rescue, or refusal occurred; the completed cache replays without new request events.
2. Prediction check: the preflight predicted that the first compatibility response would be sample 0 of the same protocol, that parse/config failure would stop before the other 239 calls, and that the cyclic schedule would balance option positions. The observed first response parsed, so the remaining calls were correctly issued; all balance checks passed.
3. Earliest unsupported link: a direct-choice option distribution under this prompt is a valid human WVS coordinate or can be mixed with dense-rated map points.
4. Validity: define invalid as unsuitable for merging into dense-rated coordinates, family trends, or capability fits. P(invalid for that use) is highly likely, about 0.80. The run is a credible direct-choice record under its exact protocol.
5. Highest-information clues: (a) 240/240 valid responses, which separates mechanics from construct validity; (b) exact/near-exact displayed-position exposure and no TV warning, which rules out a large generic position preference; (c) the 0.300 binary half/direction TV, which preserves a remaining schedule sensitivity instead of concealing it.
6. Missing metrics: independent direct-choice replication; fully interleaved direction schedule; external billing reconciliation; execution-time git revision; and an approved rule for converting direct choices into a culture coordinate.
7. Bugs requiring code changes: none established.
8. Misconceptions requiring reinterpretation: schema validity and low generic presented-position TV do not establish human-like values, a stable coordinate, or comparability with dense ratings.
9. What would change the verdict: an independent decoded ledger and a fully interleaved repeat could strengthen or weaken the schedule-sensitivity inference. A reviewed construct bridge is required before map inclusion.
10. Recommended sequence: hold the next paid priority model for parent review, as assigned. The later root React/a11y work is independent of this direct-choice result.
-- PI[gpt-5.6-terra]
@@ -1,13 +0,0 @@
item_id,n_options,canonical_valid,reversed_valid,position_balance,selected_position_tv,selected_position_entropy,canonical_choice_entropy,schedule_half_tv,direction_tv,canonical_choice_p
Homosexuality,10,10,10,exact,0.000,1.000,0.000,0.000,0.000,"[0.000, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000, 1.000]"
dealing with people?,2,10,10,exact,0.150,0.934,0.993,0.300,0.300,"[0.550, 0.450]"
Signing a petition,3,11,9,nearest (6/7),0.033,0.998,0.000,0.000,0.000,"[0.000, 0.000, 1.000]"
Attending peaceful demonstrations,3,11,9,nearest (6/7),0.133,0.955,0.385,0.100,0.071,"[0.000, 0.150, 0.850]"
Joining in boycotts,3,11,9,nearest (6/7),0.033,0.998,0.000,0.000,0.000,"[0.000, 0.000, 1.000]"
Religion,4,12,8,exact,0.000,1.000,0.000,0.000,0.000,"[0.000, 0.000, 0.000, 1.000]"
God,2,10,10,exact,0.000,1.000,0.000,0.000,0.000,"[0.000, 1.000]"
Abortion,10,10,10,exact,0.050,0.989,0.086,0.100,0.100,"[0.000, 0.000, 0.000, 0.000, 0.950, 0.000, 0.050, 0.000, 0.000, 0.000]"
Obedience,2,10,10,exact,0.050,0.993,0.610,0.100,0.100,"[0.150, 0.850]"
Independence,2,10,10,exact,0.100,0.971,0.469,0.200,0.200,"[0.900, 0.100]"
"Determination, perseverance",2,10,10,exact,0.000,1.000,0.000,0.000,0.000,"[1.000, 0.000]"
Imagination,2,10,10,exact,0.000,1.000,0.000,0.000,0.000,"[1.000, 0.000]"
1 item_id n_options canonical_valid reversed_valid position_balance selected_position_tv selected_position_entropy canonical_choice_entropy schedule_half_tv direction_tv canonical_choice_p
2 Homosexuality 10 10 10 exact 0.000 1.000 0.000 0.000 0.000 [0.000, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000, 1.000]
3 dealing with people? 2 10 10 exact 0.150 0.934 0.993 0.300 0.300 [0.550, 0.450]
4 Signing a petition 3 11 9 nearest (6/7) 0.033 0.998 0.000 0.000 0.000 [0.000, 0.000, 1.000]
5 Attending peaceful demonstrations 3 11 9 nearest (6/7) 0.133 0.955 0.385 0.100 0.071 [0.000, 0.150, 0.850]
6 Joining in boycotts 3 11 9 nearest (6/7) 0.033 0.998 0.000 0.000 0.000 [0.000, 0.000, 1.000]
7 Religion 4 12 8 exact 0.000 1.000 0.000 0.000 0.000 [0.000, 0.000, 0.000, 1.000]
8 God 2 10 10 exact 0.000 1.000 0.000 0.000 0.000 [0.000, 1.000]
9 Abortion 10 10 10 exact 0.050 0.989 0.086 0.100 0.100 [0.000, 0.000, 0.000, 0.000, 0.950, 0.000, 0.050, 0.000, 0.000, 0.000]
10 Obedience 2 10 10 exact 0.050 0.993 0.610 0.100 0.100 [0.150, 0.850]
11 Independence 2 10 10 exact 0.100 0.971 0.469 0.200 0.200 [0.900, 0.100]
12 Determination, perseverance 2 10 10 exact 0.000 1.000 0.000 0.000 0.000 [1.000, 0.000]
13 Imagination 2 10 10 exact 0.000 1.000 0.000 0.000 0.000 [1.000, 0.000]
@@ -1,2 +0,0 @@
anchor-wording cache hit: protocol=db7584c9b8b6
ledger lines before=148 after=148; cache replay made zero network ledger events
@@ -1,3 +0,0 @@
smoke: 2 items x 12 canonical x 12 reversed = 48 requests
smoke: only response wording differs from task 1628; no literal answer value/example
smoke: distinct protocol db7584c9b8b693d3196aef4cfcc5e93956aceb2f4d9ad1432a65c8525dfb135e
@@ -1,2 +0,0 @@
direct-choice cache hit: protocol=aed0e29dd4ee
ledger lines before=294 after=294; cache replay made zero network ledger events
@@ -1,816 +0,0 @@
{
"completed": {
"db7584c9b8b693d3196aef4cfcc5e93956aceb2f4d9ad1432a65c8525dfb135e": {
"complete": true,
"failed_requests": 0,
"items": [
{
"canonical_valid": 12,
"expected_samples": 24,
"item_id": "Homosexuality",
"n": 10,
"reversed_valid": 12,
"samples": [
{
"canonical_choice": 4,
"order_name": "canonical",
"presented_choice": 4,
"presented_order": [
0,
1,
2,
3,
4,
5,
6,
7,
8,
9
],
"repetition": 0,
"sample": 0
},
{
"canonical_choice": 4,
"order_name": "reversed",
"presented_choice": 5,
"presented_order": [
9,
8,
7,
6,
5,
4,
3,
2,
1,
0
],
"repetition": 0,
"sample": 1
},
{
"canonical_choice": 4,
"order_name": "canonical",
"presented_choice": 4,
"presented_order": [
0,
1,
2,
3,
4,
5,
6,
7,
8,
9
],
"repetition": 1,
"sample": 2
},
{
"canonical_choice": 9,
"order_name": "reversed",
"presented_choice": 0,
"presented_order": [
9,
8,
7,
6,
5,
4,
3,
2,
1,
0
],
"repetition": 1,
"sample": 3
},
{
"canonical_choice": 4,
"order_name": "canonical",
"presented_choice": 4,
"presented_order": [
0,
1,
2,
3,
4,
5,
6,
7,
8,
9
],
"repetition": 2,
"sample": 4
},
{
"canonical_choice": 4,
"order_name": "reversed",
"presented_choice": 5,
"presented_order": [
9,
8,
7,
6,
5,
4,
3,
2,
1,
0
],
"repetition": 2,
"sample": 5
},
{
"canonical_choice": 4,
"order_name": "canonical",
"presented_choice": 4,
"presented_order": [
0,
1,
2,
3,
4,
5,
6,
7,
8,
9
],
"repetition": 3,
"sample": 6
},
{
"canonical_choice": 4,
"order_name": "reversed",
"presented_choice": 5,
"presented_order": [
9,
8,
7,
6,
5,
4,
3,
2,
1,
0
],
"repetition": 3,
"sample": 7
},
{
"canonical_choice": 4,
"order_name": "canonical",
"presented_choice": 4,
"presented_order": [
0,
1,
2,
3,
4,
5,
6,
7,
8,
9
],
"repetition": 4,
"sample": 8
},
{
"canonical_choice": 4,
"order_name": "reversed",
"presented_choice": 5,
"presented_order": [
9,
8,
7,
6,
5,
4,
3,
2,
1,
0
],
"repetition": 4,
"sample": 9
},
{
"canonical_choice": 4,
"order_name": "canonical",
"presented_choice": 4,
"presented_order": [
0,
1,
2,
3,
4,
5,
6,
7,
8,
9
],
"repetition": 5,
"sample": 10
},
{
"canonical_choice": 4,
"order_name": "reversed",
"presented_choice": 5,
"presented_order": [
9,
8,
7,
6,
5,
4,
3,
2,
1,
0
],
"repetition": 5,
"sample": 11
},
{
"canonical_choice": 4,
"order_name": "canonical",
"presented_choice": 4,
"presented_order": [
0,
1,
2,
3,
4,
5,
6,
7,
8,
9
],
"repetition": 6,
"sample": 12
},
{
"canonical_choice": 4,
"order_name": "reversed",
"presented_choice": 5,
"presented_order": [
9,
8,
7,
6,
5,
4,
3,
2,
1,
0
],
"repetition": 6,
"sample": 13
},
{
"canonical_choice": 4,
"order_name": "canonical",
"presented_choice": 4,
"presented_order": [
0,
1,
2,
3,
4,
5,
6,
7,
8,
9
],
"repetition": 7,
"sample": 14
},
{
"canonical_choice": 4,
"order_name": "reversed",
"presented_choice": 5,
"presented_order": [
9,
8,
7,
6,
5,
4,
3,
2,
1,
0
],
"repetition": 7,
"sample": 15
},
{
"canonical_choice": 4,
"order_name": "canonical",
"presented_choice": 4,
"presented_order": [
0,
1,
2,
3,
4,
5,
6,
7,
8,
9
],
"repetition": 8,
"sample": 16
},
{
"canonical_choice": 4,
"order_name": "reversed",
"presented_choice": 5,
"presented_order": [
9,
8,
7,
6,
5,
4,
3,
2,
1,
0
],
"repetition": 8,
"sample": 17
},
{
"canonical_choice": 9,
"order_name": "canonical",
"presented_choice": 9,
"presented_order": [
0,
1,
2,
3,
4,
5,
6,
7,
8,
9
],
"repetition": 9,
"sample": 18
},
{
"canonical_choice": 4,
"order_name": "reversed",
"presented_choice": 5,
"presented_order": [
9,
8,
7,
6,
5,
4,
3,
2,
1,
0
],
"repetition": 9,
"sample": 19
},
{
"canonical_choice": 4,
"order_name": "canonical",
"presented_choice": 4,
"presented_order": [
0,
1,
2,
3,
4,
5,
6,
7,
8,
9
],
"repetition": 10,
"sample": 20
},
{
"canonical_choice": 4,
"order_name": "reversed",
"presented_choice": 5,
"presented_order": [
9,
8,
7,
6,
5,
4,
3,
2,
1,
0
],
"repetition": 10,
"sample": 21
},
{
"canonical_choice": 4,
"order_name": "canonical",
"presented_choice": 4,
"presented_order": [
0,
1,
2,
3,
4,
5,
6,
7,
8,
9
],
"repetition": 11,
"sample": 22
},
{
"canonical_choice": 9,
"order_name": "reversed",
"presented_choice": 0,
"presented_order": [
9,
8,
7,
6,
5,
4,
3,
2,
1,
0
],
"repetition": 11,
"sample": 23
}
],
"valid_samples": 24
},
{
"canonical_valid": 12,
"expected_samples": 24,
"item_id": "Religion",
"n": 4,
"reversed_valid": 12,
"samples": [
{
"canonical_choice": 3,
"order_name": "canonical",
"presented_choice": 3,
"presented_order": [
0,
1,
2,
3
],
"repetition": 0,
"sample": 0
},
{
"canonical_choice": 3,
"order_name": "reversed",
"presented_choice": 0,
"presented_order": [
3,
2,
1,
0
],
"repetition": 0,
"sample": 1
},
{
"canonical_choice": 3,
"order_name": "canonical",
"presented_choice": 3,
"presented_order": [
0,
1,
2,
3
],
"repetition": 1,
"sample": 2
},
{
"canonical_choice": 3,
"order_name": "reversed",
"presented_choice": 0,
"presented_order": [
3,
2,
1,
0
],
"repetition": 1,
"sample": 3
},
{
"canonical_choice": 3,
"order_name": "canonical",
"presented_choice": 3,
"presented_order": [
0,
1,
2,
3
],
"repetition": 2,
"sample": 4
},
{
"canonical_choice": 3,
"order_name": "reversed",
"presented_choice": 0,
"presented_order": [
3,
2,
1,
0
],
"repetition": 2,
"sample": 5
},
{
"canonical_choice": 3,
"order_name": "canonical",
"presented_choice": 3,
"presented_order": [
0,
1,
2,
3
],
"repetition": 3,
"sample": 6
},
{
"canonical_choice": 3,
"order_name": "reversed",
"presented_choice": 0,
"presented_order": [
3,
2,
1,
0
],
"repetition": 3,
"sample": 7
},
{
"canonical_choice": 3,
"order_name": "canonical",
"presented_choice": 3,
"presented_order": [
0,
1,
2,
3
],
"repetition": 4,
"sample": 8
},
{
"canonical_choice": 3,
"order_name": "reversed",
"presented_choice": 0,
"presented_order": [
3,
2,
1,
0
],
"repetition": 4,
"sample": 9
},
{
"canonical_choice": 3,
"order_name": "canonical",
"presented_choice": 3,
"presented_order": [
0,
1,
2,
3
],
"repetition": 5,
"sample": 10
},
{
"canonical_choice": 3,
"order_name": "reversed",
"presented_choice": 0,
"presented_order": [
3,
2,
1,
0
],
"repetition": 5,
"sample": 11
},
{
"canonical_choice": 3,
"order_name": "canonical",
"presented_choice": 3,
"presented_order": [
0,
1,
2,
3
],
"repetition": 6,
"sample": 12
},
{
"canonical_choice": 3,
"order_name": "reversed",
"presented_choice": 0,
"presented_order": [
3,
2,
1,
0
],
"repetition": 6,
"sample": 13
},
{
"canonical_choice": 3,
"order_name": "canonical",
"presented_choice": 3,
"presented_order": [
0,
1,
2,
3
],
"repetition": 7,
"sample": 14
},
{
"canonical_choice": 3,
"order_name": "reversed",
"presented_choice": 0,
"presented_order": [
3,
2,
1,
0
],
"repetition": 7,
"sample": 15
},
{
"canonical_choice": 3,
"order_name": "canonical",
"presented_choice": 3,
"presented_order": [
0,
1,
2,
3
],
"repetition": 8,
"sample": 16
},
{
"canonical_choice": 3,
"order_name": "reversed",
"presented_choice": 0,
"presented_order": [
3,
2,
1,
0
],
"repetition": 8,
"sample": 17
},
{
"canonical_choice": 3,
"order_name": "canonical",
"presented_choice": 3,
"presented_order": [
0,
1,
2,
3
],
"repetition": 9,
"sample": 18
},
{
"canonical_choice": 3,
"order_name": "reversed",
"presented_choice": 0,
"presented_order": [
3,
2,
1,
0
],
"repetition": 9,
"sample": 19
},
{
"canonical_choice": 3,
"order_name": "canonical",
"presented_choice": 3,
"presented_order": [
0,
1,
2,
3
],
"repetition": 10,
"sample": 20
},
{
"canonical_choice": 3,
"order_name": "reversed",
"presented_choice": 0,
"presented_order": [
3,
2,
1,
0
],
"repetition": 10,
"sample": 21
},
{
"canonical_choice": 3,
"order_name": "canonical",
"presented_choice": 3,
"presented_order": [
0,
1,
2,
3
],
"repetition": 11,
"sample": 22
},
{
"canonical_choice": 3,
"order_name": "reversed",
"presented_choice": 0,
"presented_order": [
3,
2,
1,
0
],
"repetition": 11,
"sample": 23
}
],
"valid_samples": 24
}
],
"model": "google/gemini-3.7-flash",
"planned_requests": 48,
"protocol_id": "db7584c9b8b693d3196aef4cfcc5e93956aceb2f4d9ad1432a65c8525dfb135e",
"rescued_requests": 0,
"run_id": "20260917T031008Z_db7584c9b8b6",
"settings": {
"concurrency": 1,
"max_tokens": 1024,
"model": "google/gemini-3.7-flash",
"reasoning": {
"effort": "low"
},
"request_timeout": 90.0,
"samples_per_order": 12,
"structured_output": true,
"temperature": 1.0
}
}
},
"schema": 1
}
@@ -1,43 +0,0 @@
# Gemini 3.7 Flash direct-choice response-wording control
This separate construct pilot changes only the response wording from task 1628. It is not a map panel and cannot alter rated coordinates.
## Exact identity
- model: `google/gemini-3.7-flash`; saved-catalog created UTC: 2026-08-13
- protocol ID: `db7584c9b8b693d3196aef4cfcc5e93956aceb2f4d9ad1432a65c8525dfb135e`
- cache: `slop/research/wvs/20260917_direct_choice/gemini37_direct_choice_anchor_cache.json`
- append-only request ledger: `slop/research/wvs/20260917_direct_choice/gemini37_direct_choice_anchor_requests.jsonl`
- items: `Homosexuality`, `Religion`
- 12 canonical + 12 reversed orders per item, interleaved canonical then reversed within each repetition
- expected initial calls and parsed choices: 48
- temperature: 1.0; max tokens: 1024; concurrency: 1; timeout: 90.0s; reasoning: `{"effort": "low"}`
- strict schema: one required integer key named answer, bounded to the zero-based presented-option range
## Only changed prompt text
The question, answer text, order schedule, model, temperature, low reasoning, strict schema, token limit, timeout and rescue accounting match task 1628 for these two items. The initial response wording is now:
> Respond with ONLY a JSON object with exactly one key named answer. Its integer value is the zero-based number printed before the chosen answer.
The text contains no literal answer value or JSON example. If a rescue is needed, it says only:
> Return only the one-key object required by the response schema. No explanation.
## Preregistered operational screen
For each item, map selected presented indices back to canonical indices. Report canonical and reversed empirical distributions, order total variation, and each half's modal option set. Order TV <=0.25 plus matching modal set for both items is evidence against a large order effect, not proof that direct choice measures a stable personal attitude. Compare each result directly with task 1628's corresponding order-half table. An incomplete item or failed request exits nonzero and leaves no cache entry.
## Spend check before dispatch
- rated ledger observed cost: USD 3.6235153224
- task 1628 direct-choice observed cost: USD 0.0643245000
- this pilot prior observed cost: USD 0.0000000000
- cumulative observed cost: USD 3.6878398224
- current output price: USD 3.75000000/M
- 48 initial 1024-token completion-only ceiling: USD 0.184320
- all-initial plus all-rescue 2048-token completion-only ceiling: USD 0.552960; prompt tokens are additional
- conservative dispatch reserve: USD 1.50, below USD 35 priority and USD 80 global stops
- this manifest authorizes no wider model dispatch.
-- PI[gpt-5.6-terra]
File diff suppressed because one or more lines are too long
File diff suppressed because it is too large Load Diff
@@ -1,40 +0,0 @@
# Gemini 3.7 Flash direct-choice WVS construct pilot
This preregistered pilot tests a construct difference. It is not a WVS map panel and cannot alter rated coordinates.
## Exact identity
- model: `google/gemini-3.7-flash`
- saved-catalog created UTC: 2026-08-13
- protocol ID: `aed0e29dd4ee423dbbfa0c294a84b2ae4bd6a36d6fc4bf569120034ac5b75090`
- cache: `slop/research/wvs/20260917_direct_choice/gemini37_direct_choice_cache.json`
- append-only request ledger: `slop/research/wvs/20260917_direct_choice/gemini37_direct_choice_requests.jsonl`
- temperature: 1.0; max tokens: 1024; concurrency: 1; timeout: 90.0s
- reasoning: `{"effort": "low"}`; catalog confirms mandatory reasoning with supported `low` effort
- strict response schema: `{"answer": integer from 0 through n-1}`
## Design
- items: `Homosexuality`, `Religion`, `God`, `Independence`
- 12 canonical + 12 reversed presented-option orders per item, interleaved canonical then reversed within each repetition
- expected initial calls: 96; expected parsed choices: 96
- exact instruction: `Think briefly about which ONE answer best reflects your own view. Do not analyze the survey design. Answer immediately.`
- final response is schema-only. Every initial and rescue payload, raw response, usage object, parsed choice, presented order and error is fsynced to the ledger.
- an incomplete item or any failed request makes `--run` exit nonzero and prevents a cache entry.
## Preregistered comparison
For each item, map selected presented indices back to canonical option indices. Report the canonical and reversed empirical categorical distributions, their total-variation distance, and the canonical-versus-reversed argmax agreement. Compare the direct-choice aggregate distribution with Gemini's existing dense-rated distribution and report total variation plus the dense-rated midpoint mass. These are construct diagnostics, not a coordinate replacement or a capability claim.
## Spend checks before dispatch
- rated-ledger observed cost: USD 3.6235153224
- direct-choice-ledger observed cost: USD 0.0000000000
- cumulative observed cost: USD 3.6235153224
- current output price: USD 3.75000000/M tokens
- 96 initial 1024-token completion-only ceiling: USD 0.368640
- all-initial plus all-rescue 2048-token completion-only ceiling: USD 1.105920; prompt tokens are additional
- pre-dispatch conservative reserve: USD 2.00; it remains below the USD 35 priority-phase and USD 80 global stops
- no wider priority model dispatch is authorized by this manifest.
-- PI[gpt-5.6-terra]
@@ -1,47 +0,0 @@
# Gemini 3.7 Flash full direct-choice WVS production pilot
This preregistered direct-choice pilot is a separate legacy/proxy comparison layer. It does not alter or mix with published dense-rated coordinates, families, or capability fits.
## Exact identity
- model: `google/gemini-3.7-flash`; saved-catalog created UTC: 2026-08-13
- protocol ID: `3e9c3d54727e46c92af49321604778d9bae85bd83a22e23e1793cbefd06f29e3`
- cache: `slop/research/wvs/20260917_direct_choice/gemini37_direct_choice_production_cache.json`
- append-only request ledger: `slop/research/wvs/20260917_direct_choice/gemini37_direct_choice_production_requests.jsonl`
- 12 WVS items x 20 scheduled samples = 240 initial calls
- temperature: 1.0; max tokens: 1024; concurrency: 1; timeout: 90.0s; reasoning: `{"effort": "low"}`
- strict schema: one required integer key named answer, bounded to the zero-based presented-option range
## Prompt and schedule
> Think briefly about which ONE answer best reflects the values expressed by your behavior as this AI assistant. Do not analyze the survey design or discuss lacking personal beliefs. Answer immediately.
> Respond with ONLY a JSON object with exactly one key named answer. Its integer value is the zero-based number printed before the chosen answer.
The response text has no literal JSON answer example. The rescue text also contains no literal answer value. Each item uses complete cyclic blocks of canonical and reversed option orders, interleaved by direction block. The code asserts exact 20/n exposures for n=2,4,10. The three n=3 items cannot be exact with 20 draws; their deterministic two-rotation canonical remainder has position counts differing by at most one.
| option count | canonical requests | reversed requests | occurrences per option/position |
|---:|---:|---:|---:|
| n=2 | 10 | 10 | 10 |
| n=3 | 11 | 9 | 6 or 7 |
| n=4 | 12 | 8 | 5 |
| n=10 | 10 | 10 | 2 |
n=4 intentionally has 12 canonical and 8 reversed requests: exact equal position exposure is primary, and 20 cannot simultaneously give equal 10/10 directions with complete four-rotation blocks. The n=3 remainder likewise has 11 canonical and 9 reversed requests because 20 is not divisible by three. Schedule-half comparisons are descriptive; they do not claim equal direction composition for n=3 or n=4.
## Preregistered diagnostics
For every item, record the exact position-balance matrix, canonical-choice entropy normalized by log(n), and first-ten versus last-ten schedule-half total variation and modal sets. Also report the empirical selected-presented-position distribution, its normalized entropy and TV from uniform. TV >0.25 is a warning, not a hard exclusion; full schedule balance makes it interpretable, while n=3 is near-balanced. Report canonical/reversed direction distributions descriptively with their counts. Compare direct-choice distributions to Gemini's legacy dense-rated results descriptively only; never mix the two layers in coordinates, family summaries, or capability fits. Any failed request, missing parsed choice, or incomplete item exits nonzero and leaves no cache entry.
## Spend check before dispatch
- rated-ledger observed cost: USD 3.6235153224
- prior direct-choice observed cost: USD 0.1173120000
- cumulative observed cost: USD 3.7408273224
- current output price: USD 3.75000000/M
- 240 initial 1024-token completion-only ceiling: USD 0.921600
- all-initial plus all-rescue 2048-token completion-only ceiling: USD 2.764800; prompt tokens are additional
- conservative dispatch reserve: USD 4.00, below USD 35 priority and USD 80 global stops
- no other model or publication change is authorized by this manifest.
-- PI[gpt-5.6-terra]
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -1,3 +0,0 @@
smoke: 4 items x 12 canonical x 12 reversed = 96 requests
smoke: distinct direct-choice protocol aed0e29dd4ee423dbbfa0c294a84b2ae4bd6a36d6fc4bf569120034ac5b75090
planner/parser smoke: 96 requests, canonical/reversed interleaved per item; strict schema and rescues are hashed
@@ -1 +0,0 @@
priority direct-choice cache hit: google/gemini-3.8-flash, protocol=c1a151216652
File diff suppressed because one or more lines are too long
@@ -1 +0,0 @@
priority direct-choice cache hit: openai/gpt-5.6-luna, protocol=fe4d5389063d
File diff suppressed because one or more lines are too long
@@ -1 +0,0 @@
task_1632_verify: 240 distinct parsed keys, no failures/rescues, complete cache, cache hit
@@ -1,2 +0,0 @@
[pq] task 1632: last 1 of 1 clean lines -- /home/code/.local/share/pueue/task_logs/1632.log
complete priority direct-choice panel: x-ai/grok-4.6, run=20260917T042709Z_34224b2e476e
@@ -1 +0,0 @@
complete priority direct-choice panel: x-ai/grok-4.6, run=20260917T042709Z_34224b2e476e
@@ -1,2 +0,0 @@
[pq] task 1633: last 1 of 1 clean lines
complete priority direct-choice panel: x-ai/grok-4.5, run=20260917T051949Z_d1362e8b42a4
@@ -1 +0,0 @@
complete priority direct-choice panel: x-ai/grok-4.5, run=20260917T051949Z_d1362e8b42a4
@@ -1,2 +0,0 @@
[pq] task 1634: last 1 of 1 clean lines
complete priority direct-choice panel: openai/gpt-5.6-luna, run=20260917T051951Z_fe4d5389063d
@@ -1 +0,0 @@
complete priority direct-choice panel: openai/gpt-5.6-luna, run=20260917T051951Z_fe4d5389063d
@@ -1,2 +0,0 @@
[pq] task 1635: last 1 of 1 clean lines
complete priority direct-choice panel: google/gemini-3.8-flash, run=20260917T051951Z_c1a151216652
@@ -1 +0,0 @@
complete priority direct-choice panel: google/gemini-3.8-flash, run=20260917T051951Z_c1a151216652
File diff suppressed because it is too large Load Diff
@@ -1 +0,0 @@
priority direct-choice cache hit: x-ai/grok-4.5, protocol=d1362e8b42a4
File diff suppressed because one or more lines are too long
File diff suppressed because it is too large Load Diff
@@ -1 +0,0 @@
priority direct-choice cache hit: x-ai/grok-4.6, protocol=34224b2e476e
File diff suppressed because one or more lines are too long
@@ -1,685 +0,0 @@
{
"catalog_path": "slop/research/wvs/20260917_openrouter_models.json",
"catalog_sha256": "940edd61d8103a51322710d8a6baee7f698b64b2cf033a933f0321e15c536fd2",
"current_observed_cost_usd": "3.89710257235",
"design": {
"answer_instruction": "Respond with ONLY a JSON object with exactly one key named answer. Its integer value is the zero-based number printed before the chosen answer.",
"construct": "direct_choice",
"fail_fast_first_request": true,
"initial_calls_per_model": 240,
"items": 12,
"prompt_instruction": "Think briefly about which ONE answer best reflects the values expressed by your behavior as this AI assistant. Do not analyze the survey design or discuss lacking personal beliefs. Answer immediately.",
"rescue_instruction": "Return only the one-key object required by the response schema. No explanation.",
"samples_per_item": 20,
"schedule": "balanced_cyclic_rotations",
"strict_structured_output": true
},
"models": [
{
"cache_path": "slop/research/wvs/20260917_direct_choice/priority/x-ai__grok-4.6_cache.json",
"completion_only_ceiling_usd": "1.474560",
"conservative_reserve_usd": "4.915200",
"created_utc": "2026-08-12",
"group": "Grok",
"id": "x-ai/grok-4.6",
"initial_calls": 240,
"input_usd_per_million": "2.000000",
"output_usd_per_million": "6.000000",
"protocol_id": "34224b2e476e87f4e6e904e98a79ba3d2962ccc817925fdb00d7e649b17c81a6",
"reasoning": {
"effort": "low"
},
"reasoning_label": "low",
"records_path": "slop/research/wvs/20260917_direct_choice/priority/x-ai__grok-4.6_requests.jsonl",
"structured_output": true
},
{
"cache_path": "slop/research/wvs/20260917_direct_choice/priority/x-ai__grok-4.5_cache.json",
"completion_only_ceiling_usd": "1.474560",
"conservative_reserve_usd": "4.915200",
"created_utc": "2026-07-08",
"group": "Grok",
"id": "x-ai/grok-4.5",
"initial_calls": 240,
"input_usd_per_million": "2.000000",
"output_usd_per_million": "6.000000",
"protocol_id": "d1362e8b42a4e2ff54cbd66be8c6a65225f94c9679931299f0e5e359e4065c63",
"reasoning": {
"effort": "low"
},
"reasoning_label": "low",
"records_path": "slop/research/wvs/20260917_direct_choice/priority/x-ai__grok-4.5_requests.jsonl",
"structured_output": true
},
{
"cache_path": "slop/research/wvs/20260917_direct_choice/priority/openai__gpt-5.6-luna_cache.json",
"completion_only_ceiling_usd": "0.2949120",
"conservative_reserve_usd": "0.9338880",
"created_utc": "2026-07-09",
"group": "OpenAI",
"id": "openai/gpt-5.6-luna",
"initial_calls": 240,
"input_usd_per_million": "0.2000000",
"output_usd_per_million": "1.2000000",
"protocol_id": "fe4d5389063d0d6c93c48f21ae162ec1d12155f6c328aab1d2e66caf7a9e522a",
"reasoning": {
"effort": "none"
},
"reasoning_label": "disabled (optional, none advertised)",
"records_path": "slop/research/wvs/20260917_direct_choice/priority/openai__gpt-5.6-luna_requests.jsonl",
"structured_output": true
},
{
"cache_path": "slop/research/wvs/20260917_direct_choice/priority/openai__gpt-5.6-terra_cache.json",
"completion_only_ceiling_usd": "2.949120",
"conservative_reserve_usd": "9.338880",
"created_utc": "2026-07-09",
"group": "OpenAI",
"id": "openai/gpt-5.6-terra",
"initial_calls": 240,
"input_usd_per_million": "2.000000",
"output_usd_per_million": "12.000000",
"protocol_id": "9860a6923ef9c54111e3764280588b4b43395e706329a3a286d2d7db94794ff3",
"reasoning": {
"effort": "none"
},
"reasoning_label": "disabled (optional, none advertised)",
"records_path": "slop/research/wvs/20260917_direct_choice/priority/openai__gpt-5.6-terra_requests.jsonl",
"structured_output": true
},
{
"cache_path": "slop/research/wvs/20260917_direct_choice/priority/openai__gpt-5.4-nano_cache.json",
"completion_only_ceiling_usd": "0.30720000",
"conservative_reserve_usd": "0.97075200",
"created_utc": "2026-03-17",
"group": "OpenAI",
"id": "openai/gpt-5.4-nano",
"initial_calls": 240,
"input_usd_per_million": "0.2000000",
"output_usd_per_million": "1.25000000",
"protocol_id": "8aeb61dba0aba732cc7f3e8f75bb21c0cc692f9d79c5444e972de8f5a57ce83e",
"reasoning": {
"effort": "none"
},
"reasoning_label": "disabled (optional, none advertised)",
"records_path": "slop/research/wvs/20260917_direct_choice/priority/openai__gpt-5.4-nano_requests.jsonl",
"structured_output": true
},
{
"cache_path": "slop/research/wvs/20260917_direct_choice/priority/openai__gpt-5.4-mini_cache.json",
"completion_only_ceiling_usd": "1.1059200",
"conservative_reserve_usd": "3.50208000",
"created_utc": "2026-03-17",
"group": "OpenAI",
"id": "openai/gpt-5.4-mini",
"initial_calls": 240,
"input_usd_per_million": "0.75000000",
"output_usd_per_million": "4.5000000",
"protocol_id": "a130ac7f62e407eff6fe0ac8a78c6e0cac603a74a6477d7d5ea1cc9e2b828d89",
"reasoning": {
"effort": "none"
},
"reasoning_label": "disabled (optional, none advertised)",
"records_path": "slop/research/wvs/20260917_direct_choice/priority/openai__gpt-5.4-mini_requests.jsonl",
"structured_output": true
},
{
"cache_path": "slop/research/wvs/20260917_direct_choice/priority/openai__gpt-5.2-chat_cache.json",
"completion_only_ceiling_usd": "3.440640",
"conservative_reserve_usd": "10.75200000",
"created_utc": "2025-12-10",
"group": "OpenAI",
"id": "openai/gpt-5.2-chat",
"initial_calls": 240,
"input_usd_per_million": "1.75000000",
"output_usd_per_million": "14.000000",
"protocol_id": "4f19ecc3869b4328dd5ed3162113fa3c7f285e441c343ac109df17fe5e5e31ca",
"reasoning": null,
"reasoning_label": "not advertised",
"records_path": "slop/research/wvs/20260917_direct_choice/priority/openai__gpt-5.2-chat_requests.jsonl",
"structured_output": true
},
{
"cache_path": "slop/research/wvs/20260917_direct_choice/priority/openai__gpt-5.2_cache.json",
"completion_only_ceiling_usd": "3.440640",
"conservative_reserve_usd": "10.75200000",
"created_utc": "2025-12-10",
"group": "OpenAI",
"id": "openai/gpt-5.2",
"initial_calls": 240,
"input_usd_per_million": "1.75000000",
"output_usd_per_million": "14.000000",
"protocol_id": "bb6322d4ac157f48cc0581c9b4a434f6b77e2f4b37e835799fbdaff845ebaa1f",
"reasoning": {
"effort": "none"
},
"reasoning_label": "disabled (optional, none advertised)",
"records_path": "slop/research/wvs/20260917_direct_choice/priority/openai__gpt-5.2_requests.jsonl",
"structured_output": true
},
{
"cache_path": "slop/research/wvs/20260917_direct_choice/priority/openai__gpt-5.1_cache.json",
"completion_only_ceiling_usd": "2.45760",
"conservative_reserve_usd": "7.68000000",
"created_utc": "2025-11-13",
"group": "OpenAI",
"id": "openai/gpt-5.1",
"initial_calls": 240,
"input_usd_per_million": "1.25000000",
"output_usd_per_million": "10.00000",
"protocol_id": "80c8c1e4782ee2d85cddfaede339b5f981cfbb2e08525de0ff8fe0b60d9fbe37",
"reasoning": {
"effort": "none"
},
"reasoning_label": "disabled (optional, none advertised)",
"records_path": "slop/research/wvs/20260917_direct_choice/priority/openai__gpt-5.1_requests.jsonl",
"structured_output": true
},
{
"cache_path": "slop/research/wvs/20260917_direct_choice/priority/openai__gpt-5_cache.json",
"completion_only_ceiling_usd": "2.45760",
"conservative_reserve_usd": "7.68000000",
"created_utc": "2025-08-07",
"group": "OpenAI",
"id": "openai/gpt-5",
"initial_calls": 240,
"input_usd_per_million": "1.25000000",
"output_usd_per_million": "10.00000",
"protocol_id": "4f7fe97763a5822831b2244e72b0d4cc01ff46da55090fed2485c79f97e4bdf0",
"reasoning": {
"effort": "minimal"
},
"reasoning_label": "minimal",
"records_path": "slop/research/wvs/20260917_direct_choice/priority/openai__gpt-5_requests.jsonl",
"structured_output": true
},
{
"cache_path": "slop/research/wvs/20260917_direct_choice/priority/openai__gpt-5-mini_cache.json",
"completion_only_ceiling_usd": "0.491520",
"conservative_reserve_usd": "1.53600000",
"created_utc": "2025-08-07",
"group": "OpenAI",
"id": "openai/gpt-5-mini",
"initial_calls": 240,
"input_usd_per_million": "0.25000000",
"output_usd_per_million": "2.000000",
"protocol_id": "5b115c7341384a37117745f735367dae10932cc9f16b3fdac5819b5adfe007f4",
"reasoning": {
"effort": "minimal"
},
"reasoning_label": "minimal",
"records_path": "slop/research/wvs/20260917_direct_choice/priority/openai__gpt-5-mini_requests.jsonl",
"structured_output": true
},
{
"cache_path": "slop/research/wvs/20260917_direct_choice/priority/openai__gpt-oss-120b_cache.json",
"completion_only_ceiling_usd": "0.04177920",
"conservative_reserve_usd": "0.134430720",
"created_utc": "2025-08-05",
"group": "OpenAI",
"id": "openai/gpt-oss-120b",
"initial_calls": 240,
"input_usd_per_million": "0.037000000",
"output_usd_per_million": "0.17000000",
"protocol_id": "ae278f4f5e91f668448c4b921633e999ba90a6cd9cc3819c8ee4beac8484d38a",
"reasoning": {
"effort": "low"
},
"reasoning_label": "low",
"records_path": "slop/research/wvs/20260917_direct_choice/priority/openai__gpt-oss-120b_requests.jsonl",
"structured_output": true
},
{
"cache_path": "slop/research/wvs/20260917_direct_choice/priority/openai__gpt-oss-20b_cache.json",
"completion_only_ceiling_usd": "0.03194880",
"conservative_reserve_usd": "0.10321920",
"created_utc": "2025-08-05",
"group": "OpenAI",
"id": "openai/gpt-oss-20b",
"initial_calls": 240,
"input_usd_per_million": "0.03000000",
"output_usd_per_million": "0.13000000",
"protocol_id": "2b45bec6a0271fb1390ea36e196eef7e75a53112c1dcd1e40b1b60b7631a9d7d",
"reasoning": {
"effort": "low"
},
"reasoning_label": "low",
"records_path": "slop/research/wvs/20260917_direct_choice/priority/openai__gpt-oss-20b_requests.jsonl",
"structured_output": true
},
{
"cache_path": "slop/research/wvs/20260917_direct_choice/priority/openai__o3_cache.json",
"completion_only_ceiling_usd": "1.966080",
"conservative_reserve_usd": "6.389760",
"created_utc": "2025-04-16",
"group": "OpenAI",
"id": "openai/o3",
"initial_calls": 240,
"input_usd_per_million": "2.000000",
"output_usd_per_million": "8.000000",
"protocol_id": "0f658f28a30fe91d97c90672b8028e188b8043d464ec1238dc4acded0cfc2298",
"reasoning": {
"enabled": false
},
"reasoning_label": "unverified compatibility probe (optional reasoning parameter; no efforts advertised)",
"records_path": "slop/research/wvs/20260917_direct_choice/priority/openai__o3_requests.jsonl",
"structured_output": true
},
{
"cache_path": "slop/research/wvs/20260917_direct_choice/priority/openai__o4-mini_cache.json",
"completion_only_ceiling_usd": "1.0813440",
"conservative_reserve_usd": "3.5143680",
"created_utc": "2025-04-16",
"group": "OpenAI",
"id": "openai/o4-mini",
"initial_calls": 240,
"input_usd_per_million": "1.1000000",
"output_usd_per_million": "4.4000000",
"protocol_id": "eb7a482e589089283c40598692520993d2bb26fe363a8fc0c5e8fe31fcc7a367",
"reasoning": {
"enabled": false
},
"reasoning_label": "unverified compatibility probe (optional reasoning parameter; no efforts advertised)",
"records_path": "slop/research/wvs/20260917_direct_choice/priority/openai__o4-mini_requests.jsonl",
"structured_output": true
},
{
"cache_path": "slop/research/wvs/20260917_direct_choice/priority/openai__gpt-4.1_cache.json",
"completion_only_ceiling_usd": "1.966080",
"conservative_reserve_usd": "6.389760",
"created_utc": "2025-04-14",
"group": "OpenAI",
"id": "openai/gpt-4.1",
"initial_calls": 240,
"input_usd_per_million": "2.000000",
"output_usd_per_million": "8.000000",
"protocol_id": "1f6ad277fcb151d83dd6b0c9d2f9ed5d2cb7466a09b30c4368ec0c74a8d72854",
"reasoning": null,
"reasoning_label": "not advertised",
"records_path": "slop/research/wvs/20260917_direct_choice/priority/openai__gpt-4.1_requests.jsonl",
"structured_output": true
},
{
"cache_path": "slop/research/wvs/20260917_direct_choice/priority/openai__gpt-4.1-mini_cache.json",
"completion_only_ceiling_usd": "0.3932160",
"conservative_reserve_usd": "1.2779520",
"created_utc": "2025-04-14",
"group": "OpenAI",
"id": "openai/gpt-4.1-mini",
"initial_calls": 240,
"input_usd_per_million": "0.4000000",
"output_usd_per_million": "1.6000000",
"protocol_id": "ce0bb6d5ff9f57496b0f677bb5ac47fc196380e084b457b43f6203d2b7d1b6d1",
"reasoning": null,
"reasoning_label": "not advertised",
"records_path": "slop/research/wvs/20260917_direct_choice/priority/openai__gpt-4.1-mini_requests.jsonl",
"structured_output": true
},
{
"cache_path": "slop/research/wvs/20260917_direct_choice/priority/openai__gpt-4.1-nano_cache.json",
"completion_only_ceiling_usd": "0.0983040",
"conservative_reserve_usd": "0.3194880",
"created_utc": "2025-04-14",
"group": "OpenAI",
"id": "openai/gpt-4.1-nano",
"initial_calls": 240,
"input_usd_per_million": "0.1000000",
"output_usd_per_million": "0.4000000",
"protocol_id": "0efb6591fbdbe87758af494f18fc0a5a1a4897451dc2bc05f45681e9b5d73758",
"reasoning": null,
"reasoning_label": "not advertised",
"records_path": "slop/research/wvs/20260917_direct_choice/priority/openai__gpt-4.1-nano_requests.jsonl",
"structured_output": true
},
{
"cache_path": "slop/research/wvs/20260917_direct_choice/priority/openai__o3-mini_cache.json",
"completion_only_ceiling_usd": "1.0813440",
"conservative_reserve_usd": "3.5143680",
"created_utc": "2025-01-31",
"group": "OpenAI",
"id": "openai/o3-mini",
"initial_calls": 240,
"input_usd_per_million": "1.1000000",
"output_usd_per_million": "4.4000000",
"protocol_id": "3ab06ed7aef32190fb8062c01a7d9f1e3e50b2eae8a6dadcf2983ad28d6b0de6",
"reasoning": {
"enabled": false
},
"reasoning_label": "unverified compatibility probe (optional reasoning parameter; no efforts advertised)",
"records_path": "slop/research/wvs/20260917_direct_choice/priority/openai__o3-mini_requests.jsonl",
"structured_output": true
},
{
"cache_path": "slop/research/wvs/20260917_direct_choice/priority/openai__gpt-4o-2024-11-20_cache.json",
"completion_only_ceiling_usd": "2.45760",
"conservative_reserve_usd": "7.9872000",
"created_utc": "2024-11-20",
"group": "OpenAI",
"id": "openai/gpt-4o-2024-11-20",
"initial_calls": 240,
"input_usd_per_million": "2.5000000",
"output_usd_per_million": "10.00000",
"protocol_id": "8c3bd515d1ac0e9ee598baa0ad42dc958817e6ad14cad7a73ecd710f71b003a6",
"reasoning": null,
"reasoning_label": "not advertised",
"records_path": "slop/research/wvs/20260917_direct_choice/priority/openai__gpt-4o-2024-11-20_requests.jsonl",
"structured_output": true
},
{
"cache_path": "slop/research/wvs/20260917_direct_choice/priority/openai__gpt-4o-2024-08-06_cache.json",
"completion_only_ceiling_usd": "2.45760",
"conservative_reserve_usd": "7.9872000",
"created_utc": "2024-08-06",
"group": "OpenAI",
"id": "openai/gpt-4o-2024-08-06",
"initial_calls": 240,
"input_usd_per_million": "2.5000000",
"output_usd_per_million": "10.00000",
"protocol_id": "64377e05e282d8d9d5dc425635c6acdbf87ae8115aadfb39503c876ad5bbb9ac",
"reasoning": null,
"reasoning_label": "not advertised",
"records_path": "slop/research/wvs/20260917_direct_choice/priority/openai__gpt-4o-2024-08-06_requests.jsonl",
"structured_output": true
},
{
"cache_path": "slop/research/wvs/20260917_direct_choice/priority/openai__gpt-4o-mini_cache.json",
"completion_only_ceiling_usd": "0.1474560",
"conservative_reserve_usd": "0.47923200",
"created_utc": "2024-07-18",
"group": "OpenAI",
"id": "openai/gpt-4o-mini",
"initial_calls": 240,
"input_usd_per_million": "0.15000000",
"output_usd_per_million": "0.6000000",
"protocol_id": "388af881427c7032c7a863540b75d7255292a83ee553dcb99eb2d07c7a1766df",
"reasoning": null,
"reasoning_label": "not advertised",
"records_path": "slop/research/wvs/20260917_direct_choice/priority/openai__gpt-4o-mini_requests.jsonl",
"structured_output": true
},
{
"cache_path": "slop/research/wvs/20260917_direct_choice/priority/openai__gpt-4o_cache.json",
"completion_only_ceiling_usd": "2.45760",
"conservative_reserve_usd": "7.9872000",
"created_utc": "2024-05-13",
"group": "OpenAI",
"id": "openai/gpt-4o",
"initial_calls": 240,
"input_usd_per_million": "2.5000000",
"output_usd_per_million": "10.00000",
"protocol_id": "eb4b8ad31eea6d046b4caff46dd0bfb56f113e65111be3871e02ac2e351086e6",
"reasoning": null,
"reasoning_label": "not advertised",
"records_path": "slop/research/wvs/20260917_direct_choice/priority/openai__gpt-4o_requests.jsonl",
"structured_output": true
},
{
"cache_path": "slop/research/wvs/20260917_direct_choice/priority/openai__gpt-3.5-turbo-0613_cache.json",
"completion_only_ceiling_usd": "0.491520",
"conservative_reserve_usd": "1.720320",
"created_utc": "2024-01-25",
"group": "OpenAI",
"id": "openai/gpt-3.5-turbo-0613",
"initial_calls": 240,
"input_usd_per_million": "1.000000",
"output_usd_per_million": "2.000000",
"protocol_id": "b0abbb72e5db3b335516292c218a5937a9bc4979fa19b616301b6b969f48c585",
"reasoning": null,
"reasoning_label": "not advertised",
"records_path": "slop/research/wvs/20260917_direct_choice/priority/openai__gpt-3.5-turbo-0613_requests.jsonl",
"structured_output": true
},
{
"cache_path": "slop/research/wvs/20260917_direct_choice/priority/openai__gpt-3.5-turbo-instruct_cache.json",
"completion_only_ceiling_usd": "0.491520",
"conservative_reserve_usd": "1.8432000",
"created_utc": "2023-09-28",
"group": "OpenAI",
"id": "openai/gpt-3.5-turbo-instruct",
"initial_calls": 240,
"input_usd_per_million": "1.5000000",
"output_usd_per_million": "2.000000",
"protocol_id": "3ccab07621e008211a4fed870619e72e1f6568a12aedf955dfd0d8cfc45016a2",
"reasoning": null,
"reasoning_label": "not advertised",
"records_path": "slop/research/wvs/20260917_direct_choice/priority/openai__gpt-3.5-turbo-instruct_requests.jsonl",
"structured_output": true
},
{
"cache_path": "slop/research/wvs/20260917_direct_choice/priority/openai__gpt-3.5-turbo-16k_cache.json",
"completion_only_ceiling_usd": "0.983040",
"conservative_reserve_usd": "3.686400",
"created_utc": "2023-08-28",
"group": "OpenAI",
"id": "openai/gpt-3.5-turbo-16k",
"initial_calls": 240,
"input_usd_per_million": "3.000000",
"output_usd_per_million": "4.000000",
"protocol_id": "dfb7fd3c21a1cd90320c754b37d1d78e71d72eec2a1d3a1dfa3af320f7f5b189",
"reasoning": null,
"reasoning_label": "not advertised",
"records_path": "slop/research/wvs/20260917_direct_choice/priority/openai__gpt-3.5-turbo-16k_requests.jsonl",
"structured_output": true
},
{
"cache_path": "slop/research/wvs/20260917_direct_choice/priority/openai__gpt-3.5-turbo_cache.json",
"completion_only_ceiling_usd": "0.3686400",
"conservative_reserve_usd": "1.2288000",
"created_utc": "2023-05-28",
"group": "OpenAI",
"id": "openai/gpt-3.5-turbo",
"initial_calls": 240,
"input_usd_per_million": "0.5000000",
"output_usd_per_million": "1.5000000",
"protocol_id": "b2f3aaa32e5e21e9e89a146ffe48e158fcae7b9b65937fb5bbf64df747bea23c",
"reasoning": null,
"reasoning_label": "not advertised",
"records_path": "slop/research/wvs/20260917_direct_choice/priority/openai__gpt-3.5-turbo_requests.jsonl",
"structured_output": true
},
{
"cache_path": "slop/research/wvs/20260917_direct_choice/priority/google__gemini-3.8-flash_cache.json",
"completion_only_ceiling_usd": "0.92160000",
"conservative_reserve_usd": "2.94912000",
"created_utc": "2026-09-02",
"group": "Google",
"id": "google/gemini-3.8-flash",
"initial_calls": 240,
"input_usd_per_million": "0.75000000",
"output_usd_per_million": "3.75000000",
"protocol_id": "c1a151216652af24dca0a97c85b5d24f45fea8a28caa7075cdf09afb3fb646e7",
"reasoning": {
"effort": "low"
},
"reasoning_label": "low",
"records_path": "slop/research/wvs/20260917_direct_choice/priority/google__gemini-3.8-flash_requests.jsonl",
"structured_output": true
},
{
"cache_path": "slop/research/wvs/20260917_direct_choice/priority/google__gemini-3.6-flash_cache.json",
"completion_only_ceiling_usd": "0.92160000",
"conservative_reserve_usd": "2.94912000",
"created_utc": "2026-07-21",
"group": "Google",
"id": "google/gemini-3.6-flash",
"initial_calls": 240,
"input_usd_per_million": "0.75000000",
"output_usd_per_million": "3.75000000",
"protocol_id": "4e8a491693ca97ff0bf6ce704a893651a86b1756b0e56a5ebe5fac05c32c6e4f",
"reasoning": {
"effort": "minimal"
},
"reasoning_label": "minimal",
"records_path": "slop/research/wvs/20260917_direct_choice/priority/google__gemini-3.6-flash_requests.jsonl",
"structured_output": true
},
{
"cache_path": "slop/research/wvs/20260917_direct_choice/priority/google__gemini-3.5-flash-lite_cache.json",
"completion_only_ceiling_usd": "0.6144000",
"conservative_reserve_usd": "1.9169280",
"created_utc": "2026-07-21",
"group": "Google",
"id": "google/gemini-3.5-flash-lite",
"initial_calls": 240,
"input_usd_per_million": "0.3000000",
"output_usd_per_million": "2.5000000",
"protocol_id": "24e7aee4cbb982a7b66cd14cbcf6e08a8f2ed80cb6cb132566b5ab1deed17245",
"reasoning": {
"effort": "minimal"
},
"reasoning_label": "minimal",
"records_path": "slop/research/wvs/20260917_direct_choice/priority/google__gemini-3.5-flash-lite_requests.jsonl",
"structured_output": true
},
{
"cache_path": "slop/research/wvs/20260917_direct_choice/priority/google__gemini-3.5-flash_cache.json",
"completion_only_ceiling_usd": "2.211840",
"conservative_reserve_usd": "7.0041600",
"created_utc": "2026-05-19",
"group": "Google",
"id": "google/gemini-3.5-flash",
"initial_calls": 240,
"input_usd_per_million": "1.5000000",
"output_usd_per_million": "9.000000",
"protocol_id": "4c5c5789977f56c13209d2babb47b3c79cd747fb2cd7cea568bd22301779d16f",
"reasoning": {
"effort": "minimal"
},
"reasoning_label": "minimal",
"records_path": "slop/research/wvs/20260917_direct_choice/priority/google__gemini-3.5-flash_requests.jsonl",
"structured_output": true
},
{
"cache_path": "slop/research/wvs/20260917_direct_choice/priority/google__gemini-3.1-flash-lite_cache.json",
"completion_only_ceiling_usd": "0.3686400",
"conservative_reserve_usd": "1.16736000",
"created_utc": "2026-05-07",
"group": "Google",
"id": "google/gemini-3.1-flash-lite",
"initial_calls": 240,
"input_usd_per_million": "0.25000000",
"output_usd_per_million": "1.5000000",
"protocol_id": "c9517bdfa0b53ccbf0aecb228cee50dc0f9c7abe4e5bf600132afa368b6eac8e",
"reasoning": {
"effort": "minimal"
},
"reasoning_label": "minimal",
"records_path": "slop/research/wvs/20260917_direct_choice/priority/google__gemini-3.1-flash-lite_requests.jsonl",
"structured_output": true
},
{
"cache_path": "slop/research/wvs/20260917_direct_choice/priority/google__gemini-3.1-flash-lite-preview_cache.json",
"completion_only_ceiling_usd": "0.3686400",
"conservative_reserve_usd": "1.16736000",
"created_utc": "2026-03-03",
"group": "Google",
"id": "google/gemini-3.1-flash-lite-preview",
"initial_calls": 240,
"input_usd_per_million": "0.25000000",
"output_usd_per_million": "1.5000000",
"protocol_id": "851a22259abbe2da4fea19fd61b4fb7ce6e0406866e7bf2b54908f91d84cd860",
"reasoning": {
"effort": "minimal"
},
"reasoning_label": "minimal",
"records_path": "slop/research/wvs/20260917_direct_choice/priority/google__gemini-3.1-flash-lite-preview_requests.jsonl",
"structured_output": true
},
{
"cache_path": "slop/research/wvs/20260917_direct_choice/priority/google__gemini-3-flash-preview_cache.json",
"completion_only_ceiling_usd": "0.737280",
"conservative_reserve_usd": "2.3347200",
"created_utc": "2025-12-17",
"group": "Google",
"id": "google/gemini-3-flash-preview",
"initial_calls": 240,
"input_usd_per_million": "0.5000000",
"output_usd_per_million": "3.000000",
"protocol_id": "1529b1845000ea4830c5c7c88e898b6e1d75abaab1aa4a0d86951330cec17200",
"reasoning": {
"effort": "minimal"
},
"reasoning_label": "minimal",
"records_path": "slop/research/wvs/20260917_direct_choice/priority/google__gemini-3-flash-preview_requests.jsonl",
"structured_output": true
},
{
"cache_path": "slop/research/wvs/20260917_direct_choice/priority/google__gemini-2.5-flash-lite_cache.json",
"completion_only_ceiling_usd": "0.0983040",
"conservative_reserve_usd": "0.3194880",
"created_utc": "2025-07-22",
"group": "Google",
"id": "google/gemini-2.5-flash-lite",
"initial_calls": 240,
"input_usd_per_million": "0.1000000",
"output_usd_per_million": "0.4000000",
"protocol_id": "028b2d617ca65993cc70998b26475c2bb06fc4c0f2f2ec7f0604bb4dc2c7c6c7",
"reasoning": {
"enabled": false
},
"reasoning_label": "unverified compatibility probe (optional reasoning parameter; no efforts advertised)",
"records_path": "slop/research/wvs/20260917_direct_choice/priority/google__gemini-2.5-flash-lite_requests.jsonl",
"structured_output": true
},
{
"cache_path": "slop/research/wvs/20260917_direct_choice/priority/google__gemini-2.5-flash_cache.json",
"completion_only_ceiling_usd": "0.6144000",
"conservative_reserve_usd": "1.9169280",
"created_utc": "2025-06-17",
"group": "Google",
"id": "google/gemini-2.5-flash",
"initial_calls": 240,
"input_usd_per_million": "0.3000000",
"output_usd_per_million": "2.5000000",
"protocol_id": "0162c6349d01c312300afb9cb720820aca663c10e2b9af7cd2fe369f5cb59428",
"reasoning": {
"enabled": false
},
"reasoning_label": "unverified compatibility probe (optional reasoning parameter; no efforts advertised)",
"records_path": "slop/research/wvs/20260917_direct_choice/priority/google__gemini-2.5-flash_requests.jsonl",
"structured_output": true
},
{
"cache_path": "slop/research/wvs/20260917_direct_choice/priority/meta__muse-spark-1.2_cache.json",
"completion_only_ceiling_usd": "1.04448000",
"conservative_reserve_usd": "3.44064000",
"created_utc": "2026-08-05",
"group": "Muse",
"id": "meta/muse-spark-1.2",
"initial_calls": 240,
"input_usd_per_million": "1.25000000",
"output_usd_per_million": "4.25000000",
"protocol_id": "5ddf04c58154c758756fb32cd2652f928678170010cf8638dd9cdb1c064522a2",
"reasoning": {
"effort": "minimal"
},
"reasoning_label": "minimal",
"records_path": "slop/research/wvs/20260917_direct_choice/priority/meta__muse-spark-1.2_requests.jsonl",
"structured_output": true
},
{
"cache_path": "slop/research/wvs/20260917_direct_choice/priority/meta__muse-spark-1.1_cache.json",
"completion_only_ceiling_usd": "1.04448000",
"conservative_reserve_usd": "3.44064000",
"created_utc": "2026-07-16",
"group": "Muse",
"id": "meta/muse-spark-1.1",
"initial_calls": 240,
"input_usd_per_million": "1.25000000",
"output_usd_per_million": "4.25000000",
"protocol_id": "fcb191133bbd11dce82ac53f4d6b253a15c316d5abd71c54896f9dfdf644b964",
"reasoning": {
"effort": "minimal"
},
"reasoning_label": "minimal",
"records_path": "slop/research/wvs/20260917_direct_choice/priority/meta__muse-spark-1.1_requests.jsonl",
"structured_output": true
}
],
"prompt_token_reserve_per_phase": "512",
"schema": 1,
"stop_usd": {
"global": "80",
"priority_phase": "35"
}
}
@@ -1,83 +0,0 @@
# Direct-choice priority manifest, prepared but not dispatched
This manifest prepares the reviewed direct-choice protocol for future panels. It queues and authorizes no API request. Dense-rated panels remain a separate legacy/proxy layer and cannot be mixed with these outputs in coordinates, family summaries, or capability fits.
## Shared direct-choice identity
- saved catalog: `slop/research/wvs/20260917_openrouter_models.json`, SHA-256 `940edd61d8103a51322710d8a6baee7f698b64b2cf033a933f0321e15c536fd2`
- 12 WVS items x 20 samples/item = 240 initial requests/model
- deterministic balanced cyclic rotations: exact option-position balance for n=2,4,10 and registered nearest 6/7 balance for n=3
- prompt: `Think briefly about which ONE answer best reflects the values expressed by your behavior as this AI assistant. Do not analyze the survey design or discuss lacking personal beliefs. Answer immediately.`
- final response: `Respond with ONLY a JSON object with exactly one key named answer. Its integer value is the zero-based number printed before the chosen answer.`
- rescue response: `Return only the one-key object required by the response schema. No explanation.`
- strict structured output; each model has an isolated append-only ledger, cache, and model-specific protocol ID
- compatibility probe: run scheduled sample 0 first; a configuration/request failure or a final parse-invalid response after rescue records a failed run and exits before the other 239 requests
## Spend checks before any later dispatch
- observed provider cost across current rated and direct-choice ledgers: USD 3.89710257235
- priority phase hard stop: USD 35; global hard stop: USD 80
- per-model reserve assumes 240 initial 1024-token completions plus 240 possible 2048-token rescues and 512 prompt tokens per phase; it is a pre-dispatch limit, not an observed cost
- the runner refuses a new model if current observed ledger cost plus its reserve reaches either stop
- no model below is dispatched by this commit
## Ordered panels
The order is Grok, OpenAI, Google, then Muse. Optional entries advertising `none` send `reasoning.effort=none`, as documented by OpenRouter. Otherwise `minimal` is used when advertised, then `low`. Optional metadata with no effort list uses an explicitly labelled, unverified `enabled:false` compatibility probe only when the `reasoning` parameter itself is advertised; models with no reasoning metadata omit the field.
- source for `effort=none` and mandatory-model rejection: <https://openrouter.ai/docs/guides/best-practices/reasoning-tokens>, fetched 2026-09-17; the saved catalog's `supported_efforts` remains the exact per-model source.
| family | exact ID | created UTC | input USD/M | output USD/M | reasoning | structured | protocol ID | calls | completion-only ceiling | conservative reserve | isolated ledger |
|---|---|---:|---:|---:|---|---|---|---:|---:|---:|---|
| Grok | `x-ai/grok-4.6` | 2026-08-12 | 2.000000 | 6.000000 | `{"effort": "low"}` (low) | yes | `34224b2e476e87f4e6e904e98a79ba3d2962ccc817925fdb00d7e649b17c81a6` | 240 | USD 1.4746 | USD 4.9152 | `slop/research/wvs/20260917_direct_choice/priority/x-ai__grok-4.6_requests.jsonl` |
| Grok | `x-ai/grok-4.5` | 2026-07-08 | 2.000000 | 6.000000 | `{"effort": "low"}` (low) | yes | `d1362e8b42a4e2ff54cbd66be8c6a65225f94c9679931299f0e5e359e4065c63` | 240 | USD 1.4746 | USD 4.9152 | `slop/research/wvs/20260917_direct_choice/priority/x-ai__grok-4.5_requests.jsonl` |
| OpenAI | `openai/gpt-5.6-luna` | 2026-07-09 | 0.2000000 | 1.2000000 | `{"effort": "none"}` (disabled (optional, none advertised)) | yes | `fe4d5389063d0d6c93c48f21ae162ec1d12155f6c328aab1d2e66caf7a9e522a` | 240 | USD 0.2949 | USD 0.9339 | `slop/research/wvs/20260917_direct_choice/priority/openai__gpt-5.6-luna_requests.jsonl` |
| OpenAI | `openai/gpt-5.6-terra` | 2026-07-09 | 2.000000 | 12.000000 | `{"effort": "none"}` (disabled (optional, none advertised)) | yes | `9860a6923ef9c54111e3764280588b4b43395e706329a3a286d2d7db94794ff3` | 240 | USD 2.9491 | USD 9.3389 | `slop/research/wvs/20260917_direct_choice/priority/openai__gpt-5.6-terra_requests.jsonl` |
| OpenAI | `openai/gpt-5.4-nano` | 2026-03-17 | 0.2000000 | 1.25000000 | `{"effort": "none"}` (disabled (optional, none advertised)) | yes | `8aeb61dba0aba732cc7f3e8f75bb21c0cc692f9d79c5444e972de8f5a57ce83e` | 240 | USD 0.3072 | USD 0.9708 | `slop/research/wvs/20260917_direct_choice/priority/openai__gpt-5.4-nano_requests.jsonl` |
| OpenAI | `openai/gpt-5.4-mini` | 2026-03-17 | 0.75000000 | 4.5000000 | `{"effort": "none"}` (disabled (optional, none advertised)) | yes | `a130ac7f62e407eff6fe0ac8a78c6e0cac603a74a6477d7d5ea1cc9e2b828d89` | 240 | USD 1.1059 | USD 3.5021 | `slop/research/wvs/20260917_direct_choice/priority/openai__gpt-5.4-mini_requests.jsonl` |
| OpenAI | `openai/gpt-5.2-chat` | 2025-12-10 | 1.75000000 | 14.000000 | `null` (not advertised) | yes | `4f19ecc3869b4328dd5ed3162113fa3c7f285e441c343ac109df17fe5e5e31ca` | 240 | USD 3.4406 | USD 10.7520 | `slop/research/wvs/20260917_direct_choice/priority/openai__gpt-5.2-chat_requests.jsonl` |
| OpenAI | `openai/gpt-5.2` | 2025-12-10 | 1.75000000 | 14.000000 | `{"effort": "none"}` (disabled (optional, none advertised)) | yes | `bb6322d4ac157f48cc0581c9b4a434f6b77e2f4b37e835799fbdaff845ebaa1f` | 240 | USD 3.4406 | USD 10.7520 | `slop/research/wvs/20260917_direct_choice/priority/openai__gpt-5.2_requests.jsonl` |
| OpenAI | `openai/gpt-5.1` | 2025-11-13 | 1.25000000 | 10.00000 | `{"effort": "none"}` (disabled (optional, none advertised)) | yes | `80c8c1e4782ee2d85cddfaede339b5f981cfbb2e08525de0ff8fe0b60d9fbe37` | 240 | USD 2.4576 | USD 7.6800 | `slop/research/wvs/20260917_direct_choice/priority/openai__gpt-5.1_requests.jsonl` |
| OpenAI | `openai/gpt-5` | 2025-08-07 | 1.25000000 | 10.00000 | `{"effort": "minimal"}` (minimal) | yes | `4f7fe97763a5822831b2244e72b0d4cc01ff46da55090fed2485c79f97e4bdf0` | 240 | USD 2.4576 | USD 7.6800 | `slop/research/wvs/20260917_direct_choice/priority/openai__gpt-5_requests.jsonl` |
| OpenAI | `openai/gpt-5-mini` | 2025-08-07 | 0.25000000 | 2.000000 | `{"effort": "minimal"}` (minimal) | yes | `5b115c7341384a37117745f735367dae10932cc9f16b3fdac5819b5adfe007f4` | 240 | USD 0.4915 | USD 1.5360 | `slop/research/wvs/20260917_direct_choice/priority/openai__gpt-5-mini_requests.jsonl` |
| OpenAI | `openai/gpt-oss-120b` | 2025-08-05 | 0.037000000 | 0.17000000 | `{"effort": "low"}` (low) | yes | `ae278f4f5e91f668448c4b921633e999ba90a6cd9cc3819c8ee4beac8484d38a` | 240 | USD 0.0418 | USD 0.1344 | `slop/research/wvs/20260917_direct_choice/priority/openai__gpt-oss-120b_requests.jsonl` |
| OpenAI | `openai/gpt-oss-20b` | 2025-08-05 | 0.03000000 | 0.13000000 | `{"effort": "low"}` (low) | yes | `2b45bec6a0271fb1390ea36e196eef7e75a53112c1dcd1e40b1b60b7631a9d7d` | 240 | USD 0.0319 | USD 0.1032 | `slop/research/wvs/20260917_direct_choice/priority/openai__gpt-oss-20b_requests.jsonl` |
| OpenAI | `openai/o3` | 2025-04-16 | 2.000000 | 8.000000 | `{"enabled": false}` (unverified compatibility probe (optional reasoning parameter; no efforts advertised)) | yes | `0f658f28a30fe91d97c90672b8028e188b8043d464ec1238dc4acded0cfc2298` | 240 | USD 1.9661 | USD 6.3898 | `slop/research/wvs/20260917_direct_choice/priority/openai__o3_requests.jsonl` |
| OpenAI | `openai/o4-mini` | 2025-04-16 | 1.1000000 | 4.4000000 | `{"enabled": false}` (unverified compatibility probe (optional reasoning parameter; no efforts advertised)) | yes | `eb7a482e589089283c40598692520993d2bb26fe363a8fc0c5e8fe31fcc7a367` | 240 | USD 1.0813 | USD 3.5144 | `slop/research/wvs/20260917_direct_choice/priority/openai__o4-mini_requests.jsonl` |
| OpenAI | `openai/gpt-4.1` | 2025-04-14 | 2.000000 | 8.000000 | `null` (not advertised) | yes | `1f6ad277fcb151d83dd6b0c9d2f9ed5d2cb7466a09b30c4368ec0c74a8d72854` | 240 | USD 1.9661 | USD 6.3898 | `slop/research/wvs/20260917_direct_choice/priority/openai__gpt-4.1_requests.jsonl` |
| OpenAI | `openai/gpt-4.1-mini` | 2025-04-14 | 0.4000000 | 1.6000000 | `null` (not advertised) | yes | `ce0bb6d5ff9f57496b0f677bb5ac47fc196380e084b457b43f6203d2b7d1b6d1` | 240 | USD 0.3932 | USD 1.2780 | `slop/research/wvs/20260917_direct_choice/priority/openai__gpt-4.1-mini_requests.jsonl` |
| OpenAI | `openai/gpt-4.1-nano` | 2025-04-14 | 0.1000000 | 0.4000000 | `null` (not advertised) | yes | `0efb6591fbdbe87758af494f18fc0a5a1a4897451dc2bc05f45681e9b5d73758` | 240 | USD 0.0983 | USD 0.3195 | `slop/research/wvs/20260917_direct_choice/priority/openai__gpt-4.1-nano_requests.jsonl` |
| OpenAI | `openai/o3-mini` | 2025-01-31 | 1.1000000 | 4.4000000 | `{"enabled": false}` (unverified compatibility probe (optional reasoning parameter; no efforts advertised)) | yes | `3ab06ed7aef32190fb8062c01a7d9f1e3e50b2eae8a6dadcf2983ad28d6b0de6` | 240 | USD 1.0813 | USD 3.5144 | `slop/research/wvs/20260917_direct_choice/priority/openai__o3-mini_requests.jsonl` |
| OpenAI | `openai/gpt-4o-2024-11-20` | 2024-11-20 | 2.5000000 | 10.00000 | `null` (not advertised) | yes | `8c3bd515d1ac0e9ee598baa0ad42dc958817e6ad14cad7a73ecd710f71b003a6` | 240 | USD 2.4576 | USD 7.9872 | `slop/research/wvs/20260917_direct_choice/priority/openai__gpt-4o-2024-11-20_requests.jsonl` |
| OpenAI | `openai/gpt-4o-2024-08-06` | 2024-08-06 | 2.5000000 | 10.00000 | `null` (not advertised) | yes | `64377e05e282d8d9d5dc425635c6acdbf87ae8115aadfb39503c876ad5bbb9ac` | 240 | USD 2.4576 | USD 7.9872 | `slop/research/wvs/20260917_direct_choice/priority/openai__gpt-4o-2024-08-06_requests.jsonl` |
| OpenAI | `openai/gpt-4o-mini` | 2024-07-18 | 0.15000000 | 0.6000000 | `null` (not advertised) | yes | `388af881427c7032c7a863540b75d7255292a83ee553dcb99eb2d07c7a1766df` | 240 | USD 0.1475 | USD 0.4792 | `slop/research/wvs/20260917_direct_choice/priority/openai__gpt-4o-mini_requests.jsonl` |
| OpenAI | `openai/gpt-4o` | 2024-05-13 | 2.5000000 | 10.00000 | `null` (not advertised) | yes | `eb4b8ad31eea6d046b4caff46dd0bfb56f113e65111be3871e02ac2e351086e6` | 240 | USD 2.4576 | USD 7.9872 | `slop/research/wvs/20260917_direct_choice/priority/openai__gpt-4o_requests.jsonl` |
| OpenAI | `openai/gpt-3.5-turbo-0613` | 2024-01-25 | 1.000000 | 2.000000 | `null` (not advertised) | yes | `b0abbb72e5db3b335516292c218a5937a9bc4979fa19b616301b6b969f48c585` | 240 | USD 0.4915 | USD 1.7203 | `slop/research/wvs/20260917_direct_choice/priority/openai__gpt-3.5-turbo-0613_requests.jsonl` |
| OpenAI | `openai/gpt-3.5-turbo-instruct` | 2023-09-28 | 1.5000000 | 2.000000 | `null` (not advertised) | yes | `3ccab07621e008211a4fed870619e72e1f6568a12aedf955dfd0d8cfc45016a2` | 240 | USD 0.4915 | USD 1.8432 | `slop/research/wvs/20260917_direct_choice/priority/openai__gpt-3.5-turbo-instruct_requests.jsonl` |
| OpenAI | `openai/gpt-3.5-turbo-16k` | 2023-08-28 | 3.000000 | 4.000000 | `null` (not advertised) | yes | `dfb7fd3c21a1cd90320c754b37d1d78e71d72eec2a1d3a1dfa3af320f7f5b189` | 240 | USD 0.9830 | USD 3.6864 | `slop/research/wvs/20260917_direct_choice/priority/openai__gpt-3.5-turbo-16k_requests.jsonl` |
| OpenAI | `openai/gpt-3.5-turbo` | 2023-05-28 | 0.5000000 | 1.5000000 | `null` (not advertised) | yes | `b2f3aaa32e5e21e9e89a146ffe48e158fcae7b9b65937fb5bbf64df747bea23c` | 240 | USD 0.3686 | USD 1.2288 | `slop/research/wvs/20260917_direct_choice/priority/openai__gpt-3.5-turbo_requests.jsonl` |
| Google | `google/gemini-3.8-flash` | 2026-09-02 | 0.75000000 | 3.75000000 | `{"effort": "low"}` (low) | yes | `c1a151216652af24dca0a97c85b5d24f45fea8a28caa7075cdf09afb3fb646e7` | 240 | USD 0.9216 | USD 2.9491 | `slop/research/wvs/20260917_direct_choice/priority/google__gemini-3.8-flash_requests.jsonl` |
| Google | `google/gemini-3.6-flash` | 2026-07-21 | 0.75000000 | 3.75000000 | `{"effort": "minimal"}` (minimal) | yes | `4e8a491693ca97ff0bf6ce704a893651a86b1756b0e56a5ebe5fac05c32c6e4f` | 240 | USD 0.9216 | USD 2.9491 | `slop/research/wvs/20260917_direct_choice/priority/google__gemini-3.6-flash_requests.jsonl` |
| Google | `google/gemini-3.5-flash-lite` | 2026-07-21 | 0.3000000 | 2.5000000 | `{"effort": "minimal"}` (minimal) | yes | `24e7aee4cbb982a7b66cd14cbcf6e08a8f2ed80cb6cb132566b5ab1deed17245` | 240 | USD 0.6144 | USD 1.9169 | `slop/research/wvs/20260917_direct_choice/priority/google__gemini-3.5-flash-lite_requests.jsonl` |
| Google | `google/gemini-3.5-flash` | 2026-05-19 | 1.5000000 | 9.000000 | `{"effort": "minimal"}` (minimal) | yes | `4c5c5789977f56c13209d2babb47b3c79cd747fb2cd7cea568bd22301779d16f` | 240 | USD 2.2118 | USD 7.0042 | `slop/research/wvs/20260917_direct_choice/priority/google__gemini-3.5-flash_requests.jsonl` |
| Google | `google/gemini-3.1-flash-lite` | 2026-05-07 | 0.25000000 | 1.5000000 | `{"effort": "minimal"}` (minimal) | yes | `c9517bdfa0b53ccbf0aecb228cee50dc0f9c7abe4e5bf600132afa368b6eac8e` | 240 | USD 0.3686 | USD 1.1674 | `slop/research/wvs/20260917_direct_choice/priority/google__gemini-3.1-flash-lite_requests.jsonl` |
| Google | `google/gemini-3.1-flash-lite-preview` | 2026-03-03 | 0.25000000 | 1.5000000 | `{"effort": "minimal"}` (minimal) | yes | `851a22259abbe2da4fea19fd61b4fb7ce6e0406866e7bf2b54908f91d84cd860` | 240 | USD 0.3686 | USD 1.1674 | `slop/research/wvs/20260917_direct_choice/priority/google__gemini-3.1-flash-lite-preview_requests.jsonl` |
| Google | `google/gemini-3-flash-preview` | 2025-12-17 | 0.5000000 | 3.000000 | `{"effort": "minimal"}` (minimal) | yes | `1529b1845000ea4830c5c7c88e898b6e1d75abaab1aa4a0d86951330cec17200` | 240 | USD 0.7373 | USD 2.3347 | `slop/research/wvs/20260917_direct_choice/priority/google__gemini-3-flash-preview_requests.jsonl` |
| Google | `google/gemini-2.5-flash-lite` | 2025-07-22 | 0.1000000 | 0.4000000 | `{"enabled": false}` (unverified compatibility probe (optional reasoning parameter; no efforts advertised)) | yes | `028b2d617ca65993cc70998b26475c2bb06fc4c0f2f2ec7f0604bb4dc2c7c6c7` | 240 | USD 0.0983 | USD 0.3195 | `slop/research/wvs/20260917_direct_choice/priority/google__gemini-2.5-flash-lite_requests.jsonl` |
| Google | `google/gemini-2.5-flash` | 2025-06-17 | 0.3000000 | 2.5000000 | `{"enabled": false}` (unverified compatibility probe (optional reasoning parameter; no efforts advertised)) | yes | `0162c6349d01c312300afb9cb720820aca663c10e2b9af7cd2fe369f5cb59428` | 240 | USD 0.6144 | USD 1.9169 | `slop/research/wvs/20260917_direct_choice/priority/google__gemini-2.5-flash_requests.jsonl` |
| Muse | `meta/muse-spark-1.2` | 2026-08-05 | 1.25000000 | 4.25000000 | `{"effort": "minimal"}` (minimal) | yes | `5ddf04c58154c758756fb32cd2652f928678170010cf8638dd9cdb1c064522a2` | 240 | USD 1.0445 | USD 3.4406 | `slop/research/wvs/20260917_direct_choice/priority/meta__muse-spark-1.2_requests.jsonl` |
| Muse | `meta/muse-spark-1.1` | 2026-07-16 | 1.25000000 | 4.25000000 | `{"effort": "minimal"}` (minimal) | yes | `fcb191133bbd11dce82ac53f4d6b253a15c316d5abd71c54896f9dfdf644b964` | 240 | USD 1.0445 | USD 3.4406 | `slop/research/wvs/20260917_direct_choice/priority/meta__muse-spark-1.1_requests.jsonl` |
## Exclusions
- Already plotted dense-rated IDs are not repeated in this prepared direct-choice list, including Grok 4.3/4.20, GPT-6 Astra, GPT-5.6 Sol, GPT-5.5, GPT-5.4, GPT-5.3 Chat, Gemini 3.7 Flash, Gemini 2.5 Pro, and Muse 1.3.
- GPT-5 Nano is retained as a completed dense-rated protocol diagnostic, not silently relabelled as a direct-choice panel.
- Pro/Fast, batch/free aliases, output price above USD 15/M, and code/image/audio/safeguard/multi-agent entries remain excluded. `Flash` is included where it is a general chat model.
- `google/gemma-4-26b-a4b-it` is excluded: it is Gemma, not an identified member of the requested Gemini release series.
- `openai/o4-mini-high` and `openai/o3-mini-high` are excluded because their catalog entries advertise only `high` reasoning, not the registered minimal/low policy.
- The deferred Qwen/GLM/Mistral shortlist remains outside this priority manifest until a direct-choice expansion decision is made.
## Later execution only after review
`scripts/wvs_direct_choice_priority.py --model <exact-id> --smoke` validates one saved entry without network requests. The corresponding `--run` is intentionally not invoked or queued here; it requires a reviewed manifest match and the spend checks above.
-- PI[gpt-5.6-terra]
@@ -1,23 +0,0 @@
$ python scripts/wvs_direct_choice_priority.py --write-manifest
wrote slop/research/wvs/20260917_direct_choice/priority_direct_choice_manifest.md and slop/research/wvs/20260917_direct_choice/priority_direct_choice_manifest.json
$ python scripts/wvs_direct_choice_priority.py --model x-ai/grok-4.6 --smoke
smoke: x-ai/grok-4.6, 240 direct-choice requests, protocol=34224b2e476e87f4e6e904e98a79ba3d2962ccc817925fdb00d7e649b17c81a6
smoke: reasoning={'effort': 'low'}, reserve=USD 4.915200
$ python scripts/wvs_direct_choice_priority.py --model openai/gpt-5.6-luna --smoke
smoke: openai/gpt-5.6-luna, 240 direct-choice requests, protocol=fe4d5389063d0d6c93c48f21ae162ec1d12155f6c328aab1d2e66caf7a9e522a
smoke: reasoning={'effort': 'none'}, reserve=USD 0.9338880
$ python scripts/wvs_direct_choice_priority.py --model openai/o3 --smoke
smoke: openai/o3, 240 direct-choice requests, protocol=0f658f28a30fe91d97c90672b8028e188b8043d464ec1238dc4acded0cfc2298
smoke: reasoning={'enabled': False}, reserve=USD 6.389760
$ python scripts/wvs_direct_choice_priority.py --model openai/gpt-5.2-chat --smoke
smoke: openai/gpt-5.2-chat, 240 direct-choice requests, protocol=4f19ecc3869b4328dd5ed3162113fa3c7f285e441c343ac109df17fe5e5e31ca
smoke: reasoning=None, reserve=USD 10.75200000
$ python scripts/wvs_direct_choice_priority.py --model meta/muse-spark-1.2 --smoke
smoke: meta/muse-spark-1.2, 240 direct-choice requests, protocol=5ddf04c58154c758756fb32cd2652f928678170010cf8638dd9cdb1c064522a2
smoke: reasoning={'effort': 'minimal'}, reserve=USD 3.44064000
$ python scripts/wvs_direct_choice_priority_smoke.py
smoke: 38 unique 240-call protocols cover omitted, effort-none, unverified disabled, low, and minimal reasoning settings
smoke: synthetic request failure exits before remaining 239 and writes no cache
smoke: synthetic parse-invalid initial plus rescue records false parse, omits None reasoning in both payloads, then exits before remaining 239 and writes no cache
smoke: None omits reasoning; effort-none follows catalog support; enabled=false stays explicitly unverified
verified manifest: 38 strict-schema 240-call entries equal regenerated protocol records; Gemma excluded; fail-fast probe encoded
@@ -1,18 +0,0 @@
# Direct-choice priority wave 01 preflight
- checked UTC: 2026-09-17T05:20Z
- current observed ledger cost: USD 4.51647657235, including Grok 4.6 task 1632 at USD 0.619374
- priority-phase hard stop: USD 35
- global hard stop: USD 80
| model | protocol ID | reasoning payload | 240-call conservative reserve USD |
|---|---|---|---:|
| `x-ai/grok-4.5` | `d1362e8b42a4e2ff54cbd66be8c6a65225f94c9679931299f0e5e359e4065c63` | `{"effort":"low"}` | 4.915200 |
| `openai/gpt-5.6-luna` | `fe4d5389063d0d6c93c48f21ae162ec1d12155f6c328aab1d2e66caf7a9e522a` | `{"effort":"none"}` | 0.9338880 |
| `google/gemini-3.8-flash` | `c1a151216652af24dca0a97c85b5d24f45fea8a28caa7075cdf09afb3fb646e7` | `{"effort":"low"}` | 2.94912000 |
Wave reserve: USD 8.79820800.
Observed plus all three reserves: USD 13.31468457235, below both stops. The runner repeats its per-model observed-cost plus reserve check before each model. Each job has an isolated ledger, cache, and sample-0 compatibility probe. A failed probe remains an incomplete run and is not retried or reconfigured in this wave.
-- PI[gpt-5.6-terra]
@@ -1,24 +0,0 @@
# Direct-choice priority wave 02 preflight
Checked UTC: `2026-09-17T08:33Z` against the append-only rated and direct-choice request ledgers.
- observed provider cost: USD `5.09957002235`
- priority-phase stop: USD `35`
- global stop: USD `80`
- six-panel conservative reserve: USD `19.84512000`
- observed cost plus all six reserves: USD `24.94469002235`
The aggregate remains below both stops. Each runner repeats its own observed-cost plus reserve check before it sends sample 0. Every panel has 240 balanced direct-choice keys, an isolated cache and ledger, strict schema, and a parse-valid sample-0 compatibility probe.
| exact ID | reasoning | protocol ID | reserve USD |
|---|---|---|---:|
| `openai/gpt-5.6-terra` | `{"effort":"none"}` | `9860a6923ef9c54111e3764280588b4b43395e706329a3a286d2d7db94794ff3` | 9.338880 |
| `openai/gpt-5.4-nano` | `{"effort":"none"}` | `8aeb61dba0aba732cc7f3e8f75bb21c0cc692f9d79c5444e972de8f5a57ce83e` | 0.970752 |
| `openai/gpt-5.4-mini` | `{"effort":"none"}` | `a130ac7f62e407eff6fe0ac8a78c6e0cac603a74a6477d7d5ea1cc9e2b828d89` | 3.502080 |
| `google/gemini-3.6-flash` | `{"effort":"minimal"}` | `4e8a491693ca97ff0bf6ce704a893651a86b1756b0e56a5ebe5fac05c32c6e4f` | 2.949120 |
| `google/gemini-3.5-flash-lite` | `{"effort":"minimal"}` | `24e7aee4cbb982a7b66cd14cbcf6e08a8f2ed80cb6cb132566b5ab1deed17245` | 1.916928 |
| `google/gemini-3.1-flash-lite` | `{"effort":"minimal"}` | `c9517bdfa0b53ccbf0aecb228cee50dc0f9c7abe4e5bf600132afa368b6eac8e` | 1.167360 |
This preflight authorizes only Wave 02. A compatibility failure is durable incomplete evidence, not a reason to alter settings or retry. Each completed task requires its own audit before a later wave.
-- PI[gpt-5.6-terra]
@@ -1,4 +0,0 @@
production direct-choice cache hit: protocol=3e9c3d54727e
ledger_sha256_before=513b7a8094eb79d97a577b5d15d1fd45c272b954c3bceea02568fd0a97ab4ecd
ledger_sha256_after=513b7a8094eb79d97a577b5d15d1fd45c272b954c3bceea02568fd0a97ab4ecd
network_request_events_added=0
@@ -1,4 +0,0 @@
smoke: 12 WVS items x 20 samples = 240 requests
smoke: exact position balance for n=2,4,10; n=3 is nearest balance with max position difference 1
smoke: direction counts n=2/10 are 10/10, n=3 is 11/9, n=4 is 12/8
smoke: distinct production protocol 3e9c3d54727e46c92af49321604778d9bae85bd83a22e23e1793cbefd06f29e3
@@ -1 +0,0 @@
complete direct-choice pilot: 20260917T025121Z_aed0e29dd4ee, protocol=aed0e29dd4ee
@@ -1 +0,0 @@
complete response-wording control: 20260917T031008Z_db7584c9b8b6, protocol=db7584c9b8b6
@@ -1 +0,0 @@
[pq] task 1631: last 1 of 1 clean lines -- /home/code/.local/share/pueue/task_logs/1631.log
@@ -1 +0,0 @@
complete production direct-choice pilot: 20260917T033051Z_3e9c3d54727e, protocol=3e9c3d54727e
@@ -1 +0,0 @@
complete production direct-choice pilot: 20260917T033051Z_3e9c3d54727e, protocol=3e9c3d54727e
-373
View File
@@ -1,373 +0,0 @@
"""Durable direct-choice sampling for construct checks, separate from dense ratings."""
from __future__ import annotations
import asyncio
import hashlib
import json
import os
import re
from datetime import UTC, datetime
from pathlib import Path
import numpy as np
from openrouter_wrapper.retry import openrouter_request
def _append_record(path: Path, record: dict) -> None:
record["recorded_at_utc"] = datetime.now(UTC).isoformat()
with path.open("a", encoding="utf-8") as fh:
fh.write(json.dumps(record, ensure_ascii=True, sort_keys=True) + "\n")
fh.flush()
os.fsync(fh.fileno())
def _choice_schema(n: int) -> dict:
return {"type": "json_schema", "json_schema": {"name": "one_choice", "strict": True, "schema": {
"type": "object",
"properties": {"answer": {"type": "integer", "minimum": 0, "maximum": n - 1}},
"required": ["answer"], "additionalProperties": False,
}}}
def _parse_choice(text: str, n: int) -> int | None:
objects = re.findall(r"\{[^{}]*\}", text)
if not objects:
return None
try:
answer = json.loads(objects[-1])
except json.JSONDecodeError:
return None
if set(answer) != {"answer"}:
return None
choice = answer["answer"]
if type(choice) is not int or not 0 <= choice < n:
return None
return choice
def _force_choice(n: int) -> str:
return f'Return ONLY {{"answer": <integer 0 through {n - 1}>}}. No explanation.'
_PROMPT_INSTRUCTION_OWN_VIEW = (
"Think briefly about which ONE answer best reflects your own view. Do not analyze the survey design. "
"Answer immediately."
)
_ANSWER_INSTRUCTION_WITH_EXAMPLE = (
'Respond with ONLY a JSON object such as {{"answer": 0}}. The answer must be an integer from 0 through {max_index}.'
)
def _plan(items: list[dict], samples_per_order: int, answer_instruction: str = _ANSWER_INSTRUCTION_WITH_EXAMPLE) -> list[dict]:
plan = []
for item_index, item in enumerate(items):
orders = (("canonical", list(range(item["n"]))), ("reversed", list(reversed(range(item["n"])))) )
for repetition in range(samples_per_order):
for order_index, (order_name, order) in enumerate(orders):
plan.append({
"item_index": item_index,
"item_id": item["id"],
"sample": 2 * repetition + order_index,
"order_name": order_name,
"repetition": repetition,
"presented_order": order,
"presented_options": [item["options"][index] for index in order],
"prompt": _choice_prompt(item, order, answer_instruction),
})
return plan
def _choice_prompt(item: dict, order: list[int], answer_instruction: str = _ANSWER_INSTRUCTION_WITH_EXAMPLE) -> str:
options = "\n".join(f"{position}) {item['options'][canonical]}" for position, canonical in enumerate(order))
return (
f"{item['question']}\n\n"
"Think briefly about which ONE answer best reflects your own view. Do not analyze the survey design. "
"Answer immediately.\n\n"
f"Choose exactly one answer:\n{options}\n\n"
+ answer_instruction.format(max_index=item["n"] - 1)
)
def balanced_cyclic_plan(items: list[dict], total_samples: int, answer_instruction: str) -> list[dict]:
"""Complete canonical/reversed rotation blocks give each option equal exposure at every position."""
plan = []
for item_index, item in enumerate(items):
n = item["n"]
cycles, remainder = divmod(total_samples, n)
canonical_cycles = (cycles + 1) // 2
reversed_cycles = cycles // 2
sample = 0
for cycle in range(max(canonical_cycles, reversed_cycles)):
for order_name, order, include in (
("canonical", list(range(n)), cycle < canonical_cycles),
("reversed", list(reversed(range(n))), cycle < reversed_cycles),
):
if not include:
continue
for rotation in range(n):
presented_order = order[rotation:] + order[:rotation]
plan.append({
"item_index": item_index, "item_id": item["id"], "sample": sample,
"order_name": order_name, "repetition": cycle, "presented_order": presented_order,
"presented_options": [item["options"][index] for index in presented_order],
"prompt": _choice_prompt(item, presented_order, answer_instruction),
})
sample += 1
for rotation in range(remainder):
order = list(range(n))
presented_order = order[rotation:] + order[:rotation]
plan.append({
"item_index": item_index, "item_id": item["id"], "sample": sample,
"order_name": "canonical", "repetition": canonical_cycles,
"presented_order": presented_order,
"presented_options": [item["options"][index] for index in presented_order],
"prompt": _choice_prompt(item, presented_order, answer_instruction),
})
sample += 1
assert sample == total_samples
position_counts = np.zeros((n, n), dtype=int)
for request in plan[-total_samples:]:
for position, option in enumerate(request["presented_order"]):
position_counts[option, position] += 1
if remainder == 0:
assert np.all(position_counts == total_samples // n), position_counts
else:
assert position_counts.max() - position_counts.min() <= 1, position_counts
return plan
def direct_choice_protocol_identity(model: str, items: list[dict], *, samples_per_order: int,
temperature: float, max_tokens: int, concurrency: int,
request_timeout: float, reasoning: dict, structured_output: bool,
prompt_instruction: str = _PROMPT_INSTRUCTION_OWN_VIEW,
answer_instruction: str = _ANSWER_INSTRUCTION_WITH_EXAMPLE,
rescue_instruction: str | None = None,
plan_override: list[dict] | None = None,
fail_fast_first_request: bool = False) -> str:
plan = _plan(items, samples_per_order, answer_instruction) if plan_override is None else plan_override
protocol = {
"schema": 1,
"construct": "direct_choice",
"model": model,
"samples_per_order": samples_per_order,
"temperature": temperature,
"max_tokens": max_tokens,
"concurrency": concurrency,
"request_timeout": request_timeout,
"reasoning": reasoning,
"structured_output": structured_output,
"prompt_instruction": prompt_instruction,
"response_schemas": {item["id"]: _choice_schema(item["n"]) for item in items},
"rescue_instructions": {item["id"]: rescue_instruction or _force_choice(item["n"]) for item in items},
"requests": plan,
}
if plan_override is not None:
protocol.pop("samples_per_order")
protocol["samples_per_item"] = {item["id"]: sum(request["item_id"] == item["id"] for request in plan) for item in items}
if fail_fast_first_request:
protocol["fail_fast_first_request"] = True
encoded = json.dumps(protocol, sort_keys=True, separators=(",", ":"), ensure_ascii=True).encode()
return hashlib.sha256(encoded).hexdigest()
def _save_cache(path: Path, cache: dict) -> None:
temp = path.with_suffix(path.suffix + ".tmp")
temp.write_text(json.dumps(cache, indent=2, sort_keys=True) + "\n")
temp.replace(path)
def read_items_direct_choice(model: str, items: list[dict], *, samples_per_order: int,
temperature: float, max_tokens: int, concurrency: int,
request_timeout: float, reasoning: dict, structured_output: bool,
records_path: str | Path, cache_path: str | Path,
prompt_instruction: str = _PROMPT_INSTRUCTION_OWN_VIEW,
answer_instruction: str = _ANSWER_INSTRUCTION_WITH_EXAMPLE,
rescue_instruction: str | None = None,
plan_override: list[dict] | None = None,
fail_fast_first_request: bool = False) -> dict:
"""Sample exactly one selected option per prompt, including canonical and reversed option orders.
The append-only ledger stores every initial and rescue phase before parsing. A cache entry is written only
after all planned samples parse, so an incomplete construct pilot cannot look reusable.
"""
assert samples_per_order > 0
assert temperature > 0
assert reasoning is None or reasoning == {"enabled": False} or reasoning.get("effort") in {"minimal", "low", "none"}
assert structured_output
plan = _plan(items, samples_per_order, answer_instruction) if plan_override is None else plan_override
protocol_id = direct_choice_protocol_identity(
model, items, samples_per_order=samples_per_order, temperature=temperature,
max_tokens=max_tokens, concurrency=concurrency, request_timeout=request_timeout,
reasoning=reasoning, structured_output=structured_output, prompt_instruction=prompt_instruction,
answer_instruction=answer_instruction,
rescue_instruction=rescue_instruction, plan_override=plan_override,
fail_fast_first_request=fail_fast_first_request,
)
cache_file = Path(cache_path)
cache = json.loads(cache_file.read_text()) if cache_file.exists() else {"schema": 1, "completed": {}}
assert cache["schema"] == 1
if protocol_id in cache["completed"]:
return {"cached": True, **cache["completed"][protocol_id]}
run_id = f"{datetime.now(UTC).strftime('%Y%m%dT%H%M%SZ')}_{protocol_id[:12]}"
records = Path(records_path)
records.parent.mkdir(parents=True, exist_ok=True)
settings = {
"model": model, "samples_per_order": samples_per_order, "temperature": temperature,
"max_tokens": max_tokens, "concurrency": concurrency, "request_timeout": request_timeout,
"reasoning": reasoning, "structured_output": structured_output,
"prompt_instruction": prompt_instruction, "fail_fast_first_request": fail_fast_first_request,
}
if plan_override is not None:
settings.pop("samples_per_order")
settings["samples_per_item"] = {item["id"]: sum(request["item_id"] == item["id"] for request in plan) for item in items}
settings["schedule"] = "balanced_cyclic_rotations"
_append_record(records, {
"event": "run_started", "run_id": run_id, "protocol_id": protocol_id,
"construct": "direct_choice", "settings": settings, "items": items,
"planned_requests": len(plan),
"canonical_requests": sum(request["order_name"] == "canonical" for request in plan),
"reversed_requests": sum(request["order_name"] == "reversed" for request in plan),
})
async def run_all() -> list[dict]:
semaphore = asyncio.Semaphore(concurrency)
async def call(sequence: int, request: dict) -> dict:
item = items[request["item_index"]]
request_id = f"{run_id}_{sequence:03d}"
request_meta = {
"request_id": request_id, "run_id": run_id, "protocol_id": protocol_id,
"construct": "direct_choice", "model": model, "item_id": item["id"],
"canonical_options": item["options"], "presented_options": request["presented_options"],
"presented_order": request["presented_order"], "order_name": request["order_name"],
"sample": request["sample"], "repetition": request["repetition"],
"prompt": request["prompt"], "settings": settings,
}
response_format = _choice_schema(item["n"])
payload = {
"model": model, "messages": [{"role": "user", "content": request["prompt"]}],
"temperature": temperature, "max_tokens": max_tokens, "response_format": response_format,
}
if reasoning is not None:
payload["reasoning"] = reasoning
phase = "initial"
async with semaphore:
try:
_append_record(records, {"event": "request_started", "phase": phase, **request_meta, "payload": payload})
response = await asyncio.wait_for(openrouter_request(payload), timeout=request_timeout)
_append_record(records, {"event": "request_completed", "phase": phase, **request_meta,
"response": response, "usage": response.get("usage")})
if len(response["choices"]) != 1:
raise ValueError(f"expected one choice, got {len(response['choices'])}")
message = response["choices"][0]["message"]
text = message.get("content") or ""
rescued = False
if _parse_choice(text, item["n"]) is None:
phase = "rescue"
assistant_tail = (message.get("reasoning") or message.get("content") or "")[-1500:] or "(thinking truncated)"
rescue_payload = {
"model": model, "messages": [
{"role": "user", "content": request["prompt"]},
{"role": "assistant", "content": assistant_tail},
{"role": "user", "content": rescue_instruction or _force_choice(item["n"])},
], "temperature": temperature, "max_tokens": max(max_tokens, 2048),
"response_format": response_format,
}
if reasoning is not None:
rescue_payload["reasoning"] = reasoning
_append_record(records, {"event": "request_started", "phase": phase, **request_meta,
"payload": rescue_payload, "initial_response_message": message})
response = await asyncio.wait_for(openrouter_request(rescue_payload), timeout=request_timeout)
_append_record(records, {"event": "request_completed", "phase": phase, **request_meta,
"response": response, "usage": response.get("usage")})
if len(response["choices"]) != 1:
raise ValueError(f"expected one rescue choice, got {len(response['choices'])}")
text = response["choices"][0]["message"].get("content") or ""
rescued = True
if fail_fast_first_request and sequence == 0 and _parse_choice(text, item["n"]) is None:
return {"text": text, "rescued": rescued, "error": "ParseError: first response remained invalid after rescue", "parse_invalid": True}
return {"text": text, "rescued": rescued, "error": None, "parse_invalid": False}
except Exception as exc:
_append_record(records, {"event": "request_failed", "phase": phase, **request_meta,
"error_type": type(exc).__name__, "error": str(exc)})
return {"text": None, "rescued": phase == "rescue", "error": f"{type(exc).__name__}: {exc}", "parse_invalid": False}
if not fail_fast_first_request:
return await asyncio.gather(*(call(sequence, request) for sequence, request in enumerate(plan)))
first = await call(0, plan[0])
if first["error"] is not None:
return [first]
remaining = await asyncio.gather(*(call(sequence, request) for sequence, request in enumerate(plan[1:], start=1)))
return [first, *remaining]
results = asyncio.run(run_all())
if fail_fast_first_request and results[0]["error"] is not None:
if results[0]["parse_invalid"]:
request = plan[0]
_append_record(records, {
"event": "answer_parsed", "run_id": run_id, "protocol_id": protocol_id,
"construct": "direct_choice", "model": model, "item_id": request["item_id"],
"sample": request["sample"], "order_name": request["order_name"],
"repetition": request["repetition"], "presented_order": request["presented_order"],
"text": results[0]["text"], "parsed": False, "presented_choice": None,
"canonical_choice": None,
})
summary = {
"run_id": run_id, "protocol_id": protocol_id, "model": model, "settings": settings,
"planned_requests": len(plan), "failed_requests": 1, "rescued_requests": int(results[0]["rescued"]),
"complete": False, "items": [], "failure": results[0]["error"],
}
_append_record(records, {"event": "run_finished", "construct": "direct_choice", **summary})
raise RuntimeError(f"first scheduled request failed before remaining {len(plan) - 1} requests: {results[0]['error']}")
by_item = {item["id"]: [] for item in items}
failed = 0
rescues = 0
for request, result in zip(plan, results):
rescues += int(result["rescued"])
if result["error"] is not None:
failed += 1
continue
presented_choice = _parse_choice(result["text"], items[request["item_index"]]["n"])
_append_record(records, {
"event": "answer_parsed", "run_id": run_id, "protocol_id": protocol_id,
"construct": "direct_choice", "model": model, "item_id": request["item_id"],
"sample": request["sample"], "order_name": request["order_name"],
"repetition": request["repetition"], "presented_order": request["presented_order"],
"text": result["text"], "parsed": presented_choice is not None,
"presented_choice": presented_choice,
"canonical_choice": request["presented_order"][presented_choice] if presented_choice is not None else None,
})
if presented_choice is not None:
by_item[request["item_id"]].append({
"sample": request["sample"], "order_name": request["order_name"],
"repetition": request["repetition"], "presented_order": request["presented_order"],
"presented_choice": presented_choice, "canonical_choice": request["presented_order"][presented_choice],
})
item_results = []
for item in items:
expected_samples = sum(request["item_id"] == item["id"] for request in plan)
samples = by_item[item["id"]]
canonical = sum(sample["order_name"] == "canonical" for sample in samples)
reversed_order = sum(sample["order_name"] == "reversed" for sample in samples)
result = {
"item_id": item["id"], "n": item["n"], "expected_samples": expected_samples,
"valid_samples": len(samples), "canonical_valid": canonical, "reversed_valid": reversed_order,
"samples": samples,
}
_append_record(records, {"event": "item_result", "run_id": run_id, "protocol_id": protocol_id,
"construct": "direct_choice", "model": model, **result})
item_results.append(result)
complete = failed == 0 and all(result["valid_samples"] == expected_samples for result in item_results)
summary = {
"run_id": run_id, "protocol_id": protocol_id, "model": model, "settings": settings,
"planned_requests": len(plan), "failed_requests": failed, "rescued_requests": rescues,
"complete": complete, "items": item_results,
}
_append_record(records, {"event": "run_finished", "construct": "direct_choice", **summary})
if complete:
cache["completed"][protocol_id] = summary
_save_cache(cache_file, cache)
return {"cached": False, **summary}