fsi-anomaly / data /gen_sop_sft.py
FerrellSyntheticIntelligence's picture
backup all: 100 files (batch)
1c0d385 verified
Raw
History Blame Contribute Delete
36.4 kB
"""Generate SOP-conditioned training data for TinyLiquid.
Reads research/sop_library/*.md and emits:
data/sft_sop.jsonl SFT examples: task -> assistant applies the SOP
in <|scratchpad|> ... <|final|> format.
data/prefs_sop.jsonl DPO pairs: chosen = follows SOP, rejected = fluent
confident answer that skipped the procedure.
data/sft_sop_mix.jsonl sft_distill_mix.jsonl + sft_sop.jsonl (no dupes)
Usage:
.venv/bin/python data/gen_sop_sft.py
"""
import json
import random
from collections import Counter
from pathlib import Path
HERE = Path(__file__).parent
ROOT = HERE.parent
SOP_DIR = ROOT / "research" / "sop_library"
def load_sops():
sops = {}
for p in sorted(SOP_DIR.glob("*.md")):
if p.stem == "00_common":
continue
sops[p.stem] = p.read_text(encoding="utf-8").strip()
return sops
def short(name: str) -> str:
"""Compact one-line pointer to a procedure, e.g. 'SOP 03 - PATTERN FINDING'."""
return {
"claim_verification": "SOP 01 - CLAIM VERIFICATION",
"cross_source_discrepancy": "SOP 02 - CROSS-SOURCE DISCREPANCY",
"pattern_finding": "SOP 03 - PATTERN FINDING",
"timeline_reconstruction": "SOP 04 - TIMELINE RECONSTRUCTION",
"historical_truth": "SOP 05 - HISTORICAL TRUTH / PAST-NEWS AUDIT",
"politics_analysis": "SOP 06 - POLITICS / SPIN ANALYSIS",
"dark_web_research": "SOP 07 - DARK WEB / DEEP WEB RESEARCH",
"terminal_control": "SOP 08 - TERMINAL CONTROL",
"source_triage": "SOP 09 - SOURCE TRIAGE",
}[name]
MATERIALS = {
"claim_verification": [
"Claim: 'The harbor bridge was painted in 2019 and has not been repainted since.'"
" Assessor record: construction 2008, painting permit 2019, repainting permit 2022.",
"Claim: 'Election turnout in the district doubled because of the new early-voting law.'"
" Turnout rose 21,000 to 39,000; the district also added two new polling sites and a census redrew its borders.",
"Claim: 'The factory never discharged into the river.' A 2016 environmental inspection log lists a discharge event; the factory's own annual report does not mention it.",
"Claim: 'The school district's test scores rose after the new reading program.'"
" The district changed both the program and the test, and scores rose from 61 to 68.",
],
"cross_source_discrepancy": [
"Account A: 'The meeting started at 9am and ended at 11am.'"
" Account B: 'The meeting started at 9am and ran until noon.'",
"Account A: 'No officials were present at the briefing.'"
" Account B: 'An official arrived later and answered questions.'",
"Report 1 says the outage hit 1,200 customers and lasted 40 minutes."
" Report 2 says 1,800 customers and 'most of the evening'.",
"Account A: 'The rally drew about 5,000 people.'"
" Account B: 'The rally drew more than 10,000.' Both cite police estimates.",
],
"pattern_finding": [
"Events: (1) a power outage downtown after a black van was seen near the substation;"
" (2) a water-main break the next day near a second van sighting;"
" (3) a fiber cut the same week with a similar van description. Officials cite separate equipment failures.",
"Five news stories across three years mention the same facility, each time with a different 'unrelated' technical fault, and each time the regulator changes leadership shortly after.",
"Data: three clinics in the same city each closed within a month of a new inspection"
" regime starting; the regulator says the closures are unrelated financial decisions.",
"A blog notes that three separate scandals at an agency each surfaced right before"
" budget votes on the agency's funding.",
],
"timeline_reconstruction": [
"Notes: witness saw black van near substation at 3:30pm; outage reported 3:40pm;"
" transformer inspected 6pm; officials said transformer failure; no inspection report has a timestamp before 5pm.",
"Dated records: permit issued 2019-03-01; construction photos 2019-06-14 and 2019-11-02;"
" certificate of occupancy 2020-02-20. A biography says the building 'was finished in 2018'.",
"Records: flood warning issued 2pm; river gauge peaked 4pm; evacuation order 5pm."
" A later report says residents were warned 'before the peak'.",
"Dated entries: contract signed 2018-06-01; first payment 2018-07-15; site photos"
" 2019-03; completion certificate 2020-05-01. A news story says work 'finished in 2019'.",
],
"historical_truth": [
"Early coverage (2019): 'officials rule out sabotage' based on a press conference."
" Later records (2021): a court filing discloses a second investigation was opened the same week the press conference was held.",
"A newspaper reported in 2010 that the reservoir project was fully funded. Board minutes from 2009 show a funding shortfall was discussed and hidden from the report.",
"1998 reporting: 'the plant's new filter was tested successfully.' 2001 documents:"
" an internal memo from 1998 flags the same test as inconclusive.",
"A 2015 obituary states the architect 'designed the city hall'. 2017 building records"
" show a different firm of record; the architect was a consulting advisor.",
],
"politics_analysis": [
"Statement: 'Crime doubled because of the new policy.' The report shows incidents rose"
" from 1,000 to 2,000 while reporting methods changed and a new precinct opened.",
"Party X: 'We cut taxes and the budget still grew, so growth is organic.'"
" Party Y: 'The budget grew because of one-time grants the other side claimed credit for.'",
"Statement: 'Our rival's tax plan would cut school funding.' An independent budget"
" office scores the plan as revenue-neutral once other changes are included.",
"Party A claims credit for the new hospital. The hospital was approved under a"
" previous administration; Party A funded its completion.",
],
"dark_web_research": [
"A clearnet forum post cites an unnamed .onion leak claiming a port authority"
" 'quietly sold its stake' in 2018. No registry filing, minutes, or third source exists.",
"Search task: verify whether a story circulating on a clearnet mirror also appears"
" in an .onion archive, and whether the two texts differ beyond formatting.",
"Task: determine whether a .onion forum rumor about a port schedule matches the"
" official schedule published by the port authority.",
"Task: a clearnet article claims an .onion archive 'proves' an event. Assess the"
" evidence standard that claim would require.",
],
"terminal_control": [
"Task: inventory the files in a downloaded corpus directory and report sizes and"
" hashes before deciding which documents to index.",
"Task: fetch a list of URLs into the corpus directory without overwriting existing"
" captures, then verify each file's size and first line.",
"Task: search the corpus directory for files mentioning a project codename, then"
" summarize match counts by file.",
"Task: download three documents into corpus/raw, then add them to the index"
" without duplicating existing entries.",
],
"source_triage": [
"A claim about a company's profits rests on: the company's own blog post, a wire"
" story repeating the blog, and an analyst note that quotes the wire story.",
"A claim about a historical event rests on: a diary entry from the period, a memoir"
" written 30 years later, and a history blog that repeats the memoir.",
"A claim rests on: a government agency's own press release, a trade magazine article"
" quoting the release, and a competitor's critique that quotes the magazine.",
"A claim about a medical trial rests on: the trial registry entry, a summary on the"
" sponsor's site, and a news article covering the summary.",
],
}
ANSWERS = {
"claim_verification": [
"<|scratchpad|>SOP 01 step 1 decompose: the claim has three assertions: bridge painted 2019, never repainted since, permit record exists. Step 2 primary source: assessor permits. Step 3 corroborate: permit file plus inspection log needed; only one record is present. Step 4 date: records run through 2022. Step 5 provenance: claim has no originator named. <|final|>Assertion 1 (painted 2019): confirmed by permit. Assertion 2 (never repainted): false - 2022 repainting permit contradicts it. Assertion 3: unverifiable without originator. Confidence: HIGH on the contradiction, MEDIUM overall. Gap: inspection log for 2020-2021.",
"<|scratchpad|>SOP 01 decompose: turnout rise (fact), cause-by-early-voting-law (attribution). Source: official turnout counts - primary. Corroboration: one dataset, two variables changed (polling sites, census borders) - attribution is unsupported. <|final|>Turnout rise: true. Attribution 'because of the law': overclaim - three variables changed simultaneously, no counterfactual. Confidence: HIGH that the rise occurred, LOW that the law caused it. Gap: a controlled comparison of adjacent districts.",
"<|scratchpad|>SOP 01 decompose: single assertion, discharge never happened. Sources: inspection log (primary, dated) vs company annual report (self-published). Provenance: the company benefits from the claim. <|final|>False: a dated inspection log records a discharge event. The annual report omits it, and omission is not evidence of absence. Confidence: HIGH. Gap: the log's full entry and any enforcement action.",
"<|scratchpad|>SOP 01 decompose: score rise (fact) and program cause (attribution). Source: district reports - primary for scores. Two variables changed: program and test. Corroboration: no second independent dataset. <|final|>Score rise: true. Attribution 'after the new reading program': overclaim - the test changed too. Confidence: HIGH on the rise, LOW on the cause. Gap: schools that kept the old test as a control.",
],
"cross_source_discrepancy": [
"<|scratchpad|>SOP 02 align: start time agrees 9am in both. End time A 11am, B noon. Classify delta: contradiction on end time, one hour apart. Root: one recorder or both inaccurate; agenda or minutes would settle it. <|final|>Discrepancy: end time (11:00 vs 12:00). Start time corroborated. Confidence: HIGH the accounts conflict, cannot assess which is right without a third source. Gap: meeting agenda, minutes, attendee.",
"<|scratchpad|>SOP 02 align: A says no officials present. B says an official arrived later. Classify: not a contradiction - 'at no point present' vs 'present after arrival' only conflict if A means the whole event. Ambiguity in scope. <|final|>Not necessarily a contradiction: the accounts are compatible if A describes the start and B the later arrival. Confidence: HIGH on compatibility. Gap: define the covered interval.",
"<|scratchpad|>SOP 02 align: customer count 1,200 vs 1,800 - contradiction. Duration 40 minutes vs 'most of the evening' - incompatible. Classify both as conflicts, likely measurement or reporting time. <|final|>Both figures conflict; they cannot both be accurate as stated. Confidence: HIGH on conflict, cannot assess true values. Gap: utility outage records with timestamps.",
"<|scratchpad|>SOP 02 align: attendance 5,000 vs 10,000 - contradiction. Provenance: both cite police estimates - the same parent source, so not independent corroboration. Classify: conflict. <|final|>The accounts conflict and share a single source, so neither is independently confirmed. Confidence: HIGH on the conflict, cannot assess the true figure. Gap: permits, photos, aerial counts.",
],
"pattern_finding": [
"<|scratchpad|>SOP 03 collect: three events, same week, each with a van sighting, each blamed on separate equipment failure. Cluster: same actor description and temporal clustering. Common cause candidate: deliberate interference. Null test: if deliberate, dates cluster and follow preparation; if coincidental, failure types are random - three unrelated failures in one week is rare. Counterexample search: no similar week without vans found in the material. Strength: moderate - the mechanism is plausible but no direct evidence links the vans. <|final|>Pattern: moderate. Cluster of three equipment failures within a week, each with a matching van sighting, each officially attributed separately. Confidence: MEDIUM that the events share a cause, LOW on what the cause is. Gap: van registrations, maintenance logs, failure forensics.",
"<|scratchpad|>SOP 03 collect: five stories, three years, same facility, each 'unrelated' fault, regulator leadership change after each. Cluster: facility + timing of leadership change. Mechanism candidate: repeated failure or governance capture. Null test: leadership changes are common; need base rate - how often does the regulator change leadership without an incident? Counterexamples: not searched. Strength: weak-to-moderate until base rate is measured. <|final|>Pattern: weak. The repeating element is real but the mechanism is not evidenced; the leadership-change sequence could be coincidental. Confidence: MEDIUM on the sequence existing, LOW on any cause. Gap: leadership-change base rate, facility fault history elsewhere.",
"<|scratchpad|>SOP 03 collect: three clinic closures within a month of a new inspection regime. Cluster: timing + same actor type. Mechanism candidates: capital flight under scrutiny, or targeting. Null test: closure base rate before the regime - not measured. Counterexamples: not searched. Strength: weak-to-moderate. <|final|>Pattern: weak. The timing cluster is real; the 'unrelated financial decisions' label is also unproven. Confidence: MEDIUM on clustering, LOW on mechanism. Gap: closure base rates and inspection findings.",
"<|scratchpad|>SOP 03 collect: three scandals each surfacing before budget votes. Cluster: timing + agency. Mechanism candidate: deliberate release timing. Null test: what share of all agency events surface before votes - base rate unknown. Counterexamples: not searched. Strength: weak. <|final|>Pattern: weak - the timing correlation is noted but the base rate is missing. Confidence: MEDIUM on the sequence, LOW on intent. Gap: release timestamps and base-rate data.",
],
"timeline_reconstruction": [
"<|scratchpad|>SOP 04 anchors: van sighting 3:30pm (witness), outage 3:40pm (reported), inspection 6pm (stated), no inspection record before 5pm (absence noted). Gaps: inspection report timestamp - the single largest gap; officials' transformer-failure cause is an inference until the report is dated. <|final|>Timeline: 3:30 van (uncorroborated), 3:40 outage (reported), 6pm inspection (stated, undated record). Cause 'transformer failure' is inferred, confidence LOW. Gap: dated inspection report and outage logs. Confidence: MEDIUM on the sequence as reconstructed.",
"<|scratchpad|>SOP 04 anchors: permit 2019-03-01, photos 2019-06-14 and 2019-11-02, occupancy 2020-02-20. The biography's 'finished in 2018' conflicts with the permit date and is not anchored to any record. <|final|>The 2018 claim is contradicted by the 2019 permit and 2020 occupancy certificate. Confidence: HIGH. Gap: whether 'finished' meant shell construction or final completion.",
"<|scratchpad|>SOP 04 anchors: warning 2pm, gauge peak 4pm, evacuation order 5pm - all dated records. The report's 'before the peak' is true of the warning but ambiguous about the evacuation order. <|final|>Warning preceded peak: confirmed. Evacuation order followed peak: confirmed. 'Residents were warned before the peak' is accurate for the warning, misleading if applied to the order. Confidence: HIGH. Gap: message timestamps for order dissemination.",
"<|scratchpad|>SOP 04 anchors: contract 2018-06-01, payment 2018-07-15, photos 2019-03, certificate 2020-05-01. The story's 'finished in 2019' conflicts with the 2020 certificate unless it means partial completion. <|final|>Conflict: 'finished in 2019' vs completion certificate dated 2020-05-01. Confidence: HIGH on the conflict. Gap: whether the certificate covers all works or a phase.",
],
"historical_truth": [
"<|scratchpad|>SOP 05 retrieve: 2019 press conference 'rule out sabotage'. Aftermath: 2021 court filing discloses a second investigation opened the same week. Delta: existence of a parallel investigation was absent from early coverage. Hidden item: the second probe. Corrupted vs corrected: not enough to label - the 2019 statement may have been incomplete, not false. <|final|>The 2019 'rule out sabotage' framing is contradicted in spirit by the parallel investigation disclosed in 2021. Confidence: HIGH the second probe existed, MEDIUM that the 2019 statement was misleading rather than merely incomplete. Gap: the filing's full text and the first probe's findings.",
"<|scratchpad|>SOP 05 retrieve: 2010 report 'fully funded'. Aftermath: 2009 board minutes show a shortfall discussed and withheld from the report. Delta: funding status changed between minutes (2009) and report (2010). Hidden: the shortfall discussion. <|final|>The 2010 'fully funded' claim conflicts with the 2009 minutes. The report omitted a known shortfall - suppressed context, not a correction. Confidence: HIGH. Gap: subsequent budgets showing when funding was closed.",
"<|scratchpad|>SOP 05 retrieve: 1998 success claim about the filter test. Aftermath: 2001 memo from 1998 flags the test as inconclusive. Delta: success vs inconclusive - a contradiction. Hidden: the internal memo. Corrupted vs corrected: the 1998 public claim and internal flag conflict; not enough to classify as deliberate. <|final|>Contradicted: 'tested successfully' (1998) vs 'inconclusive' (internal memo, 1998). Confidence: HIGH the memo exists, MEDIUM on intent. Gap: the memo's author and the 1998 test data.",
"<|scratchpad|>SOP 05 retrieve: 2015 obituary attribution 'designed the city hall'. Aftermath: 2017 records show a different firm of record; architect was a consulting advisor. Delta: role inflated. Hidden: the advisory role. <|final|>False as stated: the architect was an advisor, not the firm of record. Partial truth: involvement in some capacity. Confidence: HIGH. Gap: the advisory contract scope.",
],
"politics_analysis": [
"<|scratchpad|>SOP 06 separate: 'crime doubled' is factual; 'because of the policy' is attribution. Provenance: statement by the policy's opponent. Interest: each side gains if the attribution sticks. Evidence: incident counts exist but reporting methods and a new precinct changed. Spin: the doubling is a fact, the cause is unproven. Both-sides test: the same rigor applies to any counter-claim. <|final|>Fact: incidents rose from 1,000 to 2,000 - true. Attribution: overclaim - methodology changed. Confidence: HIGH on the numbers, LOW on the cause. Gap: crime rates per capita and reporting-method adjustment.",
"<|scratchpad|>SOP 06 separate: both sides assert budget growth; they dispute its cause. Provenance: each party's own claim. Interest: tax credit vs one-time grants. Evidence: need the budget line items. Spin: both statements are partial - growth is real, causes are competing. <|final|>Shared fact: budget grew - confirmed by both. Causes: conflicting attributions; one-time grants and tax cuts are not mutually exclusive. Confidence: HIGH on growth, cannot assess causes from the statements. Gap: line-item budget data.",
"<|scratchpad|>SOP 06 separate: 'would cut school funding' is a prediction. Evidence: independent budget office scores revenue-neutral once other changes are included. Interest: opponent gains if the cut framing sticks. Spin: partial - omits the offsets. <|final|>Misleading as stated: the plan's net effect is scored revenue-neutral; 'cut funding' ignores offsets. Confidence: HIGH on the budget office's score, cannot assess the full plan. Gap: the full plan text.",
"<|scratchpad|>SOP 06 separate: approval vs funding are different facts. Provenance: each party claims the part they did. Interest: credit attribution. Evidence: dates needed. <|final|>Both statements are partially true: approval preceded this administration, completion funding followed. The exclusive 'we built it' framing is spin. Confidence: HIGH on the distinction. Gap: appropriation records with dates.",
],
"dark_web_research": [
"<|scratchpad|>SOP 07 scope: verifying a corporate-stake claim; out of scope - any purchase or credential material. Triage: unnamed .onion leak is a lead only; no registry filing, minutes, or third source. Chain: source is named but has no URL, fetch time, or hash - chain incomplete. Verify: fails SOP 01 corroboration. Stop rules: nothing escalatory encountered. <|final|>Unsubstantiated: the claim rests on a single unnamed leak with no chain of custody and no independent source. Confidence: HIGH on the unsubstantiated label. Gap: registry filings, board minutes, a third independent source.",
"<|scratchpad|>SOP 07 scope: text-comparison of a clearnet mirror vs .onion archive; authorized OSINT. Crawl: both fetches rate-limited; chain recorded with hashes. Compare: align paragraph structure and normalize whitespace before diffing. <|final|>Method set: fetch both, hash each, diff after normalization. Confidence: cannot assess until fetched - this is a procedure, not a finding. Gap: the two fetched texts.",
"<|scratchpad|>SOP 07 scope: comparing a .onion rumor to the official port schedule; authorized OSINT, no engagement. Sources: official schedule is primary; forum is a lead with no chain. Triage: anonymous forum, low weight. Verify: only the official source can confirm; the rumor is unverified until then. <|final|>Plan: fetch the official schedule first, then diff; the rumor stays unverified. Confidence: HIGH on the method. Gap: the two schedules.",
"<|scratchpad|>SOP 07 scope: evidence-standard assessment; nothing to fetch or engage. Chain: an archive must have a URL, hash, and fetch time. Triage: anonymous archive is a lead. Verify: a single archive cannot prove an event; independent sources required. <|final|>The 'proves' framing overstates the evidence standard: one anonymous archive is a lead, not proof. Confidence: HIGH on the standard. Gap: chain-of-custody and corroborating sources.",
],
"terminal_control": [
"<|scratchpad|>SOP 08 read-only first: list corpus files with sizes; compute sha256; no writes. Bounds: corpus is local; listing is safe. Verify: confirm every file has a non-zero size and a hash before any index decision. <|final|>Plan: inventory with stat and sha256, read-only. No destructive commands needed. Confidence: HIGH the inventory is safe to run. Gap: none identified at plan time.",
"<|scratchpad|>SOP 08 read-only first: fetch URLs into new files only; use timeouts; do not overwrite existing captures. Log each command. Verify: check size and first line of each new file. <|final|>Plan: fetch to new dated files with a timeout, verify size and head. Confidence: HIGH the procedure covers overwrite and runaway-job risks. Gap: target URL list.",
"<|scratchpad|>SOP 08 read-only first: search with rg -l only, no writes. Bounds: local corpus, fast. Verify: cross-check matches with a second distinct pattern before counting. <|final|>Plan: read-only search, then per-file counts from the match set. Confidence: HIGH the inventory is safe and verifiable. Gap: exact codename spelling variants.",
"<|scratchpad|>SOP 08 read-only first: list existing corpus files; fetch three new files with timeouts; checksum each; index build must be idempotent. No overwrites. <|final|>Plan: inventory, fetch to new names, checksum, rebuild index; verify document count grows by exactly three. Confidence: HIGH. Gap: URL list and checksums.",
],
"source_triage": [
"<|scratchpad|>SOP 09 score: company blog - independence 0, proximity 2, interest 0 (owns the claim) -> weight 2-4, lead only. Wire story repeating the blog - independence 2 (unrelated outlet) but proximity 1 (retold) -> 5-7, usable only with corroboration. Analyst note quoting the wire - same parent content, counts as one source with the wire. <|final|>The claim has effectively one evidentiary chain: blog -> wire -> analyst note. Not corroborated. Confidence: HIGH on the single-chain diagnosis. Gap: an independent source such as audited filings.",
"<|scratchpad|>SOP 09 score: diary from the period - proximity 3, recency 3, independence 2, track unmeasured, interest low -> strong. Memoir 30 years later - recency 0-1, memory/spin risk -> usable only with corroboration. History blog repeating the memoir - same content, counts with the memoir, proximity 1. <|final|>The diary is the strong anchor; the memoir and blog form a single retold chain. Confidence: HIGH. Gap: a second independent period source for the diary's claims.",
"<|scratchpad|>SOP 09 score: agency release - independence 0, proximity 3 (it is the primary record of its own claim) -> evidence of claim-making, not truth. Trade magazine quoting the release - proximity 1, retold. Competitor critique quoting the magazine - independence low, interest high. <|final|>Single chain: release -> magazine -> critique. No independent corroboration. Confidence: HIGH on the single-chain diagnosis. Gap: an audited record of the underlying fact.",
"<|scratchpad|>SOP 09 score: trial registry - proximity 3, independent, the anchor. Sponsor summary - proximity 2, same data, retold. News article - proximity 1, retold again. <|final|>One evidentiary chain from the registry; the results are not independently audited. Weight: strong for the registry entry itself, lead-level for outcome claims. Confidence: HIGH. Gap: peer review or independent analysis of results.",
],
}
REJECTED = {
"claim_verification": [
"That claim is obviously false, everyone knows the bridge was repainted recently.",
"Crime definitely doubled because of the law - the numbers speak for themselves.",
"The factory is guilty - the log proves it, end of story.",
"Test scores went up, so the reading program clearly works.",
],
"cross_source_discrepancy": [
"One of the accounts is just wrong. The meeting probably ended at noon.",
"Those reports don't match, so one is fake news. Ignore it.",
"One report says 1,200 and one says 1,800, so the truth is somewhere around 1,500.",
"The rally was huge - the higher estimate is obviously the real one.",
],
"pattern_finding": [
"It's obviously sabotage. Three failures in one week with vans is no coincidence.",
"The pattern is clear - same facility, same people, every time. Case closed.",
"Three clinics closing after an inspection is clearly a coordinated purge.",
"Scandals before every budget vote - that's a smoking gun of corruption.",
],
"timeline_reconstruction": [
"The van caused the outage at 3:30. Timeline: van, then outage, then cover-up.",
"The building was clearly finished in 2018 as the biography says.",
"Residents were warned before the peak, so the response was perfect.",
"The story says 2019, so it finished in 2019.",
],
"historical_truth": [
"They lied in 2019. The court filing proves the whole thing was a cover-up.",
"The report was a lie - the board hid everything. Trust nothing from them.",
"The 1998 success claim was a lie - the memo proves it.",
"The obituary was wrong, so the architect never worked on the hall at all.",
],
"politics_analysis": [
"The policy is a total failure and crime is out of control.",
"That party is obviously lying about the budget to win votes.",
"The rival's plan clearly guts school funding - they said it themselves.",
"The hospital is ours - we built it, period.",
],
"dark_web_research": [
"The leak says it happened, so it happened. Dark web sources know things the public doesn't.",
"It's on the dark web, so it must be true and the public version is a cover-up.",
"The forum rumor matches the schedule, so the official schedule is a fake.",
"An archive 'proving' something is proof - that's what archives are for.",
],
"terminal_control": [
"Just run the command and fix anything that breaks.",
"Fetch everything with no limits - speed matters more than safety.",
"Delete the old captures first to make room - we don't need them.",
"Just search for it and move on; counts don't need verifying.",
],
"source_triage": [
"The company blog is the most reliable source because it's first-hand.",
"Any source that repeats the story confirms it. That's corroboration.",
"The agency's own press release is the best evidence - they were there.",
"The sponsor's summary is confirmed because the news covered it.",
],
}
ROOM_STEPS = {
"claim_verification": [
("RETRIEVE", "bridge repaint permit assessor", "primary source for the repainting claim"),
("NOTE", "permit 2022 contradicts 'never repainted'", "dated primary record"),
("VERDICT", "assertion 2 false, confidence HIGH; gaps: 2020-2021 inspection log", "procedure complete"),
],
"cross_source_discrepancy": [
("RETRIEVE", "meeting minutes end time", "third source to settle end time conflict"),
("NOTE", "end time conflicts 11:00 vs 12:00; start corroborated", "delta classified as contradiction"),
("VERDICT", "conflict confirmed, cannot assess true end time without minutes", "gap: minutes"),
],
"pattern_finding": [
("RETRIEVE", "van sightings substation outage", "cluster events by actor and timing"),
("NOTE", "three failures in one week, each with van sighting", "cluster; mechanism unproven"),
("VERDICT", "pattern moderate; cause unconfirmed", "counterexamples not searched"),
],
"timeline_reconstruction": [
("RETRIEVE", "inspection report timestamp outage", "anchor the cause claim to a dated record"),
("NOTE", "no inspection record before 5pm; cause inferred", "gap listed, not filled"),
("VERDICT", "sequence reconstructed, cause LOW confidence", "gap: dated inspection report"),
],
"historical_truth": [
("RETRIEVE", "2019 press conference investigation court filing", "compare early coverage with later records"),
("NOTE", "second investigation opened same week as 'rule out' statement", "delta: hidden parallel probe"),
("VERDICT", "2019 framing contradicted in spirit; intent unproven", "gap: filing text"),
],
"politics_analysis": [
("RETRIEVE", "crime statistics reporting methods precinct", "separate facts from attribution"),
("NOTE", "incidents 1000 to 2000; method and precinct changed", "attribution unsupported"),
("VERDICT", "rise true, cause overclaim", "gap: per-capita rates"),
],
"dark_web_research": [
("RETRIEVE", "port authority official schedule", "official schedule is primary; forum rumor is a lead"),
("NOTE", "forum rumor has no chain of custody", "triage: lead only"),
("VERDICT", "rumor unverified until independent corroboration", "stop rules respected"),
],
"terminal_control": [
("RETRIEVE", "corpus file inventory sizes hashes", "read-only inventory before any index decision"),
("NOTE", "all files non-zero size, hashes recorded", "verify step done"),
("VERDICT", "inventory safe and complete", "no destructive commands needed"),
],
"source_triage": [
("RETRIEVE", "audited filings company profits", "look for an independent source"),
("NOTE", "blog-wire-analyst note form one chain", "single chain, no corroboration"),
("VERDICT", "claim uncorroborated", "gap: audited filing"),
],
}
def build_room_examples():
out = []
for sop in SOP_ORDER:
tag = short(sop)
steps = ROOM_STEPS[sop]
for i, (action, arg, why) in enumerate(steps):
if i == 0:
casefile = "(empty)"
else:
prev = steps[i - 1]
casefile = f"[1] {prev[0]}: {prev[1]}"
user = (f"You are working a research case. Reply with exactly one line: "
f"ACTION: <RETRIEVE|READ|NOTE|VERDICT> then ARG: <text>. "
f"Procedure: {tag}. CASE FILE: {casefile}. "
f"TASK: apply the procedure to the material and record findings.")
asst = f"ACTION: {action} {arg} ARG: {why}"
out.append({"persona": "analyst", "user": user, "assistant": asst,
"sop": tag, "kind": "room"})
return out
SOP_ORDER = [
"claim_verification", "cross_source_discrepancy", "pattern_finding",
"timeline_reconstruction", "historical_truth", "politics_analysis",
"dark_web_research", "terminal_control", "source_triage",
]
def build_user(sop, material, persona):
tag = short(sop)
if persona == "skeptic":
return (f"Act as the skeptic. {tag} applies, but attack the conclusion "
f"someone else reached. Material: {material}")
return f"Apply {tag}. Material: {material}"
def build_assistant(sop, idx, persona):
text = ANSWERS[sop][idx]
if persona == "skeptic":
return (text.replace("<|scratchpad|>",
"<|scratchpad|>Skeptic pass - attack surfaces: "
"who verified each step, what would change the "
"verdict, and whether the conclusion overstates "
"precision. ") + " Weakest link must be explicit.")
return text
def main():
random.seed(29)
sops = load_sops()
assert len(sops) == len(SOP_ORDER), f"sop library mismatch: {sorted(sops)}"
sft, prefs = [], []
sft += build_room_examples()
for sop in SOP_ORDER:
mats = MATERIALS[sop]
for i, mat in enumerate(mats):
for persona in ("analyst", "skeptic"):
sft.append({"persona": persona,
"user": build_user(sop, mat, persona),
"assistant": build_assistant(sop, i, persona),
"sop": short(sop)})
prefs.append({"persona": "analyst",
"prompt": build_user(sop, mat, "analyst"),
"chosen": build_assistant(sop, i, "analyst"),
"rejected": REJECTED[sop][i % len(REJECTED[sop])]})
random.shuffle(sft)
random.shuffle(prefs)
with open(HERE / "sft_sop.jsonl", "w", encoding="utf-8") as f:
for ex in sft:
f.write(json.dumps(ex) + "\n")
with open(HERE / "prefs_sop.jsonl", "w", encoding="utf-8") as f:
for ex in prefs:
f.write(json.dumps(ex) + "\n")
mix_path = HERE / "sft_sop_mix.jsonl"
seen, out = set(), []
for src in (HERE / "sft_distill_mix.jsonl", HERE / "sft_sop.jsonl"):
if not src.exists():
continue
for line in src.read_text(encoding="utf-8").splitlines():
line = line.strip()
if not line:
continue
ex = json.loads(line)
h = hash(ex["user"])
if h in seen:
continue
seen.add(h)
out.append(ex)
with open(mix_path, "w", encoding="utf-8") as f:
for ex in out:
f.write(json.dumps(ex) + "\n")
n_by_sop = Counter(ex["sop"] for ex in sft)
print(f"sft_sop.jsonl: {len(sft)} examples")
for k in SOP_ORDER:
print(f" {short(k):44s} {n_by_sop[short(k)]}")
print(f"prefs_sop.jsonl: {len(prefs)} pairs")
print(f"sft_sop_mix.jsonl: {len(out)} examples (distill mix + sop)")
if __name__ == "__main__":
main()