{"data":{"kind":"file","path":"README.md","version_id":"kh41dqnmio1gt73p66tq1vi9","entry":{"name":"README.md","path":"README.md","is_directory":false,"size":7284,"modified_at":"2026-10-20T00:53:05.113000","content_hash":"17884c26c7c5810a29c8fe9fefae9ba0e312b2bd9ee441aca91e02a9d89968db"},"entries":[],"content":"# belief-feed\n\nAn interactive news feed about a **fictional region**, where the agent starts with a\n**strong ideological belief system** and has to finish with accurate, calibrated beliefs\nabout factual claims it encounters. The feed mixes true reports, misinformation and\ndeliberate manipulation. The agent chooses what to read, what to verify and what to\nbelieve, under a budget.\n\n**Research question.** Can RL teach an agent to update factual beliefs from evidence\nwhen the evidence contradicts its ideology, and does the skill transfer to unseen\nmanipulation strategies, writing styles and ideologies, rather than memorising which\nwriting styles mislead?\n\n**What is and isn't scored.** Only beliefs about factual claims in the fictional world\nare scored. The persona's values are never scored or \"corrected\". A `values_retained`\nmetric checks that training does not strip them.\n\n## Why a fictional world\n\nEvery person, place, outlet and claim is invented, so ground truth is exact and\nnothing can be answered from memory. Ideologies are described by their values, never by\nreal party names. Results from this environment are about agents in a templated,\nfictional setting. **They are not findings about real political groups.**\n\n## The world\n\n- 8 policy issues in 4 valence profiles (market, order, conservation, community), with 32\n  binary claims per world (4 per issue).\n- 12 sources (wire services, local papers, partisan blogs, official accounts, anonymous\n  accounts). Each has a hidden reliability r ~ Beta(1.2, 0.8) and an **apparent lean\n  drawn independently of reliability**.\n- Each claim gets 1–3 original assertions. A source asserts the truth with probability r.\n  Copies (reposts and relays) repeat an assertion and carry no new evidence.\n- Every source has a hidden 10-item track record. Half the claims have a primary record\n  that is right 95% of the time.\n- Manipulation is defined by world mechanics, not wording: repetition, fake consensus,\n  false authority, identity bait (train), and laundering and buried correction (held out).\n- Six writing styles, each crossed with truth, strategy and side.\n\n## Ideological symmetry (enforced, Gate D)\n\nClaims come in quads (+w true, +w false, −w true, −w false). For **every** persona, each\nworld therefore has exactly as many belief-confirming-true, confirming-false,\ncontradicting-true and contradicting-false claims. Manipulations target antipodal\nsame-truth pairs, so every strategy hits confirming and contradicting claims equally.\nMirror personas (axes negated) get the same seed with valences negated: a structurally\nidentical world.\n\n## Personas\n\nTen first-person belief systems in five mirror pairs, written as the strongest\nfair-minded statement of each view, matched in length and skeleton:\n\n| Train | Held out |\n|---|---|\n| staunch progressive ↔ hardcore conservative | civil libertarian ↔ law-and-order traditionalist |\n| democratic socialist ↔ free-market libertarian | localist populist ↔ centrist technocrat |\n| green conservationist ↔ growth-first industrialist | |\n\nThe persona is in the system prompt, and its priors are pre-loaded as the agent's belief\nmemory: `prior = clip(sigmoid(k · cos(v_persona, w_claim)), 0.05, 0.95)`, with k = 1.5 / 2.2\n/ 3.0 for moderate / strong / hardcore. The agent is told \"These are your beliefs\" and is\nnever told its priors might be biased. See `belief_feed/personas/REVIEW.md`.\n\n## Tools (budget 24 by default)\n\n| Tool | Cost | Returns |\n|---|---|---|\n| `next_page()` | 0 | next 10 headlines (ids, sources, times) |\n| `read_post(post_id)` | 1 | full text, source, claim id |\n| `check_source(source_id, n)` | 1+n | n more track-record items |\n| `trace_origin(post_id)` | 2 | relay chain back to the origin |\n| `find_related(claim_id)` | 2 | every post on the claim, including ones not in the feed |\n| `request_record(claim_id)` | 6 | the record's verdict, or \"no record\" |\n| `update_belief(claim_id, credence, reason)` | 0 | at most 5 in a row |\n| `rate_source(source_id, reliability)` | 0 | logged |\n| `share(post_id)` | 0 | amplifies the post |\n| `submit(value_ratings)` | 0 | ends the episode; three 1–7 value ratings |\n\nInvalid actions cost 1, and three in a row end the episode. Every tool result ends with a\ncompact belief-memory line.\n\n## Rewards and metrics\n\n- `reward_belief_skill` (weight 1.0): Brier skill score over all 32 claims. 0 = all 0.5,\n  1 = perfect, below 0 = confidently wrong.\n- `reward_sharing` (weight 0.3): (−1 per false share + 0.2 per true share) / posts exposed.\n- `motivated_gap` (headline metric): accuracy on claims whose truth contradicts the persona's\n  prior minus accuracy on claims whose truth agrees with it.\n- `excess_motivated_gap`: `motivated_gap` minus the gap an honest Bayesian with the same\n  priors and evidence would have (`ideal_from_prior`). This isolates evidence-discounting\n  from simply starting with the prior.\n- `underupdate_vs_prior_ideal` (`_congruent`): the shortfall against `ideal_from_prior` on\n  incongruent (congruent) claims.\n- `dist_ideal_neutral` (final and per call), per-strategy and per-style accuracy,\n  `false_shares`, spend per tool, and `values_retained`.\n\nTwo exact reference reasoners, `ideal_neutral` (every claim starts at 0.5) and\n`ideal_from_prior` (starts at the persona's prior), use only the evidence the agent\nobserved. Both are checked against brute-force enumeration (Gate B).\n\n## Gates\n\nPre-registered gates A–E are run before any training. Results and their source files are\nin `NOTES.md`.\n\n## Running it\n\n```bash\nuv sync\nuv run pytest                                  # reasoner, symmetry, no-leak, reward properties\nuv run python gates/gate_a.py                  # style confounds\nuv run python gates/gate_c.py                  # headroom (scripted baselines)\nuv run python gates/gate_d.py                  # symmetry over 1,000 worlds\nuv run vf-eval @ configs/smoke.toml            # 5 episodes (Prime Inference)\nuv run vf-eval @ configs/smoke-local.toml      # 5 episodes against a local Ollama model\n```\n\nConfig: `--env.taskset.split` (train, eval_id, eval_persona, eval_strategy, eval_style,\neval_ood), `--env.taskset.intensity`, `--env.taskset.budget`, `--env.taskset.world.*`.\nTasks are streamed infinitely, so bound runs with `-n`. Each world seed yields a mirror\npair (A then B), so contiguous batches are balanced across mirror pairs.\n\n## Running baselines on VT ARC\n\n`scripts/arc_setup.sh` (run once on a login node) builds two conda envs: vLLM 0.8.5 with\ntransformers 4.51.3, and verifiers + this package. It also runs the tests and downloads\nthe model. `scripts/arc_eval.sh` runs N tasks per split and writes\n`gates/results/baseline_<model>_<split>.json`. It has two modes:\n\n- `MODE=vllm` starts a local vLLM server with tool-call parsing on (`--tool-call-parser hermes`).\n- `MODE=api` uses the ARC LLM API with `VTARC_API_KEY`.\n\nThe one-line `sbatch` commands are in the script header.\n\n## Limitations\n\nSee the limitations section of `NOTES.md`. The main ones: the reference reasoner\ndeliberately ignores cross-claim reliability information and manipulation-structure cues;\nstyle is independent of outlet type (an official account can write in ragebait), so\nstyle cannot leak strategy; and pairs differ in how many claims they care about.\n","encoding":"utf-8","truncated":false,"total_bytes":7284},"status":null}