1 line
316 KiB
JSON
1 line
316 KiB
JSON
{"repo": "6up-b/learnanything", "files": {"fixtures/probability/learnloop.toml": {"d7f5830f824d7636193af334e950c1d2ffc477c4": {"t": 1785745334.4873033, "n": 22681, "h": "2b12573db227f750", "c": "schema_version = 1\n\n[storage]\nsqlite_path = \"state.sqlite\"\n\n[algorithms]\n# mvp-0.7: canonical shared-facet knowledge model (KM §15). New vaults start\n# here; only pre-existing vaults with legacy mvp-0.6 content need\n# `learnloop upgrade` to activate it. Legacy `probe_<lo_id>` phases recorded\n# under earlier versions replay through the frozen path in services/probes.py\n# forever; new diagnostic episodes replay exclusively through\n# probe_observations.\nalgorithm_version = \"mvp-0.7\"\n\n# Single source of truth for per-attempt-type evidence (Fable's-take item 3).\n# evidence_mass weights ability-belief updates (mastery EKF / reliability);\n# surface_exposure is the fraction of the item's facet surface the attempt\n# certifies as probed (coverage). surface_exposure defaults to evidence_mass;\n# dont_know overrides it because a confident \"don't know\" fully covers the\n# surface as evidence-of-absence while remaining self-diagnosis, not\n# demonstration.\n[evidence.attempt_types]\nindependent_attempt = { evidence_mass = 1.0 }\nopen_text = { evidence_mass = 1.0 }\ndiagnostic_probe = { evidence_mass = 1.0 }\nhinted_attempt = { evidence_mass = 1.0 }\nreconstruction_after_walkthrough = { evidence_mass = 0.5 }\ndont_know = { evidence_mass = 0.7, surface_exposure = 1.0 }\nself_report = { evidence_mass = 0.3 }\n# Imported past-exam outcome: one exam is one correlated evidence event, so\n# each seeded question carries a fraction of a live independent attempt.\nexam_evidence = { evidence_mass = 0.35 }\n# Held-out practice-exam answer on a fresh, never-practiced item: a proctored\n# fresh-item answer is the highest-quality evidence in the system, so it carries\n# full evidence mass (deliberately unlike the discounted `exam_evidence` import).\nexam_attempt = { evidence_mass = 1.0 }\n# Teach-back conversation graded as one attempt: high-quality generative\n# evidence, but the opening explanation and follow-up answers are one\n# correlated multi-question event, so it carries less than a full independent\n# attempt per facet.\nteach_back = { evidence_mass = 0.8 }\nguided_walkthrough = { evidence_mass = 0.0 }\nskip = { evidence_mass = 0.0 }\n\n# Item-side coverage prior per practice mode: how much of an LO's facet surface\n# an item of this mode can surface when it has no evidence weights or rubric.\n# Not derivable from attempt-type evidence_mass (different question).\n[evidence.item_coverage_by_practice_mode]\nconstructed_response = 0.85\nopen_text = 0.85\nshort_answer = 0.75\ndiagnostic_probe = 0.80\nindependent_attempt = 0.75\nhinted_attempt = 0.65\nmultiple_choice = 0.45\nself_report = 0.25\n\n# Vault-wide evidence correlation lookup (knowledge-model spec §6): discounts\n# for repeated/near-clone/shared-stimulus surfaces once facet state is global.\n# Reserved for KM2; parsed now so vault TOMLs can set values early.\n[evidence.correlation]\n\n# Capability-aware certification budgets (knowledge-model spec §5.4).\n# group_budget defaults to evidence_mass(attempt_type) per correlation group;\n# max_groups_per_attempt caps the attempt-wide certification ceiling.\n[evidence.certification]\nmax_groups_per_attempt = 3\n\n# Blueprint recipe likelihood defaults (knowledge-model spec §9.2): noisy-AND\n# core with slip, plus a guess floor by response format.\n[evidence.blueprints]\nslip = 0.05\n\n[evidence.blueprints.guess_by_format]\nmultiple_choice = 0.25\nconstructed_response = 0.0\n\n[scheduler]\nforgetting_risk_weight = 1.0\n# Goal facet frontier: fraction of an item's evidence facets not yet on track\n# for an active goal (unexamined/known_gap or projected below target_recall\n# at the goal's due date), scaled by goal priority.\ngoal_frontier_weight = 0.25\nrecent_error_weight = 0.50\nprobe_eig_weight = 0.25\n# Goal quota: guaranteed floor share of the queue overlapping the goal\n# frontier; ramps min -> max over the last ramp_days before due_at.\ngoal_quota_floor_min = 0.30\ngoal_quota_floor_max = 0.70\ngoal_quota_ramp_days = 28\nshort_session_minutes = 20\n# Seeded exploration over near-tie candidates so logged slates carry non-degenerate\n# selection propensities (off-policy learnability). See architecture_pivot.md Stage 0.\nselection_exploration_rate = 0.1\nselection_exploration_reward_window = 0.15\n\n[scheduler.surprise]\ntheta_pos = 1.5\ntheta_neg = 1.5\nalpha_interval = 0.3\nf_min = 0.5\nf_max = 1.5\nepsilon_error_surprise = 0.05\n\n[scheduler.followup]\ntau_followup_nats = 0.05\ngamma_min = 0.5\nmin_target_facet_overlap = 0.5\n# Gate modernization: thresholds resolve as quantiles of this learner's own\n# signal history; the absolute values above remain the cold-start fallback.\nthreshold_mode = \"quantile\"\ntau_followup_quantile = 0.85\ntau_severe_error_quantile = 0.90\nquantile_min_samples = 30\nquantile_window = 200\n# gate_mode = \"score\" scores all signals through one logistic (threshold last);\n# \"cascade\" preserves the legacy hard trigger/suppression chain bit-for-bit.\ngate_mode = \"score\"\ngate_score_threshold = 0.5\ngate_subscore_steepness = 12.0\n# Predictive facet EIG (logged-but-inert at weight 0.0; see services/predictive_eig.py).\npredictive_eig_weight = 0.0\npredictive_eig_target_cap = 4\n# Misconception discrimination gate (spec_misconception_diagnostics.md §4.1).\n# tau_discrimination_power is the Youden-J lower bound a diagnostic candidate\n# must clear against an active misconception; require_misconception_discrimination\n# routes to no_suitable_item rather than queueing a non-discriminating paraphrase.\ntau_discrimination_power = 0.3\nrequire_misconception_discrimination = true\n\n# Goal projection: open-ended goals (no due_at) project facet recall at a\n# fixed horizon so the frontier stays defined.\n[goals]\ndefault_projection_horizon_days = 30\n\n[hypothesis]\nsession_card_budget = 2\nclaim_cooldown_days = 7\noverconfidence_min_evidence_mass = 1.0\nreentry_gap_days = 7\ndecay_pressure_target_recall = 0.8\ndecay_pressure_horizon_days = 60\n\n[forecasts]\ndefault_horizon_days = 14\n\n# Automatic misconception resolution (\"close the loop\"): an active error event\n# is resolved once the learning object accumulates N clean attempts after the\n# event was created. Clean = correctness >= auto_resolve_min_correctness, no\n# error attribution written, and not a dont_know/skip self-diagnosis.\n[misconceptions]\nauto_resolve_clean_attempts = 3\nauto_resolve_min_correctness = 0.85\n# Registry-based resolution and the sim discrimination gate\n# (spec_misconception_diagnostics.md §6, §7). Parsed now; consumed in later phases.\ntau_misconception_resolved = 0.15\nsim_gate_min_sensitivity_lb = 0.7\nsim_gate_min_specificity_lb = 0.8\n# 8, not 5: a perfect run over N trials has lower bound 0.25^(1/(N+1)) at the\n# 25th percentile — 0.794 at N=5 (below the 0.8 specificity gate), 0.857 at N=8.\nsim_gate_trials = 8\n# Opt-in codex answers-under-belief pass for the gate. 0 = pure deterministic\n# (no provider tokens). When > 0, codex role-plays that many planted + clean\n# students in ONE call per gate run and their fires combine with the\n# deterministic trials. Costs provider tokens per accepted item; the same N>=8\n# caveat applies (0.25^(1/(N+1)) at the 25th percentile) to the COMBINED counts.\nsim_gate_llm_trials = 0\n\n# Offline parameter fitting from the learner's own logs (`learnloop fit`).\n# Fitted sets live in the fitted_parameters table; defaults apply when none is active.\n[fitting.fsrs]\nmin_reviews = 50\nmin_elapsed_days = 0.5\nl2_lambda = 1.0\nmax_iterations = 300\ninitial_step = 0.05\nmin_relative_improvement = 0.01\n\n[mastery]\nbase_observation_variance = 1.0\nsigma2_drift = 0.01\np_max = 4.0\n# Display banding: > strong renders green, > developing renders amber, else red.\ndisplay_strong_threshold = 0.6\ndisplay_developing_threshold = 0.35\n\n# IRT 2PL difficulty-aware mastery update (spec_irt_difficulty.md §4).\n# enabled = false restores the legacy logit-space Kalman update bit-for-bit.\n[mastery.irt]\nenabled = true\ndiscrimination_default = 1.0\ndifficulty_default = 0.0\ndifficulty_from_prior = true\ndifficulty_prior_scale = 2.5\nb_abs_max = 4.0\np_clip = 1e-4\nmu_abs_max = 5.0\nmax_logit_step = 4.0\n# Empirical-Bayes per-item difficulty posterior (dark by default; see\n# MasteryIRTConfig for the identifiability rationale).\neb_difficulty_enabled = false\nb_prior_variance = 0.25\nb_learning_rate_scale = 0.2\nb_max_step = 0.25\nb_var_min = 0.01\n\n[probe]\n# LEGACY (probe redesign Checkpoint 0.4): attempts_target_default,\n# attempts_target_with_strong_claim, claim_skip_threshold, and\n# variance_convergence_threshold configure only the frozen pre-redesign replay\n# path. Their live roles moved to [probe.episode]: the attempt targets map to\n# minimum/maximum_observations, the strong-claim skip maps to the explicit\n# fast-path policy (fast_path_claim_threshold), and variance convergence is\n# superseded by the §11 completion policy (posterior_stop_threshold).\nattempts_target_default = 3\nattempts_target_with_strong_claim = 1\nclaim_skip_threshold = 0.75\nvariance_convergence_threshold = 0.10\nhypothesis_set_max_size = 5\n\n# Diagnostic episodes (spec_probe_eig_redesign.md §5/§11).\n[probe.episode]\nminimum_independent_observations = 2\nmaximum_observations = 4\nposterior_stop_threshold = 0.85\nambiguity_threshold = 0.30\nopen_set_prior = 0.10\nopen_set_trigger_threshold = 0.35\nhinted_evidence_weight = 0.5\ncontaminated_evidence_weight = 0.3\nself_graded_evidence_weight = 0.3\nsession_qualifying_observation_cap = 4\nfast_path_enabled = true\nfast_path_claim_threshold = 0.75\npresentation_ttl_minutes = 240\n# Predictive EIG per expected time is the diagnostic default objective (§7.4/§7.5)\n# whenever at least predictive_target_minimum held-out instruments exist for the\n# episode; hypothesis EIG remains the fallback and audit signal.\npredictive_selection_enabled = true\npredictive_target_minimum = 2\npredictive_target_cap = 6\nselection_overhead_seconds = 10.0\n# §5.9 fresh-vault onboarding: probes deactivate after this many qualifying\n# observations until ordinary practice has started (0 disables).\nonboarding_practice_ceiling_observations = 4\n# §6.5 re-probe triggers: repeated prediction errors and stale uncertainty.\nreprobe_prediction_error_count = 3\nreprobe_prediction_error_window = 10\nreprobe_predictive_surprise_threshold = 1.0\nreprobe_stale_uncertainty_variance = 0.6\nreprobe_stale_uncertainty_days = 30\n\n# Parameterized instance generation from admitted family/card bindings (§10).\n# llm_surfaces: when an AI provider capable of run_probe_instance_surfaces is\n# wired through, instance surfaces come from the LLM (grounded in the LO,\n# validated by the structural instance gate) and fall back to the parametric\n# templates on provider failure or gate rejection.\n[probe.generation]\ninstances_per_need = 2\nauto_generate_on_entry = false\nllm_surfaces = true\n\n# Short adaptive dialogue microprobes (§8.1): turns within one block share the\n# family's total task evidence mass (§7.7).\n[probe.dialogue]\nplanned_turns = 3\nmax_turns = 4\n\n# Learner-initiated calibration sessions (§5.9): batch episode blocks across a\n# goal scope; lift only the per-session qualifying-observation cap within the\n# declared time budget.\n[probe.calibration]\ndefault_time_budget_minutes = 20\nmax_planned_episodes = 8\ndisagreement_weight = 0.5\n\n# Hierarchical family -> item shrinkage (§9.7, Checkpoint 4.2): item rows shrink\n# toward the family-version posterior with this much family-equivalent mass.\n[probe.hierarchy]\nitem_shrinkage_pseudo_count = 25.0\n\n# Family-version lifecycle gates (§9.7, Checkpoint 4.7). Trust requires\n# real-learner evidence; synthetic gate statistics never qualify a family.\n[probe.lifecycle]\ntrust_minimum_real_sample = 20\ntrust_minimum_regrade_checks = 5\ntrust_minimum_regrade_agreement = 0.80\ntrust_maximum_negative_information_rate = 0.20\nretire_minimum_sample = 10\nretire_negative_information_rate = 0.50\nretire_regrade_agreement_floor = 0.50\n\n# Shadow-mode alternative selection policies (§13.3, Checkpoint 5.1): log-only\n# rankings on the committed presentation. Off-policy estimation stays on hold\n# for single-learner vaults.\n[probe.shadow]\nenabled = true\ntop_k = 3\n\n# Precommitted diagnostic blocks (Checkpoint 5.2/5.3): redundancy penalty is a\n# separate ranking component (never labeled EIG); joint greedy conditional EIG\n# applies only to blocks committed before answers are observed.\n[probe.block]\nfamily_redundancy_penalty = 0.6\nmax_block_size = 4\nconditional_branch_cap = 3\n# §5.6/§5.7: sequential probes run the block-end hook after this many\n# observations in the current state segment.\ndefault_block_observations = 2\n\n# IRT difficulty-aware probe conditionals (spec_irt_difficulty.md §5).\n[probe.irt]\ntheta_mastered = 2.0\ntheta_unfamiliar = -2.0\ncut_mid = -1.0\ncut_high = 1.0\nunfamiliar_error_leak = 0.20\nerr_low_frac = 0.80\nerr_mid_frac = 0.50\n\n# Learner self-attributed misconception probe coverage (spec_irt_difficulty.md §12).\n[probe.self_tag]\nw_base = 0.5\nw_max = 0.7\ntarget_degree = 2.0\npromotion_threshold = 3\n\n# Exam seeding (`learnloop ingest-exam` + `learnloop seed-exam-attempts`):\n# imported per-question outcomes become backdated exam_evidence attempts.\n# grader_confidence is the reliability discount persisted on seeded attempts;\n# default_learner_confidence (1-5) is used when an outcome omits confidence.\n[exam_seeding]\ngrader_confidence = 0.7\ndefault_learner_confidence = 3\n\n# Tutor Q&A (\"ask\"): question limits per context (practice: per item+session,\n# feedback: per attempt, library: per note per day) and the read-side\n# uncertainty bump applied for recent unresolved questions about a facet.\n[tutor_qa]\nmax_questions_practice = 3\nmax_questions_feedback = 5\nmax_questions_library = 8\napply_uncertainty_effect = true\nuncertainty_evidence_mass = 0.15\n\n# Promoting Socratic tutor questions to practice items / learning objects.\n# Gap route: a \"this exposed a gap\" promotion writes a low self-report claim\n# (gap_claim_level at gap_claim_pseudo_count pseudo-observations) and counts as\n# an unresolved-question observation with its own likelihood slot fit from the\n# learner's gap-declaration -> failure lift, falling back to\n# gap_declaration_solid_likelihood_ratio below gap_declaration_likelihood_min_samples.\n# The filed need goes stale after gap_need_ttl_days; requested_items_per_session\n# bounds the scheduler floor for promoted-but-unattempted items.\n[tutor_promotion]\ngap_claim_level = 0.25\ngap_claim_pseudo_count = 2.0\ngap_declaration_solid_likelihood_ratio = 0.35\ngap_declaration_likelihood_min_samples = 12\ngap_need_ttl_days = 21\nrequested_items_per_session = 1\n\n# Teach-back conversations: the learner explains, an AI naive student asks up\n# to max_followups questions (one per rubric criterion, uncertainty-ranked with\n# transfer escalation), and the transcript is graded as one attempt.\n# transfer_evidence_multiplier symmetrically discounts the evidence mass of\n# transfer-tier criterion evidence; session_cap bounds teach_back items per\n# built queue.\n[teach_back]\nmax_followups = 4\ntransfer_evidence_multiplier = 0.5\nsession_cap = 1\n\n[ingest]\nwindow_char_cap = 150000\nmin_content_chars = 400\ndefault_goal_priority = 0.5\nallow_auto_captions = false\n\n# PDF extraction for canonical sources (textbook chapters, past exams, any\n# ingested .pdf). engine \"auto\" uses marker-pdf (structured Markdown with\n# headings, tables, LaTeX math, and OCR for scanned pages) when installed\n# (`pip install learnloop[pdf]`), falling back to plain pypdf text extraction.\n# use_llm adds marker's VLM boost for difficult scans and dense math: hard\n# regions are sent to an OpenAI-compatible endpoint -- e.g. a local vLLM\n# serving deepseek-ai/DeepSeek-OCR (llm_base_url = \"http://127.0.0.1:8000/v1\",\n# llm_model = \"deepseek-ai/DeepSeek-OCR\") or any hosted vision model. The API\n# key is read from the env var named by llm_api_key_env. Marker conversions\n# are cached under .learnloop/source-cache/pdf/ keyed by file bytes + config.\n[ingest.pdf]\nengine = \"auto\"\n# \"\" = auto-detect (GPU when the installed torch supports it); pin with\n# \"cuda\", \"cuda:1\", \"cpu\", or \"mps\" to override.\ntorch_device = \"\"\nforce_ocr = false\nuse_llm = false\nllm_service = \"marker.services.openai.OpenAIService\"\nllm_base_url = \"\"\nllm_model = \"\"\nllm_api_key_env = \"LEARNLOOP_PDF_LLM_API_KEY\"\n\n# Per-stage token budgets for ingestion v2 (source-ingestion spec §3.1).\n# Preflight/build-plan estimates read these; a stage exceeding its ceiling\n# shards or pauses for narrower scope — it never silently truncates.\n[ingest.budgets]\ninventory_input_tokens = 20000\ninventory_output_tokens = 3000\nsynthesis_shard_input_tokens = 40000\nsynthesis_shard_output_tokens = 10000\nevidence_span_input_tokens = 12000\nsynthesis_total_input_ceiling = 48000\nsynthesis_output_tokens = 16000\nappend_neighborhood_input_tokens = 24000\nappend_output_tokens = 10000\n# Span-request protocol caps (§8.5): one bounded request round only.\nsynthesis_span_request_max_count = 12\nsynthesis_span_char_cap = 4000\n# Quick add (§1): ToC-guided relevant-scope cap.\nquick_add_scope_input_tokens = 40000\n\n# Per-provider context/output limits consulted by preflight, keyed by the\n# [ai.providers.<name>] entries (source-ingestion spec §3.1), e.g.\n# [ingest.providers.codex] context_tokens / max_output_tokens.\n\n# Durable ingest-queue worker settings (source-ingestion spec §6.2). One worker\n# (sidecar background loop or foreground CLI) drains queued jobs at a time under\n# a single lease; a running lease older than lease_ttl_seconds is recovered to\n# failed(interrupted) on startup and its queued siblings resume.\n[ingest.runner]\nlease_ttl_seconds = 120\nheartbeat_interval_seconds = 15\npoll_interval_seconds = 1.0\n\n[ai]\nactive_provider = \"codex\"\nfallback_provider = \"\"\ntimeout_seconds = 60\n\n[ai.routing]\ngrading = \"codex_low\"\ncanonical_ingest = \"codex_medium\"\ncanonical_ingest_retry = \"codex_medium\"\nauthoring = \"codex_medium\"\n# Empty = follow ai.active_provider; point at any configured provider to route\n# tutor Q&A elsewhere (a vault decision, not forced-cheap).\ntutor_qa = \"codex_low\"\n# Empty = follow ai.active_provider; teach-back questions + grading routing.\nteach_back = \"codex_low\"\n\n[ai.providers.codex]\ntype = \"codex_sdk\"\nmodel = \"gpt-5.6-sol\"\n# Per-machine; set LEARNLOOP_CODEX_CHECKOUT_PATH in ~/.config/learnloop/settings.env.\ncheckout_path = \"\"\nrevision = \"<pinned-commit>\"\nstartup_command = \"\"\nstartup_timeout_seconds = 20\nhealthcheck_timeout_seconds = 5\nauth_mode = \"chatgpt\"\nreasoning_effort = \"low\"\nreasoning_summary = \"none\"\nsdk_python_path = \"sdk/python/src\"\nsdk_codex_bin = \"\"\nsdk_launch_command = \"\"\nbase_url = \"http://127.0.0.1:8765\"\nhealthcheck_path = \"/health\"\nauthoring_path = \"/authoring-proposal\"\ncanonical_ingest_path = \"/canonical-ingest\"\ngrading_path = \"/grading-proposal\"\nmisconception_match_path = \"/misconception-match\"\n\n[ai.providers.deepseek_flash]\ntype = \"openai_chat\"\nbase_url = \"https://api.deepseek.com\"\napi_key_env = \"DEEPSEEK_API_KEY\"\nmodel = \"deepseek-v4-flash\"\nresponse_format = \"json_object\"\nthinking = \"disabled\"\nmax_tokens = 8192\ntimeout_seconds = 90\n\n[ai.providers.deepseek_pro]\ntype = \"openai_chat\"\nbase_url = \"https://api.deepseek.com\"\napi_key_env = \"DEEPSEEK_API_KEY\"\nmodel = \"deepseek-v4-pro\"\nresponse_format = \"json_object\"\nthinking = \"enabled\"\nreasoning_effort = \"high\"\nmax_tokens = 16384\ntimeout_seconds = 180\n\n[codex]\nprovider = \"sdk\"\n# Per-machine; set LEARNLOOP_CODEX_CHECKOUT_PATH in ~/.config/learnloop/settings.env.\ncheckout_path = \"\"\nrevision = \"<pinned-commit>\"\nstartup_command = \"\"\nstartup_timeout_seconds = 20\nhealthcheck_timeout_seconds = 5\nauth_mode = \"chatgpt\"\nmodel = \"gpt-5.6-sol\"\nreasoning_effort = \"low\"\nreasoning_summary = \"none\"\nsdk_python_path = \"sdk/python/src\"\nsdk_codex_bin = \"\"\nsdk_launch_command = \"\"\nbase_url = \"http://127.0.0.1:8765\"\nhealthcheck_path = \"/health\"\nauthoring_path = \"/authoring-proposal\"\ncanonical_ingest_path = \"/canonical-ingest\"\ngrading_path = \"/grading-proposal\"\nmisconception_match_path = \"/misconception-match\"\n\n# Family-keyed mastery damage per error type (spec §\"Error-aware updates\").\n# recall_failure is the deterministic attribution for `dont_know` attempts.\n[error_impacts]\nmax_sharpening = 3.0\n\n[error_impacts.recall_failure]\nfamilies = { recall = -0.25 }\nlo_mastery_delta = -0.05\nlocal_severity_gain = 0.8\n\n[error_impacts.scaffold_failure]\nfamilies = { recall = -0.35 }\nlo_mastery_delta = -0.05\nlocal_severity_gain = 1.5\n\n[error_impacts.arithmetic_slip]\nfamilies = { numeric = -0.05 }\nlo_mastery_delta = 0.0\nlocal_severity_gain = 0.35\n\n# Capability damping/shrinkage for shared-parent facet belief (knowledge-model\n# spec §4.2). Reserved for KM2+; residual activation ships default-off.\n[capabilities]\n\n# Identity-lock policy (knowledge-model spec §3.4): a facet's semantic identity\n# locks at direct evidence in >=2 distinct surface/correlation groups, at\n# facet_lock_mass independent evidence mass, or on entering an active goal's\n# certified scope — whichever comes first.\n[locks]\nfacet_lock_mass = 2.0\nfacet_surface_groups = 2\n\n# NOTE: [cross_lo_propagation] is retired (knowledge-model §8.3/§15). The LO-to-LO\n# graph-propagated prior is prerequisite-only, direction-respecting, and\n# shadow/diagnostic-only; its error_gates were dormant. `learnloop doctor` warns\n# when a vault TOML still declares the block.\n\n[recall_coverage.severity_examples.first_dont_know]\nattempt_type = \"dont_know\"\nhints_used = 0\ncorrectness = 0.0\nexpected_correctness = 0.65\neffective_coverage = 0.85\nexpected_error_type = \"recall_failure\"\nexpected_severity_band = [0.70, 0.82]\n\n[recall_coverage.severity_examples.second_same_item_dont_know]\nattempt_type = \"dont_know\"\nhints_used = 0\ncorrectness = 0.0\nexpected_correctness = 0.65\neffective_coverage = 0.85\nrecent_same_item_failures = 1\nexpected_error_type = \"recall_failure\"\nexpected_severity_band = [0.95, 1.00]\n\n[recall_coverage.severity_examples.second_same_facet_dont_know]\nattempt_type = \"dont_know\"\nhints_used = 0\ncorrectness = 0.0\nexpected_correctness = 0.65\neffective_coverage = 0.85\nrecent_same_facet_failures = 1\nexpected_error_type = \"recall_failure\"\nexpected_severity_band = [0.80, 1.00]\n\n[recall_coverage.severity_examples.hinted_dont_know]\nattempt_type = \"dont_know\"\nhints_used = 2\ncorrectness = 0.0\nexpected_correctness = 0.65\neffective_coverage = 0.80\nexpected_error_type = \"scaffold_failure\"\nexpected_severity_band = [0.85, 0.95]\n\n[recall_coverage.severity_examples.arithmetic_slip]\nattempt_type = \"independent_attempt\"\ncorrectness = 0.75\nexpected_correctness = 0.70\neffective_coverage = 0.85\ntarget_error_type = \"arithmetic_slip\"\nexpected_error_type = \"arithmetic_slip\"\nexpected_severity_band = [0.25, 0.35]\n\n[recall_coverage.severity_examples.ambiguous_item]\nattempt_type = \"independent_attempt\"\ncorrectness = 0.0\nexpected_correctness = 0.70\neffective_coverage = 0.85\nbad_item_suspicion = 0.70\nexpected_error_type = \"recall_failure\"\nexpected_severity_band = [0.45, 0.75]\n"}, "1c72cbabade1a4be2d2f4d18b22d1cf0ac171657": {"t": 1785750318.452359, "n": 22681, "h": "2b12573db227f750", "c": "schema_version = 1\n\n[storage]\nsqlite_path = \"state.sqlite\"\n\n[algorithms]\n# mvp-0.7: canonical shared-facet knowledge model (KM §15). New vaults start\n# here; only pre-existing vaults with legacy mvp-0.6 content need\n# `learnloop upgrade` to activate it. Legacy `probe_<lo_id>` phases recorded\n# under earlier versions replay through the frozen path in services/probes.py\n# forever; new diagnostic episodes replay exclusively through\n# probe_observations.\nalgorithm_version = \"mvp-0.7\"\n\n# Single source of truth for per-attempt-type evidence (Fable's-take item 3).\n# evidence_mass weights ability-belief updates (mastery EKF / reliability);\n# surface_exposure is the fraction of the item's facet surface the attempt\n# certifies as probed (coverage). surface_exposure defaults to evidence_mass;\n# dont_know overrides it because a confident \"don't know\" fully covers the\n# surface as evidence-of-absence while remaining self-diagnosis, not\n# demonstration.\n[evidence.attempt_types]\nindependent_attempt = { evidence_mass = 1.0 }\nopen_text = { evidence_mass = 1.0 }\ndiagnostic_probe = { evidence_mass = 1.0 }\nhinted_attempt = { evidence_mass = 1.0 }\nreconstruction_after_walkthrough = { evidence_mass = 0.5 }\ndont_know = { evidence_mass = 0.7, surface_exposure = 1.0 }\nself_report = { evidence_mass = 0.3 }\n# Imported past-exam outcome: one exam is one correlated evidence event, so\n# each seeded question carries a fraction of a live independent attempt.\nexam_evidence = { evidence_mass = 0.35 }\n# Held-out practice-exam answer on a fresh, never-practiced item: a proctored\n# fresh-item answer is the highest-quality evidence in the system, so it carries\n# full evidence mass (deliberately unlike the discounted `exam_evidence` import).\nexam_attempt = { evidence_mass = 1.0 }\n# Teach-back conversation graded as one attempt: high-quality generative\n# evidence, but the opening explanation and follow-up answers are one\n# correlated multi-question event, so it carries less than a full independent\n# attempt per facet.\nteach_back = { evidence_mass = 0.8 }\nguided_walkthrough = { evidence_mass = 0.0 }\nskip = { evidence_mass = 0.0 }\n\n# Item-side coverage prior per practice mode: how much of an LO's facet surface\n# an item of this mode can surface when it has no evidence weights or rubric.\n# Not derivable from attempt-type evidence_mass (different question).\n[evidence.item_coverage_by_practice_mode]\nconstructed_response = 0.85\nopen_text = 0.85\nshort_answer = 0.75\ndiagnostic_probe = 0.80\nindependent_attempt = 0.75\nhinted_attempt = 0.65\nmultiple_choice = 0.45\nself_report = 0.25\n\n# Vault-wide evidence correlation lookup (knowledge-model spec §6): discounts\n# for repeated/near-clone/shared-stimulus surfaces once facet state is global.\n# Reserved for KM2; parsed now so vault TOMLs can set values early.\n[evidence.correlation]\n\n# Capability-aware certification budgets (knowledge-model spec §5.4).\n# group_budget defaults to evidence_mass(attempt_type) per correlation group;\n# max_groups_per_attempt caps the attempt-wide certification ceiling.\n[evidence.certification]\nmax_groups_per_attempt = 3\n\n# Blueprint recipe likelihood defaults (knowledge-model spec §9.2): noisy-AND\n# core with slip, plus a guess floor by response format.\n[evidence.blueprints]\nslip = 0.05\n\n[evidence.blueprints.guess_by_format]\nmultiple_choice = 0.25\nconstructed_response = 0.0\n\n[scheduler]\nforgetting_risk_weight = 1.0\n# Goal facet frontier: fraction of an item's evidence facets not yet on track\n# for an active goal (unexamined/known_gap or projected below target_recall\n# at the goal's due date), scaled by goal priority.\ngoal_frontier_weight = 0.25\nrecent_error_weight = 0.50\nprobe_eig_weight = 0.25\n# Goal quota: guaranteed floor share of the queue overlapping the goal\n# frontier; ramps min -> max over the last ramp_days before due_at.\ngoal_quota_floor_min = 0.30\ngoal_quota_floor_max = 0.70\ngoal_quota_ramp_days = 28\nshort_session_minutes = 20\n# Seeded exploration over near-tie candidates so logged slates carry non-degenerate\n# selection propensities (off-policy learnability). See architecture_pivot.md Stage 0.\nselection_exploration_rate = 0.1\nselection_exploration_reward_window = 0.15\n\n[scheduler.surprise]\ntheta_pos = 1.5\ntheta_neg = 1.5\nalpha_interval = 0.3\nf_min = 0.5\nf_max = 1.5\nepsilon_error_surprise = 0.05\n\n[scheduler.followup]\ntau_followup_nats = 0.05\ngamma_min = 0.5\nmin_target_facet_overlap = 0.5\n# Gate modernization: thresholds resolve as quantiles of this learner's own\n# signal history; the absolute values above remain the cold-start fallback.\nthreshold_mode = \"quantile\"\ntau_followup_quantile = 0.85\ntau_severe_error_quantile = 0.90\nquantile_min_samples = 30\nquantile_window = 200\n# gate_mode = \"score\" scores all signals through one logistic (threshold last);\n# \"cascade\" preserves the legacy hard trigger/suppression chain bit-for-bit.\ngate_mode = \"score\"\ngate_score_threshold = 0.5\ngate_subscore_steepness = 12.0\n# Predictive facet EIG (logged-but-inert at weight 0.0; see services/predictive_eig.py).\npredictive_eig_weight = 0.0\npredictive_eig_target_cap = 4\n# Misconception discrimination gate (spec_misconception_diagnostics.md §4.1).\n# tau_discrimination_power is the Youden-J lower bound a diagnostic candidate\n# must clear against an active misconception; require_misconception_discrimination\n# routes to no_suitable_item rather than queueing a non-discriminating paraphrase.\ntau_discrimination_power = 0.3\nrequire_misconception_discrimination = true\n\n# Goal projection: open-ended goals (no due_at) project facet recall at a\n# fixed horizon so the frontier stays defined.\n[goals]\ndefault_projection_horizon_days = 30\n\n[hypothesis]\nsession_card_budget = 2\nclaim_cooldown_days = 7\noverconfidence_min_evidence_mass = 1.0\nreentry_gap_days = 7\ndecay_pressure_target_recall = 0.8\ndecay_pressure_horizon_days = 60\n\n[forecasts]\ndefault_horizon_days = 14\n\n# Automatic misconception resolution (\"close the loop\"): an active error event\n# is resolved once the learning object accumulates N clean attempts after the\n# event was created. Clean = correctness >= auto_resolve_min_correctness, no\n# error attribution written, and not a dont_know/skip self-diagnosis.\n[misconceptions]\nauto_resolve_clean_attempts = 3\nauto_resolve_min_correctness = 0.85\n# Registry-based resolution and the sim discrimination gate\n# (spec_misconception_diagnostics.md §6, §7). Parsed now; consumed in later phases.\ntau_misconception_resolved = 0.15\nsim_gate_min_sensitivity_lb = 0.7\nsim_gate_min_specificity_lb = 0.8\n# 8, not 5: a perfect run over N trials has lower bound 0.25^(1/(N+1)) at the\n# 25th percentile — 0.794 at N=5 (below the 0.8 specificity gate), 0.857 at N=8.\nsim_gate_trials = 8\n# Opt-in codex answers-under-belief pass for the gate. 0 = pure deterministic\n# (no provider tokens). When > 0, codex role-plays that many planted + clean\n# students in ONE call per gate run and their fires combine with the\n# deterministic trials. Costs provider tokens per accepted item; the same N>=8\n# caveat applies (0.25^(1/(N+1)) at the 25th percentile) to the COMBINED counts.\nsim_gate_llm_trials = 0\n\n# Offline parameter fitting from the learner's own logs (`learnloop fit`).\n# Fitted sets live in the fitted_parameters table; defaults apply when none is active.\n[fitting.fsrs]\nmin_reviews = 50\nmin_elapsed_days = 0.5\nl2_lambda = 1.0\nmax_iterations = 300\ninitial_step = 0.05\nmin_relative_improvement = 0.01\n\n[mastery]\nbase_observation_variance = 1.0\nsigma2_drift = 0.01\np_max = 4.0\n# Display banding: > strong renders green, > developing renders amber, else red.\ndisplay_strong_threshold = 0.6\ndisplay_developing_threshold = 0.35\n\n# IRT 2PL difficulty-aware mastery update (spec_irt_difficulty.md §4).\n# enabled = false restores the legacy logit-space Kalman update bit-for-bit.\n[mastery.irt]\nenabled = true\ndiscrimination_default = 1.0\ndifficulty_default = 0.0\ndifficulty_from_prior = true\ndifficulty_prior_scale = 2.5\nb_abs_max = 4.0\np_clip = 1e-4\nmu_abs_max = 5.0\nmax_logit_step = 4.0\n# Empirical-Bayes per-item difficulty posterior (dark by default; see\n# MasteryIRTConfig for the identifiability rationale).\neb_difficulty_enabled = false\nb_prior_variance = 0.25\nb_learning_rate_scale = 0.2\nb_max_step = 0.25\nb_var_min = 0.01\n\n[probe]\n# LEGACY (probe redesign Checkpoint 0.4): attempts_target_default,\n# attempts_target_with_strong_claim, claim_skip_threshold, and\n# variance_convergence_threshold configure only the frozen pre-redesign replay\n# path. Their live roles moved to [probe.episode]: the attempt targets map to\n# minimum/maximum_observations, the strong-claim skip maps to the explicit\n# fast-path policy (fast_path_claim_threshold), and variance convergence is\n# superseded by the §11 completion policy (posterior_stop_threshold).\nattempts_target_default = 3\nattempts_target_with_strong_claim = 1\nclaim_skip_threshold = 0.75\nvariance_convergence_threshold = 0.10\nhypothesis_set_max_size = 5\n\n# Diagnostic episodes (spec_probe_eig_redesign.md §5/§11).\n[probe.episode]\nminimum_independent_observations = 2\nmaximum_observations = 4\nposterior_stop_threshold = 0.85\nambiguity_threshold = 0.30\nopen_set_prior = 0.10\nopen_set_trigger_threshold = 0.35\nhinted_evidence_weight = 0.5\ncontaminated_evidence_weight = 0.3\nself_graded_evidence_weight = 0.3\nsession_qualifying_observation_cap = 4\nfast_path_enabled = true\nfast_path_claim_threshold = 0.75\npresentation_ttl_minutes = 240\n# Predictive EIG per expected time is the diagnostic default objective (§7.4/§7.5)\n# whenever at least predictive_target_minimum held-out instruments exist for the\n# episode; hypothesis EIG remains the fallback and audit signal.\npredictive_selection_enabled = true\npredictive_target_minimum = 2\npredictive_target_cap = 6\nselection_overhead_seconds = 10.0\n# §5.9 fresh-vault onboarding: probes deactivate after this many qualifying\n# observations until ordinary practice has started (0 disables).\nonboarding_practice_ceiling_observations = 4\n# §6.5 re-probe triggers: repeated prediction errors and stale uncertainty.\nreprobe_prediction_error_count = 3\nreprobe_prediction_error_window = 10\nreprobe_predictive_surprise_threshold = 1.0\nreprobe_stale_uncertainty_variance = 0.6\nreprobe_stale_uncertainty_days = 30\n\n# Parameterized instance generation from admitted family/card bindings (§10).\n# llm_surfaces: when an AI provider capable of run_probe_instance_surfaces is\n# wired through, instance surfaces come from the LLM (grounded in the LO,\n# validated by the structural instance gate) and fall back to the parametric\n# templates on provider failure or gate rejection.\n[probe.generation]\ninstances_per_need = 2\nauto_generate_on_entry = false\nllm_surfaces = true\n\n# Short adaptive dialogue microprobes (§8.1): turns within one block share the\n# family's total task evidence mass (§7.7).\n[probe.dialogue]\nplanned_turns = 3\nmax_turns = 4\n\n# Learner-initiated calibration sessions (§5.9): batch episode blocks across a\n# goal scope; lift only the per-session qualifying-observation cap within the\n# declared time budget.\n[probe.calibration]\ndefault_time_budget_minutes = 20\nmax_planned_episodes = 8\ndisagreement_weight = 0.5\n\n# Hierarchical family -> item shrinkage (§9.7, Checkpoint 4.2): item rows shrink\n# toward the family-version posterior with this much family-equivalent mass.\n[probe.hierarchy]\nitem_shrinkage_pseudo_count = 25.0\n\n# Family-version lifecycle gates (§9.7, Checkpoint 4.7). Trust requires\n# real-learner evidence; synthetic gate statistics never qualify a family.\n[probe.lifecycle]\ntrust_minimum_real_sample = 20\ntrust_minimum_regrade_checks = 5\ntrust_minimum_regrade_agreement = 0.80\ntrust_maximum_negative_information_rate = 0.20\nretire_minimum_sample = 10\nretire_negative_information_rate = 0.50\nretire_regrade_agreement_floor = 0.50\n\n# Shadow-mode alternative selection policies (§13.3, Checkpoint 5.1): log-only\n# rankings on the committed presentation. Off-policy estimation stays on hold\n# for single-learner vaults.\n[probe.shadow]\nenabled = true\ntop_k = 3\n\n# Precommitted diagnostic blocks (Checkpoint 5.2/5.3): redundancy penalty is a\n# separate ranking component (never labeled EIG); joint greedy conditional EIG\n# applies only to blocks committed before answers are observed.\n[probe.block]\nfamily_redundancy_penalty = 0.6\nmax_block_size = 4\nconditional_branch_cap = 3\n# §5.6/§5.7: sequential probes run the block-end hook after this many\n# observations in the current state segment.\ndefault_block_observations = 2\n\n# IRT difficulty-aware probe conditionals (spec_irt_difficulty.md §5).\n[probe.irt]\ntheta_mastered = 2.0\ntheta_unfamiliar = -2.0\ncut_mid = -1.0\ncut_high = 1.0\nunfamiliar_error_leak = 0.20\nerr_low_frac = 0.80\nerr_mid_frac = 0.50\n\n# Learner self-attributed misconception probe coverage (spec_irt_difficulty.md §12).\n[probe.self_tag]\nw_base = 0.5\nw_max = 0.7\ntarget_degree = 2.0\npromotion_threshold = 3\n\n# Exam seeding (`learnloop ingest-exam` + `learnloop seed-exam-attempts`):\n# imported per-question outcomes become backdated exam_evidence attempts.\n# grader_confidence is the reliability discount persisted on seeded attempts;\n# default_learner_confidence (1-5) is used when an outcome omits confidence.\n[exam_seeding]\ngrader_confidence = 0.7\ndefault_learner_confidence = 3\n\n# Tutor Q&A (\"ask\"): question limits per context (practice: per item+session,\n# feedback: per attempt, library: per note per day) and the read-side\n# uncertainty bump applied for recent unresolved questions about a facet.\n[tutor_qa]\nmax_questions_practice = 3\nmax_questions_feedback = 5\nmax_questions_library = 8\napply_uncertainty_effect = true\nuncertainty_evidence_mass = 0.15\n\n# Promoting Socratic tutor questions to practice items / learning objects.\n# Gap route: a \"this exposed a gap\" promotion writes a low self-report claim\n# (gap_claim_level at gap_claim_pseudo_count pseudo-observations) and counts as\n# an unresolved-question observation with its own likelihood slot fit from the\n# learner's gap-declaration -> failure lift, falling back to\n# gap_declaration_solid_likelihood_ratio below gap_declaration_likelihood_min_samples.\n# The filed need goes stale after gap_need_ttl_days; requested_items_per_session\n# bounds the scheduler floor for promoted-but-unattempted items.\n[tutor_promotion]\ngap_claim_level = 0.25\ngap_claim_pseudo_count = 2.0\ngap_declaration_solid_likelihood_ratio = 0.35\ngap_declaration_likelihood_min_samples = 12\ngap_need_ttl_days = 21\nrequested_items_per_session = 1\n\n# Teach-back conversations: the learner explains, an AI naive student asks up\n# to max_followups questions (one per rubric criterion, uncertainty-ranked with\n# transfer escalation), and the transcript is graded as one attempt.\n# transfer_evidence_multiplier symmetrically discounts the evidence mass of\n# transfer-tier criterion evidence; session_cap bounds teach_back items per\n# built queue.\n[teach_back]\nmax_followups = 4\ntransfer_evidence_multiplier = 0.5\nsession_cap = 1\n\n[ingest]\nwindow_char_cap = 150000\nmin_content_chars = 400\ndefault_goal_priority = 0.5\nallow_auto_captions = false\n\n# PDF extraction for canonical sources (textbook chapters, past exams, any\n# ingested .pdf). engine \"auto\" uses marker-pdf (structured Markdown with\n# headings, tables, LaTeX math, and OCR for scanned pages) when installed\n# (`pip install learnloop[pdf]`), falling back to plain pypdf text extraction.\n# use_llm adds marker's VLM boost for difficult scans and dense math: hard\n# regions are sent to an OpenAI-compatible endpoint -- e.g. a local vLLM\n# serving deepseek-ai/DeepSeek-OCR (llm_base_url = \"http://127.0.0.1:8000/v1\",\n# llm_model = \"deepseek-ai/DeepSeek-OCR\") or any hosted vision model. The API\n# key is read from the env var named by llm_api_key_env. Marker conversions\n# are cached under .learnloop/source-cache/pdf/ keyed by file bytes + config.\n[ingest.pdf]\nengine = \"auto\"\n# \"\" = auto-detect (GPU when the installed torch supports it); pin with\n# \"cuda\", \"cuda:1\", \"cpu\", or \"mps\" to override.\ntorch_device = \"\"\nforce_ocr = false\nuse_llm = false\nllm_service = \"marker.services.openai.OpenAIService\"\nllm_base_url = \"\"\nllm_model = \"\"\nllm_api_key_env = \"LEARNLOOP_PDF_LLM_API_KEY\"\n\n# Per-stage token budgets for ingestion v2 (source-ingestion spec §3.1).\n# Preflight/build-plan estimates read these; a stage exceeding its ceiling\n# shards or pauses for narrower scope — it never silently truncates.\n[ingest.budgets]\ninventory_input_tokens = 20000\ninventory_output_tokens = 3000\nsynthesis_shard_input_tokens = 40000\nsynthesis_shard_output_tokens = 10000\nevidence_span_input_tokens = 12000\nsynthesis_total_input_ceiling = 48000\nsynthesis_output_tokens = 16000\nappend_neighborhood_input_tokens = 24000\nappend_output_tokens = 10000\n# Span-request protocol caps (§8.5): one bounded request round only.\nsynthesis_span_request_max_count = 12\nsynthesis_span_char_cap = 4000\n# Quick add (§1): ToC-guided relevant-scope cap.\nquick_add_scope_input_tokens = 40000\n\n# Per-provider context/output limits consulted by preflight, keyed by the\n# [ai.providers.<name>] entries (source-ingestion spec §3.1), e.g.\n# [ingest.providers.codex] context_tokens / max_output_tokens.\n\n# Durable ingest-queue worker settings (source-ingestion spec §6.2). One worker\n# (sidecar background loop or foreground CLI) drains queued jobs at a time under\n# a single lease; a running lease older than lease_ttl_seconds is recovered to\n# failed(interrupted) on startup and its queued siblings resume.\n[ingest.runner]\nlease_ttl_seconds = 120\nheartbeat_interval_seconds = 15\npoll_interval_seconds = 1.0\n\n[ai]\nactive_provider = \"codex\"\nfallback_provider = \"\"\ntimeout_seconds = 60\n\n[ai.routing]\ngrading = \"codex_low\"\ncanonical_ingest = \"codex_medium\"\ncanonical_ingest_retry = \"codex_medium\"\nauthoring = \"codex_medium\"\n# Empty = follow ai.active_provider; point at any configured provider to route\n# tutor Q&A elsewhere (a vault decision, not forced-cheap).\ntutor_qa = \"codex_low\"\n# Empty = follow ai.active_provider; teach-back questions + grading routing.\nteach_back = \"codex_low\"\n\n[ai.providers.codex]\ntype = \"codex_sdk\"\nmodel = \"gpt-5.6-sol\"\n# Per-machine; set LEARNLOOP_CODEX_CHECKOUT_PATH in ~/.config/learnloop/settings.env.\ncheckout_path = \"\"\nrevision = \"<pinned-commit>\"\nstartup_command = \"\"\nstartup_timeout_seconds = 20\nhealthcheck_timeout_seconds = 5\nauth_mode = \"chatgpt\"\nreasoning_effort = \"low\"\nreasoning_summary = \"none\"\nsdk_python_path = \"sdk/python/src\"\nsdk_codex_bin = \"\"\nsdk_launch_command = \"\"\nbase_url = \"http://127.0.0.1:8765\"\nhealthcheck_path = \"/health\"\nauthoring_path = \"/authoring-proposal\"\ncanonical_ingest_path = \"/canonical-ingest\"\ngrading_path = \"/grading-proposal\"\nmisconception_match_path = \"/misconception-match\"\n\n[ai.providers.deepseek_flash]\ntype = \"openai_chat\"\nbase_url = \"https://api.deepseek.com\"\napi_key_env = \"DEEPSEEK_API_KEY\"\nmodel = \"deepseek-v4-flash\"\nresponse_format = \"json_object\"\nthinking = \"disabled\"\nmax_tokens = 8192\ntimeout_seconds = 90\n\n[ai.providers.deepseek_pro]\ntype = \"openai_chat\"\nbase_url = \"https://api.deepseek.com\"\napi_key_env = \"DEEPSEEK_API_KEY\"\nmodel = \"deepseek-v4-pro\"\nresponse_format = \"json_object\"\nthinking = \"enabled\"\nreasoning_effort = \"high\"\nmax_tokens = 16384\ntimeout_seconds = 180\n\n[codex]\nprovider = \"sdk\"\n# Per-machine; set LEARNLOOP_CODEX_CHECKOUT_PATH in ~/.config/learnloop/settings.env.\ncheckout_path = \"\"\nrevision = \"<pinned-commit>\"\nstartup_command = \"\"\nstartup_timeout_seconds = 20\nhealthcheck_timeout_seconds = 5\nauth_mode = \"chatgpt\"\nmodel = \"gpt-5.6-sol\"\nreasoning_effort = \"low\"\nreasoning_summary = \"none\"\nsdk_python_path = \"sdk/python/src\"\nsdk_codex_bin = \"\"\nsdk_launch_command = \"\"\nbase_url = \"http://127.0.0.1:8765\"\nhealthcheck_path = \"/health\"\nauthoring_path = \"/authoring-proposal\"\ncanonical_ingest_path = \"/canonical-ingest\"\ngrading_path = \"/grading-proposal\"\nmisconception_match_path = \"/misconception-match\"\n\n# Family-keyed mastery damage per error type (spec §\"Error-aware updates\").\n# recall_failure is the deterministic attribution for `dont_know` attempts.\n[error_impacts]\nmax_sharpening = 3.0\n\n[error_impacts.recall_failure]\nfamilies = { recall = -0.25 }\nlo_mastery_delta = -0.05\nlocal_severity_gain = 0.8\n\n[error_impacts.scaffold_failure]\nfamilies = { recall = -0.35 }\nlo_mastery_delta = -0.05\nlocal_severity_gain = 1.5\n\n[error_impacts.arithmetic_slip]\nfamilies = { numeric = -0.05 }\nlo_mastery_delta = 0.0\nlocal_severity_gain = 0.35\n\n# Capability damping/shrinkage for shared-parent facet belief (knowledge-model\n# spec §4.2). Reserved for KM2+; residual activation ships default-off.\n[capabilities]\n\n# Identity-lock policy (knowledge-model spec §3.4): a facet's semantic identity\n# locks at direct evidence in >=2 distinct surface/correlation groups, at\n# facet_lock_mass independent evidence mass, or on entering an active goal's\n# certified scope — whichever comes first.\n[locks]\nfacet_lock_mass = 2.0\nfacet_surface_groups = 2\n\n# NOTE: [cross_lo_propagation] is retired (knowledge-model §8.3/§15). The LO-to-LO\n# graph-propagated prior is prerequisite-only, direction-respecting, and\n# shadow/diagnostic-only; its error_gates were dormant. `learnloop doctor` warns\n# when a vault TOML still declares the block.\n\n[recall_coverage.severity_examples.first_dont_know]\nattempt_type = \"dont_know\"\nhints_used = 0\ncorrectness = 0.0\nexpected_correctness = 0.65\neffective_coverage = 0.85\nexpected_error_type = \"recall_failure\"\nexpected_severity_band = [0.70, 0.82]\n\n[recall_coverage.severity_examples.second_same_item_dont_know]\nattempt_type = \"dont_know\"\nhints_used = 0\ncorrectness = 0.0\nexpected_correctness = 0.65\neffective_coverage = 0.85\nrecent_same_item_failures = 1\nexpected_error_type = \"recall_failure\"\nexpected_severity_band = [0.95, 1.00]\n\n[recall_coverage.severity_examples.second_same_facet_dont_know]\nattempt_type = \"dont_know\"\nhints_used = 0\ncorrectness = 0.0\nexpected_correctness = 0.65\neffective_coverage = 0.85\nrecent_same_facet_failures = 1\nexpected_error_type = \"recall_failure\"\nexpected_severity_band = [0.80, 1.00]\n\n[recall_coverage.severity_examples.hinted_dont_know]\nattempt_type = \"dont_know\"\nhints_used = 2\ncorrectness = 0.0\nexpected_correctness = 0.65\neffective_coverage = 0.80\nexpected_error_type = \"scaffold_failure\"\nexpected_severity_band = [0.85, 0.95]\n\n[recall_coverage.severity_examples.arithmetic_slip]\nattempt_type = \"independent_attempt\"\ncorrectness = 0.75\nexpected_correctness = 0.70\neffective_coverage = 0.85\ntarget_error_type = \"arithmetic_slip\"\nexpected_error_type = \"arithmetic_slip\"\nexpected_severity_band = [0.25, 0.35]\n\n[recall_coverage.severity_examples.ambiguous_item]\nattempt_type = \"independent_attempt\"\ncorrectness = 0.0\nexpected_correctness = 0.70\neffective_coverage = 0.85\nbad_item_suspicion = 0.70\nexpected_error_type = \"recall_failure\"\nexpected_severity_band = [0.45, 0.75]\n"}, "02c3e6e10f5ca37e16cef05657ee693b33502fb7": {"t": 1785750319.68092, "n": 22681, "h": "10d96009e3d6d83b", "c": "schema_version = 1\n\n[storage]\nsqlite_path = \"state.sqlite\"\n\n[algorithms]\n# mvp-0.7: canonical shared-facet knowledge model (KM §15). New vaults start\n# here; only pre-existing vaults with legacy mvp-0.6 content need\n# `learnloop upgrade` to activate it. Legacy `probe_<lo_id>` phases recorded\n# under earlier versions replay through the frozen path in services/probes.py\n# forever; new diagnostic episodes replay exclusively through\n# probe_observations.\nalgorithm_version = \"mvp-0.7\"\n\n# Single source of truth for per-attempt-type evidence (Fable's-take item 3).\n# evidence_mass weights ability-belief updates (mastery EKF / reliability);\n# surface_exposure is the fraction of the item's facet surface the attempt\n# certifies as probed (coverage). surface_exposure defaults to evidence_mass;\n# dont_know overrides it because a confident \"don't know\" fully covers the\n# surface as evidence-of-absence while remaining self-diagnosis, not\n# demonstration.\n[evidence.attempt_types]\nindependent_attempt = { evidence_mass = 1.0 }\nopen_text = { evidence_mass = 1.0 }\ndiagnostic_probe = { evidence_mass = 1.0 }\nhinted_attempt = { evidence_mass = 1.0 }\nreconstruction_after_walkthrough = { evidence_mass = 0.5 }\ndont_know = { evidence_mass = 0.7, surface_exposure = 1.0 }\nself_report = { evidence_mass = 0.3 }\n# Imported past-exam outcome: one exam is one correlated evidence event, so\n# each seeded question carries a fraction of a live independent attempt.\nexam_evidence = { evidence_mass = 0.35 }\n# Held-out practice-exam answer on a fresh, never-practiced item: a proctored\n# fresh-item answer is the highest-quality evidence in the system, so it carries\n# full evidence mass (deliberately unlike the discounted `exam_evidence` import).\nexam_attempt = { evidence_mass = 1.0 }\n# Teach-back conversation graded as one attempt: high-quality generative\n# evidence, but the opening explanation and follow-up answers are one\n# correlated multi-question event, so it carries less than a full independent\n# attempt per facet.\nteach_back = { evidence_mass = 0.8 }\nguided_walkthrough = { evidence_mass = 0.0 }\nskip = { evidence_mass = 0.0 }\n\n# Item-side coverage prior per practice mode: how much of an LO's facet surface\n# an item of this mode can surface when it has no evidence weights or rubric.\n# Not derivable from attempt-type evidence_mass (different question).\n[evidence.item_coverage_by_practice_mode]\nconstructed_response = 0.85\nopen_text = 0.85\nshort_answer = 0.75\ndiagnostic_probe = 0.80\nindependent_attempt = 0.75\nhinted_attempt = 0.65\nmultiple_choice = 0.45\nself_report = 0.25\n\n# Vault-wide evidence correlation lookup (knowledge-model spec §6): discounts\n# for repeated/near-clone/shared-stimulus surfaces once facet state is global.\n# Reserved for KM2; parsed now so vault TOMLs can set values early.\n[evidence.correlation]\n\n# Capability-aware certification budgets (knowledge-model spec §5.4).\n# group_budget defaults to evidence_mass(attempt_type) per correlation group;\n# max_groups_per_attempt caps the attempt-wide certification ceiling.\n[evidence.certification]\nmax_groups_per_attempt = 3\n\n# Blueprint recipe likelihood defaults (knowledge-model spec §9.2): noisy-AND\n# core with slip, plus a guess floor by response format.\n[evidence.blueprints]\nslip = 0.05\n\n[evidence.blueprints.guess_by_format]\nmultiple_choice = 0.25\nconstructed_response = 0.0\n\n[scheduler]\nforgetting_risk_weight = 1.0\n# Goal facet frontier: fraction of an item's evidence facets not yet on track\n# for an active goal (unexamined/known_gap or projected below target_recall\n# at the goal's due date), scaled by goal priority.\ngoal_frontier_weight = 0.25\nrecent_error_weight = 0.50\nprobe_eig_weight = 0.25\n# Goal quota: guaranteed floor share of the queue overlapping the goal\n# frontier; ramps min -> max over the last ramp_days before due_at.\ngoal_quota_floor_min = 0.30\ngoal_quota_floor_max = 0.70\ngoal_quota_ramp_days = 28\nshort_session_minutes = 20\n# Seeded exploration over near-tie candidates so logged slates carry non-degenerate\n# selection propensities (off-policy learnability). See architecture_pivot.md Stage 0.\nselection_exploration_rate = 0.1\nselection_exploration_reward_window = 0.15\n\n[scheduler.surprise]\ntheta_pos = 1.5\ntheta_neg = 1.5\nalpha_interval = 0.3\nf_min = 0.5\nf_max = 1.5\nepsilon_error_surprise = 0.05\n\n[scheduler.followup]\ntau_followup_nats = 0.05\ngamma_min = 0.5\nmin_target_facet_overlap = 0.5\n# Gate modernization: thresholds resolve as quantiles of this learner's own\n# signal history; the absolute values above remain the cold-start fallback.\nthreshold_mode = \"quantile\"\ntau_followup_quantile = 0.85\ntau_severe_error_quantile = 0.90\nquantile_min_samples = 30\nquantile_window = 200\n# gate_mode = \"score\" scores all signals through one logistic (threshold last);\n# \"cascade\" preserves the legacy hard trigger/suppression chain bit-for-bit.\ngate_mode = \"score\"\ngate_score_threshold = 0.5\ngate_subscore_steepness = 12.0\n# Predictive facet EIG (logged-but-inert at weight 0.0; see services/predictive_eig.py).\npredictive_eig_weight = 0.0\npredictive_eig_target_cap = 4\n# Misconception discrimination gate (spec_misconception_diagnostics.md §4.1).\n# tau_discrimination_power is the Youden-J lower bound a diagnostic candidate\n# must clear against an active misconception; require_misconception_discrimination\n# routes to no_suitable_item rather than queueing a non-discriminating paraphrase.\ntau_discrimination_power = 0.3\nrequire_misconception_discrimination = true\n\n# Goal projection: open-ended goals (no due_at) project facet recall at a\n# fixed horizon so the frontier stays defined.\n[goals]\ndefault_projection_horizon_days = 30\n\n[hypothesis]\nsession_card_budget = 2\nclaim_cooldown_days = 7\noverconfidence_min_evidence_mass = 1.0\nreentry_gap_days = 7\ndecay_pressure_target_recall = 0.8\ndecay_pressure_horizon_days = 60\n\n[forecasts]\ndefault_horizon_days = 14\n\n# Automatic misconception resolution (\"close the loop\"): an active error event\n# is resolved once the learning object accumulates N clean attempts after the\n# event was created. Clean = correctness >= auto_resolve_min_correctness, no\n# error attribution written, and not a dont_know/skip self-diagnosis.\n[misconceptions]\nauto_resolve_clean_attempts = 3\nauto_resolve_min_correctness = 0.85\n# Registry-based resolution and the sim discrimination gate\n# (spec_misconception_diagnostics.md §6, §7). Parsed now; consumed in later phases.\ntau_misconception_resolved = 0.15\nsim_gate_min_sensitivity_lb = 0.7\nsim_gate_min_specificity_lb = 0.8\n# 8, not 5: a perfect run over N trials has lower bound 0.25^(1/(N+1)) at the\n# 25th percentile — 0.794 at N=5 (below the 0.8 specificity gate), 0.857 at N=8.\nsim_gate_trials = 8\n# Opt-in codex answers-under-belief pass for the gate. 0 = pure deterministic\n# (no provider tokens). When > 0, codex role-plays that many planted + clean\n# students in ONE call per gate run and their fires combine with the\n# deterministic trials. Costs provider tokens per accepted item; the same N>=8\n# caveat applies (0.25^(1/(N+1)) at the 25th percentile) to the COMBINED counts.\nsim_gate_llm_trials = 0\n\n# Offline parameter fitting from the learner's own logs (`learnloop fit`).\n# Fitted sets live in the fitted_parameters table; defaults apply when none is active.\n[fitting.fsrs]\nmin_reviews = 50\nmin_elapsed_days = 0.5\nl2_lambda = 1.0\nmax_iterations = 300\ninitial_step = 0.05\nmin_relative_improvement = 0.01\n\n[mastery]\nbase_observation_variance = 1.0\nsigma2_drift = 0.01\np_max = 4.0\n# Display banding: > strong renders green, > developing renders amber, else red.\ndisplay_strong_threshold = 0.6\ndisplay_developing_threshold = 0.35\n\n# IRT 2PL difficulty-aware mastery update (spec_irt_difficulty.md §4).\n# enabled = false restores the legacy logit-space Kalman update bit-for-bit.\n[mastery.irt]\nenabled = true\ndiscrimination_default = 1.0\ndifficulty_default = 0.0\ndifficulty_from_prior = true\ndifficulty_prior_scale = 2.5\nb_abs_max = 4.0\np_clip = 1e-4\nmu_abs_max = 5.0\nmax_logit_step = 4.0\n# Empirical-Bayes per-item difficulty posterior (dark by default; see\n# MasteryIRTConfig for the identifiability rationale).\neb_difficulty_enabled = false\nb_prior_variance = 0.25\nb_learning_rate_scale = 0.2\nb_max_step = 0.25\nb_var_min = 0.01\n\n[probe]\n# LEGACY (probe redesign Checkpoint 0.4): attempts_target_default,\n# attempts_target_with_strong_claim, claim_skip_threshold, and\n# variance_convergence_threshold configure only the frozen pre-redesign replay\n# path. Their live roles moved to [probe.episode]: the attempt targets map to\n# minimum/maximum_observations, the strong-claim skip maps to the explicit\n# fast-path policy (fast_path_claim_threshold), and variance convergence is\n# superseded by the §11 completion policy (posterior_stop_threshold).\nattempts_target_default = 3\nattempts_target_with_strong_claim = 1\nclaim_skip_threshold = 0.75\nvariance_convergence_threshold = 0.10\nhypothesis_set_max_size = 5\n\n# Diagnostic episodes (spec_probe_eig_redesign.md §5/§11).\n[probe.episode]\nminimum_independent_observations = 2\nmaximum_observations = 4\nposterior_stop_threshold = 0.85\nambiguity_threshold = 0.30\nopen_set_prior = 0.10\nopen_set_trigger_threshold = 0.35\nhinted_evidence_weight = 0.5\ncontaminated_evidence_weight = 0.3\nself_graded_evidence_weight = 0.3\nsession_qualifying_observation_cap = 4\nfast_path_enabled = true\nfast_path_claim_threshold = 0.75\npresentation_ttl_minutes = 240\n# Predictive EIG per expected time is the diagnostic default objective (§7.4/§7.5)\n# whenever at least predictive_target_minimum held-out instruments exist for the\n# episode; hypothesis EIG remains the fallback and audit signal.\npredictive_selection_enabled = true\npredictive_target_minimum = 2\npredictive_target_cap = 6\nselection_overhead_seconds = 10.0\n# §5.9 fresh-vault onboarding: probes deactivate after this many qualifying\n# observations until ordinary practice has started (0 disables).\nonboarding_practice_ceiling_observations = 4\n# §6.5 re-probe triggers: repeated prediction errors and stale uncertainty.\nreprobe_prediction_error_count = 3\nreprobe_prediction_error_window = 10\nreprobe_predictive_surprise_threshold = 1.0\nreprobe_stale_uncertainty_variance = 0.6\nreprobe_stale_uncertainty_days = 30\n\n# Parameterized instance generation from admitted family/card bindings (§10).\n# llm_surfaces: when an AI provider capable of run_probe_instance_surfaces is\n# wired through, instance surfaces come from the LLM (grounded in the LO,\n# validated by the structural instance gate) and fall back to the parametric\n# templates on provider failure or gate rejection.\n[probe.generation]\ninstances_per_need = 2\nauto_generate_on_entry = false\nllm_surfaces = true\n\n# Short adaptive dialogue microprobes (§8.1): turns within one block share the\n# family's total task evidence mass (§7.7).\n[probe.dialogue]\nplanned_turns = 3\nmax_turns = 4\n\n# Learner-initiated calibration sessions (§5.9): batch episode blocks across a\n# goal scope; lift only the per-session qualifying-observation cap within the\n# declared time budget.\n[probe.calibration]\ndefault_time_budget_minutes = 20\nmax_planned_episodes = 8\ndisagreement_weight = 0.5\n\n# Hierarchical family -> item shrinkage (§9.7, Checkpoint 4.2): item rows shrink\n# toward the family-version posterior with this much family-equivalent mass.\n[probe.hierarchy]\nitem_shrinkage_pseudo_count = 25.0\n\n# Family-version lifecycle gates (§9.7, Checkpoint 4.7). Trust requires\n# real-learner evidence; synthetic gate statistics never qualify a family.\n[probe.lifecycle]\ntrust_minimum_real_sample = 20\ntrust_minimum_regrade_checks = 5\ntrust_minimum_regrade_agreement = 0.80\ntrust_maximum_negative_information_rate = 0.20\nretire_minimum_sample = 10\nretire_negative_information_rate = 0.50\nretire_regrade_agreement_floor = 0.50\n\n# Shadow-mode alternative selection policies (§13.3, Checkpoint 5.1): log-only\n# rankings on the committed presentation. Off-policy estimation stays on hold\n# for single-learner vaults.\n[probe.shadow]\nenabled = true\ntop_k = 3\n\n# Precommitted diagnostic blocks (Checkpoint 5.2/5.3): redundancy penalty is a\n# separate ranking component (never labeled EIG); joint greedy conditional EIG\n# applies only to blocks committed before answers are observed.\n[probe.block]\nfamily_redundancy_penalty = 0.6\nmax_block_size = 4\nconditional_branch_cap = 3\n# §5.6/§5.7: sequential probes run the block-end hook after this many\n# observations in the current state segment.\ndefault_block_observations = 2\n\n# IRT difficulty-aware probe conditionals (spec_irt_difficulty.md §5).\n[probe.irt]\ntheta_mastered = 2.0\ntheta_unfamiliar = -2.0\ncut_mid = -1.0\ncut_high = 1.0\nunfamiliar_error_leak = 0.20\nerr_low_frac = 0.80\nerr_mid_frac = 0.50\n\n# Learner self-attributed misconception probe coverage (spec_irt_difficulty.md §12).\n[probe.self_tag]\nw_base = 0.5\nw_max = 0.7\ntarget_degree = 2.0\npromotion_threshold = 3\n\n# Exam seeding (`learnloop ingest-exam` + `learnloop seed-exam-attempts`):\n# imported per-question outcomes become backdated exam_evidence attempts.\n# grader_confidence is the reliability discount persisted on seeded attempts;\n# default_learner_confidence (1-5) is used when an outcome omits confidence.\n[exam_seeding]\ngrader_confidence = 0.7\ndefault_learner_confidence = 3\n\n# Tutor Q&A (\"ask\"): question limits per context (practice: per item+session,\n# feedback: per attempt, library: per note per day) and the read-side\n# uncertainty bump applied for recent unresolved questions about a facet.\n[tutor_qa]\nmax_questions_practice = 3\nmax_questions_feedback = 5\nmax_questions_library = 8\napply_uncertainty_effect = true\nuncertainty_evidence_mass = 0.15\n\n# Promoting Socratic tutor questions to practice items / learning objects.\n# Gap route: a \"this exposed a gap\" promotion writes a low self-report claim\n# (gap_claim_level at gap_claim_pseudo_count pseudo-observations) and counts as\n# an unresolved-question observation with its own likelihood slot fit from the\n# learner's gap-declaration -> failure lift, falling back to\n# gap_declaration_solid_likelihood_ratio below gap_declaration_likelihood_min_samples.\n# The filed need goes stale after gap_need_ttl_days; requested_items_per_session\n# bounds the scheduler floor for promoted-but-unattempted items.\n[tutor_promotion]\ngap_claim_level = 0.25\ngap_claim_pseudo_count = 2.0\ngap_declaration_solid_likelihood_ratio = 0.35\ngap_declaration_likelihood_min_samples = 12\ngap_need_ttl_days = 21\nrequested_items_per_session = 1\n\n# Teach-back conversations: the learner explains, an AI naive student asks up\n# to max_followups questions (one per rubric criterion, uncertainty-ranked with\n# transfer escalation), and the transcript is graded as one attempt.\n# transfer_evidence_multiplier symmetrically discounts the evidence mass of\n# transfer-tier criterion evidence; session_cap bounds teach_back items per\n# built queue.\n[teach_back]\nmax_followups = 3\ntransfer_evidence_multiplier = 0.5\nsession_cap = 1\n\n[ingest]\nwindow_char_cap = 150000\nmin_content_chars = 400\ndefault_goal_priority = 0.5\nallow_auto_captions = false\n\n# PDF extraction for canonical sources (textbook chapters, past exams, any\n# ingested .pdf). engine \"auto\" uses marker-pdf (structured Markdown with\n# headings, tables, LaTeX math, and OCR for scanned pages) when installed\n# (`pip install learnloop[pdf]`), falling back to plain pypdf text extraction.\n# use_llm adds marker's VLM boost for difficult scans and dense math: hard\n# regions are sent to an OpenAI-compatible endpoint -- e.g. a local vLLM\n# serving deepseek-ai/DeepSeek-OCR (llm_base_url = \"http://127.0.0.1:8000/v1\",\n# llm_model = \"deepseek-ai/DeepSeek-OCR\") or any hosted vision model. The API\n# key is read from the env var named by llm_api_key_env. Marker conversions\n# are cached under .learnloop/source-cache/pdf/ keyed by file bytes + config.\n[ingest.pdf]\nengine = \"auto\"\n# \"\" = auto-detect (GPU when the installed torch supports it); pin with\n# \"cuda\", \"cuda:1\", \"cpu\", or \"mps\" to override.\ntorch_device = \"\"\nforce_ocr = false\nuse_llm = false\nllm_service = \"marker.services.openai.OpenAIService\"\nllm_base_url = \"\"\nllm_model = \"\"\nllm_api_key_env = \"LEARNLOOP_PDF_LLM_API_KEY\"\n\n# Per-stage token budgets for ingestion v2 (source-ingestion spec §3.1).\n# Preflight/build-plan estimates read these; a stage exceeding its ceiling\n# shards or pauses for narrower scope — it never silently truncates.\n[ingest.budgets]\ninventory_input_tokens = 20000\ninventory_output_tokens = 3000\nsynthesis_shard_input_tokens = 40000\nsynthesis_shard_output_tokens = 10000\nevidence_span_input_tokens = 12000\nsynthesis_total_input_ceiling = 48000\nsynthesis_output_tokens = 16000\nappend_neighborhood_input_tokens = 24000\nappend_output_tokens = 10000\n# Span-request protocol caps (§8.5): one bounded request round only.\nsynthesis_span_request_max_count = 12\nsynthesis_span_char_cap = 4000\n# Quick add (§1): ToC-guided relevant-scope cap.\nquick_add_scope_input_tokens = 40000\n\n# Per-provider context/output limits consulted by preflight, keyed by the\n# [ai.providers.<name>] entries (source-ingestion spec §3.1), e.g.\n# [ingest.providers.codex] context_tokens / max_output_tokens.\n\n# Durable ingest-queue worker settings (source-ingestion spec §6.2). One worker\n# (sidecar background loop or foreground CLI) drains queued jobs at a time under\n# a single lease; a running lease older than lease_ttl_seconds is recovered to\n# failed(interrupted) on startup and its queued siblings resume.\n[ingest.runner]\nlease_ttl_seconds = 120\nheartbeat_interval_seconds = 15\npoll_interval_seconds = 1.0\n\n[ai]\nactive_provider = \"codex\"\nfallback_provider = \"\"\ntimeout_seconds = 60\n\n[ai.routing]\ngrading = \"codex_low\"\ncanonical_ingest = \"codex_medium\"\ncanonical_ingest_retry = \"codex_medium\"\nauthoring = \"codex_medium\"\n# Empty = follow ai.active_provider; point at any configured provider to route\n# tutor Q&A elsewhere (a vault decision, not forced-cheap).\ntutor_qa = \"codex_low\"\n# Empty = follow ai.active_provider; teach-back questions + grading routing.\nteach_back = \"codex_low\"\n\n[ai.providers.codex]\ntype = \"codex_sdk\"\nmodel = \"gpt-5.6-sol\"\n# Per-machine; set LEARNLOOP_CODEX_CHECKOUT_PATH in ~/.config/learnloop/settings.env.\ncheckout_path = \"\"\nrevision = \"<pinned-commit>\"\nstartup_command = \"\"\nstartup_timeout_seconds = 20\nhealthcheck_timeout_seconds = 5\nauth_mode = \"chatgpt\"\nreasoning_effort = \"low\"\nreasoning_summary = \"none\"\nsdk_python_path = \"sdk/python/src\"\nsdk_codex_bin = \"\"\nsdk_launch_command = \"\"\nbase_url = \"http://127.0.0.1:8765\"\nhealthcheck_path = \"/health\"\nauthoring_path = \"/authoring-proposal\"\ncanonical_ingest_path = \"/canonical-ingest\"\ngrading_path = \"/grading-proposal\"\nmisconception_match_path = \"/misconception-match\"\n\n[ai.providers.deepseek_flash]\ntype = \"openai_chat\"\nbase_url = \"https://api.deepseek.com\"\napi_key_env = \"DEEPSEEK_API_KEY\"\nmodel = \"deepseek-v4-flash\"\nresponse_format = \"json_object\"\nthinking = \"disabled\"\nmax_tokens = 8192\ntimeout_seconds = 90\n\n[ai.providers.deepseek_pro]\ntype = \"openai_chat\"\nbase_url = \"https://api.deepseek.com\"\napi_key_env = \"DEEPSEEK_API_KEY\"\nmodel = \"deepseek-v4-pro\"\nresponse_format = \"json_object\"\nthinking = \"enabled\"\nreasoning_effort = \"high\"\nmax_tokens = 16384\ntimeout_seconds = 180\n\n[codex]\nprovider = \"sdk\"\n# Per-machine; set LEARNLOOP_CODEX_CHECKOUT_PATH in ~/.config/learnloop/settings.env.\ncheckout_path = \"\"\nrevision = \"<pinned-commit>\"\nstartup_command = \"\"\nstartup_timeout_seconds = 20\nhealthcheck_timeout_seconds = 5\nauth_mode = \"chatgpt\"\nmodel = \"gpt-5.6-sol\"\nreasoning_effort = \"low\"\nreasoning_summary = \"none\"\nsdk_python_path = \"sdk/python/src\"\nsdk_codex_bin = \"\"\nsdk_launch_command = \"\"\nbase_url = \"http://127.0.0.1:8765\"\nhealthcheck_path = \"/health\"\nauthoring_path = \"/authoring-proposal\"\ncanonical_ingest_path = \"/canonical-ingest\"\ngrading_path = \"/grading-proposal\"\nmisconception_match_path = \"/misconception-match\"\n\n# Family-keyed mastery damage per error type (spec §\"Error-aware updates\").\n# recall_failure is the deterministic attribution for `dont_know` attempts.\n[error_impacts]\nmax_sharpening = 3.0\n\n[error_impacts.recall_failure]\nfamilies = { recall = -0.25 }\nlo_mastery_delta = -0.05\nlocal_severity_gain = 0.8\n\n[error_impacts.scaffold_failure]\nfamilies = { recall = -0.35 }\nlo_mastery_delta = -0.05\nlocal_severity_gain = 1.5\n\n[error_impacts.arithmetic_slip]\nfamilies = { numeric = -0.05 }\nlo_mastery_delta = 0.0\nlocal_severity_gain = 0.35\n\n# Capability damping/shrinkage for shared-parent facet belief (knowledge-model\n# spec §4.2). Reserved for KM2+; residual activation ships default-off.\n[capabilities]\n\n# Identity-lock policy (knowledge-model spec §3.4): a facet's semantic identity\n# locks at direct evidence in >=2 distinct surface/correlation groups, at\n# facet_lock_mass independent evidence mass, or on entering an active goal's\n# certified scope — whichever comes first.\n[locks]\nfacet_lock_mass = 2.0\nfacet_surface_groups = 2\n\n# NOTE: [cross_lo_propagation] is retired (knowledge-model §8.3/§15). The LO-to-LO\n# graph-propagated prior is prerequisite-only, direction-respecting, and\n# shadow/diagnostic-only; its error_gates were dormant. `learnloop doctor` warns\n# when a vault TOML still declares the block.\n\n[recall_coverage.severity_examples.first_dont_know]\nattempt_type = \"dont_know\"\nhints_used = 0\ncorrectness = 0.0\nexpected_correctness = 0.65\neffective_coverage = 0.85\nexpected_error_type = \"recall_failure\"\nexpected_severity_band = [0.70, 0.82]\n\n[recall_coverage.severity_examples.second_same_item_dont_know]\nattempt_type = \"dont_know\"\nhints_used = 0\ncorrectness = 0.0\nexpected_correctness = 0.65\neffective_coverage = 0.85\nrecent_same_item_failures = 1\nexpected_error_type = \"recall_failure\"\nexpected_severity_band = [0.95, 1.00]\n\n[recall_coverage.severity_examples.second_same_facet_dont_know]\nattempt_type = \"dont_know\"\nhints_used = 0\ncorrectness = 0.0\nexpected_correctness = 0.65\neffective_coverage = 0.85\nrecent_same_facet_failures = 1\nexpected_error_type = \"recall_failure\"\nexpected_severity_band = [0.80, 1.00]\n\n[recall_coverage.severity_examples.hinted_dont_know]\nattempt_type = \"dont_know\"\nhints_used = 2\ncorrectness = 0.0\nexpected_correctness = 0.65\neffective_coverage = 0.80\nexpected_error_type = \"scaffold_failure\"\nexpected_severity_band = [0.85, 0.95]\n\n[recall_coverage.severity_examples.arithmetic_slip]\nattempt_type = \"independent_attempt\"\ncorrectness = 0.75\nexpected_correctness = 0.70\neffective_coverage = 0.85\ntarget_error_type = \"arithmetic_slip\"\nexpected_error_type = \"arithmetic_slip\"\nexpected_severity_band = [0.25, 0.35]\n\n[recall_coverage.severity_examples.ambiguous_item]\nattempt_type = \"independent_attempt\"\ncorrectness = 0.0\nexpected_correctness = 0.70\neffective_coverage = 0.85\nbad_item_suspicion = 0.70\nexpected_error_type = \"recall_failure\"\nexpected_severity_band = [0.45, 0.75]\n"}}, "fixtures/law/learnloop.toml": {"d7f5830f824d7636193af334e950c1d2ffc477c4": {"t": 1785745345.4259655, "n": 6304, "h": "e2eff264c84890f3", "c": "schema_version = 1\n\n[storage]\nsqlite_path = \"state.sqlite\"\n\n[algorithms]\nalgorithm_version = \"mvp-0.6\"\n\n[scheduler]\nforgetting_risk_weight = 1.0\nrecent_error_weight = 0.50\nprobe_eig_weight = 0.25\nshort_session_minutes = 20\n# Seeded exploration over near-tie candidates so logged slates carry non-degenerate\n# selection propensities (off-policy learnability). See architecture_pivot.md Stage 0.\nselection_exploration_rate = 0.1\nselection_exploration_reward_window = 0.15\n\n[scheduler.surprise]\ntheta_pos = 1.5\ntheta_neg = 1.5\nalpha_interval = 0.3\nf_min = 0.5\nf_max = 1.5\nepsilon_error_surprise = 0.05\n\n[scheduler.followup]\ntau_followup_nats = 0.05\ngamma_min = 0.5\n\n[mastery]\nbase_observation_variance = 1.0\nsigma2_drift = 0.01\np_max = 4.0\n\n# IRT 2PL difficulty-aware mastery update (spec_irt_difficulty.md §4).\n# enabled = false restores the legacy logit-space Kalman update bit-for-bit.\n[mastery.irt]\nenabled = true\ndiscrimination_default = 1.0\ndifficulty_default = 0.0\ndifficulty_from_prior = true\ndifficulty_prior_scale = 2.5\nb_abs_max = 4.0\np_clip = 1e-4\nmu_abs_max = 5.0\nmax_logit_step = 4.0\n\n[probe]\nattempts_target_default = 3\nattempts_target_with_strong_claim = 1\nclaim_skip_threshold = 0.75\nvariance_convergence_threshold = 0.10\nhypothesis_set_max_size = 5\n\n# IRT difficulty-aware probe conditionals (spec_irt_difficulty.md §5).\n[probe.irt]\ntheta_mastered = 2.0\ntheta_unfamiliar = -2.0\ncut_mid = -1.0\ncut_high = 1.0\nunfamiliar_error_leak = 0.20\nerr_low_frac = 0.80\nerr_mid_frac = 0.50\n\n# Learner self-attributed misconception probe coverage (spec_irt_difficulty.md §12).\n[probe.self_tag]\nw_base = 0.5\nw_max = 0.7\ntarget_degree = 2.0\npromotion_threshold = 3\n\n[ingest]\nwindow_char_cap = 150000\nmin_content_chars = 400\ndefault_goal_priority = 0.5\nallow_auto_captions = false\n\n[ai]\nactive_provider = \"codex\"\nfallback_provider = \"\"\ntimeout_seconds = 60\n\n[ai.routing]\ngrading = \"codex\"\ncanonical_ingest = \"codex\"\ncanonical_ingest_retry = \"\"\nauthoring = \"codex\"\n\n[ai.providers.codex]\ntype = \"codex_sdk\"\nmodel = \"gpt-5.5\"\ncheckout_path = \"/home/chloe/Documents/thinking/learnanything/codex\"\nrevision = \"<pinned-commit>\"\nstartup_command = \"\"\nstartup_timeout_seconds = 20\nhealthcheck_timeout_seconds = 5\nauth_mode = \"chatgpt\"\nreasoning_effort = \"medium\"\nreasoning_summary = \"none\"\nsdk_python_path = \"sdk/python/src\"\nsdk_codex_bin = \"\"\nsdk_launch_command = \"\"\nbase_url = \"http://127.0.0.1:8765\"\nhealthcheck_path = \"/health\"\nauthoring_path = \"/authoring-proposal\"\ncanonical_ingest_path = \"/canonical-ingest\"\ngrading_path = \"/grading-proposal\"\n\n[ai.providers.deepseek_flash]\ntype = \"openai_chat\"\nbase_url = \"https://api.deepseek.com\"\napi_key_env = \"DEEPSEEK_API_KEY\"\nmodel = \"deepseek-v4-flash\"\nresponse_format = \"json_object\"\nthinking = \"disabled\"\nmax_tokens = 8192\ntimeout_seconds = 90\n\n[ai.providers.deepseek_pro]\ntype = \"openai_chat\"\nbase_url = \"https://api.deepseek.com\"\napi_key_env = \"DEEPSEEK_API_KEY\"\nmodel = \"deepseek-v4-pro\"\nresponse_format = \"json_object\"\nthinking = \"enabled\"\nreasoning_effort = \"high\"\nmax_tokens = 16384\ntimeout_seconds = 180\n\n[codex]\nprovider = \"sdk\"\ncheckout_path = \"/home/chloe/Documents/thinking/learnanything/codex\"\nrevision = \"<pinned-commit>\"\nstartup_command = \"\"\nstartup_timeout_seconds = 20\nhealthcheck_timeout_seconds = 5\nauth_mode = \"chatgpt\"\nmodel = \"gpt-5.5\"\nreasoning_effort = \"medium\"\nreasoning_summary = \"none\"\nsdk_python_path = \"sdk/python/src\"\nsdk_codex_bin = \"\"\nsdk_launch_command = \"\"\nbase_url = \"http://127.0.0.1:8765\"\nhealthcheck_path = \"/health\"\nauthoring_path = \"/authoring-proposal\"\ncanonical_ingest_path = \"/canonical-ingest\"\ngrading_path = \"/grading-proposal\"\n\n# Family-keyed mastery damage per error type (spec §\"Error-aware updates\").\n# recall_failure is the deterministic attribution for `dont_know` attempts.\n[error_impacts]\nmax_sharpening = 3.0\n\n[error_impacts.recall_failure]\nfamilies = { recall = -0.25 }\nlo_mastery_delta = -0.05\nlocal_severity_gain = 0.8\n\n[error_impacts.scaffold_failure]\nfamilies = { recall = -0.35 }\nlo_mastery_delta = -0.05\nlocal_severity_gain = 1.5\n\n[error_impacts.arithmetic_slip]\nfamilies = { numeric = -0.05 }\nlo_mastery_delta = 0.0\nlocal_severity_gain = 0.35\n\n# Cross-LO propagation gates per error type (spec §\"Error-type gate\").\n[cross_lo_propagation.default]\nmax_depth = 3\nhop_decay = 0.5\ntotal_propagated_weight_cap = 0.7\n\n[cross_lo_propagation.error_gates.recall_failure]\nmean_factor = 0.0 # forgetting a definition is not evidence prereqs are weak\nvariance_factor = 0.25\nscope = \"all\"\n\n[cross_lo_propagation.error_gates.scaffold_failure]\nmean_factor = 0.0\nvariance_factor = 0.35\nscope = \"all\"\n\n[cross_lo_propagation.error_gates.arithmetic_slip]\nmean_factor = 0.0\nvariance_factor = 0.10\nscope = \"all\"\n\n[recall_coverage.severity_examples.first_dont_know]\nattempt_type = \"dont_know\"\nhints_used = 0\ncorrectness = 0.0\nexpected_correctness = 0.65\neffective_coverage = 0.85\nexpected_error_type = \"recall_failure\"\nexpected_severity_band = [0.70, 0.82]\n\n[recall_coverage.severity_examples.second_same_item_dont_know]\nattempt_type = \"dont_know\"\nhints_used = 0\ncorrectness = 0.0\nexpected_correctness = 0.65\neffective_coverage = 0.85\nrecent_same_item_failures = 1\nexpected_error_type = \"recall_failure\"\nexpected_severity_band = [0.95, 1.00]\n\n[recall_coverage.severity_examples.second_same_facet_dont_know]\nattempt_type = \"dont_know\"\nhints_used = 0\ncorrectness = 0.0\nexpected_correctness = 0.65\neffective_coverage = 0.85\nrecent_same_facet_failures = 1\nexpected_error_type = \"recall_failure\"\nexpected_severity_band = [0.80, 1.00]\n\n[recall_coverage.severity_examples.hinted_dont_know]\nattempt_type = \"dont_know\"\nhints_used = 2\ncorrectness = 0.0\nexpected_correctness = 0.65\neffective_coverage = 0.80\nexpected_error_type = \"scaffold_failure\"\nexpected_severity_band = [0.85, 0.95]\n\n[recall_coverage.severity_examples.arithmetic_slip]\nattempt_type = \"independent_attempt\"\ncorrectness = 0.75\nexpected_correctness = 0.70\neffective_coverage = 0.85\ntarget_error_type = \"arithmetic_slip\"\nexpected_error_type = \"arithmetic_slip\"\nexpected_severity_band = [0.25, 0.35]\n\n[recall_coverage.severity_examples.ambiguous_item]\nattempt_type = \"independent_attempt\"\ncorrectness = 0.0\nexpected_correctness = 0.70\neffective_coverage = 0.85\nbad_item_suspicion = 0.70\nexpected_error_type = \"recall_failure\"\nexpected_severity_band = [0.45, 0.75]\n"}, "b19e81d9993c28e995049da1aa16f8d316d56d68": {"t": 1785750318.346143, "n": 6304, "h": "e2eff264c84890f3", "c": "schema_version = 1\n\n[storage]\nsqlite_path = \"state.sqlite\"\n\n[algorithms]\nalgorithm_version = \"mvp-0.6\"\n\n[scheduler]\nforgetting_risk_weight = 1.0\nrecent_error_weight = 0.50\nprobe_eig_weight = 0.25\nshort_session_minutes = 20\n# Seeded exploration over near-tie candidates so logged slates carry non-degenerate\n# selection propensities (off-policy learnability). See architecture_pivot.md Stage 0.\nselection_exploration_rate = 0.1\nselection_exploration_reward_window = 0.15\n\n[scheduler.surprise]\ntheta_pos = 1.5\ntheta_neg = 1.5\nalpha_interval = 0.3\nf_min = 0.5\nf_max = 1.5\nepsilon_error_surprise = 0.05\n\n[scheduler.followup]\ntau_followup_nats = 0.05\ngamma_min = 0.5\n\n[mastery]\nbase_observation_variance = 1.0\nsigma2_drift = 0.01\np_max = 4.0\n\n# IRT 2PL difficulty-aware mastery update (spec_irt_difficulty.md §4).\n# enabled = false restores the legacy logit-space Kalman update bit-for-bit.\n[mastery.irt]\nenabled = true\ndiscrimination_default = 1.0\ndifficulty_default = 0.0\ndifficulty_from_prior = true\ndifficulty_prior_scale = 2.5\nb_abs_max = 4.0\np_clip = 1e-4\nmu_abs_max = 5.0\nmax_logit_step = 4.0\n\n[probe]\nattempts_target_default = 3\nattempts_target_with_strong_claim = 1\nclaim_skip_threshold = 0.75\nvariance_convergence_threshold = 0.10\nhypothesis_set_max_size = 5\n\n# IRT difficulty-aware probe conditionals (spec_irt_difficulty.md §5).\n[probe.irt]\ntheta_mastered = 2.0\ntheta_unfamiliar = -2.0\ncut_mid = -1.0\ncut_high = 1.0\nunfamiliar_error_leak = 0.20\nerr_low_frac = 0.80\nerr_mid_frac = 0.50\n\n# Learner self-attributed misconception probe coverage (spec_irt_difficulty.md §12).\n[probe.self_tag]\nw_base = 0.5\nw_max = 0.7\ntarget_degree = 2.0\npromotion_threshold = 3\n\n[ingest]\nwindow_char_cap = 150000\nmin_content_chars = 400\ndefault_goal_priority = 0.5\nallow_auto_captions = false\n\n[ai]\nactive_provider = \"codex\"\nfallback_provider = \"\"\ntimeout_seconds = 60\n\n[ai.routing]\ngrading = \"codex\"\ncanonical_ingest = \"codex\"\ncanonical_ingest_retry = \"\"\nauthoring = \"codex\"\n\n[ai.providers.codex]\ntype = \"codex_sdk\"\nmodel = \"gpt-5.5\"\ncheckout_path = \"/home/chloe/Documents/thinking/learnanything/codex\"\nrevision = \"<pinned-commit>\"\nstartup_command = \"\"\nstartup_timeout_seconds = 20\nhealthcheck_timeout_seconds = 5\nauth_mode = \"chatgpt\"\nreasoning_effort = \"medium\"\nreasoning_summary = \"none\"\nsdk_python_path = \"sdk/python/src\"\nsdk_codex_bin = \"\"\nsdk_launch_command = \"\"\nbase_url = \"http://127.0.0.1:8765\"\nhealthcheck_path = \"/health\"\nauthoring_path = \"/authoring-proposal\"\ncanonical_ingest_path = \"/canonical-ingest\"\ngrading_path = \"/grading-proposal\"\n\n[ai.providers.deepseek_flash]\ntype = \"openai_chat\"\nbase_url = \"https://api.deepseek.com\"\napi_key_env = \"DEEPSEEK_API_KEY\"\nmodel = \"deepseek-v4-flash\"\nresponse_format = \"json_object\"\nthinking = \"disabled\"\nmax_tokens = 8192\ntimeout_seconds = 90\n\n[ai.providers.deepseek_pro]\ntype = \"openai_chat\"\nbase_url = \"https://api.deepseek.com\"\napi_key_env = \"DEEPSEEK_API_KEY\"\nmodel = \"deepseek-v4-pro\"\nresponse_format = \"json_object\"\nthinking = \"enabled\"\nreasoning_effort = \"high\"\nmax_tokens = 16384\ntimeout_seconds = 180\n\n[codex]\nprovider = \"sdk\"\ncheckout_path = \"/home/chloe/Documents/thinking/learnanything/codex\"\nrevision = \"<pinned-commit>\"\nstartup_command = \"\"\nstartup_timeout_seconds = 20\nhealthcheck_timeout_seconds = 5\nauth_mode = \"chatgpt\"\nmodel = \"gpt-5.5\"\nreasoning_effort = \"medium\"\nreasoning_summary = \"none\"\nsdk_python_path = \"sdk/python/src\"\nsdk_codex_bin = \"\"\nsdk_launch_command = \"\"\nbase_url = \"http://127.0.0.1:8765\"\nhealthcheck_path = \"/health\"\nauthoring_path = \"/authoring-proposal\"\ncanonical_ingest_path = \"/canonical-ingest\"\ngrading_path = \"/grading-proposal\"\n\n# Family-keyed mastery damage per error type (spec §\"Error-aware updates\").\n# recall_failure is the deterministic attribution for `dont_know` attempts.\n[error_impacts]\nmax_sharpening = 3.0\n\n[error_impacts.recall_failure]\nfamilies = { recall = -0.25 }\nlo_mastery_delta = -0.05\nlocal_severity_gain = 0.8\n\n[error_impacts.scaffold_failure]\nfamilies = { recall = -0.35 }\nlo_mastery_delta = -0.05\nlocal_severity_gain = 1.5\n\n[error_impacts.arithmetic_slip]\nfamilies = { numeric = -0.05 }\nlo_mastery_delta = 0.0\nlocal_severity_gain = 0.35\n\n# Cross-LO propagation gates per error type (spec §\"Error-type gate\").\n[cross_lo_propagation.default]\nmax_depth = 3\nhop_decay = 0.5\ntotal_propagated_weight_cap = 0.7\n\n[cross_lo_propagation.error_gates.recall_failure]\nmean_factor = 0.0 # forgetting a definition is not evidence prereqs are weak\nvariance_factor = 0.25\nscope = \"all\"\n\n[cross_lo_propagation.error_gates.scaffold_failure]\nmean_factor = 0.0\nvariance_factor = 0.35\nscope = \"all\"\n\n[cross_lo_propagation.error_gates.arithmetic_slip]\nmean_factor = 0.0\nvariance_factor = 0.10\nscope = \"all\"\n\n[recall_coverage.severity_examples.first_dont_know]\nattempt_type = \"dont_know\"\nhints_used = 0\ncorrectness = 0.0\nexpected_correctness = 0.65\neffective_coverage = 0.85\nexpected_error_type = \"recall_failure\"\nexpected_severity_band = [0.70, 0.82]\n\n[recall_coverage.severity_examples.second_same_item_dont_know]\nattempt_type = \"dont_know\"\nhints_used = 0\ncorrectness = 0.0\nexpected_correctness = 0.65\neffective_coverage = 0.85\nrecent_same_item_failures = 1\nexpected_error_type = \"recall_failure\"\nexpected_severity_band = [0.95, 1.00]\n\n[recall_coverage.severity_examples.second_same_facet_dont_know]\nattempt_type = \"dont_know\"\nhints_used = 0\ncorrectness = 0.0\nexpected_correctness = 0.65\neffective_coverage = 0.85\nrecent_same_facet_failures = 1\nexpected_error_type = \"recall_failure\"\nexpected_severity_band = [0.80, 1.00]\n\n[recall_coverage.severity_examples.hinted_dont_know]\nattempt_type = \"dont_know\"\nhints_used = 2\ncorrectness = 0.0\nexpected_correctness = 0.65\neffective_coverage = 0.80\nexpected_error_type = \"scaffold_failure\"\nexpected_severity_band = [0.85, 0.95]\n\n[recall_coverage.severity_examples.arithmetic_slip]\nattempt_type = \"independent_attempt\"\ncorrectness = 0.75\nexpected_correctness = 0.70\neffective_coverage = 0.85\ntarget_error_type = \"arithmetic_slip\"\nexpected_error_type = \"arithmetic_slip\"\nexpected_severity_band = [0.25, 0.35]\n\n[recall_coverage.severity_examples.ambiguous_item]\nattempt_type = \"independent_attempt\"\ncorrectness = 0.0\nexpected_correctness = 0.70\neffective_coverage = 0.85\nbad_item_suspicion = 0.70\nexpected_error_type = \"recall_failure\"\nexpected_severity_band = [0.45, 0.75]\n"}, "565100878e11bc9ac281139570040c118fbaf1a5": {"t": 1785750319.427589, "n": 6304, "h": "5a3d223da6708acc", "c": "schema_version = 1\n\n[storage]\nsqlite_path = \"state.sqlite\"\n\n[algorithms]\nalgorithm_version = \"mvp-0.5\"\n\n[scheduler]\nforgetting_risk_weight = 1.0\nrecent_error_weight = 0.50\nprobe_eig_weight = 0.25\nshort_session_minutes = 20\n# Seeded exploration over near-tie candidates so logged slates carry non-degenerate\n# selection propensities (off-policy learnability). See architecture_pivot.md Stage 0.\nselection_exploration_rate = 0.1\nselection_exploration_reward_window = 0.15\n\n[scheduler.surprise]\ntheta_pos = 1.5\ntheta_neg = 1.5\nalpha_interval = 0.3\nf_min = 0.5\nf_max = 1.5\nepsilon_error_surprise = 0.05\n\n[scheduler.followup]\ntau_followup_nats = 0.05\ngamma_min = 0.5\n\n[mastery]\nbase_observation_variance = 1.0\nsigma2_drift = 0.01\np_max = 4.0\n\n# IRT 2PL difficulty-aware mastery update (spec_irt_difficulty.md §4).\n# enabled = false restores the legacy logit-space Kalman update bit-for-bit.\n[mastery.irt]\nenabled = true\ndiscrimination_default = 1.0\ndifficulty_default = 0.0\ndifficulty_from_prior = true\ndifficulty_prior_scale = 2.5\nb_abs_max = 4.0\np_clip = 1e-4\nmu_abs_max = 5.0\nmax_logit_step = 4.0\n\n[probe]\nattempts_target_default = 3\nattempts_target_with_strong_claim = 1\nclaim_skip_threshold = 0.75\nvariance_convergence_threshold = 0.10\nhypothesis_set_max_size = 5\n\n# IRT difficulty-aware probe conditionals (spec_irt_difficulty.md §5).\n[probe.irt]\ntheta_mastered = 2.0\ntheta_unfamiliar = -2.0\ncut_mid = -1.0\ncut_high = 1.0\nunfamiliar_error_leak = 0.20\nerr_low_frac = 0.80\nerr_mid_frac = 0.50\n\n# Learner self-attributed misconception probe coverage (spec_irt_difficulty.md §12).\n[probe.self_tag]\nw_base = 0.5\nw_max = 0.7\ntarget_degree = 2.0\npromotion_threshold = 3\n\n[ingest]\nwindow_char_cap = 150000\nmin_content_chars = 400\ndefault_goal_priority = 0.5\nallow_auto_captions = false\n\n[ai]\nactive_provider = \"codex\"\nfallback_provider = \"\"\ntimeout_seconds = 60\n\n[ai.routing]\ngrading = \"codex\"\ncanonical_ingest = \"codex\"\ncanonical_ingest_retry = \"\"\nauthoring = \"codex\"\n\n[ai.providers.codex]\ntype = \"codex_sdk\"\nmodel = \"gpt-5.5\"\ncheckout_path = \"/home/chloe/Documents/thinking/learnanything/codex\"\nrevision = \"<pinned-commit>\"\nstartup_command = \"\"\nstartup_timeout_seconds = 20\nhealthcheck_timeout_seconds = 5\nauth_mode = \"chatgpt\"\nreasoning_effort = \"medium\"\nreasoning_summary = \"none\"\nsdk_python_path = \"sdk/python/src\"\nsdk_codex_bin = \"\"\nsdk_launch_command = \"\"\nbase_url = \"http://127.0.0.1:8765\"\nhealthcheck_path = \"/health\"\nauthoring_path = \"/authoring-proposal\"\ncanonical_ingest_path = \"/canonical-ingest\"\ngrading_path = \"/grading-proposal\"\n\n[ai.providers.deepseek_flash]\ntype = \"openai_chat\"\nbase_url = \"https://api.deepseek.com\"\napi_key_env = \"DEEPSEEK_API_KEY\"\nmodel = \"deepseek-v4-flash\"\nresponse_format = \"json_object\"\nthinking = \"disabled\"\nmax_tokens = 8192\ntimeout_seconds = 90\n\n[ai.providers.deepseek_pro]\ntype = \"openai_chat\"\nbase_url = \"https://api.deepseek.com\"\napi_key_env = \"DEEPSEEK_API_KEY\"\nmodel = \"deepseek-v4-pro\"\nresponse_format = \"json_object\"\nthinking = \"enabled\"\nreasoning_effort = \"high\"\nmax_tokens = 16384\ntimeout_seconds = 180\n\n[codex]\nprovider = \"sdk\"\ncheckout_path = \"/home/chloe/Documents/thinking/learnanything/codex\"\nrevision = \"<pinned-commit>\"\nstartup_command = \"\"\nstartup_timeout_seconds = 20\nhealthcheck_timeout_seconds = 5\nauth_mode = \"chatgpt\"\nmodel = \"gpt-5.5\"\nreasoning_effort = \"medium\"\nreasoning_summary = \"none\"\nsdk_python_path = \"sdk/python/src\"\nsdk_codex_bin = \"\"\nsdk_launch_command = \"\"\nbase_url = \"http://127.0.0.1:8765\"\nhealthcheck_path = \"/health\"\nauthoring_path = \"/authoring-proposal\"\ncanonical_ingest_path = \"/canonical-ingest\"\ngrading_path = \"/grading-proposal\"\n\n# Family-keyed mastery damage per error type (spec §\"Error-aware updates\").\n# recall_failure is the deterministic attribution for `dont_know` attempts.\n[error_impacts]\nmax_sharpening = 3.0\n\n[error_impacts.recall_failure]\nfamilies = { recall = -0.25 }\nlo_mastery_delta = -0.05\nlocal_severity_gain = 0.8\n\n[error_impacts.scaffold_failure]\nfamilies = { recall = -0.35 }\nlo_mastery_delta = -0.05\nlocal_severity_gain = 1.5\n\n[error_impacts.arithmetic_slip]\nfamilies = { numeric = -0.05 }\nlo_mastery_delta = 0.0\nlocal_severity_gain = 0.35\n\n# Cross-LO propagation gates per error type (spec §\"Error-type gate\").\n[cross_lo_propagation.default]\nmax_depth = 3\nhop_decay = 0.5\ntotal_propagated_weight_cap = 0.7\n\n[cross_lo_propagation.error_gates.recall_failure]\nmean_factor = 0.0 # forgetting a definition is not evidence prereqs are weak\nvariance_factor = 0.25\nscope = \"all\"\n\n[cross_lo_propagation.error_gates.scaffold_failure]\nmean_factor = 0.0\nvariance_factor = 0.35\nscope = \"all\"\n\n[cross_lo_propagation.error_gates.arithmetic_slip]\nmean_factor = 0.0\nvariance_factor = 0.10\nscope = \"all\"\n\n[recall_coverage.severity_examples.first_dont_know]\nattempt_type = \"dont_know\"\nhints_used = 0\ncorrectness = 0.0\nexpected_correctness = 0.65\neffective_coverage = 0.85\nexpected_error_type = \"recall_failure\"\nexpected_severity_band = [0.70, 0.82]\n\n[recall_coverage.severity_examples.second_same_item_dont_know]\nattempt_type = \"dont_know\"\nhints_used = 0\ncorrectness = 0.0\nexpected_correctness = 0.65\neffective_coverage = 0.85\nrecent_same_item_failures = 1\nexpected_error_type = \"recall_failure\"\nexpected_severity_band = [0.95, 1.00]\n\n[recall_coverage.severity_examples.second_same_facet_dont_know]\nattempt_type = \"dont_know\"\nhints_used = 0\ncorrectness = 0.0\nexpected_correctness = 0.65\neffective_coverage = 0.85\nrecent_same_facet_failures = 1\nexpected_error_type = \"recall_failure\"\nexpected_severity_band = [0.80, 1.00]\n\n[recall_coverage.severity_examples.hinted_dont_know]\nattempt_type = \"dont_know\"\nhints_used = 2\ncorrectness = 0.0\nexpected_correctness = 0.65\neffective_coverage = 0.80\nexpected_error_type = \"scaffold_failure\"\nexpected_severity_band = [0.85, 0.95]\n\n[recall_coverage.severity_examples.arithmetic_slip]\nattempt_type = \"independent_attempt\"\ncorrectness = 0.75\nexpected_correctness = 0.70\neffective_coverage = 0.85\ntarget_error_type = \"arithmetic_slip\"\nexpected_error_type = \"arithmetic_slip\"\nexpected_severity_band = [0.25, 0.35]\n\n[recall_coverage.severity_examples.ambiguous_item]\nattempt_type = \"independent_attempt\"\ncorrectness = 0.0\nexpected_correctness = 0.70\neffective_coverage = 0.85\nbad_item_suspicion = 0.70\nexpected_error_type = \"recall_failure\"\nexpected_severity_band = [0.45, 0.75]\n"}, "b48c1ee9be4bc2a4ff5612870d8bf38391e7061b": {"t": 1785750320.5172253, "n": 6330, "h": "7ab240b4649f2836", "c": "schema_version = 1\n\n[storage]\nsqlite_path = \"state.sqlite\"\n\n[algorithms]\nalgorithm_version = \"mvp-0.4\"\n\n[scheduler]\nforgetting_risk_weight = 1.0\nactive_goal_weight = 0.35\nrecent_error_weight = 0.50\nprobe_eig_weight = 0.25\nshort_session_minutes = 20\n# Seeded exploration over near-tie candidates so logged slates carry non-degenerate\n# selection propensities (off-policy learnability). See architecture_pivot.md Stage 0.\nselection_exploration_rate = 0.1\nselection_exploration_reward_window = 0.15\n\n[scheduler.surprise]\ntheta_pos = 1.5\ntheta_neg = 1.5\nalpha_interval = 0.3\nf_min = 0.5\nf_max = 1.5\nepsilon_error_surprise = 0.05\n\n[scheduler.followup]\ntau_followup_nats = 0.05\ngamma_min = 0.5\n\n[mastery]\nbase_observation_variance = 1.0\nsigma2_drift = 0.01\np_max = 4.0\n\n# IRT 2PL difficulty-aware mastery update (spec_irt_difficulty.md §4).\n# enabled = false restores the legacy logit-space Kalman update bit-for-bit.\n[mastery.irt]\nenabled = true\ndiscrimination_default = 1.0\ndifficulty_default = 0.0\ndifficulty_from_prior = true\ndifficulty_prior_scale = 2.5\nb_abs_max = 4.0\np_clip = 1e-4\nmu_abs_max = 5.0\nmax_logit_step = 4.0\n\n[probe]\nattempts_target_default = 3\nattempts_target_with_strong_claim = 1\nclaim_skip_threshold = 0.75\nvariance_convergence_threshold = 0.10\nhypothesis_set_max_size = 5\n\n# IRT difficulty-aware probe conditionals (spec_irt_difficulty.md §5).\n[probe.irt]\ntheta_mastered = 2.0\ntheta_unfamiliar = -2.0\ncut_mid = -1.0\ncut_high = 1.0\nunfamiliar_error_leak = 0.20\nerr_low_frac = 0.80\nerr_mid_frac = 0.50\n\n# Learner self-attributed misconception probe coverage (spec_irt_difficulty.md §12).\n[probe.self_tag]\nw_base = 0.5\nw_max = 0.7\ntarget_degree = 2.0\npromotion_threshold = 3\n\n[ingest]\nwindow_char_cap = 150000\nmin_content_chars = 400\ndefault_goal_priority = 0.5\nallow_auto_captions = false\n\n[ai]\nactive_provider = \"codex\"\nfallback_provider = \"\"\ntimeout_seconds = 60\n\n[ai.routing]\ngrading = \"codex\"\ncanonical_ingest = \"codex\"\ncanonical_ingest_retry = \"\"\nauthoring = \"codex\"\n\n[ai.providers.codex]\ntype = \"codex_sdk\"\nmodel = \"gpt-5.5\"\ncheckout_path = \"/home/chloe/Documents/thinking/learnanything/codex\"\nrevision = \"<pinned-commit>\"\nstartup_command = \"\"\nstartup_timeout_seconds = 20\nhealthcheck_timeout_seconds = 5\nauth_mode = \"chatgpt\"\nreasoning_effort = \"medium\"\nreasoning_summary = \"none\"\nsdk_python_path = \"sdk/python/src\"\nsdk_codex_bin = \"\"\nsdk_launch_command = \"\"\nbase_url = \"http://127.0.0.1:8765\"\nhealthcheck_path = \"/health\"\nauthoring_path = \"/authoring-proposal\"\ncanonical_ingest_path = \"/canonical-ingest\"\ngrading_path = \"/grading-proposal\"\n\n[ai.providers.deepseek_flash]\ntype = \"openai_chat\"\nbase_url = \"https://api.deepseek.com\"\napi_key_env = \"DEEPSEEK_API_KEY\"\nmodel = \"deepseek-v4-flash\"\nresponse_format = \"json_object\"\nthinking = \"disabled\"\nmax_tokens = 8192\ntimeout_seconds = 90\n\n[ai.providers.deepseek_pro]\ntype = \"openai_chat\"\nbase_url = \"https://api.deepseek.com\"\napi_key_env = \"DEEPSEEK_API_KEY\"\nmodel = \"deepseek-v4-pro\"\nresponse_format = \"json_object\"\nthinking = \"enabled\"\nreasoning_effort = \"high\"\nmax_tokens = 16384\ntimeout_seconds = 180\n\n[codex]\nprovider = \"sdk\"\ncheckout_path = \"/home/chloe/Documents/thinking/learnanything/codex\"\nrevision = \"<pinned-commit>\"\nstartup_command = \"\"\nstartup_timeout_seconds = 20\nhealthcheck_timeout_seconds = 5\nauth_mode = \"chatgpt\"\nmodel = \"gpt-5.5\"\nreasoning_effort = \"medium\"\nreasoning_summary = \"none\"\nsdk_python_path = \"sdk/python/src\"\nsdk_codex_bin = \"\"\nsdk_launch_command = \"\"\nbase_url = \"http://127.0.0.1:8765\"\nhealthcheck_path = \"/health\"\nauthoring_path = \"/authoring-proposal\"\ncanonical_ingest_path = \"/canonical-ingest\"\ngrading_path = \"/grading-proposal\"\n\n# Family-keyed mastery damage per error type (spec §\"Error-aware updates\").\n# recall_failure is the deterministic attribution for `dont_know` attempts.\n[error_impacts]\nmax_sharpening = 3.0\n\n[error_impacts.recall_failure]\nfamilies = { recall = -0.25 }\nlo_mastery_delta = -0.05\nlocal_severity_gain = 0.8\n\n[error_impacts.scaffold_failure]\nfamilies = { recall = -0.35 }\nlo_mastery_delta = -0.05\nlocal_severity_gain = 1.5\n\n[error_impacts.arithmetic_slip]\nfamilies = { numeric = -0.05 }\nlo_mastery_delta = 0.0\nlocal_severity_gain = 0.35\n\n# Cross-LO propagation gates per error type (spec §\"Error-type gate\").\n[cross_lo_propagation.default]\nmax_depth = 3\nhop_decay = 0.5\ntotal_propagated_weight_cap = 0.7\n\n[cross_lo_propagation.error_gates.recall_failure]\nmean_factor = 0.0 # forgetting a definition is not evidence prereqs are weak\nvariance_factor = 0.25\nscope = \"all\"\n\n[cross_lo_propagation.error_gates.scaffold_failure]\nmean_factor = 0.0\nvariance_factor = 0.35\nscope = \"all\"\n\n[cross_lo_propagation.error_gates.arithmetic_slip]\nmean_factor = 0.0\nvariance_factor = 0.10\nscope = \"all\"\n\n[recall_coverage.severity_examples.first_dont_know]\nattempt_type = \"dont_know\"\nhints_used = 0\ncorrectness = 0.0\nexpected_correctness = 0.65\neffective_coverage = 0.85\nexpected_error_type = \"recall_failure\"\nexpected_severity_band = [0.70, 0.82]\n\n[recall_coverage.severity_examples.second_same_item_dont_know]\nattempt_type = \"dont_know\"\nhints_used = 0\ncorrectness = 0.0\nexpected_correctness = 0.65\neffective_coverage = 0.85\nrecent_same_item_failures = 1\nexpected_error_type = \"recall_failure\"\nexpected_severity_band = [0.95, 1.00]\n\n[recall_coverage.severity_examples.second_same_facet_dont_know]\nattempt_type = \"dont_know\"\nhints_used = 0\ncorrectness = 0.0\nexpected_correctness = 0.65\neffective_coverage = 0.85\nrecent_same_facet_failures = 1\nexpected_error_type = \"recall_failure\"\nexpected_severity_band = [0.80, 1.00]\n\n[recall_coverage.severity_examples.hinted_dont_know]\nattempt_type = \"dont_know\"\nhints_used = 2\ncorrectness = 0.0\nexpected_correctness = 0.65\neffective_coverage = 0.80\nexpected_error_type = \"scaffold_failure\"\nexpected_severity_band = [0.85, 0.95]\n\n[recall_coverage.severity_examples.arithmetic_slip]\nattempt_type = \"independent_attempt\"\ncorrectness = 0.75\nexpected_correctness = 0.70\neffective_coverage = 0.85\ntarget_error_type = \"arithmetic_slip\"\nexpected_error_type = \"arithmetic_slip\"\nexpected_severity_band = [0.25, 0.35]\n\n[recall_coverage.severity_examples.ambiguous_item]\nattempt_type = \"independent_attempt\"\ncorrectness = 0.0\nexpected_correctness = 0.70\neffective_coverage = 0.85\nbad_item_suspicion = 0.70\nexpected_error_type = \"recall_failure\"\nexpected_severity_band = [0.45, 0.75]\n"}}, "fixtures/linear_algebra_legacy/learnloop.toml": {"d7f5830f824d7636193af334e950c1d2ffc477c4": {"t": 1785745346.30465, "n": 6376, "h": "a45762d6a55352da", "c": "schema_version = 1\n\n[storage]\nsqlite_path = \"state.sqlite\"\n\n[algorithms]\nalgorithm_version = \"mvp-0.6\"\n\n[scheduler]\nforgetting_risk_weight = 1.0\nrecent_error_weight = 0.50\nprobe_eig_weight = 0.25\nshort_session_minutes = 20\n# Seeded exploration over near-tie candidates so logged slates carry non-degenerate\n# selection propensities (off-policy learnability). See architecture_pivot.md Stage 0.\nselection_exploration_rate = 0.1\nselection_exploration_reward_window = 0.15\n\n[scheduler.surprise]\ntheta_pos = 1.5\ntheta_neg = 1.5\nalpha_interval = 0.3\nf_min = 0.5\nf_max = 1.5\nepsilon_error_surprise = 0.05\n\n[scheduler.followup]\ntau_followup_nats = 0.05\ngamma_min = 0.5\n\n[mastery]\nbase_observation_variance = 1.0\nsigma2_drift = 0.01\np_max = 4.0\n\n# IRT 2PL difficulty-aware mastery update (spec_irt_difficulty.md §4).\n# enabled = false restores the legacy logit-space Kalman update bit-for-bit.\n[mastery.irt]\nenabled = true\ndiscrimination_default = 1.0\ndifficulty_default = 0.0\ndifficulty_from_prior = true\ndifficulty_prior_scale = 2.5\nb_abs_max = 4.0\np_clip = 1e-4\nmu_abs_max = 5.0\nmax_logit_step = 4.0\n\n[probe]\nattempts_target_default = 3\nattempts_target_with_strong_claim = 1\nclaim_skip_threshold = 0.75\nvariance_convergence_threshold = 0.10\nhypothesis_set_max_size = 5\n\n# IRT difficulty-aware probe conditionals (spec_irt_difficulty.md §5).\n[probe.irt]\ntheta_mastered = 2.0\ntheta_unfamiliar = -2.0\ncut_mid = -1.0\ncut_high = 1.0\nunfamiliar_error_leak = 0.20\nerr_low_frac = 0.80\nerr_mid_frac = 0.50\n\n# Learner self-attributed misconception probe coverage (spec_irt_difficulty.md §12).\n[probe.self_tag]\nw_base = 0.5\nw_max = 0.7\ntarget_degree = 2.0\npromotion_threshold = 3\n\n[ingest]\nwindow_char_cap = 150000\nmin_content_chars = 400\ndefault_goal_priority = 0.5\nallow_auto_captions = false\n\n[ai]\nactive_provider = \"codex\"\nfallback_provider = \"\"\ntimeout_seconds = 60\n\n[ai.routing]\ngrading = \"codex\"\ncanonical_ingest = \"codex\"\ncanonical_ingest_retry = \"\"\nauthoring = \"codex\"\n\n[ai.providers.codex]\ntype = \"codex_sdk\"\nmodel = \"gpt-5.5\"\n# Per-machine; set LEARNLOOP_CODEX_CHECKOUT_PATH in ~/.config/learnloop/settings.env.\ncheckout_path = \"\"\nrevision = \"<pinned-commit>\"\nstartup_command = \"\"\nstartup_timeout_seconds = 20\nhealthcheck_timeout_seconds = 5\nauth_mode = \"chatgpt\"\nreasoning_effort = \"medium\"\nreasoning_summary = \"none\"\nsdk_python_path = \"sdk/python/src\"\nsdk_codex_bin = \"\"\nsdk_launch_command = \"\"\nbase_url = \"http://127.0.0.1:8765\"\nhealthcheck_path = \"/health\"\nauthoring_path = \"/authoring-proposal\"\ncanonical_ingest_path = \"/canonical-ingest\"\ngrading_path = \"/grading-proposal\"\n\n[ai.providers.deepseek_flash]\ntype = \"openai_chat\"\nbase_url = \"https://api.deepseek.com\"\napi_key_env = \"DEEPSEEK_API_KEY\"\nmodel = \"deepseek-v4-flash\"\nresponse_format = \"json_object\"\nthinking = \"disabled\"\nmax_tokens = 8192\ntimeout_seconds = 90\n\n[ai.providers.deepseek_pro]\ntype = \"openai_chat\"\nbase_url = \"https://api.deepseek.com\"\napi_key_env = \"DEEPSEEK_API_KEY\"\nmodel = \"deepseek-v4-pro\"\nresponse_format = \"json_object\"\nthinking = \"enabled\"\nreasoning_effort = \"high\"\nmax_tokens = 16384\ntimeout_seconds = 180\n\n[codex]\nprovider = \"sdk\"\n# Per-machine; set LEARNLOOP_CODEX_CHECKOUT_PATH in ~/.config/learnloop/settings.env.\ncheckout_path = \"\"\nrevision = \"<pinned-commit>\"\nstartup_command = \"\"\nstartup_timeout_seconds = 20\nhealthcheck_timeout_seconds = 5\nauth_mode = \"chatgpt\"\nmodel = \"gpt-5.5\"\nreasoning_effort = \"medium\"\nreasoning_summary = \"none\"\nsdk_python_path = \"sdk/python/src\"\nsdk_codex_bin = \"\"\nsdk_launch_command = \"\"\nbase_url = \"http://127.0.0.1:8765\"\nhealthcheck_path = \"/health\"\nauthoring_path = \"/authoring-proposal\"\ncanonical_ingest_path = \"/canonical-ingest\"\ngrading_path = \"/grading-proposal\"\n\n# Family-keyed mastery damage per error type (spec §\"Error-aware updates\").\n# recall_failure is the deterministic attribution for `dont_know` attempts.\n[error_impacts]\nmax_sharpening = 3.0\n\n[error_impacts.recall_failure]\nfamilies = { recall = -0.25 }\nlo_mastery_delta = -0.05\nlocal_severity_gain = 0.8\n\n[error_impacts.scaffold_failure]\nfamilies = { recall = -0.35 }\nlo_mastery_delta = -0.05\nlocal_severity_gain = 1.5\n\n[error_impacts.arithmetic_slip]\nfamilies = { numeric = -0.05 }\nlo_mastery_delta = 0.0\nlocal_severity_gain = 0.35\n\n# Cross-LO propagation gates per error type (spec §\"Error-type gate\").\n[cross_lo_propagation.default]\nmax_depth = 3\nhop_decay = 0.5\ntotal_propagated_weight_cap = 0.7\n\n[cross_lo_propagation.error_gates.recall_failure]\nmean_factor = 0.0 # forgetting a definition is not evidence prereqs are weak\nvariance_factor = 0.25\nscope = \"all\"\n\n[cross_lo_propagation.error_gates.scaffold_failure]\nmean_factor = 0.0\nvariance_factor = 0.35\nscope = \"all\"\n\n[cross_lo_propagation.error_gates.arithmetic_slip]\nmean_factor = 0.0\nvariance_factor = 0.10\nscope = \"all\"\n\n[recall_coverage.severity_examples.first_dont_know]\nattempt_type = \"dont_know\"\nhints_used = 0\ncorrectness = 0.0\nexpected_correctness = 0.65\neffective_coverage = 0.85\nexpected_error_type = \"recall_failure\"\nexpected_severity_band = [0.70, 0.82]\n\n[recall_coverage.severity_examples.second_same_item_dont_know]\nattempt_type = \"dont_know\"\nhints_used = 0\ncorrectness = 0.0\nexpected_correctness = 0.65\neffective_coverage = 0.85\nrecent_same_item_failures = 1\nexpected_error_type = \"recall_failure\"\nexpected_severity_band = [0.95, 1.00]\n\n[recall_coverage.severity_examples.second_same_facet_dont_know]\nattempt_type = \"dont_know\"\nhints_used = 0\ncorrectness = 0.0\nexpected_correctness = 0.65\neffective_coverage = 0.85\nrecent_same_facet_failures = 1\nexpected_error_type = \"recall_failure\"\nexpected_severity_band = [0.80, 1.00]\n\n[recall_coverage.severity_examples.hinted_dont_know]\nattempt_type = \"dont_know\"\nhints_used = 2\ncorrectness = 0.0\nexpected_correctness = 0.65\neffective_coverage = 0.80\nexpected_error_type = \"scaffold_failure\"\nexpected_severity_band = [0.85, 0.95]\n\n[recall_coverage.severity_examples.arithmetic_slip]\nattempt_type = \"independent_attempt\"\ncorrectness = 0.75\nexpected_correctness = 0.70\neffective_coverage = 0.85\ntarget_error_type = \"arithmetic_slip\"\nexpected_error_type = \"arithmetic_slip\"\nexpected_severity_band = [0.25, 0.35]\n\n[recall_coverage.severity_examples.ambiguous_item]\nattempt_type = \"independent_attempt\"\ncorrectness = 0.0\nexpected_correctness = 0.70\neffective_coverage = 0.85\nbad_item_suspicion = 0.70\nexpected_error_type = \"recall_failure\"\nexpected_severity_band = [0.45, 0.75]\n"}, "f0052f7260eb63224bd103193929a03fd54660d6": {"t": 1785750320.406011, "n": 6376, "h": "a45762d6a55352da", "c": "schema_version = 1\n\n[storage]\nsqlite_path = \"state.sqlite\"\n\n[algorithms]\nalgorithm_version = \"mvp-0.6\"\n\n[scheduler]\nforgetting_risk_weight = 1.0\nrecent_error_weight = 0.50\nprobe_eig_weight = 0.25\nshort_session_minutes = 20\n# Seeded exploration over near-tie candidates so logged slates carry non-degenerate\n# selection propensities (off-policy learnability). See architecture_pivot.md Stage 0.\nselection_exploration_rate = 0.1\nselection_exploration_reward_window = 0.15\n\n[scheduler.surprise]\ntheta_pos = 1.5\ntheta_neg = 1.5\nalpha_interval = 0.3\nf_min = 0.5\nf_max = 1.5\nepsilon_error_surprise = 0.05\n\n[scheduler.followup]\ntau_followup_nats = 0.05\ngamma_min = 0.5\n\n[mastery]\nbase_observation_variance = 1.0\nsigma2_drift = 0.01\np_max = 4.0\n\n# IRT 2PL difficulty-aware mastery update (spec_irt_difficulty.md §4).\n# enabled = false restores the legacy logit-space Kalman update bit-for-bit.\n[mastery.irt]\nenabled = true\ndiscrimination_default = 1.0\ndifficulty_default = 0.0\ndifficulty_from_prior = true\ndifficulty_prior_scale = 2.5\nb_abs_max = 4.0\np_clip = 1e-4\nmu_abs_max = 5.0\nmax_logit_step = 4.0\n\n[probe]\nattempts_target_default = 3\nattempts_target_with_strong_claim = 1\nclaim_skip_threshold = 0.75\nvariance_convergence_threshold = 0.10\nhypothesis_set_max_size = 5\n\n# IRT difficulty-aware probe conditionals (spec_irt_difficulty.md §5).\n[probe.irt]\ntheta_mastered = 2.0\ntheta_unfamiliar = -2.0\ncut_mid = -1.0\ncut_high = 1.0\nunfamiliar_error_leak = 0.20\nerr_low_frac = 0.80\nerr_mid_frac = 0.50\n\n# Learner self-attributed misconception probe coverage (spec_irt_difficulty.md §12).\n[probe.self_tag]\nw_base = 0.5\nw_max = 0.7\ntarget_degree = 2.0\npromotion_threshold = 3\n\n[ingest]\nwindow_char_cap = 150000\nmin_content_chars = 400\ndefault_goal_priority = 0.5\nallow_auto_captions = false\n\n[ai]\nactive_provider = \"codex\"\nfallback_provider = \"\"\ntimeout_seconds = 60\n\n[ai.routing]\ngrading = \"codex\"\ncanonical_ingest = \"codex\"\ncanonical_ingest_retry = \"\"\nauthoring = \"codex\"\n\n[ai.providers.codex]\ntype = \"codex_sdk\"\nmodel = \"gpt-5.5\"\n# Per-machine; set LEARNLOOP_CODEX_CHECKOUT_PATH in ~/.config/learnloop/settings.env.\ncheckout_path = \"\"\nrevision = \"<pinned-commit>\"\nstartup_command = \"\"\nstartup_timeout_seconds = 20\nhealthcheck_timeout_seconds = 5\nauth_mode = \"chatgpt\"\nreasoning_effort = \"medium\"\nreasoning_summary = \"none\"\nsdk_python_path = \"sdk/python/src\"\nsdk_codex_bin = \"\"\nsdk_launch_command = \"\"\nbase_url = \"http://127.0.0.1:8765\"\nhealthcheck_path = \"/health\"\nauthoring_path = \"/authoring-proposal\"\ncanonical_ingest_path = \"/canonical-ingest\"\ngrading_path = \"/grading-proposal\"\n\n[ai.providers.deepseek_flash]\ntype = \"openai_chat\"\nbase_url = \"https://api.deepseek.com\"\napi_key_env = \"DEEPSEEK_API_KEY\"\nmodel = \"deepseek-v4-flash\"\nresponse_format = \"json_object\"\nthinking = \"disabled\"\nmax_tokens = 8192\ntimeout_seconds = 90\n\n[ai.providers.deepseek_pro]\ntype = \"openai_chat\"\nbase_url = \"https://api.deepseek.com\"\napi_key_env = \"DEEPSEEK_API_KEY\"\nmodel = \"deepseek-v4-pro\"\nresponse_format = \"json_object\"\nthinking = \"enabled\"\nreasoning_effort = \"high\"\nmax_tokens = 16384\ntimeout_seconds = 180\n\n[codex]\nprovider = \"sdk\"\n# Per-machine; set LEARNLOOP_CODEX_CHECKOUT_PATH in ~/.config/learnloop/settings.env.\ncheckout_path = \"\"\nrevision = \"<pinned-commit>\"\nstartup_command = \"\"\nstartup_timeout_seconds = 20\nhealthcheck_timeout_seconds = 5\nauth_mode = \"chatgpt\"\nmodel = \"gpt-5.5\"\nreasoning_effort = \"medium\"\nreasoning_summary = \"none\"\nsdk_python_path = \"sdk/python/src\"\nsdk_codex_bin = \"\"\nsdk_launch_command = \"\"\nbase_url = \"http://127.0.0.1:8765\"\nhealthcheck_path = \"/health\"\nauthoring_path = \"/authoring-proposal\"\ncanonical_ingest_path = \"/canonical-ingest\"\ngrading_path = \"/grading-proposal\"\n\n# Family-keyed mastery damage per error type (spec §\"Error-aware updates\").\n# recall_failure is the deterministic attribution for `dont_know` attempts.\n[error_impacts]\nmax_sharpening = 3.0\n\n[error_impacts.recall_failure]\nfamilies = { recall = -0.25 }\nlo_mastery_delta = -0.05\nlocal_severity_gain = 0.8\n\n[error_impacts.scaffold_failure]\nfamilies = { recall = -0.35 }\nlo_mastery_delta = -0.05\nlocal_severity_gain = 1.5\n\n[error_impacts.arithmetic_slip]\nfamilies = { numeric = -0.05 }\nlo_mastery_delta = 0.0\nlocal_severity_gain = 0.35\n\n# Cross-LO propagation gates per error type (spec §\"Error-type gate\").\n[cross_lo_propagation.default]\nmax_depth = 3\nhop_decay = 0.5\ntotal_propagated_weight_cap = 0.7\n\n[cross_lo_propagation.error_gates.recall_failure]\nmean_factor = 0.0 # forgetting a definition is not evidence prereqs are weak\nvariance_factor = 0.25\nscope = \"all\"\n\n[cross_lo_propagation.error_gates.scaffold_failure]\nmean_factor = 0.0\nvariance_factor = 0.35\nscope = \"all\"\n\n[cross_lo_propagation.error_gates.arithmetic_slip]\nmean_factor = 0.0\nvariance_factor = 0.10\nscope = \"all\"\n\n[recall_coverage.severity_examples.first_dont_know]\nattempt_type = \"dont_know\"\nhints_used = 0\ncorrectness = 0.0\nexpected_correctness = 0.65\neffective_coverage = 0.85\nexpected_error_type = \"recall_failure\"\nexpected_severity_band = [0.70, 0.82]\n\n[recall_coverage.severity_examples.second_same_item_dont_know]\nattempt_type = \"dont_know\"\nhints_used = 0\ncorrectness = 0.0\nexpected_correctness = 0.65\neffective_coverage = 0.85\nrecent_same_item_failures = 1\nexpected_error_type = \"recall_failure\"\nexpected_severity_band = [0.95, 1.00]\n\n[recall_coverage.severity_examples.second_same_facet_dont_know]\nattempt_type = \"dont_know\"\nhints_used = 0\ncorrectness = 0.0\nexpected_correctness = 0.65\neffective_coverage = 0.85\nrecent_same_facet_failures = 1\nexpected_error_type = \"recall_failure\"\nexpected_severity_band = [0.80, 1.00]\n\n[recall_coverage.severity_examples.hinted_dont_know]\nattempt_type = \"dont_know\"\nhints_used = 2\ncorrectness = 0.0\nexpected_correctness = 0.65\neffective_coverage = 0.80\nexpected_error_type = \"scaffold_failure\"\nexpected_severity_band = [0.85, 0.95]\n\n[recall_coverage.severity_examples.arithmetic_slip]\nattempt_type = \"independent_attempt\"\ncorrectness = 0.75\nexpected_correctness = 0.70\neffective_coverage = 0.85\ntarget_error_type = \"arithmetic_slip\"\nexpected_error_type = \"arithmetic_slip\"\nexpected_severity_band = [0.25, 0.35]\n\n[recall_coverage.severity_examples.ambiguous_item]\nattempt_type = \"independent_attempt\"\ncorrectness = 0.0\nexpected_correctness = 0.70\neffective_coverage = 0.85\nbad_item_suspicion = 0.70\nexpected_error_type = \"recall_failure\"\nexpected_severity_band = [0.45, 0.75]\n"}, "565100878e11bc9ac281139570040c118fbaf1a5": {"t": 1785750321.49211, "n": 2048, "h": "33ddd866eda3cebc", "c": "schema_version = 1\n\n[storage]\nsqlite_path = \"state.sqlite\"\n\n[algorithms]\nalgorithm_version = \"mvp-0.5\"\n\n[scheduler]\nforgetting_risk_weight = 1.0\nrecent_error_weight = 0.50\nprobe_eig_weight = 0.25\nshort_session_minutes = 20\n# Seeded exploration over near-tie candidates so logged slates carry non-degenerate\n# selection propensities (off-policy learnability). See architecture_pivot.md Stage 0.\nselection_exploration_rate = 0.1\nselection_exploration_reward_window = 0.15\n\n[scheduler.surprise]\ntheta_pos = 1.5\ntheta_neg = 1.5\nalpha_interval = 0.3\nf_min = 0.5\nf_max = 1.5\nepsilon_error_surprise = 0.05\n\n[scheduler.followup]\ntau_followup_nats = 0.3\ngamma_min = 0.5\n\n[mastery]\nbase_observation_variance = 1.0\nsigma2_drift = 0.01\np_max = 4.0\n\n[probe]\nattempts_target_default = 3\nattempts_target_with_strong_claim = 1\nclaim_skip_threshold = 0.75\nvariance_convergence_threshold = 0.10\nhypothesis_set_max_size = 5\n\n[codex]\nprovider = \"sdk\"\ncheckout_path = \"../../../codex\"\nrevision = \"<pinned-commit>\"\nstartup_command = \"\"\nstartup_timeout_seconds = 20\nhealthcheck_timeout_seconds = 5\nauth_mode = \"chatgpt\"\nmodel = \"gpt-5.5\"\nreasoning_effort = \"medium\"\nreasoning_summary = \"none\"\nsdk_python_path = \"sdk/python/src\"\nsdk_codex_bin = \"\"\nsdk_launch_command = \"\"\nbase_url = \"http://127.0.0.1:8765\"\nhealthcheck_path = \"/health\"\ncanonical_ingest_path = \"/canonical-ingest\"\nauthoring_path = \"/authoring-proposal\"\ngrading_path = \"/grading-proposal\"\n\n# Family-keyed mastery damage per error type (spec §\"Error-aware updates\").\n# recall_failure is the deterministic attribution for `dont_know` attempts.\n[error_impacts.recall_failure]\nfamilies = { recall = -0.25 }\nlo_mastery_delta = -0.05\n\n# Cross-LO propagation gates per error type (spec §\"Error-type gate\").\n[cross_lo_propagation.default]\nmax_depth = 3\nhop_decay = 0.5\ntotal_propagated_weight_cap = 0.7\n\n[cross_lo_propagation.error_gates.recall_failure]\nmean_factor = 0.0 # forgetting a definition is not evidence prereqs are weak\nvariance_factor = 0.25\nscope = \"all\"\n"}, "b48c1ee9be4bc2a4ff5612870d8bf38391e7061b": {"t": 1785750322.5545828, "n": 2074, "h": "b7c1460929f4edde", "c": "schema_version = 1\n\n[storage]\nsqlite_path = \"state.sqlite\"\n\n[algorithms]\nalgorithm_version = \"mvp-0.4\"\n\n[scheduler]\nforgetting_risk_weight = 1.0\nactive_goal_weight = 0.35\nrecent_error_weight = 0.50\nprobe_eig_weight = 0.25\nshort_session_minutes = 20\n# Seeded exploration over near-tie candidates so logged slates carry non-degenerate\n# selection propensities (off-policy learnability). See architecture_pivot.md Stage 0.\nselection_exploration_rate = 0.1\nselection_exploration_reward_window = 0.15\n\n[scheduler.surprise]\ntheta_pos = 1.5\ntheta_neg = 1.5\nalpha_interval = 0.3\nf_min = 0.5\nf_max = 1.5\nepsilon_error_surprise = 0.05\n\n[scheduler.followup]\ntau_followup_nats = 0.3\ngamma_min = 0.5\n\n[mastery]\nbase_observation_variance = 1.0\nsigma2_drift = 0.01\np_max = 4.0\n\n[probe]\nattempts_target_default = 3\nattempts_target_with_strong_claim = 1\nclaim_skip_threshold = 0.75\nvariance_convergence_threshold = 0.10\nhypothesis_set_max_size = 5\n\n[codex]\nprovider = \"sdk\"\ncheckout_path = \"../../../codex\"\nrevision = \"<pinned-commit>\"\nstartup_command = \"\"\nstartup_timeout_seconds = 20\nhealthcheck_timeout_seconds = 5\nauth_mode = \"chatgpt\"\nmodel = \"gpt-5.5\"\nreasoning_effort = \"medium\"\nreasoning_summary = \"none\"\nsdk_python_path = \"sdk/python/src\"\nsdk_codex_bin = \"\"\nsdk_launch_command = \"\"\nbase_url = \"http://127.0.0.1:8765\"\nhealthcheck_path = \"/health\"\ncanonical_ingest_path = \"/canonical-ingest\"\nauthoring_path = \"/authoring-proposal\"\ngrading_path = \"/grading-proposal\"\n\n# Family-keyed mastery damage per error type (spec §\"Error-aware updates\").\n# recall_failure is the deterministic attribution for `dont_know` attempts.\n[error_impacts.recall_failure]\nfamilies = { recall = -0.25 }\nlo_mastery_delta = -0.05\n\n# Cross-LO propagation gates per error type (spec §\"Error-type gate\").\n[cross_lo_propagation.default]\nmax_depth = 3\nhop_decay = 0.5\ntotal_propagated_weight_cap = 0.7\n\n[cross_lo_propagation.error_gates.recall_failure]\nmean_factor = 0.0 # forgetting a definition is not evidence prereqs are weak\nvariance_factor = 0.25\nscope = \"all\"\n"}, "a02b11ed403a376167112e21192c7de7692fdf17": {"t": 1785750323.6478581, "n": 2074, "h": "74e46806482c3c79", "c": "schema_version = 1\n\n[storage]\nsqlite_path = \"state.sqlite\"\n\n[algorithms]\nalgorithm_version = \"mvp-0.3\"\n\n[scheduler]\nforgetting_risk_weight = 1.0\nactive_goal_weight = 0.35\nrecent_error_weight = 0.50\nprobe_eig_weight = 0.25\nshort_session_minutes = 20\n# Seeded exploration over near-tie candidates so logged slates carry non-degenerate\n# selection propensities (off-policy learnability). See architecture_pivot.md Stage 0.\nselection_exploration_rate = 0.1\nselection_exploration_reward_window = 0.15\n\n[scheduler.surprise]\ntheta_pos = 1.5\ntheta_neg = 1.5\nalpha_interval = 0.3\nf_min = 0.5\nf_max = 1.5\nepsilon_error_surprise = 0.05\n\n[scheduler.followup]\ntau_followup_nats = 0.3\ngamma_min = 0.5\n\n[mastery]\nbase_observation_variance = 1.0\nsigma2_drift = 0.01\np_max = 4.0\n\n[probe]\nattempts_target_default = 3\nattempts_target_with_strong_claim = 1\nclaim_skip_threshold = 0.75\nvariance_convergence_threshold = 0.10\nhypothesis_set_max_size = 5\n\n[codex]\nprovider = \"sdk\"\ncheckout_path = \"../../../codex\"\nrevision = \"<pinned-commit>\"\nstartup_command = \"\"\nstartup_timeout_seconds = 20\nhealthcheck_timeout_seconds = 5\nauth_mode = \"chatgpt\"\nmodel = \"gpt-5.5\"\nreasoning_effort = \"medium\"\nreasoning_summary = \"none\"\nsdk_python_path = \"sdk/python/src\"\nsdk_codex_bin = \"\"\nsdk_launch_command = \"\"\nbase_url = \"http://127.0.0.1:8765\"\nhealthcheck_path = \"/health\"\ncanonical_ingest_path = \"/canonical-ingest\"\nauthoring_path = \"/authoring-proposal\"\ngrading_path = \"/grading-proposal\"\n\n# Family-keyed mastery damage per error type (spec §\"Error-aware updates\").\n# recall_failure is the deterministic attribution for `dont_know` attempts.\n[error_impacts.recall_failure]\nfamilies = { recall = -0.25 }\nlo_mastery_delta = -0.05\n\n# Cross-LO propagation gates per error type (spec §\"Error-type gate\").\n[cross_lo_propagation.default]\nmax_depth = 3\nhop_decay = 0.5\ntotal_propagated_weight_cap = 0.7\n\n[cross_lo_propagation.error_gates.recall_failure]\nmean_factor = 0.0 # forgetting a definition is not evidence prereqs are weak\nvariance_factor = 0.25\nscope = \"all\"\n"}, "a742f898acd99e0bd5c263aa0e287d013fba7c04": {"t": 1785750324.7625587, "n": 2074, "h": "aa20ae9b50c72970", "c": "schema_version = 1\n\n[storage]\nsqlite_path = \"state.sqlite\"\n\n[algorithms]\nalgorithm_version = \"mvp-0.2\"\n\n[scheduler]\nforgetting_risk_weight = 1.0\nactive_goal_weight = 0.35\nrecent_error_weight = 0.50\nprobe_eig_weight = 0.25\nshort_session_minutes = 20\n# Seeded exploration over near-tie candidates so logged slates carry non-degenerate\n# selection propensities (off-policy learnability). See architecture_pivot.md Stage 0.\nselection_exploration_rate = 0.1\nselection_exploration_reward_window = 0.15\n\n[scheduler.surprise]\ntheta_pos = 1.5\ntheta_neg = 1.5\nalpha_interval = 0.3\nf_min = 0.5\nf_max = 1.5\nepsilon_error_surprise = 0.05\n\n[scheduler.followup]\ntau_followup_nats = 0.3\ngamma_min = 0.5\n\n[mastery]\nbase_observation_variance = 1.0\nsigma2_drift = 0.01\np_max = 4.0\n\n[probe]\nattempts_target_default = 3\nattempts_target_with_strong_claim = 1\nclaim_skip_threshold = 0.75\nvariance_convergence_threshold = 0.10\nhypothesis_set_max_size = 5\n\n[codex]\nprovider = \"sdk\"\ncheckout_path = \"../../../codex\"\nrevision = \"<pinned-commit>\"\nstartup_command = \"\"\nstartup_timeout_seconds = 20\nhealthcheck_timeout_seconds = 5\nauth_mode = \"chatgpt\"\nmodel = \"gpt-5.5\"\nreasoning_effort = \"medium\"\nreasoning_summary = \"none\"\nsdk_python_path = \"sdk/python/src\"\nsdk_codex_bin = \"\"\nsdk_launch_command = \"\"\nbase_url = \"http://127.0.0.1:8765\"\nhealthcheck_path = \"/health\"\ncanonical_ingest_path = \"/canonical-ingest\"\nauthoring_path = \"/authoring-proposal\"\ngrading_path = \"/grading-proposal\"\n\n# Family-keyed mastery damage per error type (spec §\"Error-aware updates\").\n# recall_failure is the deterministic attribution for `dont_know` attempts.\n[error_impacts.recall_failure]\nfamilies = { recall = -0.25 }\nlo_mastery_delta = -0.05\n\n# Cross-LO propagation gates per error type (spec §\"Error-type gate\").\n[cross_lo_propagation.default]\nmax_depth = 3\nhop_decay = 0.5\ntotal_propagated_weight_cap = 0.7\n\n[cross_lo_propagation.error_gates.recall_failure]\nmean_factor = 0.0 # forgetting a definition is not evidence prereqs are weak\nvariance_factor = 0.25\nscope = \"all\"\n"}, "4a28c9635f24945d78366fa26212db7488d82545": {"t": 1785750325.8329592, "n": 1827, "h": "0239277752f60262", "c": "schema_version = 1\n\n[storage]\nsqlite_path = \"state.sqlite\"\n\n[algorithms]\nalgorithm_version = \"mvp-0.2\"\n\n[scheduler]\nforgetting_risk_weight = 1.0\nactive_goal_weight = 0.35\nrecent_error_weight = 0.50\nprobe_eig_weight = 0.25\nshort_session_minutes = 20\n\n[scheduler.surprise]\ntheta_pos = 1.5\ntheta_neg = 1.5\nalpha_interval = 0.3\nf_min = 0.5\nf_max = 1.5\nepsilon_error_surprise = 0.05\n\n[scheduler.followup]\ntau_followup_nats = 0.3\ngamma_min = 0.5\n\n[mastery]\nbase_observation_variance = 1.0\nsigma2_drift = 0.01\np_max = 4.0\n\n[probe]\nattempts_target_default = 3\nattempts_target_with_strong_claim = 1\nclaim_skip_threshold = 0.75\nvariance_convergence_threshold = 0.10\nhypothesis_set_max_size = 5\n\n[codex]\nprovider = \"sdk\"\ncheckout_path = \"../../../codex\"\nrevision = \"<pinned-commit>\"\nstartup_command = \"\"\nstartup_timeout_seconds = 20\nhealthcheck_timeout_seconds = 5\nauth_mode = \"chatgpt\"\nmodel = \"gpt-5.5\"\nreasoning_effort = \"medium\"\nreasoning_summary = \"none\"\nsdk_python_path = \"sdk/python/src\"\nsdk_codex_bin = \"\"\nsdk_launch_command = \"\"\nbase_url = \"http://127.0.0.1:8765\"\nhealthcheck_path = \"/health\"\ncanonical_ingest_path = \"/canonical-ingest\"\nauthoring_path = \"/authoring-proposal\"\ngrading_path = \"/grading-proposal\"\n\n# Family-keyed mastery damage per error type (spec §\"Error-aware updates\").\n# recall_failure is the deterministic attribution for `dont_know` attempts.\n[error_impacts.recall_failure]\nfamilies = { recall = -0.25 }\nlo_mastery_delta = -0.05\n\n# Cross-LO propagation gates per error type (spec §\"Error-type gate\").\n[cross_lo_propagation.default]\nmax_depth = 3\nhop_decay = 0.5\ntotal_propagated_weight_cap = 0.7\n\n[cross_lo_propagation.error_gates.recall_failure]\nmean_factor = 0.0 # forgetting a definition is not evidence prereqs are weak\nvariance_factor = 0.25\nscope = \"all\"\n"}}, "fixtures/probability_v2/learnloop.toml": {"d7f5830f824d7636193af334e950c1d2ffc477c4": {"t": 1785745346.683648, "n": 22765, "h": "8b6ef40db596869f", "c": "schema_version = 1\n\n[storage]\nsqlite_path = \"state.sqlite\"\n\n[algorithms]\n# mvp-0.8: authority-propagation projection (P0.5 cutover, spec §7.2). New vaults\n# start here -- mvp-0.8 is a strict superset of the mvp-0.7 canonical shared-facet\n# knowledge model plus the P0.2/P0.3 calibrated grade channel, robust composition,\n# and reliability-discounted certification. Pre-existing mvp-0.7 vaults activate it\n# via `learnloop upgrade`; pre-existing legacy mvp-0.6 content upgrades to mvp-0.7\n# first. Legacy `probe_<lo_id>` phases recorded under earlier versions replay\n# through the frozen path forever; new diagnostic episodes replay exclusively\n# through probe_observations under the pinned channel snapshot.\nalgorithm_version = \"mvp-0.8\"\n\n# Single source of truth for per-attempt-type evidence (Fable's-take item 3).\n# evidence_mass weights ability-belief updates (mastery EKF / reliability);\n# surface_exposure is the fraction of the item's facet surface the attempt\n# certifies as probed (coverage). surface_exposure defaults to evidence_mass;\n# dont_know overrides it because a confident \"don't know\" fully covers the\n# surface as evidence-of-absence while remaining self-diagnosis, not\n# demonstration.\n[evidence.attempt_types]\nindependent_attempt = { evidence_mass = 1.0 }\nopen_text = { evidence_mass = 1.0 }\ndiagnostic_probe = { evidence_mass = 1.0 }\nhinted_attempt = { evidence_mass = 1.0 }\nreconstruction_after_walkthrough = { evidence_mass = 0.5 }\ndont_know = { evidence_mass = 0.7, surface_exposure = 1.0 }\nself_report = { evidence_mass = 0.3 }\n# Imported past-exam outcome: one exam is one correlated evidence event, so\n# each seeded question carries a fraction of a live independent attempt.\nexam_evidence = { evidence_mass = 0.35 }\n# Held-out practice-exam answer on a fresh, never-practiced item: a proctored\n# fresh-item answer is the highest-quality evidence in the system, so it carries\n# full evidence mass (deliberately unlike the discounted `exam_evidence` import).\nexam_attempt = { evidence_mass = 1.0 }\n# Teach-back conversation graded as one attempt: high-quality generative\n# evidence, but the opening explanation and follow-up answers are one\n# correlated multi-question event, so it carries less than a full independent\n# attempt per facet.\nteach_back = { evidence_mass = 0.8 }\nguided_walkthrough = { evidence_mass = 0.0 }\nskip = { evidence_mass = 0.0 }\n\n# Item-side coverage prior per practice mode: how much of an LO's facet surface\n# an item of this mode can surface when it has no evidence weights or rubric.\n# Not derivable from attempt-type evidence_mass (different question).\n[evidence.item_coverage_by_practice_mode]\nconstructed_response = 0.85\nopen_text = 0.85\nshort_answer = 0.75\ndiagnostic_probe = 0.80\nindependent_attempt = 0.75\nhinted_attempt = 0.65\nmultiple_choice = 0.45\nself_report = 0.25\n\n# Vault-wide evidence correlation lookup (knowledge-model spec §6): discounts\n# for repeated/near-clone/shared-stimulus surfaces once facet state is global.\n# Reserved for KM2; parsed now so vault TOMLs can set values early.\n[evidence.correlation]\n\n# Capability-aware certification budgets (knowledge-model spec §5.4).\n# group_budget defaults to evidence_mass(attempt_type) per correlation group;\n# max_groups_per_attempt caps the attempt-wide certification ceiling.\n[evidence.certification]\nmax_groups_per_attempt = 3\n\n# Blueprint recipe likelihood defaults (knowledge-model spec §9.2): noisy-AND\n# core with slip, plus a guess floor by response format.\n[evidence.blueprints]\nslip = 0.05\n\n[evidence.blueprints.guess_by_format]\nmultiple_choice = 0.25\nconstructed_response = 0.0\n\n[scheduler]\nforgetting_risk_weight = 1.0\n# Goal facet frontier: fraction of an item's evidence facets not yet on track\n# for an active goal (unexamined/known_gap or projected below target_recall\n# at the goal's due date), scaled by goal priority.\ngoal_frontier_weight = 0.25\nrecent_error_weight = 0.50\nprobe_eig_weight = 0.25\n# Goal quota: guaranteed floor share of the queue overlapping the goal\n# frontier; ramps min -> max over the last ramp_days before due_at.\ngoal_quota_floor_min = 0.30\ngoal_quota_floor_max = 0.70\ngoal_quota_ramp_days = 28\nshort_session_minutes = 20\n# Seeded exploration over near-tie candidates so logged slates carry non-degenerate\n# selection propensities (off-policy learnability). See architecture_pivot.md Stage 0.\nselection_exploration_rate = 0.1\nselection_exploration_reward_window = 0.15\n\n[scheduler.surprise]\ntheta_pos = 1.5\ntheta_neg = 1.5\nalpha_interval = 0.3\nf_min = 0.5\nf_max = 1.5\nepsilon_error_surprise = 0.05\n\n[scheduler.followup]\ntau_followup_nats = 0.05\ngamma_min = 0.5\nmin_target_facet_overlap = 0.5\n# Gate modernization: thresholds resolve as quantiles of this learner's own\n# signal history; the absolute values above remain the cold-start fallback.\nthreshold_mode = \"quantile\"\ntau_followup_quantile = 0.85\ntau_severe_error_quantile = 0.90\nquantile_min_samples = 30\nquantile_window = 200\n# gate_mode = \"score\" scores all signals through one logistic (threshold last);\n# \"cascade\" preserves the legacy hard trigger/suppression chain bit-for-bit.\ngate_mode = \"score\"\ngate_score_threshold = 0.5\ngate_subscore_steepness = 12.0\n# Predictive facet EIG (logged-but-inert at weight 0.0; see services/predictive_eig.py).\npredictive_eig_weight = 0.0\npredictive_eig_target_cap = 4\n# Misconception discrimination gate (spec_misconception_diagnostics.md §4.1).\n# tau_discrimination_power is the Youden-J lower bound a diagnostic candidate\n# must clear against an active misconception; require_misconception_discrimination\n# routes to no_suitable_item rather than queueing a non-discriminating paraphrase.\ntau_discrimination_power = 0.3\nrequire_misconception_discrimination = true\n\n# Goal projection: open-ended goals (no due_at) project facet recall at a\n# fixed horizon so the frontier stays defined.\n[goals]\ndefault_projection_horizon_days = 30\n\n[hypothesis]\nsession_card_budget = 2\nclaim_cooldown_days = 7\noverconfidence_min_evidence_mass = 1.0\nreentry_gap_days = 7\ndecay_pressure_target_recall = 0.8\ndecay_pressure_horizon_days = 60\n\n[forecasts]\ndefault_horizon_days = 14\n\n# Automatic misconception resolution (\"close the loop\"): an active error event\n# is resolved once the learning object accumulates N clean attempts after the\n# event was created. Clean = correctness >= auto_resolve_min_correctness, no\n# error attribution written, and not a dont_know/skip self-diagnosis.\n[misconceptions]\nauto_resolve_clean_attempts = 3\nauto_resolve_min_correctness = 0.85\n# Registry-based resolution and the sim discrimination gate\n# (spec_misconception_diagnostics.md §6, §7). Parsed now; consumed in later phases.\ntau_misconception_resolved = 0.15\nsim_gate_min_sensitivity_lb = 0.7\nsim_gate_min_specificity_lb = 0.8\n# 8, not 5: a perfect run over N trials has lower bound 0.25^(1/(N+1)) at the\n# 25th percentile — 0.794 at N=5 (below the 0.8 specificity gate), 0.857 at N=8.\nsim_gate_trials = 8\n# Opt-in codex answers-under-belief pass for the gate. 0 = pure deterministic\n# (no provider tokens). When > 0, codex role-plays that many planted + clean\n# students in ONE call per gate run and their fires combine with the\n# deterministic trials. Costs provider tokens per accepted item; the same N>=8\n# caveat applies (0.25^(1/(N+1)) at the 25th percentile) to the COMBINED counts.\nsim_gate_llm_trials = 0\n\n# Offline parameter fitting from the learner's own logs (`learnloop fit`).\n# Fitted sets live in the fitted_parameters table; defaults apply when none is active.\n[fitting.fsrs]\nmin_reviews = 50\nmin_elapsed_days = 0.5\nl2_lambda = 1.0\nmax_iterations = 300\ninitial_step = 0.05\nmin_relative_improvement = 0.01\n\n[mastery]\nbase_observation_variance = 1.0\nsigma2_drift = 0.01\np_max = 4.0\n# Display banding: > strong renders green, > developing renders amber, else red.\ndisplay_strong_threshold = 0.6\ndisplay_developing_threshold = 0.35\n\n# IRT 2PL difficulty-aware mastery update (spec_irt_difficulty.md §4).\n# enabled = false restores the legacy logit-space Kalman update bit-for-bit.\n[mastery.irt]\nenabled = true\ndiscrimination_default = 1.0\ndifficulty_default = 0.0\ndifficulty_from_prior = true\ndifficulty_prior_scale = 2.5\nb_abs_max = 4.0\np_clip = 1e-4\nmu_abs_max = 5.0\nmax_logit_step = 4.0\n# Empirical-Bayes per-item difficulty posterior (dark by default; see\n# MasteryIRTConfig for the identifiability rationale).\neb_difficulty_enabled = false\nb_prior_variance = 0.25\nb_learning_rate_scale = 0.2\nb_max_step = 0.25\nb_var_min = 0.01\n\n[probe]\n# LEGACY (probe redesign Checkpoint 0.4): attempts_target_default,\n# attempts_target_with_strong_claim, claim_skip_threshold, and\n# variance_convergence_threshold configure only the frozen pre-redesign replay\n# path. Their live roles moved to [probe.episode]: the attempt targets map to\n# minimum/maximum_observations, the strong-claim skip maps to the explicit\n# fast-path policy (fast_path_claim_threshold), and variance convergence is\n# superseded by the §11 completion policy (posterior_stop_threshold).\nattempts_target_default = 3\nattempts_target_with_strong_claim = 1\nclaim_skip_threshold = 0.75\nvariance_convergence_threshold = 0.10\nhypothesis_set_max_size = 5\n\n# Diagnostic episodes (spec_probe_eig_redesign.md §5/§11).\n[probe.episode]\nminimum_independent_observations = 2\nmaximum_observations = 4\nposterior_stop_threshold = 0.85\nambiguity_threshold = 0.30\nopen_set_prior = 0.10\nopen_set_trigger_threshold = 0.35\nhinted_evidence_weight = 0.5\ncontaminated_evidence_weight = 0.3\nself_graded_evidence_weight = 0.3\nsession_qualifying_observation_cap = 4\nfast_path_enabled = true\nfast_path_claim_threshold = 0.75\npresentation_ttl_minutes = 240\n# Predictive EIG per expected time is the diagnostic default objective (§7.4/§7.5)\n# whenever at least predictive_target_minimum held-out instruments exist for the\n# episode; hypothesis EIG remains the fallback and audit signal.\npredictive_selection_enabled = true\npredictive_target_minimum = 2\npredictive_target_cap = 6\nselection_overhead_seconds = 10.0\n# §5.9 fresh-vault onboarding: probes deactivate after this many qualifying\n# observations until ordinary practice has started (0 disables).\nonboarding_practice_ceiling_observations = 4\n# §6.5 re-probe triggers: repeated prediction errors and stale uncertainty.\nreprobe_prediction_error_count = 3\nreprobe_prediction_error_window = 10\nreprobe_predictive_surprise_threshold = 1.0\nreprobe_stale_uncertainty_variance = 0.6\nreprobe_stale_uncertainty_days = 30\n\n# Parameterized instance generation from admitted family/card bindings (§10).\n# llm_surfaces: when an AI provider capable of run_probe_instance_surfaces is\n# wired through, instance surfaces come from the LLM (grounded in the LO,\n# validated by the structural instance gate) and fall back to the parametric\n# templates on provider failure or gate rejection.\n[probe.generation]\ninstances_per_need = 2\nauto_generate_on_entry = false\nllm_surfaces = true\n\n# Short adaptive dialogue microprobes (§8.1): turns within one block share the\n# family's total task evidence mass (§7.7).\n[probe.dialogue]\nplanned_turns = 3\nmax_turns = 4\n\n# Learner-initiated calibration sessions (§5.9): batch episode blocks across a\n# goal scope; lift only the per-session qualifying-observation cap within the\n# declared time budget.\n[probe.calibration]\ndefault_time_budget_minutes = 20\nmax_planned_episodes = 8\ndisagreement_weight = 0.5\n\n# Hierarchical family -> item shrinkage (§9.7, Checkpoint 4.2): item rows shrink\n# toward the family-version posterior with this much family-equivalent mass.\n[probe.hierarchy]\nitem_shrinkage_pseudo_count = 25.0\n\n# Family-version lifecycle gates (§9.7, Checkpoint 4.7). Trust requires\n# real-learner evidence; synthetic gate statistics never qualify a family.\n[probe.lifecycle]\ntrust_minimum_real_sample = 20\ntrust_minimum_regrade_checks = 5\ntrust_minimum_regrade_agreement = 0.80\ntrust_maximum_negative_information_rate = 0.20\nretire_minimum_sample = 10\nretire_negative_information_rate = 0.50\nretire_regrade_agreement_floor = 0.50\n\n# Shadow-mode alternative selection policies (§13.3, Checkpoint 5.1): log-only\n# rankings on the committed presentation. Off-policy estimation stays on hold\n# for single-learner vaults.\n[probe.shadow]\nenabled = true\ntop_k = 3\n\n# Precommitted diagnostic blocks (Checkpoint 5.2/5.3): redundancy penalty is a\n# separate ranking component (never labeled EIG); joint greedy conditional EIG\n# applies only to blocks committed before answers are observed.\n[probe.block]\nfamily_redundancy_penalty = 0.6\nmax_block_size = 4\nconditional_branch_cap = 3\n# §5.6/§5.7: sequential probes run the block-end hook after this many\n# observations in the current state segment.\ndefault_block_observations = 2\n\n# IRT difficulty-aware probe conditionals (spec_irt_difficulty.md §5).\n[probe.irt]\ntheta_mastered = 2.0\ntheta_unfamiliar = -2.0\ncut_mid = -1.0\ncut_high = 1.0\nunfamiliar_error_leak = 0.20\nerr_low_frac = 0.80\nerr_mid_frac = 0.50\n\n# Learner self-attributed misconception probe coverage (spec_irt_difficulty.md §12).\n[probe.self_tag]\nw_base = 0.5\nw_max = 0.7\ntarget_degree = 2.0\npromotion_threshold = 3\n\n# Exam seeding (`learnloop ingest-exam` + `learnloop seed-exam-attempts`):\n# imported per-question outcomes become backdated exam_evidence attempts.\n# grader_confidence is the reliability discount persisted on seeded attempts;\n# default_learner_confidence (1-5) is used when an outcome omits confidence.\n[exam_seeding]\ngrader_confidence = 0.7\ndefault_learner_confidence = 3\n\n# Tutor Q&A (\"ask\"): question limits per context (practice: per item+session,\n# feedback: per attempt, library: per note per day) and the read-side\n# uncertainty bump applied for recent unresolved questions about a facet.\n[tutor_qa]\nmax_questions_practice = 3\nmax_questions_feedback = 5\nmax_questions_library = 8\nmax_questions_reader = 8\nreader_enabled = true\napply_uncertainty_effect = true\nuncertainty_evidence_mass = 0.15\n\n# Promoting Socratic tutor questions to practice items / learning objects.\n# Gap route: a \"this exposed a gap\" promotion writes a low self-report claim\n# (gap_claim_level at gap_claim_pseudo_count pseudo-observations) and counts as\n# an unresolved-question observation with its own likelihood slot fit from the\n# learner's gap-declaration -> failure lift, falling back to\n# gap_declaration_solid_likelihood_ratio below gap_declaration_likelihood_min_samples.\n# The filed need goes stale after gap_need_ttl_days; requested_items_per_session\n# bounds the scheduler floor for promoted-but-unattempted items.\n[tutor_promotion]\ngap_claim_level = 0.25\ngap_claim_pseudo_count = 2.0\ngap_declaration_solid_likelihood_ratio = 0.35\ngap_declaration_likelihood_min_samples = 12\ngap_need_ttl_days = 21\nrequested_items_per_session = 1\n\n# Teach-back conversations: the learner explains, an AI naive student asks up\n# to max_followups questions (one per rubric criterion, uncertainty-ranked with\n# transfer escalation), and the transcript is graded as one attempt.\n# transfer_evidence_multiplier symmetrically discounts the evidence mass of\n# transfer-tier criterion evidence; session_cap bounds teach_back items per\n# built queue.\n[teach_back]\nmax_followups = 4\ntransfer_evidence_multiplier = 0.5\nsession_cap = 1\n\n[ingest]\nwindow_char_cap = 150000\nmin_content_chars = 400\ndefault_goal_priority = 0.5\nallow_auto_captions = false\n\n# PDF extraction for canonical sources (textbook chapters, past exams, any\n# ingested .pdf). engine \"auto\" uses marker-pdf (structured Markdown with\n# headings, tables, LaTeX math, and OCR for scanned pages) when installed\n# (`pip install learnloop[pdf]`), falling back to plain pypdf text extraction.\n# use_llm adds marker's VLM boost for difficult scans and dense math: hard\n# regions are sent to an OpenAI-compatible endpoint -- e.g. a local vLLM\n# serving deepseek-ai/DeepSeek-OCR (llm_base_url = \"http://127.0.0.1:8000/v1\",\n# llm_model = \"deepseek-ai/DeepSeek-OCR\") or any hosted vision model. The API\n# key is read from the env var named by llm_api_key_env. Marker conversions\n# are cached under .learnloop/source-cache/pdf/ keyed by file bytes + config.\n[ingest.pdf]\nengine = \"auto\"\n# \"\" = auto-detect (GPU when the installed torch supports it); pin with\n# \"cuda\", \"cuda:1\", \"cpu\", or \"mps\" to override.\ntorch_device = \"\"\nforce_ocr = false\nuse_llm = false\nllm_service = \"marker.services.openai.OpenAIService\"\nllm_base_url = \"\"\nllm_model = \"\"\nllm_api_key_env = \"LEARNLOOP_PDF_LLM_API_KEY\"\n\n# Per-stage token budgets for ingestion v2 (source-ingestion spec §3.1).\n# Preflight/build-plan estimates read these; a stage exceeding its ceiling\n# shards or pauses for narrower scope — it never silently truncates.\n[ingest.budgets]\ninventory_input_tokens = 20000\ninventory_output_tokens = 3000\nsynthesis_shard_input_tokens = 40000\nsynthesis_shard_output_tokens = 10000\nevidence_span_input_tokens = 12000\nsynthesis_total_input_ceiling = 48000\nsynthesis_output_tokens = 16000\nappend_neighborhood_input_tokens = 24000\nappend_output_tokens = 10000\n# Span-request protocol caps (§8.5): one bounded request round only.\nsynthesis_span_request_max_count = 12\nsynthesis_span_char_cap = 4000\n# Quick add (§1): ToC-guided relevant-scope cap.\nquick_add_scope_input_tokens = 40000\n\n# Per-provider context/output limits consulted by preflight, keyed by the\n# [ai.providers.<name>] entries (source-ingestion spec §3.1), e.g.\n# [ingest.providers.codex] context_tokens / max_output_tokens.\n\n# Durable ingest-queue worker settings (source-ingestion spec §6.2). One worker\n# (sidecar background loop or foreground CLI) drains queued jobs at a time under\n# a single lease; a running lease older than lease_ttl_seconds is recovered to\n# failed(interrupted) on startup and its queued siblings resume.\n[ingest.runner]\nlease_ttl_seconds = 120\nheartbeat_interval_seconds = 15\npoll_interval_seconds = 1.0\n\n[ai]\nactive_provider = \"codex\"\nfallback_provider = \"\"\ntimeout_seconds = 60\n\n[ai.routing]\ngrading = \"codex_low\"\ncanonical_ingest = \"codex_medium\"\ncanonical_ingest_retry = \"codex_medium\"\nauthoring = \"codex_medium\"\ntutor_qa = \"codex_low\"\nteach_back = \"codex_low\"\n\n[ai.providers.codex]\ntype = \"codex_sdk\"\nmodel = \"gpt-5.6-sol\"\n# Per-machine; set LEARNLOOP_CODEX_CHECKOUT_PATH in ~/.config/learnloop/settings.env.\ncheckout_path = \"\"\nrevision = \"<pinned-commit>\"\nstartup_command = \"\"\nstartup_timeout_seconds = 20\nhealthcheck_timeout_seconds = 5\nauth_mode = \"chatgpt\"\nreasoning_effort = \"low\"\nreasoning_summary = \"none\"\nsdk_python_path = \"sdk/python/src\"\nsdk_codex_bin = \"\"\nsdk_launch_command = \"\"\nbase_url = \"http://127.0.0.1:8765\"\nhealthcheck_path = \"/health\"\nauthoring_path = \"/authoring-proposal\"\ncanonical_ingest_path = \"/canonical-ingest\"\ngrading_path = \"/grading-proposal\"\nmisconception_match_path = \"/misconception-match\"\n\n[ai.providers.deepseek_flash]\ntype = \"openai_chat\"\nbase_url = \"https://api.deepseek.com\"\napi_key_env = \"DEEPSEEK_API_KEY\"\nmodel = \"deepseek-v4-flash\"\nresponse_format = \"json_object\"\nthinking = \"disabled\"\nmax_tokens = 8192\ntimeout_seconds = 90\n\n[ai.providers.deepseek_pro]\ntype = \"openai_chat\"\nbase_url = \"https://api.deepseek.com\"\napi_key_env = \"DEEPSEEK_API_KEY\"\nmodel = \"deepseek-v4-pro\"\nresponse_format = \"json_object\"\nthinking = \"enabled\"\nreasoning_effort = \"high\"\nmax_tokens = 16384\ntimeout_seconds = 180\n\n[codex]\nprovider = \"sdk\"\n# Per-machine; set LEARNLOOP_CODEX_CHECKOUT_PATH in ~/.config/learnloop/settings.env.\ncheckout_path = \"\"\nrevision = \"<pinned-commit>\"\nstartup_command = \"\"\nstartup_timeout_seconds = 20\nhealthcheck_timeout_seconds = 5\nauth_mode = \"chatgpt\"\nmodel = \"gpt-5.6-sol\"\nreasoning_effort = \"low\"\nreasoning_summary = \"none\"\nsdk_python_path = \"sdk/python/src\"\nsdk_codex_bin = \"\"\nsdk_launch_command = \"\"\nbase_url = \"http://127.0.0.1:8765\"\nhealthcheck_path = \"/health\"\nauthoring_path = \"/authoring-proposal\"\ncanonical_ingest_path = \"/canonical-ingest\"\ngrading_path = \"/grading-proposal\"\nmisconception_match_path = \"/misconception-match\"\n\n# Family-keyed mastery damage per error type (spec §\"Error-aware updates\").\n# recall_failure is the deterministic attribution for `dont_know` attempts.\n[error_impacts]\nmax_sharpening = 3.0\n\n[error_impacts.recall_failure]\nfamilies = { recall = -0.25 }\nlo_mastery_delta = -0.05\nlocal_severity_gain = 0.8\n\n[error_impacts.scaffold_failure]\nfamilies = { recall = -0.35 }\nlo_mastery_delta = -0.05\nlocal_severity_gain = 1.5\n\n[error_impacts.arithmetic_slip]\nfamilies = { numeric = -0.05 }\nlo_mastery_delta = 0.0\nlocal_severity_gain = 0.35\n\n# Capability damping/shrinkage for shared-parent facet belief (knowledge-model\n# spec §4.2). Reserved for KM2+; residual activation ships default-off.\n[capabilities]\n\n# Identity-lock policy (knowledge-model spec §3.4): a facet's semantic identity\n# locks at direct evidence in >=2 distinct surface/correlation groups, at\n# facet_lock_mass independent evidence mass, or on entering an active goal's\n# certified scope — whichever comes first.\n[locks]\nfacet_lock_mass = 2.0\nfacet_surface_groups = 2\n\n# NOTE: [cross_lo_propagation] is retired (knowledge-model §8.3/§15). The LO-to-LO\n# graph-propagated prior is prerequisite-only, direction-respecting, and\n# shadow/diagnostic-only; its error_gates were dormant. `learnloop doctor` warns\n# when a vault TOML still declares the block.\n\n[recall_coverage.severity_examples.first_dont_know]\nattempt_type = \"dont_know\"\nhints_used = 0\ncorrectness = 0.0\nexpected_correctness = 0.65\neffective_coverage = 0.85\nexpected_error_type = \"recall_failure\"\nexpected_severity_band = [0.70, 0.82]\n\n[recall_coverage.severity_examples.second_same_item_dont_know]\nattempt_type = \"dont_know\"\nhints_used = 0\ncorrectness = 0.0\nexpected_correctness = 0.65\neffective_coverage = 0.85\nrecent_same_item_failures = 1\nexpected_error_type = \"recall_failure\"\nexpected_severity_band = [0.95, 1.00]\n\n[recall_coverage.severity_examples.second_same_facet_dont_know]\nattempt_type = \"dont_know\"\nhints_used = 0\ncorrectness = 0.0\nexpected_correctness = 0.65\neffective_coverage = 0.85\nrecent_same_facet_failures = 1\nexpected_error_type = \"recall_failure\"\nexpected_severity_band = [0.80, 1.00]\n\n[recall_coverage.severity_examples.hinted_dont_know]\nattempt_type = \"dont_know\"\nhints_used = 2\ncorrectness = 0.0\nexpected_correctness = 0.65\neffective_coverage = 0.80\nexpected_error_type = \"scaffold_failure\"\nexpected_severity_band = [0.85, 0.95]\n\n[recall_coverage.severity_examples.arithmetic_slip]\nattempt_type = \"independent_attempt\"\ncorrectness = 0.75\nexpected_correctness = 0.70\neffective_coverage = 0.85\ntarget_error_type = \"arithmetic_slip\"\nexpected_error_type = \"arithmetic_slip\"\nexpected_severity_band = [0.25, 0.35]\n\n[recall_coverage.severity_examples.ambiguous_item]\nattempt_type = \"independent_attempt\"\ncorrectness = 0.0\nexpected_correctness = 0.70\neffective_coverage = 0.85\nbad_item_suspicion = 0.70\nexpected_error_type = \"recall_failure\"\nexpected_severity_band = [0.45, 0.75]\n"}, "1c72cbabade1a4be2d2f4d18b22d1cf0ac171657": {"t": 1785750321.4307013, "n": 22765, "h": "8b6ef40db596869f", "c": "schema_version = 1\n\n[storage]\nsqlite_path = \"state.sqlite\"\n\n[algorithms]\n# mvp-0.8: authority-propagation projection (P0.5 cutover, spec §7.2). New vaults\n# start here -- mvp-0.8 is a strict superset of the mvp-0.7 canonical shared-facet\n# knowledge model plus the P0.2/P0.3 calibrated grade channel, robust composition,\n# and reliability-discounted certification. Pre-existing mvp-0.7 vaults activate it\n# via `learnloop upgrade`; pre-existing legacy mvp-0.6 content upgrades to mvp-0.7\n# first. Legacy `probe_<lo_id>` phases recorded under earlier versions replay\n# through the frozen path forever; new diagnostic episodes replay exclusively\n# through probe_observations under the pinned channel snapshot.\nalgorithm_version = \"mvp-0.8\"\n\n# Single source of truth for per-attempt-type evidence (Fable's-take item 3).\n# evidence_mass weights ability-belief updates (mastery EKF / reliability);\n# surface_exposure is the fraction of the item's facet surface the attempt\n# certifies as probed (coverage). surface_exposure defaults to evidence_mass;\n# dont_know overrides it because a confident \"don't know\" fully covers the\n# surface as evidence-of-absence while remaining self-diagnosis, not\n# demonstration.\n[evidence.attempt_types]\nindependent_attempt = { evidence_mass = 1.0 }\nopen_text = { evidence_mass = 1.0 }\ndiagnostic_probe = { evidence_mass = 1.0 }\nhinted_attempt = { evidence_mass = 1.0 }\nreconstruction_after_walkthrough = { evidence_mass = 0.5 }\ndont_know = { evidence_mass = 0.7, surface_exposure = 1.0 }\nself_report = { evidence_mass = 0.3 }\n# Imported past-exam outcome: one exam is one correlated evidence event, so\n# each seeded question carries a fraction of a live independent attempt.\nexam_evidence = { evidence_mass = 0.35 }\n# Held-out practice-exam answer on a fresh, never-practiced item: a proctored\n# fresh-item answer is the highest-quality evidence in the system, so it carries\n# full evidence mass (deliberately unlike the discounted `exam_evidence` import).\nexam_attempt = { evidence_mass = 1.0 }\n# Teach-back conversation graded as one attempt: high-quality generative\n# evidence, but the opening explanation and follow-up answers are one\n# correlated multi-question event, so it carries less than a full independent\n# attempt per facet.\nteach_back = { evidence_mass = 0.8 }\nguided_walkthrough = { evidence_mass = 0.0 }\nskip = { evidence_mass = 0.0 }\n\n# Item-side coverage prior per practice mode: how much of an LO's facet surface\n# an item of this mode can surface when it has no evidence weights or rubric.\n# Not derivable from attempt-type evidence_mass (different question).\n[evidence.item_coverage_by_practice_mode]\nconstructed_response = 0.85\nopen_text = 0.85\nshort_answer = 0.75\ndiagnostic_probe = 0.80\nindependent_attempt = 0.75\nhinted_attempt = 0.65\nmultiple_choice = 0.45\nself_report = 0.25\n\n# Vault-wide evidence correlation lookup (knowledge-model spec §6): discounts\n# for repeated/near-clone/shared-stimulus surfaces once facet state is global.\n# Reserved for KM2; parsed now so vault TOMLs can set values early.\n[evidence.correlation]\n\n# Capability-aware certification budgets (knowledge-model spec §5.4).\n# group_budget defaults to evidence_mass(attempt_type) per correlation group;\n# max_groups_per_attempt caps the attempt-wide certification ceiling.\n[evidence.certification]\nmax_groups_per_attempt = 3\n\n# Blueprint recipe likelihood defaults (knowledge-model spec §9.2): noisy-AND\n# core with slip, plus a guess floor by response format.\n[evidence.blueprints]\nslip = 0.05\n\n[evidence.blueprints.guess_by_format]\nmultiple_choice = 0.25\nconstructed_response = 0.0\n\n[scheduler]\nforgetting_risk_weight = 1.0\n# Goal facet frontier: fraction of an item's evidence facets not yet on track\n# for an active goal (unexamined/known_gap or projected below target_recall\n# at the goal's due date), scaled by goal priority.\ngoal_frontier_weight = 0.25\nrecent_error_weight = 0.50\nprobe_eig_weight = 0.25\n# Goal quota: guaranteed floor share of the queue overlapping the goal\n# frontier; ramps min -> max over the last ramp_days before due_at.\ngoal_quota_floor_min = 0.30\ngoal_quota_floor_max = 0.70\ngoal_quota_ramp_days = 28\nshort_session_minutes = 20\n# Seeded exploration over near-tie candidates so logged slates carry non-degenerate\n# selection propensities (off-policy learnability). See architecture_pivot.md Stage 0.\nselection_exploration_rate = 0.1\nselection_exploration_reward_window = 0.15\n\n[scheduler.surprise]\ntheta_pos = 1.5\ntheta_neg = 1.5\nalpha_interval = 0.3\nf_min = 0.5\nf_max = 1.5\nepsilon_error_surprise = 0.05\n\n[scheduler.followup]\ntau_followup_nats = 0.05\ngamma_min = 0.5\nmin_target_facet_overlap = 0.5\n# Gate modernization: thresholds resolve as quantiles of this learner's own\n# signal history; the absolute values above remain the cold-start fallback.\nthreshold_mode = \"quantile\"\ntau_followup_quantile = 0.85\ntau_severe_error_quantile = 0.90\nquantile_min_samples = 30\nquantile_window = 200\n# gate_mode = \"score\" scores all signals through one logistic (threshold last);\n# \"cascade\" preserves the legacy hard trigger/suppression chain bit-for-bit.\ngate_mode = \"score\"\ngate_score_threshold = 0.5\ngate_subscore_steepness = 12.0\n# Predictive facet EIG (logged-but-inert at weight 0.0; see services/predictive_eig.py).\npredictive_eig_weight = 0.0\npredictive_eig_target_cap = 4\n# Misconception discrimination gate (spec_misconception_diagnostics.md §4.1).\n# tau_discrimination_power is the Youden-J lower bound a diagnostic candidate\n# must clear against an active misconception; require_misconception_discrimination\n# routes to no_suitable_item rather than queueing a non-discriminating paraphrase.\ntau_discrimination_power = 0.3\nrequire_misconception_discrimination = true\n\n# Goal projection: open-ended goals (no due_at) project facet recall at a\n# fixed horizon so the frontier stays defined.\n[goals]\ndefault_projection_horizon_days = 30\n\n[hypothesis]\nsession_card_budget = 2\nclaim_cooldown_days = 7\noverconfidence_min_evidence_mass = 1.0\nreentry_gap_days = 7\ndecay_pressure_target_recall = 0.8\ndecay_pressure_horizon_days = 60\n\n[forecasts]\ndefault_horizon_days = 14\n\n# Automatic misconception resolution (\"close the loop\"): an active error event\n# is resolved once the learning object accumulates N clean attempts after the\n# event was created. Clean = correctness >= auto_resolve_min_correctness, no\n# error attribution written, and not a dont_know/skip self-diagnosis.\n[misconceptions]\nauto_resolve_clean_attempts = 3\nauto_resolve_min_correctness = 0.85\n# Registry-based resolution and the sim discrimination gate\n# (spec_misconception_diagnostics.md §6, §7). Parsed now; consumed in later phases.\ntau_misconception_resolved = 0.15\nsim_gate_min_sensitivity_lb = 0.7\nsim_gate_min_specificity_lb = 0.8\n# 8, not 5: a perfect run over N trials has lower bound 0.25^(1/(N+1)) at the\n# 25th percentile — 0.794 at N=5 (below the 0.8 specificity gate), 0.857 at N=8.\nsim_gate_trials = 8\n# Opt-in codex answers-under-belief pass for the gate. 0 = pure deterministic\n# (no provider tokens). When > 0, codex role-plays that many planted + clean\n# students in ONE call per gate run and their fires combine with the\n# deterministic trials. Costs provider tokens per accepted item; the same N>=8\n# caveat applies (0.25^(1/(N+1)) at the 25th percentile) to the COMBINED counts.\nsim_gate_llm_trials = 0\n\n# Offline parameter fitting from the learner's own logs (`learnloop fit`).\n# Fitted sets live in the fitted_parameters table; defaults apply when none is active.\n[fitting.fsrs]\nmin_reviews = 50\nmin_elapsed_days = 0.5\nl2_lambda = 1.0\nmax_iterations = 300\ninitial_step = 0.05\nmin_relative_improvement = 0.01\n\n[mastery]\nbase_observation_variance = 1.0\nsigma2_drift = 0.01\np_max = 4.0\n# Display banding: > strong renders green, > developing renders amber, else red.\ndisplay_strong_threshold = 0.6\ndisplay_developing_threshold = 0.35\n\n# IRT 2PL difficulty-aware mastery update (spec_irt_difficulty.md §4).\n# enabled = false restores the legacy logit-space Kalman update bit-for-bit.\n[mastery.irt]\nenabled = true\ndiscrimination_default = 1.0\ndifficulty_default = 0.0\ndifficulty_from_prior = true\ndifficulty_prior_scale = 2.5\nb_abs_max = 4.0\np_clip = 1e-4\nmu_abs_max = 5.0\nmax_logit_step = 4.0\n# Empirical-Bayes per-item difficulty posterior (dark by default; see\n# MasteryIRTConfig for the identifiability rationale).\neb_difficulty_enabled = false\nb_prior_variance = 0.25\nb_learning_rate_scale = 0.2\nb_max_step = 0.25\nb_var_min = 0.01\n\n[probe]\n# LEGACY (probe redesign Checkpoint 0.4): attempts_target_default,\n# attempts_target_with_strong_claim, claim_skip_threshold, and\n# variance_convergence_threshold configure only the frozen pre-redesign replay\n# path. Their live roles moved to [probe.episode]: the attempt targets map to\n# minimum/maximum_observations, the strong-claim skip maps to the explicit\n# fast-path policy (fast_path_claim_threshold), and variance convergence is\n# superseded by the §11 completion policy (posterior_stop_threshold).\nattempts_target_default = 3\nattempts_target_with_strong_claim = 1\nclaim_skip_threshold = 0.75\nvariance_convergence_threshold = 0.10\nhypothesis_set_max_size = 5\n\n# Diagnostic episodes (spec_probe_eig_redesign.md §5/§11).\n[probe.episode]\nminimum_independent_observations = 2\nmaximum_observations = 4\nposterior_stop_threshold = 0.85\nambiguity_threshold = 0.30\nopen_set_prior = 0.10\nopen_set_trigger_threshold = 0.35\nhinted_evidence_weight = 0.5\ncontaminated_evidence_weight = 0.3\nself_graded_evidence_weight = 0.3\nsession_qualifying_observation_cap = 4\nfast_path_enabled = true\nfast_path_claim_threshold = 0.75\npresentation_ttl_minutes = 240\n# Predictive EIG per expected time is the diagnostic default objective (§7.4/§7.5)\n# whenever at least predictive_target_minimum held-out instruments exist for the\n# episode; hypothesis EIG remains the fallback and audit signal.\npredictive_selection_enabled = true\npredictive_target_minimum = 2\npredictive_target_cap = 6\nselection_overhead_seconds = 10.0\n# §5.9 fresh-vault onboarding: probes deactivate after this many qualifying\n# observations until ordinary practice has started (0 disables).\nonboarding_practice_ceiling_observations = 4\n# §6.5 re-probe triggers: repeated prediction errors and stale uncertainty.\nreprobe_prediction_error_count = 3\nreprobe_prediction_error_window = 10\nreprobe_predictive_surprise_threshold = 1.0\nreprobe_stale_uncertainty_variance = 0.6\nreprobe_stale_uncertainty_days = 30\n\n# Parameterized instance generation from admitted family/card bindings (§10).\n# llm_surfaces: when an AI provider capable of run_probe_instance_surfaces is\n# wired through, instance surfaces come from the LLM (grounded in the LO,\n# validated by the structural instance gate) and fall back to the parametric\n# templates on provider failure or gate rejection.\n[probe.generation]\ninstances_per_need = 2\nauto_generate_on_entry = false\nllm_surfaces = true\n\n# Short adaptive dialogue microprobes (§8.1): turns within one block share the\n# family's total task evidence mass (§7.7).\n[probe.dialogue]\nplanned_turns = 3\nmax_turns = 4\n\n# Learner-initiated calibration sessions (§5.9): batch episode blocks across a\n# goal scope; lift only the per-session qualifying-observation cap within the\n# declared time budget.\n[probe.calibration]\ndefault_time_budget_minutes = 20\nmax_planned_episodes = 8\ndisagreement_weight = 0.5\n\n# Hierarchical family -> item shrinkage (§9.7, Checkpoint 4.2): item rows shrink\n# toward the family-version posterior with this much family-equivalent mass.\n[probe.hierarchy]\nitem_shrinkage_pseudo_count = 25.0\n\n# Family-version lifecycle gates (§9.7, Checkpoint 4.7). Trust requires\n# real-learner evidence; synthetic gate statistics never qualify a family.\n[probe.lifecycle]\ntrust_minimum_real_sample = 20\ntrust_minimum_regrade_checks = 5\ntrust_minimum_regrade_agreement = 0.80\ntrust_maximum_negative_information_rate = 0.20\nretire_minimum_sample = 10\nretire_negative_information_rate = 0.50\nretire_regrade_agreement_floor = 0.50\n\n# Shadow-mode alternative selection policies (§13.3, Checkpoint 5.1): log-only\n# rankings on the committed presentation. Off-policy estimation stays on hold\n# for single-learner vaults.\n[probe.shadow]\nenabled = true\ntop_k = 3\n\n# Precommitted diagnostic blocks (Checkpoint 5.2/5.3): redundancy penalty is a\n# separate ranking component (never labeled EIG); joint greedy conditional EIG\n# applies only to blocks committed before answers are observed.\n[probe.block]\nfamily_redundancy_penalty = 0.6\nmax_block_size = 4\nconditional_branch_cap = 3\n# §5.6/§5.7: sequential probes run the block-end hook after this many\n# observations in the current state segment.\ndefault_block_observations = 2\n\n# IRT difficulty-aware probe conditionals (spec_irt_difficulty.md §5).\n[probe.irt]\ntheta_mastered = 2.0\ntheta_unfamiliar = -2.0\ncut_mid = -1.0\ncut_high = 1.0\nunfamiliar_error_leak = 0.20\nerr_low_frac = 0.80\nerr_mid_frac = 0.50\n\n# Learner self-attributed misconception probe coverage (spec_irt_difficulty.md §12).\n[probe.self_tag]\nw_base = 0.5\nw_max = 0.7\ntarget_degree = 2.0\npromotion_threshold = 3\n\n# Exam seeding (`learnloop ingest-exam` + `learnloop seed-exam-attempts`):\n# imported per-question outcomes become backdated exam_evidence attempts.\n# grader_confidence is the reliability discount persisted on seeded attempts;\n# default_learner_confidence (1-5) is used when an outcome omits confidence.\n[exam_seeding]\ngrader_confidence = 0.7\ndefault_learner_confidence = 3\n\n# Tutor Q&A (\"ask\"): question limits per context (practice: per item+session,\n# feedback: per attempt, library: per note per day) and the read-side\n# uncertainty bump applied for recent unresolved questions about a facet.\n[tutor_qa]\nmax_questions_practice = 3\nmax_questions_feedback = 5\nmax_questions_library = 8\nmax_questions_reader = 8\nreader_enabled = true\napply_uncertainty_effect = true\nuncertainty_evidence_mass = 0.15\n\n# Promoting Socratic tutor questions to practice items / learning objects.\n# Gap route: a \"this exposed a gap\" promotion writes a low self-report claim\n# (gap_claim_level at gap_claim_pseudo_count pseudo-observations) and counts as\n# an unresolved-question observation with its own likelihood slot fit from the\n# learner's gap-declaration -> failure lift, falling back to\n# gap_declaration_solid_likelihood_ratio below gap_declaration_likelihood_min_samples.\n# The filed need goes stale after gap_need_ttl_days; requested_items_per_session\n# bounds the scheduler floor for promoted-but-unattempted items.\n[tutor_promotion]\ngap_claim_level = 0.25\ngap_claim_pseudo_count = 2.0\ngap_declaration_solid_likelihood_ratio = 0.35\ngap_declaration_likelihood_min_samples = 12\ngap_need_ttl_days = 21\nrequested_items_per_session = 1\n\n# Teach-back conversations: the learner explains, an AI naive student asks up\n# to max_followups questions (one per rubric criterion, uncertainty-ranked with\n# transfer escalation), and the transcript is graded as one attempt.\n# transfer_evidence_multiplier symmetrically discounts the evidence mass of\n# transfer-tier criterion evidence; session_cap bounds teach_back items per\n# built queue.\n[teach_back]\nmax_followups = 4\ntransfer_evidence_multiplier = 0.5\nsession_cap = 1\n\n[ingest]\nwindow_char_cap = 150000\nmin_content_chars = 400\ndefault_goal_priority = 0.5\nallow_auto_captions = false\n\n# PDF extraction for canonical sources (textbook chapters, past exams, any\n# ingested .pdf). engine \"auto\" uses marker-pdf (structured Markdown with\n# headings, tables, LaTeX math, and OCR for scanned pages) when installed\n# (`pip install learnloop[pdf]`), falling back to plain pypdf text extraction.\n# use_llm adds marker's VLM boost for difficult scans and dense math: hard\n# regions are sent to an OpenAI-compatible endpoint -- e.g. a local vLLM\n# serving deepseek-ai/DeepSeek-OCR (llm_base_url = \"http://127.0.0.1:8000/v1\",\n# llm_model = \"deepseek-ai/DeepSeek-OCR\") or any hosted vision model. The API\n# key is read from the env var named by llm_api_key_env. Marker conversions\n# are cached under .learnloop/source-cache/pdf/ keyed by file bytes + config.\n[ingest.pdf]\nengine = \"auto\"\n# \"\" = auto-detect (GPU when the installed torch supports it); pin with\n# \"cuda\", \"cuda:1\", \"cpu\", or \"mps\" to override.\ntorch_device = \"\"\nforce_ocr = false\nuse_llm = false\nllm_service = \"marker.services.openai.OpenAIService\"\nllm_base_url = \"\"\nllm_model = \"\"\nllm_api_key_env = \"LEARNLOOP_PDF_LLM_API_KEY\"\n\n# Per-stage token budgets for ingestion v2 (source-ingestion spec §3.1).\n# Preflight/build-plan estimates read these; a stage exceeding its ceiling\n# shards or pauses for narrower scope — it never silently truncates.\n[ingest.budgets]\ninventory_input_tokens = 20000\ninventory_output_tokens = 3000\nsynthesis_shard_input_tokens = 40000\nsynthesis_shard_output_tokens = 10000\nevidence_span_input_tokens = 12000\nsynthesis_total_input_ceiling = 48000\nsynthesis_output_tokens = 16000\nappend_neighborhood_input_tokens = 24000\nappend_output_tokens = 10000\n# Span-request protocol caps (§8.5): one bounded request round only.\nsynthesis_span_request_max_count = 12\nsynthesis_span_char_cap = 4000\n# Quick add (§1): ToC-guided relevant-scope cap.\nquick_add_scope_input_tokens = 40000\n\n# Per-provider context/output limits consulted by preflight, keyed by the\n# [ai.providers.<name>] entries (source-ingestion spec §3.1), e.g.\n# [ingest.providers.codex] context_tokens / max_output_tokens.\n\n# Durable ingest-queue worker settings (source-ingestion spec §6.2). One worker\n# (sidecar background loop or foreground CLI) drains queued jobs at a time under\n# a single lease; a running lease older than lease_ttl_seconds is recovered to\n# failed(interrupted) on startup and its queued siblings resume.\n[ingest.runner]\nlease_ttl_seconds = 120\nheartbeat_interval_seconds = 15\npoll_interval_seconds = 1.0\n\n[ai]\nactive_provider = \"codex\"\nfallback_provider = \"\"\ntimeout_seconds = 60\n\n[ai.routing]\ngrading = \"codex_low\"\ncanonical_ingest = \"codex_medium\"\ncanonical_ingest_retry = \"codex_medium\"\nauthoring = \"codex_medium\"\ntutor_qa = \"codex_low\"\nteach_back = \"codex_low\"\n\n[ai.providers.codex]\ntype = \"codex_sdk\"\nmodel = \"gpt-5.6-sol\"\n# Per-machine; set LEARNLOOP_CODEX_CHECKOUT_PATH in ~/.config/learnloop/settings.env.\ncheckout_path = \"\"\nrevision = \"<pinned-commit>\"\nstartup_command = \"\"\nstartup_timeout_seconds = 20\nhealthcheck_timeout_seconds = 5\nauth_mode = \"chatgpt\"\nreasoning_effort = \"low\"\nreasoning_summary = \"none\"\nsdk_python_path = \"sdk/python/src\"\nsdk_codex_bin = \"\"\nsdk_launch_command = \"\"\nbase_url = \"http://127.0.0.1:8765\"\nhealthcheck_path = \"/health\"\nauthoring_path = \"/authoring-proposal\"\ncanonical_ingest_path = \"/canonical-ingest\"\ngrading_path = \"/grading-proposal\"\nmisconception_match_path = \"/misconception-match\"\n\n[ai.providers.deepseek_flash]\ntype = \"openai_chat\"\nbase_url = \"https://api.deepseek.com\"\napi_key_env = \"DEEPSEEK_API_KEY\"\nmodel = \"deepseek-v4-flash\"\nresponse_format = \"json_object\"\nthinking = \"disabled\"\nmax_tokens = 8192\ntimeout_seconds = 90\n\n[ai.providers.deepseek_pro]\ntype = \"openai_chat\"\nbase_url = \"https://api.deepseek.com\"\napi_key_env = \"DEEPSEEK_API_KEY\"\nmodel = \"deepseek-v4-pro\"\nresponse_format = \"json_object\"\nthinking = \"enabled\"\nreasoning_effort = \"high\"\nmax_tokens = 16384\ntimeout_seconds = 180\n\n[codex]\nprovider = \"sdk\"\n# Per-machine; set LEARNLOOP_CODEX_CHECKOUT_PATH in ~/.config/learnloop/settings.env.\ncheckout_path = \"\"\nrevision = \"<pinned-commit>\"\nstartup_command = \"\"\nstartup_timeout_seconds = 20\nhealthcheck_timeout_seconds = 5\nauth_mode = \"chatgpt\"\nmodel = \"gpt-5.6-sol\"\nreasoning_effort = \"low\"\nreasoning_summary = \"none\"\nsdk_python_path = \"sdk/python/src\"\nsdk_codex_bin = \"\"\nsdk_launch_command = \"\"\nbase_url = \"http://127.0.0.1:8765\"\nhealthcheck_path = \"/health\"\nauthoring_path = \"/authoring-proposal\"\ncanonical_ingest_path = \"/canonical-ingest\"\ngrading_path = \"/grading-proposal\"\nmisconception_match_path = \"/misconception-match\"\n\n# Family-keyed mastery damage per error type (spec §\"Error-aware updates\").\n# recall_failure is the deterministic attribution for `dont_know` attempts.\n[error_impacts]\nmax_sharpening = 3.0\n\n[error_impacts.recall_failure]\nfamilies = { recall = -0.25 }\nlo_mastery_delta = -0.05\nlocal_severity_gain = 0.8\n\n[error_impacts.scaffold_failure]\nfamilies = { recall = -0.35 }\nlo_mastery_delta = -0.05\nlocal_severity_gain = 1.5\n\n[error_impacts.arithmetic_slip]\nfamilies = { numeric = -0.05 }\nlo_mastery_delta = 0.0\nlocal_severity_gain = 0.35\n\n# Capability damping/shrinkage for shared-parent facet belief (knowledge-model\n# spec §4.2). Reserved for KM2+; residual activation ships default-off.\n[capabilities]\n\n# Identity-lock policy (knowledge-model spec §3.4): a facet's semantic identity\n# locks at direct evidence in >=2 distinct surface/correlation groups, at\n# facet_lock_mass independent evidence mass, or on entering an active goal's\n# certified scope — whichever comes first.\n[locks]\nfacet_lock_mass = 2.0\nfacet_surface_groups = 2\n\n# NOTE: [cross_lo_propagation] is retired (knowledge-model §8.3/§15). The LO-to-LO\n# graph-propagated prior is prerequisite-only, direction-respecting, and\n# shadow/diagnostic-only; its error_gates were dormant. `learnloop doctor` warns\n# when a vault TOML still declares the block.\n\n[recall_coverage.severity_examples.first_dont_know]\nattempt_type = \"dont_know\"\nhints_used = 0\ncorrectness = 0.0\nexpected_correctness = 0.65\neffective_coverage = 0.85\nexpected_error_type = \"recall_failure\"\nexpected_severity_band = [0.70, 0.82]\n\n[recall_coverage.severity_examples.second_same_item_dont_know]\nattempt_type = \"dont_know\"\nhints_used = 0\ncorrectness = 0.0\nexpected_correctness = 0.65\neffective_coverage = 0.85\nrecent_same_item_failures = 1\nexpected_error_type = \"recall_failure\"\nexpected_severity_band = [0.95, 1.00]\n\n[recall_coverage.severity_examples.second_same_facet_dont_know]\nattempt_type = \"dont_know\"\nhints_used = 0\ncorrectness = 0.0\nexpected_correctness = 0.65\neffective_coverage = 0.85\nrecent_same_facet_failures = 1\nexpected_error_type = \"recall_failure\"\nexpected_severity_band = [0.80, 1.00]\n\n[recall_coverage.severity_examples.hinted_dont_know]\nattempt_type = \"dont_know\"\nhints_used = 2\ncorrectness = 0.0\nexpected_correctness = 0.65\neffective_coverage = 0.80\nexpected_error_type = \"scaffold_failure\"\nexpected_severity_band = [0.85, 0.95]\n\n[recall_coverage.severity_examples.arithmetic_slip]\nattempt_type = \"independent_attempt\"\ncorrectness = 0.75\nexpected_correctness = 0.70\neffective_coverage = 0.85\ntarget_error_type = \"arithmetic_slip\"\nexpected_error_type = \"arithmetic_slip\"\nexpected_severity_band = [0.25, 0.35]\n\n[recall_coverage.severity_examples.ambiguous_item]\nattempt_type = \"independent_attempt\"\ncorrectness = 0.0\nexpected_correctness = 0.70\neffective_coverage = 0.85\nbad_item_suspicion = 0.70\nexpected_error_type = \"recall_failure\"\nexpected_severity_band = [0.45, 0.75]\n"}, "02c3e6e10f5ca37e16cef05657ee693b33502fb7": {"t": 1785750322.6407166, "n": 22765, "h": "86af68f9615cd00d", "c": "schema_version = 1\n\n[storage]\nsqlite_path = \"state.sqlite\"\n\n[algorithms]\n# mvp-0.8: authority-propagation projection (P0.5 cutover, spec §7.2). New vaults\n# start here -- mvp-0.8 is a strict superset of the mvp-0.7 canonical shared-facet\n# knowledge model plus the P0.2/P0.3 calibrated grade channel, robust composition,\n# and reliability-discounted certification. Pre-existing mvp-0.7 vaults activate it\n# via `learnloop upgrade`; pre-existing legacy mvp-0.6 content upgrades to mvp-0.7\n# first. Legacy `probe_<lo_id>` phases recorded under earlier versions replay\n# through the frozen path forever; new diagnostic episodes replay exclusively\n# through probe_observations under the pinned channel snapshot.\nalgorithm_version = \"mvp-0.8\"\n\n# Single source of truth for per-attempt-type evidence (Fable's-take item 3).\n# evidence_mass weights ability-belief updates (mastery EKF / reliability);\n# surface_exposure is the fraction of the item's facet surface the attempt\n# certifies as probed (coverage). surface_exposure defaults to evidence_mass;\n# dont_know overrides it because a confident \"don't know\" fully covers the\n# surface as evidence-of-absence while remaining self-diagnosis, not\n# demonstration.\n[evidence.attempt_types]\nindependent_attempt = { evidence_mass = 1.0 }\nopen_text = { evidence_mass = 1.0 }\ndiagnostic_probe = { evidence_mass = 1.0 }\nhinted_attempt = { evidence_mass = 1.0 }\nreconstruction_after_walkthrough = { evidence_mass = 0.5 }\ndont_know = { evidence_mass = 0.7, surface_exposure = 1.0 }\nself_report = { evidence_mass = 0.3 }\n# Imported past-exam outcome: one exam is one correlated evidence event, so\n# each seeded question carries a fraction of a live independent attempt.\nexam_evidence = { evidence_mass = 0.35 }\n# Held-out practice-exam answer on a fresh, never-practiced item: a proctored\n# fresh-item answer is the highest-quality evidence in the system, so it carries\n# full evidence mass (deliberately unlike the discounted `exam_evidence` import).\nexam_attempt = { evidence_mass = 1.0 }\n# Teach-back conversation graded as one attempt: high-quality generative\n# evidence, but the opening explanation and follow-up answers are one\n# correlated multi-question event, so it carries less than a full independent\n# attempt per facet.\nteach_back = { evidence_mass = 0.8 }\nguided_walkthrough = { evidence_mass = 0.0 }\nskip = { evidence_mass = 0.0 }\n\n# Item-side coverage prior per practice mode: how much of an LO's facet surface\n# an item of this mode can surface when it has no evidence weights or rubric.\n# Not derivable from attempt-type evidence_mass (different question).\n[evidence.item_coverage_by_practice_mode]\nconstructed_response = 0.85\nopen_text = 0.85\nshort_answer = 0.75\ndiagnostic_probe = 0.80\nindependent_attempt = 0.75\nhinted_attempt = 0.65\nmultiple_choice = 0.45\nself_report = 0.25\n\n# Vault-wide evidence correlation lookup (knowledge-model spec §6): discounts\n# for repeated/near-clone/shared-stimulus surfaces once facet state is global.\n# Reserved for KM2; parsed now so vault TOMLs can set values early.\n[evidence.correlation]\n\n# Capability-aware certification budgets (knowledge-model spec §5.4).\n# group_budget defaults to evidence_mass(attempt_type) per correlation group;\n# max_groups_per_attempt caps the attempt-wide certification ceiling.\n[evidence.certification]\nmax_groups_per_attempt = 3\n\n# Blueprint recipe likelihood defaults (knowledge-model spec §9.2): noisy-AND\n# core with slip, plus a guess floor by response format.\n[evidence.blueprints]\nslip = 0.05\n\n[evidence.blueprints.guess_by_format]\nmultiple_choice = 0.25\nconstructed_response = 0.0\n\n[scheduler]\nforgetting_risk_weight = 1.0\n# Goal facet frontier: fraction of an item's evidence facets not yet on track\n# for an active goal (unexamined/known_gap or projected below target_recall\n# at the goal's due date), scaled by goal priority.\ngoal_frontier_weight = 0.25\nrecent_error_weight = 0.50\nprobe_eig_weight = 0.25\n# Goal quota: guaranteed floor share of the queue overlapping the goal\n# frontier; ramps min -> max over the last ramp_days before due_at.\ngoal_quota_floor_min = 0.30\ngoal_quota_floor_max = 0.70\ngoal_quota_ramp_days = 28\nshort_session_minutes = 20\n# Seeded exploration over near-tie candidates so logged slates carry non-degenerate\n# selection propensities (off-policy learnability). See architecture_pivot.md Stage 0.\nselection_exploration_rate = 0.1\nselection_exploration_reward_window = 0.15\n\n[scheduler.surprise]\ntheta_pos = 1.5\ntheta_neg = 1.5\nalpha_interval = 0.3\nf_min = 0.5\nf_max = 1.5\nepsilon_error_surprise = 0.05\n\n[scheduler.followup]\ntau_followup_nats = 0.05\ngamma_min = 0.5\nmin_target_facet_overlap = 0.5\n# Gate modernization: thresholds resolve as quantiles of this learner's own\n# signal history; the absolute values above remain the cold-start fallback.\nthreshold_mode = \"quantile\"\ntau_followup_quantile = 0.85\ntau_severe_error_quantile = 0.90\nquantile_min_samples = 30\nquantile_window = 200\n# gate_mode = \"score\" scores all signals through one logistic (threshold last);\n# \"cascade\" preserves the legacy hard trigger/suppression chain bit-for-bit.\ngate_mode = \"score\"\ngate_score_threshold = 0.5\ngate_subscore_steepness = 12.0\n# Predictive facet EIG (logged-but-inert at weight 0.0; see services/predictive_eig.py).\npredictive_eig_weight = 0.0\npredictive_eig_target_cap = 4\n# Misconception discrimination gate (spec_misconception_diagnostics.md §4.1).\n# tau_discrimination_power is the Youden-J lower bound a diagnostic candidate\n# must clear against an active misconception; require_misconception_discrimination\n# routes to no_suitable_item rather than queueing a non-discriminating paraphrase.\ntau_discrimination_power = 0.3\nrequire_misconception_discrimination = true\n\n# Goal projection: open-ended goals (no due_at) project facet recall at a\n# fixed horizon so the frontier stays defined.\n[goals]\ndefault_projection_horizon_days = 30\n\n[hypothesis]\nsession_card_budget = 2\nclaim_cooldown_days = 7\noverconfidence_min_evidence_mass = 1.0\nreentry_gap_days = 7\ndecay_pressure_target_recall = 0.8\ndecay_pressure_horizon_days = 60\n\n[forecasts]\ndefault_horizon_days = 14\n\n# Automatic misconception resolution (\"close the loop\"): an active error event\n# is resolved once the learning object accumulates N clean attempts after the\n# event was created. Clean = correctness >= auto_resolve_min_correctness, no\n# error attribution written, and not a dont_know/skip self-diagnosis.\n[misconceptions]\nauto_resolve_clean_attempts = 3\nauto_resolve_min_correctness = 0.85\n# Registry-based resolution and the sim discrimination gate\n# (spec_misconception_diagnostics.md §6, §7). Parsed now; consumed in later phases.\ntau_misconception_resolved = 0.15\nsim_gate_min_sensitivity_lb = 0.7\nsim_gate_min_specificity_lb = 0.8\n# 8, not 5: a perfect run over N trials has lower bound 0.25^(1/(N+1)) at the\n# 25th percentile — 0.794 at N=5 (below the 0.8 specificity gate), 0.857 at N=8.\nsim_gate_trials = 8\n# Opt-in codex answers-under-belief pass for the gate. 0 = pure deterministic\n# (no provider tokens). When > 0, codex role-plays that many planted + clean\n# students in ONE call per gate run and their fires combine with the\n# deterministic trials. Costs provider tokens per accepted item; the same N>=8\n# caveat applies (0.25^(1/(N+1)) at the 25th percentile) to the COMBINED counts.\nsim_gate_llm_trials = 0\n\n# Offline parameter fitting from the learner's own logs (`learnloop fit`).\n# Fitted sets live in the fitted_parameters table; defaults apply when none is active.\n[fitting.fsrs]\nmin_reviews = 50\nmin_elapsed_days = 0.5\nl2_lambda = 1.0\nmax_iterations = 300\ninitial_step = 0.05\nmin_relative_improvement = 0.01\n\n[mastery]\nbase_observation_variance = 1.0\nsigma2_drift = 0.01\np_max = 4.0\n# Display banding: > strong renders green, > developing renders amber, else red.\ndisplay_strong_threshold = 0.6\ndisplay_developing_threshold = 0.35\n\n# IRT 2PL difficulty-aware mastery update (spec_irt_difficulty.md §4).\n# enabled = false restores the legacy logit-space Kalman update bit-for-bit.\n[mastery.irt]\nenabled = true\ndiscrimination_default = 1.0\ndifficulty_default = 0.0\ndifficulty_from_prior = true\ndifficulty_prior_scale = 2.5\nb_abs_max = 4.0\np_clip = 1e-4\nmu_abs_max = 5.0\nmax_logit_step = 4.0\n# Empirical-Bayes per-item difficulty posterior (dark by default; see\n# MasteryIRTConfig for the identifiability rationale).\neb_difficulty_enabled = false\nb_prior_variance = 0.25\nb_learning_rate_scale = 0.2\nb_max_step = 0.25\nb_var_min = 0.01\n\n[probe]\n# LEGACY (probe redesign Checkpoint 0.4): attempts_target_default,\n# attempts_target_with_strong_claim, claim_skip_threshold, and\n# variance_convergence_threshold configure only the frozen pre-redesign replay\n# path. Their live roles moved to [probe.episode]: the attempt targets map to\n# minimum/maximum_observations, the strong-claim skip maps to the explicit\n# fast-path policy (fast_path_claim_threshold), and variance convergence is\n# superseded by the §11 completion policy (posterior_stop_threshold).\nattempts_target_default = 3\nattempts_target_with_strong_claim = 1\nclaim_skip_threshold = 0.75\nvariance_convergence_threshold = 0.10\nhypothesis_set_max_size = 5\n\n# Diagnostic episodes (spec_probe_eig_redesign.md §5/§11).\n[probe.episode]\nminimum_independent_observations = 2\nmaximum_observations = 4\nposterior_stop_threshold = 0.85\nambiguity_threshold = 0.30\nopen_set_prior = 0.10\nopen_set_trigger_threshold = 0.35\nhinted_evidence_weight = 0.5\ncontaminated_evidence_weight = 0.3\nself_graded_evidence_weight = 0.3\nsession_qualifying_observation_cap = 4\nfast_path_enabled = true\nfast_path_claim_threshold = 0.75\npresentation_ttl_minutes = 240\n# Predictive EIG per expected time is the diagnostic default objective (§7.4/§7.5)\n# whenever at least predictive_target_minimum held-out instruments exist for the\n# episode; hypothesis EIG remains the fallback and audit signal.\npredictive_selection_enabled = true\npredictive_target_minimum = 2\npredictive_target_cap = 6\nselection_overhead_seconds = 10.0\n# §5.9 fresh-vault onboarding: probes deactivate after this many qualifying\n# observations until ordinary practice has started (0 disables).\nonboarding_practice_ceiling_observations = 4\n# §6.5 re-probe triggers: repeated prediction errors and stale uncertainty.\nreprobe_prediction_error_count = 3\nreprobe_prediction_error_window = 10\nreprobe_predictive_surprise_threshold = 1.0\nreprobe_stale_uncertainty_variance = 0.6\nreprobe_stale_uncertainty_days = 30\n\n# Parameterized instance generation from admitted family/card bindings (§10).\n# llm_surfaces: when an AI provider capable of run_probe_instance_surfaces is\n# wired through, instance surfaces come from the LLM (grounded in the LO,\n# validated by the structural instance gate) and fall back to the parametric\n# templates on provider failure or gate rejection.\n[probe.generation]\ninstances_per_need = 2\nauto_generate_on_entry = false\nllm_surfaces = true\n\n# Short adaptive dialogue microprobes (§8.1): turns within one block share the\n# family's total task evidence mass (§7.7).\n[probe.dialogue]\nplanned_turns = 3\nmax_turns = 4\n\n# Learner-initiated calibration sessions (§5.9): batch episode blocks across a\n# goal scope; lift only the per-session qualifying-observation cap within the\n# declared time budget.\n[probe.calibration]\ndefault_time_budget_minutes = 20\nmax_planned_episodes = 8\ndisagreement_weight = 0.5\n\n# Hierarchical family -> item shrinkage (§9.7, Checkpoint 4.2): item rows shrink\n# toward the family-version posterior with this much family-equivalent mass.\n[probe.hierarchy]\nitem_shrinkage_pseudo_count = 25.0\n\n# Family-version lifecycle gates (§9.7, Checkpoint 4.7). Trust requires\n# real-learner evidence; synthetic gate statistics never qualify a family.\n[probe.lifecycle]\ntrust_minimum_real_sample = 20\ntrust_minimum_regrade_checks = 5\ntrust_minimum_regrade_agreement = 0.80\ntrust_maximum_negative_information_rate = 0.20\nretire_minimum_sample = 10\nretire_negative_information_rate = 0.50\nretire_regrade_agreement_floor = 0.50\n\n# Shadow-mode alternative selection policies (§13.3, Checkpoint 5.1): log-only\n# rankings on the committed presentation. Off-policy estimation stays on hold\n# for single-learner vaults.\n[probe.shadow]\nenabled = true\ntop_k = 3\n\n# Precommitted diagnostic blocks (Checkpoint 5.2/5.3): redundancy penalty is a\n# separate ranking component (never labeled EIG); joint greedy conditional EIG\n# applies only to blocks committed before answers are observed.\n[probe.block]\nfamily_redundancy_penalty = 0.6\nmax_block_size = 4\nconditional_branch_cap = 3\n# §5.6/§5.7: sequential probes run the block-end hook after this many\n# observations in the current state segment.\ndefault_block_observations = 2\n\n# IRT difficulty-aware probe conditionals (spec_irt_difficulty.md §5).\n[probe.irt]\ntheta_mastered = 2.0\ntheta_unfamiliar = -2.0\ncut_mid = -1.0\ncut_high = 1.0\nunfamiliar_error_leak = 0.20\nerr_low_frac = 0.80\nerr_mid_frac = 0.50\n\n# Learner self-attributed misconception probe coverage (spec_irt_difficulty.md §12).\n[probe.self_tag]\nw_base = 0.5\nw_max = 0.7\ntarget_degree = 2.0\npromotion_threshold = 3\n\n# Exam seeding (`learnloop ingest-exam` + `learnloop seed-exam-attempts`):\n# imported per-question outcomes become backdated exam_evidence attempts.\n# grader_confidence is the reliability discount persisted on seeded attempts;\n# default_learner_confidence (1-5) is used when an outcome omits confidence.\n[exam_seeding]\ngrader_confidence = 0.7\ndefault_learner_confidence = 3\n\n# Tutor Q&A (\"ask\"): question limits per context (practice: per item+session,\n# feedback: per attempt, library: per note per day) and the read-side\n# uncertainty bump applied for recent unresolved questions about a facet.\n[tutor_qa]\nmax_questions_practice = 3\nmax_questions_feedback = 5\nmax_questions_library = 8\nmax_questions_reader = 8\nreader_enabled = true\napply_uncertainty_effect = true\nuncertainty_evidence_mass = 0.15\n\n# Promoting Socratic tutor questions to practice items / learning objects.\n# Gap route: a \"this exposed a gap\" promotion writes a low self-report claim\n# (gap_claim_level at gap_claim_pseudo_count pseudo-observations) and counts as\n# an unresolved-question observation with its own likelihood slot fit from the\n# learner's gap-declaration -> failure lift, falling back to\n# gap_declaration_solid_likelihood_ratio below gap_declaration_likelihood_min_samples.\n# The filed need goes stale after gap_need_ttl_days; requested_items_per_session\n# bounds the scheduler floor for promoted-but-unattempted items.\n[tutor_promotion]\ngap_claim_level = 0.25\ngap_claim_pseudo_count = 2.0\ngap_declaration_solid_likelihood_ratio = 0.35\ngap_declaration_likelihood_min_samples = 12\ngap_need_ttl_days = 21\nrequested_items_per_session = 1\n\n# Teach-back conversations: the learner explains, an AI naive student asks up\n# to max_followups questions (one per rubric criterion, uncertainty-ranked with\n# transfer escalation), and the transcript is graded as one attempt.\n# transfer_evidence_multiplier symmetrically discounts the evidence mass of\n# transfer-tier criterion evidence; session_cap bounds teach_back items per\n# built queue.\n[teach_back]\nmax_followups = 3\ntransfer_evidence_multiplier = 0.5\nsession_cap = 1\n\n[ingest]\nwindow_char_cap = 150000\nmin_content_chars = 400\ndefault_goal_priority = 0.5\nallow_auto_captions = false\n\n# PDF extraction for canonical sources (textbook chapters, past exams, any\n# ingested .pdf). engine \"auto\" uses marker-pdf (structured Markdown with\n# headings, tables, LaTeX math, and OCR for scanned pages) when installed\n# (`pip install learnloop[pdf]`), falling back to plain pypdf text extraction.\n# use_llm adds marker's VLM boost for difficult scans and dense math: hard\n# regions are sent to an OpenAI-compatible endpoint -- e.g. a local vLLM\n# serving deepseek-ai/DeepSeek-OCR (llm_base_url = \"http://127.0.0.1:8000/v1\",\n# llm_model = \"deepseek-ai/DeepSeek-OCR\") or any hosted vision model. The API\n# key is read from the env var named by llm_api_key_env. Marker conversions\n# are cached under .learnloop/source-cache/pdf/ keyed by file bytes + config.\n[ingest.pdf]\nengine = \"auto\"\n# \"\" = auto-detect (GPU when the installed torch supports it); pin with\n# \"cuda\", \"cuda:1\", \"cpu\", or \"mps\" to override.\ntorch_device = \"\"\nforce_ocr = false\nuse_llm = false\nllm_service = \"marker.services.openai.OpenAIService\"\nllm_base_url = \"\"\nllm_model = \"\"\nllm_api_key_env = \"LEARNLOOP_PDF_LLM_API_KEY\"\n\n# Per-stage token budgets for ingestion v2 (source-ingestion spec §3.1).\n# Preflight/build-plan estimates read these; a stage exceeding its ceiling\n# shards or pauses for narrower scope — it never silently truncates.\n[ingest.budgets]\ninventory_input_tokens = 20000\ninventory_output_tokens = 3000\nsynthesis_shard_input_tokens = 40000\nsynthesis_shard_output_tokens = 10000\nevidence_span_input_tokens = 12000\nsynthesis_total_input_ceiling = 48000\nsynthesis_output_tokens = 16000\nappend_neighborhood_input_tokens = 24000\nappend_output_tokens = 10000\n# Span-request protocol caps (§8.5): one bounded request round only.\nsynthesis_span_request_max_count = 12\nsynthesis_span_char_cap = 4000\n# Quick add (§1): ToC-guided relevant-scope cap.\nquick_add_scope_input_tokens = 40000\n\n# Per-provider context/output limits consulted by preflight, keyed by the\n# [ai.providers.<name>] entries (source-ingestion spec §3.1), e.g.\n# [ingest.providers.codex] context_tokens / max_output_tokens.\n\n# Durable ingest-queue worker settings (source-ingestion spec §6.2). One worker\n# (sidecar background loop or foreground CLI) drains queued jobs at a time under\n# a single lease; a running lease older than lease_ttl_seconds is recovered to\n# failed(interrupted) on startup and its queued siblings resume.\n[ingest.runner]\nlease_ttl_seconds = 120\nheartbeat_interval_seconds = 15\npoll_interval_seconds = 1.0\n\n[ai]\nactive_provider = \"codex\"\nfallback_provider = \"\"\ntimeout_seconds = 60\n\n[ai.routing]\ngrading = \"codex_low\"\ncanonical_ingest = \"codex_medium\"\ncanonical_ingest_retry = \"codex_medium\"\nauthoring = \"codex_medium\"\ntutor_qa = \"codex_low\"\nteach_back = \"codex_low\"\n\n[ai.providers.codex]\ntype = \"codex_sdk\"\nmodel = \"gpt-5.6-sol\"\n# Per-machine; set LEARNLOOP_CODEX_CHECKOUT_PATH in ~/.config/learnloop/settings.env.\ncheckout_path = \"\"\nrevision = \"<pinned-commit>\"\nstartup_command = \"\"\nstartup_timeout_seconds = 20\nhealthcheck_timeout_seconds = 5\nauth_mode = \"chatgpt\"\nreasoning_effort = \"low\"\nreasoning_summary = \"none\"\nsdk_python_path = \"sdk/python/src\"\nsdk_codex_bin = \"\"\nsdk_launch_command = \"\"\nbase_url = \"http://127.0.0.1:8765\"\nhealthcheck_path = \"/health\"\nauthoring_path = \"/authoring-proposal\"\ncanonical_ingest_path = \"/canonical-ingest\"\ngrading_path = \"/grading-proposal\"\nmisconception_match_path = \"/misconception-match\"\n\n[ai.providers.deepseek_flash]\ntype = \"openai_chat\"\nbase_url = \"https://api.deepseek.com\"\napi_key_env = \"DEEPSEEK_API_KEY\"\nmodel = \"deepseek-v4-flash\"\nresponse_format = \"json_object\"\nthinking = \"disabled\"\nmax_tokens = 8192\ntimeout_seconds = 90\n\n[ai.providers.deepseek_pro]\ntype = \"openai_chat\"\nbase_url = \"https://api.deepseek.com\"\napi_key_env = \"DEEPSEEK_API_KEY\"\nmodel = \"deepseek-v4-pro\"\nresponse_format = \"json_object\"\nthinking = \"enabled\"\nreasoning_effort = \"high\"\nmax_tokens = 16384\ntimeout_seconds = 180\n\n[codex]\nprovider = \"sdk\"\n# Per-machine; set LEARNLOOP_CODEX_CHECKOUT_PATH in ~/.config/learnloop/settings.env.\ncheckout_path = \"\"\nrevision = \"<pinned-commit>\"\nstartup_command = \"\"\nstartup_timeout_seconds = 20\nhealthcheck_timeout_seconds = 5\nauth_mode = \"chatgpt\"\nmodel = \"gpt-5.6-sol\"\nreasoning_effort = \"low\"\nreasoning_summary = \"none\"\nsdk_python_path = \"sdk/python/src\"\nsdk_codex_bin = \"\"\nsdk_launch_command = \"\"\nbase_url = \"http://127.0.0.1:8765\"\nhealthcheck_path = \"/health\"\nauthoring_path = \"/authoring-proposal\"\ncanonical_ingest_path = \"/canonical-ingest\"\ngrading_path = \"/grading-proposal\"\nmisconception_match_path = \"/misconception-match\"\n\n# Family-keyed mastery damage per error type (spec §\"Error-aware updates\").\n# recall_failure is the deterministic attribution for `dont_know` attempts.\n[error_impacts]\nmax_sharpening = 3.0\n\n[error_impacts.recall_failure]\nfamilies = { recall = -0.25 }\nlo_mastery_delta = -0.05\nlocal_severity_gain = 0.8\n\n[error_impacts.scaffold_failure]\nfamilies = { recall = -0.35 }\nlo_mastery_delta = -0.05\nlocal_severity_gain = 1.5\n\n[error_impacts.arithmetic_slip]\nfamilies = { numeric = -0.05 }\nlo_mastery_delta = 0.0\nlocal_severity_gain = 0.35\n\n# Capability damping/shrinkage for shared-parent facet belief (knowledge-model\n# spec §4.2). Reserved for KM2+; residual activation ships default-off.\n[capabilities]\n\n# Identity-lock policy (knowledge-model spec §3.4): a facet's semantic identity\n# locks at direct evidence in >=2 distinct surface/correlation groups, at\n# facet_lock_mass independent evidence mass, or on entering an active goal's\n# certified scope — whichever comes first.\n[locks]\nfacet_lock_mass = 2.0\nfacet_surface_groups = 2\n\n# NOTE: [cross_lo_propagation] is retired (knowledge-model §8.3/§15). The LO-to-LO\n# graph-propagated prior is prerequisite-only, direction-respecting, and\n# shadow/diagnostic-only; its error_gates were dormant. `learnloop doctor` warns\n# when a vault TOML still declares the block.\n\n[recall_coverage.severity_examples.first_dont_know]\nattempt_type = \"dont_know\"\nhints_used = 0\ncorrectness = 0.0\nexpected_correctness = 0.65\neffective_coverage = 0.85\nexpected_error_type = \"recall_failure\"\nexpected_severity_band = [0.70, 0.82]\n\n[recall_coverage.severity_examples.second_same_item_dont_know]\nattempt_type = \"dont_know\"\nhints_used = 0\ncorrectness = 0.0\nexpected_correctness = 0.65\neffective_coverage = 0.85\nrecent_same_item_failures = 1\nexpected_error_type = \"recall_failure\"\nexpected_severity_band = [0.95, 1.00]\n\n[recall_coverage.severity_examples.second_same_facet_dont_know]\nattempt_type = \"dont_know\"\nhints_used = 0\ncorrectness = 0.0\nexpected_correctness = 0.65\neffective_coverage = 0.85\nrecent_same_facet_failures = 1\nexpected_error_type = \"recall_failure\"\nexpected_severity_band = [0.80, 1.00]\n\n[recall_coverage.severity_examples.hinted_dont_know]\nattempt_type = \"dont_know\"\nhints_used = 2\ncorrectness = 0.0\nexpected_correctness = 0.65\neffective_coverage = 0.80\nexpected_error_type = \"scaffold_failure\"\nexpected_severity_band = [0.85, 0.95]\n\n[recall_coverage.severity_examples.arithmetic_slip]\nattempt_type = \"independent_attempt\"\ncorrectness = 0.75\nexpected_correctness = 0.70\neffective_coverage = 0.85\ntarget_error_type = \"arithmetic_slip\"\nexpected_error_type = \"arithmetic_slip\"\nexpected_severity_band = [0.25, 0.35]\n\n[recall_coverage.severity_examples.ambiguous_item]\nattempt_type = \"independent_attempt\"\ncorrectness = 0.0\nexpected_correctness = 0.70\neffective_coverage = 0.85\nbad_item_suspicion = 0.70\nexpected_error_type = \"recall_failure\"\nexpected_severity_band = [0.45, 0.75]\n"}}, "fixtures/arxiv/learnloop.toml": {"d7f5830f824d7636193af334e950c1d2ffc477c4": {"t": 1785745365.378781, "n": 5819, "h": "cc5a58d55a4911bd", "c": "schema_version = 1\n\n[storage]\nsqlite_path = \"state.sqlite\"\n\n[algorithms]\nalgorithm_version = \"mvp-0.8\"\n\n[scheduler]\nforgetting_risk_weight = 1.0\nrecent_error_weight = 0.50\nprobe_eig_weight = 0.25\nshort_session_minutes = 20\n# Seeded exploration over near-tie candidates so logged slates carry non-degenerate\n# selection propensities (off-policy learnability). See architecture_pivot.md Stage 0.\nselection_exploration_rate = 0.1\nselection_exploration_reward_window = 0.15\n\n[scheduler.surprise]\ntheta_pos = 1.5\ntheta_neg = 1.5\nalpha_interval = 0.3\nf_min = 0.5\nf_max = 1.5\nepsilon_error_surprise = 0.05\n\n[scheduler.followup]\ntau_followup_nats = 0.05\ngamma_min = 0.5\n\n[mastery]\nbase_observation_variance = 1.0\nsigma2_drift = 0.01\np_max = 4.0\n\n# IRT 2PL difficulty-aware mastery update (spec_irt_difficulty.md §4).\n# enabled = false restores the legacy logit-space Kalman update bit-for-bit.\n[mastery.irt]\nenabled = true\ndiscrimination_default = 1.0\ndifficulty_default = 0.0\ndifficulty_from_prior = true\ndifficulty_prior_scale = 2.5\nb_abs_max = 4.0\np_clip = 1e-4\nmu_abs_max = 5.0\nmax_logit_step = 4.0\n\n[probe]\nattempts_target_default = 3\nattempts_target_with_strong_claim = 1\nclaim_skip_threshold = 0.75\nvariance_convergence_threshold = 0.10\nhypothesis_set_max_size = 5\n\n# IRT difficulty-aware probe conditionals (spec_irt_difficulty.md §5).\n[probe.irt]\ntheta_mastered = 2.0\ntheta_unfamiliar = -2.0\ncut_mid = -1.0\ncut_high = 1.0\nunfamiliar_error_leak = 0.20\nerr_low_frac = 0.80\nerr_mid_frac = 0.50\n\n# Learner self-attributed misconception probe coverage (spec_irt_difficulty.md §12).\n[probe.self_tag]\nw_base = 0.5\nw_max = 0.7\ntarget_degree = 2.0\npromotion_threshold = 3\n\n[ingest]\nwindow_char_cap = 150000\nmin_content_chars = 400\ndefault_goal_priority = 0.5\nallow_auto_captions = false\n\n[ai]\nactive_provider = \"codex\"\nfallback_provider = \"\"\ntimeout_seconds = 60\n\n[ai.routing]\ngrading = \"codex\"\ncanonical_ingest = \"codex\"\ncanonical_ingest_retry = \"\"\nauthoring = \"codex\"\n\n[ai.providers.codex]\ntype = \"codex_sdk\"\nmodel = \"gpt-5.5\"\ncheckout_path = \"/home/chloe/Documents/thinking/learnanything/codex\"\nrevision = \"<pinned-commit>\"\nstartup_command = \"\"\nstartup_timeout_seconds = 20\nhealthcheck_timeout_seconds = 5\nauth_mode = \"chatgpt\"\nreasoning_effort = \"medium\"\nreasoning_summary = \"none\"\nsdk_python_path = \"sdk/python/src\"\nsdk_codex_bin = \"\"\nsdk_launch_command = \"\"\nbase_url = \"http://127.0.0.1:8765\"\nhealthcheck_path = \"/health\"\nauthoring_path = \"/authoring-proposal\"\ncanonical_ingest_path = \"/canonical-ingest\"\ngrading_path = \"/grading-proposal\"\n\n[ai.providers.deepseek_flash]\ntype = \"openai_chat\"\nbase_url = \"https://api.deepseek.com\"\napi_key_env = \"DEEPSEEK_API_KEY\"\nmodel = \"deepseek-v4-flash\"\nresponse_format = \"json_object\"\nthinking = \"disabled\"\nmax_tokens = 8192\ntimeout_seconds = 90\n\n[ai.providers.deepseek_pro]\ntype = \"openai_chat\"\nbase_url = \"https://api.deepseek.com\"\napi_key_env = \"DEEPSEEK_API_KEY\"\nmodel = \"deepseek-v4-pro\"\nresponse_format = \"json_object\"\nthinking = \"enabled\"\nreasoning_effort = \"high\"\nmax_tokens = 16384\ntimeout_seconds = 180\n\n[codex]\nprovider = \"sdk\"\ncheckout_path = \"/home/chloe/Documents/thinking/learnanything/codex\"\nrevision = \"<pinned-commit>\"\nstartup_command = \"\"\nstartup_timeout_seconds = 20\nhealthcheck_timeout_seconds = 5\nauth_mode = \"chatgpt\"\nmodel = \"gpt-5.5\"\nreasoning_effort = \"medium\"\nreasoning_summary = \"none\"\nsdk_python_path = \"sdk/python/src\"\nsdk_codex_bin = \"\"\nsdk_launch_command = \"\"\nbase_url = \"http://127.0.0.1:8765\"\nhealthcheck_path = \"/health\"\nauthoring_path = \"/authoring-proposal\"\ncanonical_ingest_path = \"/canonical-ingest\"\ngrading_path = \"/grading-proposal\"\n\n# Family-keyed mastery damage per error type (spec §\"Error-aware updates\").\n# recall_failure is the deterministic attribution for `dont_know` attempts.\n[error_impacts]\nmax_sharpening = 3.0\n\n[error_impacts.recall_failure]\nfamilies = { recall = -0.25 }\nlo_mastery_delta = -0.05\nlocal_severity_gain = 0.8\n\n[error_impacts.scaffold_failure]\nfamilies = { recall = -0.35 }\nlo_mastery_delta = -0.05\nlocal_severity_gain = 1.5\n\n[error_impacts.arithmetic_slip]\nfamilies = { numeric = -0.05 }\nlo_mastery_delta = 0.0\nlocal_severity_gain = 0.35\n\n# Cross-LO propagation gates per error type (spec §\"Error-type gate\").\n[recall_coverage.severity_examples.first_dont_know]\nattempt_type = \"dont_know\"\nhints_used = 0\ncorrectness = 0.0\nexpected_correctness = 0.65\neffective_coverage = 0.85\nexpected_error_type = \"recall_failure\"\nexpected_severity_band = [0.70, 0.82]\n\n[recall_coverage.severity_examples.second_same_item_dont_know]\nattempt_type = \"dont_know\"\nhints_used = 0\ncorrectness = 0.0\nexpected_correctness = 0.65\neffective_coverage = 0.85\nrecent_same_item_failures = 1\nexpected_error_type = \"recall_failure\"\nexpected_severity_band = [0.95, 1.00]\n\n[recall_coverage.severity_examples.second_same_facet_dont_know]\nattempt_type = \"dont_know\"\nhints_used = 0\ncorrectness = 0.0\nexpected_correctness = 0.65\neffective_coverage = 0.85\nrecent_same_facet_failures = 1\nexpected_error_type = \"recall_failure\"\nexpected_severity_band = [0.80, 1.00]\n\n[recall_coverage.severity_examples.hinted_dont_know]\nattempt_type = \"dont_know\"\nhints_used = 2\ncorrectness = 0.0\nexpected_correctness = 0.65\neffective_coverage = 0.80\nexpected_error_type = \"scaffold_failure\"\nexpected_severity_band = [0.85, 0.95]\n\n[recall_coverage.severity_examples.arithmetic_slip]\nattempt_type = \"independent_attempt\"\ncorrectness = 0.75\nexpected_correctness = 0.70\neffective_coverage = 0.85\ntarget_error_type = \"arithmetic_slip\"\nexpected_error_type = \"arithmetic_slip\"\nexpected_severity_band = [0.25, 0.35]\n\n[recall_coverage.severity_examples.ambiguous_item]\nattempt_type = \"independent_attempt\"\ncorrectness = 0.0\nexpected_correctness = 0.70\neffective_coverage = 0.85\nbad_item_suspicion = 0.70\nexpected_error_type = \"recall_failure\"\nexpected_severity_band = [0.45, 0.75]\n"}, "a6c3391bee0c4732249b52d238aa1660b1a3042e": {"t": 1785750314.9088693, "n": 5819, "h": "cc5a58d55a4911bd", "c": "schema_version = 1\n\n[storage]\nsqlite_path = \"state.sqlite\"\n\n[algorithms]\nalgorithm_version = \"mvp-0.8\"\n\n[scheduler]\nforgetting_risk_weight = 1.0\nrecent_error_weight = 0.50\nprobe_eig_weight = 0.25\nshort_session_minutes = 20\n# Seeded exploration over near-tie candidates so logged slates carry non-degenerate\n# selection propensities (off-policy learnability). See architecture_pivot.md Stage 0.\nselection_exploration_rate = 0.1\nselection_exploration_reward_window = 0.15\n\n[scheduler.surprise]\ntheta_pos = 1.5\ntheta_neg = 1.5\nalpha_interval = 0.3\nf_min = 0.5\nf_max = 1.5\nepsilon_error_surprise = 0.05\n\n[scheduler.followup]\ntau_followup_nats = 0.05\ngamma_min = 0.5\n\n[mastery]\nbase_observation_variance = 1.0\nsigma2_drift = 0.01\np_max = 4.0\n\n# IRT 2PL difficulty-aware mastery update (spec_irt_difficulty.md §4).\n# enabled = false restores the legacy logit-space Kalman update bit-for-bit.\n[mastery.irt]\nenabled = true\ndiscrimination_default = 1.0\ndifficulty_default = 0.0\ndifficulty_from_prior = true\ndifficulty_prior_scale = 2.5\nb_abs_max = 4.0\np_clip = 1e-4\nmu_abs_max = 5.0\nmax_logit_step = 4.0\n\n[probe]\nattempts_target_default = 3\nattempts_target_with_strong_claim = 1\nclaim_skip_threshold = 0.75\nvariance_convergence_threshold = 0.10\nhypothesis_set_max_size = 5\n\n# IRT difficulty-aware probe conditionals (spec_irt_difficulty.md §5).\n[probe.irt]\ntheta_mastered = 2.0\ntheta_unfamiliar = -2.0\ncut_mid = -1.0\ncut_high = 1.0\nunfamiliar_error_leak = 0.20\nerr_low_frac = 0.80\nerr_mid_frac = 0.50\n\n# Learner self-attributed misconception probe coverage (spec_irt_difficulty.md §12).\n[probe.self_tag]\nw_base = 0.5\nw_max = 0.7\ntarget_degree = 2.0\npromotion_threshold = 3\n\n[ingest]\nwindow_char_cap = 150000\nmin_content_chars = 400\ndefault_goal_priority = 0.5\nallow_auto_captions = false\n\n[ai]\nactive_provider = \"codex\"\nfallback_provider = \"\"\ntimeout_seconds = 60\n\n[ai.routing]\ngrading = \"codex\"\ncanonical_ingest = \"codex\"\ncanonical_ingest_retry = \"\"\nauthoring = \"codex\"\n\n[ai.providers.codex]\ntype = \"codex_sdk\"\nmodel = \"gpt-5.5\"\ncheckout_path = \"/home/chloe/Documents/thinking/learnanything/codex\"\nrevision = \"<pinned-commit>\"\nstartup_command = \"\"\nstartup_timeout_seconds = 20\nhealthcheck_timeout_seconds = 5\nauth_mode = \"chatgpt\"\nreasoning_effort = \"medium\"\nreasoning_summary = \"none\"\nsdk_python_path = \"sdk/python/src\"\nsdk_codex_bin = \"\"\nsdk_launch_command = \"\"\nbase_url = \"http://127.0.0.1:8765\"\nhealthcheck_path = \"/health\"\nauthoring_path = \"/authoring-proposal\"\ncanonical_ingest_path = \"/canonical-ingest\"\ngrading_path = \"/grading-proposal\"\n\n[ai.providers.deepseek_flash]\ntype = \"openai_chat\"\nbase_url = \"https://api.deepseek.com\"\napi_key_env = \"DEEPSEEK_API_KEY\"\nmodel = \"deepseek-v4-flash\"\nresponse_format = \"json_object\"\nthinking = \"disabled\"\nmax_tokens = 8192\ntimeout_seconds = 90\n\n[ai.providers.deepseek_pro]\ntype = \"openai_chat\"\nbase_url = \"https://api.deepseek.com\"\napi_key_env = \"DEEPSEEK_API_KEY\"\nmodel = \"deepseek-v4-pro\"\nresponse_format = \"json_object\"\nthinking = \"enabled\"\nreasoning_effort = \"high\"\nmax_tokens = 16384\ntimeout_seconds = 180\n\n[codex]\nprovider = \"sdk\"\ncheckout_path = \"/home/chloe/Documents/thinking/learnanything/codex\"\nrevision = \"<pinned-commit>\"\nstartup_command = \"\"\nstartup_timeout_seconds = 20\nhealthcheck_timeout_seconds = 5\nauth_mode = \"chatgpt\"\nmodel = \"gpt-5.5\"\nreasoning_effort = \"medium\"\nreasoning_summary = \"none\"\nsdk_python_path = \"sdk/python/src\"\nsdk_codex_bin = \"\"\nsdk_launch_command = \"\"\nbase_url = \"http://127.0.0.1:8765\"\nhealthcheck_path = \"/health\"\nauthoring_path = \"/authoring-proposal\"\ncanonical_ingest_path = \"/canonical-ingest\"\ngrading_path = \"/grading-proposal\"\n\n# Family-keyed mastery damage per error type (spec §\"Error-aware updates\").\n# recall_failure is the deterministic attribution for `dont_know` attempts.\n[error_impacts]\nmax_sharpening = 3.0\n\n[error_impacts.recall_failure]\nfamilies = { recall = -0.25 }\nlo_mastery_delta = -0.05\nlocal_severity_gain = 0.8\n\n[error_impacts.scaffold_failure]\nfamilies = { recall = -0.35 }\nlo_mastery_delta = -0.05\nlocal_severity_gain = 1.5\n\n[error_impacts.arithmetic_slip]\nfamilies = { numeric = -0.05 }\nlo_mastery_delta = 0.0\nlocal_severity_gain = 0.35\n\n# Cross-LO propagation gates per error type (spec §\"Error-type gate\").\n[recall_coverage.severity_examples.first_dont_know]\nattempt_type = \"dont_know\"\nhints_used = 0\ncorrectness = 0.0\nexpected_correctness = 0.65\neffective_coverage = 0.85\nexpected_error_type = \"recall_failure\"\nexpected_severity_band = [0.70, 0.82]\n\n[recall_coverage.severity_examples.second_same_item_dont_know]\nattempt_type = \"dont_know\"\nhints_used = 0\ncorrectness = 0.0\nexpected_correctness = 0.65\neffective_coverage = 0.85\nrecent_same_item_failures = 1\nexpected_error_type = \"recall_failure\"\nexpected_severity_band = [0.95, 1.00]\n\n[recall_coverage.severity_examples.second_same_facet_dont_know]\nattempt_type = \"dont_know\"\nhints_used = 0\ncorrectness = 0.0\nexpected_correctness = 0.65\neffective_coverage = 0.85\nrecent_same_facet_failures = 1\nexpected_error_type = \"recall_failure\"\nexpected_severity_band = [0.80, 1.00]\n\n[recall_coverage.severity_examples.hinted_dont_know]\nattempt_type = \"dont_know\"\nhints_used = 2\ncorrectness = 0.0\nexpected_correctness = 0.65\neffective_coverage = 0.80\nexpected_error_type = \"scaffold_failure\"\nexpected_severity_band = [0.85, 0.95]\n\n[recall_coverage.severity_examples.arithmetic_slip]\nattempt_type = \"independent_attempt\"\ncorrectness = 0.75\nexpected_correctness = 0.70\neffective_coverage = 0.85\ntarget_error_type = \"arithmetic_slip\"\nexpected_error_type = \"arithmetic_slip\"\nexpected_severity_band = [0.25, 0.35]\n\n[recall_coverage.severity_examples.ambiguous_item]\nattempt_type = \"independent_attempt\"\ncorrectness = 0.0\nexpected_correctness = 0.70\neffective_coverage = 0.85\nbad_item_suspicion = 0.70\nexpected_error_type = \"recall_failure\"\nexpected_severity_band = [0.45, 0.75]\n"}, "6fb2c13944c0431c70d3dba01553c23f93db883d": {"t": 1785750316.0256772, "n": 6304, "h": "a31e1fe4687e0906", "c": "schema_version = 1\n\n[storage]\nsqlite_path = \"state.sqlite\"\n\n[algorithms]\nalgorithm_version = \"mvp-0.8\"\n\n[scheduler]\nforgetting_risk_weight = 1.0\nrecent_error_weight = 0.50\nprobe_eig_weight = 0.25\nshort_session_minutes = 20\n# Seeded exploration over near-tie candidates so logged slates carry non-degenerate\n# selection propensities (off-policy learnability). See architecture_pivot.md Stage 0.\nselection_exploration_rate = 0.1\nselection_exploration_reward_window = 0.15\n\n[scheduler.surprise]\ntheta_pos = 1.5\ntheta_neg = 1.5\nalpha_interval = 0.3\nf_min = 0.5\nf_max = 1.5\nepsilon_error_surprise = 0.05\n\n[scheduler.followup]\ntau_followup_nats = 0.05\ngamma_min = 0.5\n\n[mastery]\nbase_observation_variance = 1.0\nsigma2_drift = 0.01\np_max = 4.0\n\n# IRT 2PL difficulty-aware mastery update (spec_irt_difficulty.md §4).\n# enabled = false restores the legacy logit-space Kalman update bit-for-bit.\n[mastery.irt]\nenabled = true\ndiscrimination_default = 1.0\ndifficulty_default = 0.0\ndifficulty_from_prior = true\ndifficulty_prior_scale = 2.5\nb_abs_max = 4.0\np_clip = 1e-4\nmu_abs_max = 5.0\nmax_logit_step = 4.0\n\n[probe]\nattempts_target_default = 3\nattempts_target_with_strong_claim = 1\nclaim_skip_threshold = 0.75\nvariance_convergence_threshold = 0.10\nhypothesis_set_max_size = 5\n\n# IRT difficulty-aware probe conditionals (spec_irt_difficulty.md §5).\n[probe.irt]\ntheta_mastered = 2.0\ntheta_unfamiliar = -2.0\ncut_mid = -1.0\ncut_high = 1.0\nunfamiliar_error_leak = 0.20\nerr_low_frac = 0.80\nerr_mid_frac = 0.50\n\n# Learner self-attributed misconception probe coverage (spec_irt_difficulty.md §12).\n[probe.self_tag]\nw_base = 0.5\nw_max = 0.7\ntarget_degree = 2.0\npromotion_threshold = 3\n\n[ingest]\nwindow_char_cap = 150000\nmin_content_chars = 400\ndefault_goal_priority = 0.5\nallow_auto_captions = false\n\n[ai]\nactive_provider = \"codex\"\nfallback_provider = \"\"\ntimeout_seconds = 60\n\n[ai.routing]\ngrading = \"codex\"\ncanonical_ingest = \"codex\"\ncanonical_ingest_retry = \"\"\nauthoring = \"codex\"\n\n[ai.providers.codex]\ntype = \"codex_sdk\"\nmodel = \"gpt-5.5\"\ncheckout_path = \"/home/chloe/Documents/thinking/learnanything/codex\"\nrevision = \"<pinned-commit>\"\nstartup_command = \"\"\nstartup_timeout_seconds = 20\nhealthcheck_timeout_seconds = 5\nauth_mode = \"chatgpt\"\nreasoning_effort = \"medium\"\nreasoning_summary = \"none\"\nsdk_python_path = \"sdk/python/src\"\nsdk_codex_bin = \"\"\nsdk_launch_command = \"\"\nbase_url = \"http://127.0.0.1:8765\"\nhealthcheck_path = \"/health\"\nauthoring_path = \"/authoring-proposal\"\ncanonical_ingest_path = \"/canonical-ingest\"\ngrading_path = \"/grading-proposal\"\n\n[ai.providers.deepseek_flash]\ntype = \"openai_chat\"\nbase_url = \"https://api.deepseek.com\"\napi_key_env = \"DEEPSEEK_API_KEY\"\nmodel = \"deepseek-v4-flash\"\nresponse_format = \"json_object\"\nthinking = \"disabled\"\nmax_tokens = 8192\ntimeout_seconds = 90\n\n[ai.providers.deepseek_pro]\ntype = \"openai_chat\"\nbase_url = \"https://api.deepseek.com\"\napi_key_env = \"DEEPSEEK_API_KEY\"\nmodel = \"deepseek-v4-pro\"\nresponse_format = \"json_object\"\nthinking = \"enabled\"\nreasoning_effort = \"high\"\nmax_tokens = 16384\ntimeout_seconds = 180\n\n[codex]\nprovider = \"sdk\"\ncheckout_path = \"/home/chloe/Documents/thinking/learnanything/codex\"\nrevision = \"<pinned-commit>\"\nstartup_command = \"\"\nstartup_timeout_seconds = 20\nhealthcheck_timeout_seconds = 5\nauth_mode = \"chatgpt\"\nmodel = \"gpt-5.5\"\nreasoning_effort = \"medium\"\nreasoning_summary = \"none\"\nsdk_python_path = \"sdk/python/src\"\nsdk_codex_bin = \"\"\nsdk_launch_command = \"\"\nbase_url = \"http://127.0.0.1:8765\"\nhealthcheck_path = \"/health\"\nauthoring_path = \"/authoring-proposal\"\ncanonical_ingest_path = \"/canonical-ingest\"\ngrading_path = \"/grading-proposal\"\n\n# Family-keyed mastery damage per error type (spec §\"Error-aware updates\").\n# recall_failure is the deterministic attribution for `dont_know` attempts.\n[error_impacts]\nmax_sharpening = 3.0\n\n[error_impacts.recall_failure]\nfamilies = { recall = -0.25 }\nlo_mastery_delta = -0.05\nlocal_severity_gain = 0.8\n\n[error_impacts.scaffold_failure]\nfamilies = { recall = -0.35 }\nlo_mastery_delta = -0.05\nlocal_severity_gain = 1.5\n\n[error_impacts.arithmetic_slip]\nfamilies = { numeric = -0.05 }\nlo_mastery_delta = 0.0\nlocal_severity_gain = 0.35\n\n# Cross-LO propagation gates per error type (spec §\"Error-type gate\").\n[cross_lo_propagation.default]\nmax_depth = 3\nhop_decay = 0.5\ntotal_propagated_weight_cap = 0.7\n\n[cross_lo_propagation.error_gates.recall_failure]\nmean_factor = 0.0 # forgetting a definition is not evidence prereqs are weak\nvariance_factor = 0.25\nscope = \"all\"\n\n[cross_lo_propagation.error_gates.scaffold_failure]\nmean_factor = 0.0\nvariance_factor = 0.35\nscope = \"all\"\n\n[cross_lo_propagation.error_gates.arithmetic_slip]\nmean_factor = 0.0\nvariance_factor = 0.10\nscope = \"all\"\n\n[recall_coverage.severity_examples.first_dont_know]\nattempt_type = \"dont_know\"\nhints_used = 0\ncorrectness = 0.0\nexpected_correctness = 0.65\neffective_coverage = 0.85\nexpected_error_type = \"recall_failure\"\nexpected_severity_band = [0.70, 0.82]\n\n[recall_coverage.severity_examples.second_same_item_dont_know]\nattempt_type = \"dont_know\"\nhints_used = 0\ncorrectness = 0.0\nexpected_correctness = 0.65\neffective_coverage = 0.85\nrecent_same_item_failures = 1\nexpected_error_type = \"recall_failure\"\nexpected_severity_band = [0.95, 1.00]\n\n[recall_coverage.severity_examples.second_same_facet_dont_know]\nattempt_type = \"dont_know\"\nhints_used = 0\ncorrectness = 0.0\nexpected_correctness = 0.65\neffective_coverage = 0.85\nrecent_same_facet_failures = 1\nexpected_error_type = \"recall_failure\"\nexpected_severity_band = [0.80, 1.00]\n\n[recall_coverage.severity_examples.hinted_dont_know]\nattempt_type = \"dont_know\"\nhints_used = 2\ncorrectness = 0.0\nexpected_correctness = 0.65\neffective_coverage = 0.80\nexpected_error_type = \"scaffold_failure\"\nexpected_severity_band = [0.85, 0.95]\n\n[recall_coverage.severity_examples.arithmetic_slip]\nattempt_type = \"independent_attempt\"\ncorrectness = 0.75\nexpected_correctness = 0.70\neffective_coverage = 0.85\ntarget_error_type = \"arithmetic_slip\"\nexpected_error_type = \"arithmetic_slip\"\nexpected_severity_band = [0.25, 0.35]\n\n[recall_coverage.severity_examples.ambiguous_item]\nattempt_type = \"independent_attempt\"\ncorrectness = 0.0\nexpected_correctness = 0.70\neffective_coverage = 0.85\nbad_item_suspicion = 0.70\nexpected_error_type = \"recall_failure\"\nexpected_severity_band = [0.45, 0.75]\n"}, "96eb5c906aa28df898ce8a4485b0817efcf154bd": {"t": 1785750317.1337445, "n": 6304, "h": "4d1f8490fbf77304", "c": "schema_version = 1\n\n[storage]\nsqlite_path = \"state.sqlite\"\n\n[algorithms]\nalgorithm_version = \"mvp-0.7\"\n\n[scheduler]\nforgetting_risk_weight = 1.0\nrecent_error_weight = 0.50\nprobe_eig_weight = 0.25\nshort_session_minutes = 20\n# Seeded exploration over near-tie candidates so logged slates carry non-degenerate\n# selection propensities (off-policy learnability). See architecture_pivot.md Stage 0.\nselection_exploration_rate = 0.1\nselection_exploration_reward_window = 0.15\n\n[scheduler.surprise]\ntheta_pos = 1.5\ntheta_neg = 1.5\nalpha_interval = 0.3\nf_min = 0.5\nf_max = 1.5\nepsilon_error_surprise = 0.05\n\n[scheduler.followup]\ntau_followup_nats = 0.05\ngamma_min = 0.5\n\n[mastery]\nbase_observation_variance = 1.0\nsigma2_drift = 0.01\np_max = 4.0\n\n# IRT 2PL difficulty-aware mastery update (spec_irt_difficulty.md §4).\n# enabled = false restores the legacy logit-space Kalman update bit-for-bit.\n[mastery.irt]\nenabled = true\ndiscrimination_default = 1.0\ndifficulty_default = 0.0\ndifficulty_from_prior = true\ndifficulty_prior_scale = 2.5\nb_abs_max = 4.0\np_clip = 1e-4\nmu_abs_max = 5.0\nmax_logit_step = 4.0\n\n[probe]\nattempts_target_default = 3\nattempts_target_with_strong_claim = 1\nclaim_skip_threshold = 0.75\nvariance_convergence_threshold = 0.10\nhypothesis_set_max_size = 5\n\n# IRT difficulty-aware probe conditionals (spec_irt_difficulty.md §5).\n[probe.irt]\ntheta_mastered = 2.0\ntheta_unfamiliar = -2.0\ncut_mid = -1.0\ncut_high = 1.0\nunfamiliar_error_leak = 0.20\nerr_low_frac = 0.80\nerr_mid_frac = 0.50\n\n# Learner self-attributed misconception probe coverage (spec_irt_difficulty.md §12).\n[probe.self_tag]\nw_base = 0.5\nw_max = 0.7\ntarget_degree = 2.0\npromotion_threshold = 3\n\n[ingest]\nwindow_char_cap = 150000\nmin_content_chars = 400\ndefault_goal_priority = 0.5\nallow_auto_captions = false\n\n[ai]\nactive_provider = \"codex\"\nfallback_provider = \"\"\ntimeout_seconds = 60\n\n[ai.routing]\ngrading = \"codex\"\ncanonical_ingest = \"codex\"\ncanonical_ingest_retry = \"\"\nauthoring = \"codex\"\n\n[ai.providers.codex]\ntype = \"codex_sdk\"\nmodel = \"gpt-5.5\"\ncheckout_path = \"/home/chloe/Documents/thinking/learnanything/codex\"\nrevision = \"<pinned-commit>\"\nstartup_command = \"\"\nstartup_timeout_seconds = 20\nhealthcheck_timeout_seconds = 5\nauth_mode = \"chatgpt\"\nreasoning_effort = \"medium\"\nreasoning_summary = \"none\"\nsdk_python_path = \"sdk/python/src\"\nsdk_codex_bin = \"\"\nsdk_launch_command = \"\"\nbase_url = \"http://127.0.0.1:8765\"\nhealthcheck_path = \"/health\"\nauthoring_path = \"/authoring-proposal\"\ncanonical_ingest_path = \"/canonical-ingest\"\ngrading_path = \"/grading-proposal\"\n\n[ai.providers.deepseek_flash]\ntype = \"openai_chat\"\nbase_url = \"https://api.deepseek.com\"\napi_key_env = \"DEEPSEEK_API_KEY\"\nmodel = \"deepseek-v4-flash\"\nresponse_format = \"json_object\"\nthinking = \"disabled\"\nmax_tokens = 8192\ntimeout_seconds = 90\n\n[ai.providers.deepseek_pro]\ntype = \"openai_chat\"\nbase_url = \"https://api.deepseek.com\"\napi_key_env = \"DEEPSEEK_API_KEY\"\nmodel = \"deepseek-v4-pro\"\nresponse_format = \"json_object\"\nthinking = \"enabled\"\nreasoning_effort = \"high\"\nmax_tokens = 16384\ntimeout_seconds = 180\n\n[codex]\nprovider = \"sdk\"\ncheckout_path = \"/home/chloe/Documents/thinking/learnanything/codex\"\nrevision = \"<pinned-commit>\"\nstartup_command = \"\"\nstartup_timeout_seconds = 20\nhealthcheck_timeout_seconds = 5\nauth_mode = \"chatgpt\"\nmodel = \"gpt-5.5\"\nreasoning_effort = \"medium\"\nreasoning_summary = \"none\"\nsdk_python_path = \"sdk/python/src\"\nsdk_codex_bin = \"\"\nsdk_launch_command = \"\"\nbase_url = \"http://127.0.0.1:8765\"\nhealthcheck_path = \"/health\"\nauthoring_path = \"/authoring-proposal\"\ncanonical_ingest_path = \"/canonical-ingest\"\ngrading_path = \"/grading-proposal\"\n\n# Family-keyed mastery damage per error type (spec §\"Error-aware updates\").\n# recall_failure is the deterministic attribution for `dont_know` attempts.\n[error_impacts]\nmax_sharpening = 3.0\n\n[error_impacts.recall_failure]\nfamilies = { recall = -0.25 }\nlo_mastery_delta = -0.05\nlocal_severity_gain = 0.8\n\n[error_impacts.scaffold_failure]\nfamilies = { recall = -0.35 }\nlo_mastery_delta = -0.05\nlocal_severity_gain = 1.5\n\n[error_impacts.arithmetic_slip]\nfamilies = { numeric = -0.05 }\nlo_mastery_delta = 0.0\nlocal_severity_gain = 0.35\n\n# Cross-LO propagation gates per error type (spec §\"Error-type gate\").\n[cross_lo_propagation.default]\nmax_depth = 3\nhop_decay = 0.5\ntotal_propagated_weight_cap = 0.7\n\n[cross_lo_propagation.error_gates.recall_failure]\nmean_factor = 0.0 # forgetting a definition is not evidence prereqs are weak\nvariance_factor = 0.25\nscope = \"all\"\n\n[cross_lo_propagation.error_gates.scaffold_failure]\nmean_factor = 0.0\nvariance_factor = 0.35\nscope = \"all\"\n\n[cross_lo_propagation.error_gates.arithmetic_slip]\nmean_factor = 0.0\nvariance_factor = 0.10\nscope = \"all\"\n\n[recall_coverage.severity_examples.first_dont_know]\nattempt_type = \"dont_know\"\nhints_used = 0\ncorrectness = 0.0\nexpected_correctness = 0.65\neffective_coverage = 0.85\nexpected_error_type = \"recall_failure\"\nexpected_severity_band = [0.70, 0.82]\n\n[recall_coverage.severity_examples.second_same_item_dont_know]\nattempt_type = \"dont_know\"\nhints_used = 0\ncorrectness = 0.0\nexpected_correctness = 0.65\neffective_coverage = 0.85\nrecent_same_item_failures = 1\nexpected_error_type = \"recall_failure\"\nexpected_severity_band = [0.95, 1.00]\n\n[recall_coverage.severity_examples.second_same_facet_dont_know]\nattempt_type = \"dont_know\"\nhints_used = 0\ncorrectness = 0.0\nexpected_correctness = 0.65\neffective_coverage = 0.85\nrecent_same_facet_failures = 1\nexpected_error_type = \"recall_failure\"\nexpected_severity_band = [0.80, 1.00]\n\n[recall_coverage.severity_examples.hinted_dont_know]\nattempt_type = \"dont_know\"\nhints_used = 2\ncorrectness = 0.0\nexpected_correctness = 0.65\neffective_coverage = 0.80\nexpected_error_type = \"scaffold_failure\"\nexpected_severity_band = [0.85, 0.95]\n\n[recall_coverage.severity_examples.arithmetic_slip]\nattempt_type = \"independent_attempt\"\ncorrectness = 0.75\nexpected_correctness = 0.70\neffective_coverage = 0.85\ntarget_error_type = \"arithmetic_slip\"\nexpected_error_type = \"arithmetic_slip\"\nexpected_severity_band = [0.25, 0.35]\n\n[recall_coverage.severity_examples.ambiguous_item]\nattempt_type = \"independent_attempt\"\ncorrectness = 0.0\nexpected_correctness = 0.70\neffective_coverage = 0.85\nbad_item_suspicion = 0.70\nexpected_error_type = \"recall_failure\"\nexpected_severity_band = [0.45, 0.75]\n"}, "b19e81d9993c28e995049da1aa16f8d316d56d68": {"t": 1785750318.6343951, "n": 6304, "h": "e2eff264c84890f3", "c": "schema_version = 1\n\n[storage]\nsqlite_path = \"state.sqlite\"\n\n[algorithms]\nalgorithm_version = \"mvp-0.6\"\n\n[scheduler]\nforgetting_risk_weight = 1.0\nrecent_error_weight = 0.50\nprobe_eig_weight = 0.25\nshort_session_minutes = 20\n# Seeded exploration over near-tie candidates so logged slates carry non-degenerate\n# selection propensities (off-policy learnability). See architecture_pivot.md Stage 0.\nselection_exploration_rate = 0.1\nselection_exploration_reward_window = 0.15\n\n[scheduler.surprise]\ntheta_pos = 1.5\ntheta_neg = 1.5\nalpha_interval = 0.3\nf_min = 0.5\nf_max = 1.5\nepsilon_error_surprise = 0.05\n\n[scheduler.followup]\ntau_followup_nats = 0.05\ngamma_min = 0.5\n\n[mastery]\nbase_observation_variance = 1.0\nsigma2_drift = 0.01\np_max = 4.0\n\n# IRT 2PL difficulty-aware mastery update (spec_irt_difficulty.md §4).\n# enabled = false restores the legacy logit-space Kalman update bit-for-bit.\n[mastery.irt]\nenabled = true\ndiscrimination_default = 1.0\ndifficulty_default = 0.0\ndifficulty_from_prior = true\ndifficulty_prior_scale = 2.5\nb_abs_max = 4.0\np_clip = 1e-4\nmu_abs_max = 5.0\nmax_logit_step = 4.0\n\n[probe]\nattempts_target_default = 3\nattempts_target_with_strong_claim = 1\nclaim_skip_threshold = 0.75\nvariance_convergence_threshold = 0.10\nhypothesis_set_max_size = 5\n\n# IRT difficulty-aware probe conditionals (spec_irt_difficulty.md §5).\n[probe.irt]\ntheta_mastered = 2.0\ntheta_unfamiliar = -2.0\ncut_mid = -1.0\ncut_high = 1.0\nunfamiliar_error_leak = 0.20\nerr_low_frac = 0.80\nerr_mid_frac = 0.50\n\n# Learner self-attributed misconception probe coverage (spec_irt_difficulty.md §12).\n[probe.self_tag]\nw_base = 0.5\nw_max = 0.7\ntarget_degree = 2.0\npromotion_threshold = 3\n\n[ingest]\nwindow_char_cap = 150000\nmin_content_chars = 400\ndefault_goal_priority = 0.5\nallow_auto_captions = false\n\n[ai]\nactive_provider = \"codex\"\nfallback_provider = \"\"\ntimeout_seconds = 60\n\n[ai.routing]\ngrading = \"codex\"\ncanonical_ingest = \"codex\"\ncanonical_ingest_retry = \"\"\nauthoring = \"codex\"\n\n[ai.providers.codex]\ntype = \"codex_sdk\"\nmodel = \"gpt-5.5\"\ncheckout_path = \"/home/chloe/Documents/thinking/learnanything/codex\"\nrevision = \"<pinned-commit>\"\nstartup_command = \"\"\nstartup_timeout_seconds = 20\nhealthcheck_timeout_seconds = 5\nauth_mode = \"chatgpt\"\nreasoning_effort = \"medium\"\nreasoning_summary = \"none\"\nsdk_python_path = \"sdk/python/src\"\nsdk_codex_bin = \"\"\nsdk_launch_command = \"\"\nbase_url = \"http://127.0.0.1:8765\"\nhealthcheck_path = \"/health\"\nauthoring_path = \"/authoring-proposal\"\ncanonical_ingest_path = \"/canonical-ingest\"\ngrading_path = \"/grading-proposal\"\n\n[ai.providers.deepseek_flash]\ntype = \"openai_chat\"\nbase_url = \"https://api.deepseek.com\"\napi_key_env = \"DEEPSEEK_API_KEY\"\nmodel = \"deepseek-v4-flash\"\nresponse_format = \"json_object\"\nthinking = \"disabled\"\nmax_tokens = 8192\ntimeout_seconds = 90\n\n[ai.providers.deepseek_pro]\ntype = \"openai_chat\"\nbase_url = \"https://api.deepseek.com\"\napi_key_env = \"DEEPSEEK_API_KEY\"\nmodel = \"deepseek-v4-pro\"\nresponse_format = \"json_object\"\nthinking = \"enabled\"\nreasoning_effort = \"high\"\nmax_tokens = 16384\ntimeout_seconds = 180\n\n[codex]\nprovider = \"sdk\"\ncheckout_path = \"/home/chloe/Documents/thinking/learnanything/codex\"\nrevision = \"<pinned-commit>\"\nstartup_command = \"\"\nstartup_timeout_seconds = 20\nhealthcheck_timeout_seconds = 5\nauth_mode = \"chatgpt\"\nmodel = \"gpt-5.5\"\nreasoning_effort = \"medium\"\nreasoning_summary = \"none\"\nsdk_python_path = \"sdk/python/src\"\nsdk_codex_bin = \"\"\nsdk_launch_command = \"\"\nbase_url = \"http://127.0.0.1:8765\"\nhealthcheck_path = \"/health\"\nauthoring_path = \"/authoring-proposal\"\ncanonical_ingest_path = \"/canonical-ingest\"\ngrading_path = \"/grading-proposal\"\n\n# Family-keyed mastery damage per error type (spec §\"Error-aware updates\").\n# recall_failure is the deterministic attribution for `dont_know` attempts.\n[error_impacts]\nmax_sharpening = 3.0\n\n[error_impacts.recall_failure]\nfamilies = { recall = -0.25 }\nlo_mastery_delta = -0.05\nlocal_severity_gain = 0.8\n\n[error_impacts.scaffold_failure]\nfamilies = { recall = -0.35 }\nlo_mastery_delta = -0.05\nlocal_severity_gain = 1.5\n\n[error_impacts.arithmetic_slip]\nfamilies = { numeric = -0.05 }\nlo_mastery_delta = 0.0\nlocal_severity_gain = 0.35\n\n# Cross-LO propagation gates per error type (spec §\"Error-type gate\").\n[cross_lo_propagation.default]\nmax_depth = 3\nhop_decay = 0.5\ntotal_propagated_weight_cap = 0.7\n\n[cross_lo_propagation.error_gates.recall_failure]\nmean_factor = 0.0 # forgetting a definition is not evidence prereqs are weak\nvariance_factor = 0.25\nscope = \"all\"\n\n[cross_lo_propagation.error_gates.scaffold_failure]\nmean_factor = 0.0\nvariance_factor = 0.35\nscope = \"all\"\n\n[cross_lo_propagation.error_gates.arithmetic_slip]\nmean_factor = 0.0\nvariance_factor = 0.10\nscope = \"all\"\n\n[recall_coverage.severity_examples.first_dont_know]\nattempt_type = \"dont_know\"\nhints_used = 0\ncorrectness = 0.0\nexpected_correctness = 0.65\neffective_coverage = 0.85\nexpected_error_type = \"recall_failure\"\nexpected_severity_band = [0.70, 0.82]\n\n[recall_coverage.severity_examples.second_same_item_dont_know]\nattempt_type = \"dont_know\"\nhints_used = 0\ncorrectness = 0.0\nexpected_correctness = 0.65\neffective_coverage = 0.85\nrecent_same_item_failures = 1\nexpected_error_type = \"recall_failure\"\nexpected_severity_band = [0.95, 1.00]\n\n[recall_coverage.severity_examples.second_same_facet_dont_know]\nattempt_type = \"dont_know\"\nhints_used = 0\ncorrectness = 0.0\nexpected_correctness = 0.65\neffective_coverage = 0.85\nrecent_same_facet_failures = 1\nexpected_error_type = \"recall_failure\"\nexpected_severity_band = [0.80, 1.00]\n\n[recall_coverage.severity_examples.hinted_dont_know]\nattempt_type = \"dont_know\"\nhints_used = 2\ncorrectness = 0.0\nexpected_correctness = 0.65\neffective_coverage = 0.80\nexpected_error_type = \"scaffold_failure\"\nexpected_severity_band = [0.85, 0.95]\n\n[recall_coverage.severity_examples.arithmetic_slip]\nattempt_type = \"independent_attempt\"\ncorrectness = 0.75\nexpected_correctness = 0.70\neffective_coverage = 0.85\ntarget_error_type = \"arithmetic_slip\"\nexpected_error_type = \"arithmetic_slip\"\nexpected_severity_band = [0.25, 0.35]\n\n[recall_coverage.severity_examples.ambiguous_item]\nattempt_type = \"independent_attempt\"\ncorrectness = 0.0\nexpected_correctness = 0.70\neffective_coverage = 0.85\nbad_item_suspicion = 0.70\nexpected_error_type = \"recall_failure\"\nexpected_severity_band = [0.45, 0.75]\n"}, "565100878e11bc9ac281139570040c118fbaf1a5": {"t": 1785750319.7071776, "n": 6304, "h": "5a3d223da6708acc", "c": "schema_version = 1\n\n[storage]\nsqlite_path = \"state.sqlite\"\n\n[algorithms]\nalgorithm_version = \"mvp-0.5\"\n\n[scheduler]\nforgetting_risk_weight = 1.0\nrecent_error_weight = 0.50\nprobe_eig_weight = 0.25\nshort_session_minutes = 20\n# Seeded exploration over near-tie candidates so logged slates carry non-degenerate\n# selection propensities (off-policy learnability). See architecture_pivot.md Stage 0.\nselection_exploration_rate = 0.1\nselection_exploration_reward_window = 0.15\n\n[scheduler.surprise]\ntheta_pos = 1.5\ntheta_neg = 1.5\nalpha_interval = 0.3\nf_min = 0.5\nf_max = 1.5\nepsilon_error_surprise = 0.05\n\n[scheduler.followup]\ntau_followup_nats = 0.05\ngamma_min = 0.5\n\n[mastery]\nbase_observation_variance = 1.0\nsigma2_drift = 0.01\np_max = 4.0\n\n# IRT 2PL difficulty-aware mastery update (spec_irt_difficulty.md §4).\n# enabled = false restores the legacy logit-space Kalman update bit-for-bit.\n[mastery.irt]\nenabled = true\ndiscrimination_default = 1.0\ndifficulty_default = 0.0\ndifficulty_from_prior = true\ndifficulty_prior_scale = 2.5\nb_abs_max = 4.0\np_clip = 1e-4\nmu_abs_max = 5.0\nmax_logit_step = 4.0\n\n[probe]\nattempts_target_default = 3\nattempts_target_with_strong_claim = 1\nclaim_skip_threshold = 0.75\nvariance_convergence_threshold = 0.10\nhypothesis_set_max_size = 5\n\n# IRT difficulty-aware probe conditionals (spec_irt_difficulty.md §5).\n[probe.irt]\ntheta_mastered = 2.0\ntheta_unfamiliar = -2.0\ncut_mid = -1.0\ncut_high = 1.0\nunfamiliar_error_leak = 0.20\nerr_low_frac = 0.80\nerr_mid_frac = 0.50\n\n# Learner self-attributed misconception probe coverage (spec_irt_difficulty.md §12).\n[probe.self_tag]\nw_base = 0.5\nw_max = 0.7\ntarget_degree = 2.0\npromotion_threshold = 3\n\n[ingest]\nwindow_char_cap = 150000\nmin_content_chars = 400\ndefault_goal_priority = 0.5\nallow_auto_captions = false\n\n[ai]\nactive_provider = \"codex\"\nfallback_provider = \"\"\ntimeout_seconds = 60\n\n[ai.routing]\ngrading = \"codex\"\ncanonical_ingest = \"codex\"\ncanonical_ingest_retry = \"\"\nauthoring = \"codex\"\n\n[ai.providers.codex]\ntype = \"codex_sdk\"\nmodel = \"gpt-5.5\"\ncheckout_path = \"/home/chloe/Documents/thinking/learnanything/codex\"\nrevision = \"<pinned-commit>\"\nstartup_command = \"\"\nstartup_timeout_seconds = 20\nhealthcheck_timeout_seconds = 5\nauth_mode = \"chatgpt\"\nreasoning_effort = \"medium\"\nreasoning_summary = \"none\"\nsdk_python_path = \"sdk/python/src\"\nsdk_codex_bin = \"\"\nsdk_launch_command = \"\"\nbase_url = \"http://127.0.0.1:8765\"\nhealthcheck_path = \"/health\"\nauthoring_path = \"/authoring-proposal\"\ncanonical_ingest_path = \"/canonical-ingest\"\ngrading_path = \"/grading-proposal\"\n\n[ai.providers.deepseek_flash]\ntype = \"openai_chat\"\nbase_url = \"https://api.deepseek.com\"\napi_key_env = \"DEEPSEEK_API_KEY\"\nmodel = \"deepseek-v4-flash\"\nresponse_format = \"json_object\"\nthinking = \"disabled\"\nmax_tokens = 8192\ntimeout_seconds = 90\n\n[ai.providers.deepseek_pro]\ntype = \"openai_chat\"\nbase_url = \"https://api.deepseek.com\"\napi_key_env = \"DEEPSEEK_API_KEY\"\nmodel = \"deepseek-v4-pro\"\nresponse_format = \"json_object\"\nthinking = \"enabled\"\nreasoning_effort = \"high\"\nmax_tokens = 16384\ntimeout_seconds = 180\n\n[codex]\nprovider = \"sdk\"\ncheckout_path = \"/home/chloe/Documents/thinking/learnanything/codex\"\nrevision = \"<pinned-commit>\"\nstartup_command = \"\"\nstartup_timeout_seconds = 20\nhealthcheck_timeout_seconds = 5\nauth_mode = \"chatgpt\"\nmodel = \"gpt-5.5\"\nreasoning_effort = \"medium\"\nreasoning_summary = \"none\"\nsdk_python_path = \"sdk/python/src\"\nsdk_codex_bin = \"\"\nsdk_launch_command = \"\"\nbase_url = \"http://127.0.0.1:8765\"\nhealthcheck_path = \"/health\"\nauthoring_path = \"/authoring-proposal\"\ncanonical_ingest_path = \"/canonical-ingest\"\ngrading_path = \"/grading-proposal\"\n\n# Family-keyed mastery damage per error type (spec §\"Error-aware updates\").\n# recall_failure is the deterministic attribution for `dont_know` attempts.\n[error_impacts]\nmax_sharpening = 3.0\n\n[error_impacts.recall_failure]\nfamilies = { recall = -0.25 }\nlo_mastery_delta = -0.05\nlocal_severity_gain = 0.8\n\n[error_impacts.scaffold_failure]\nfamilies = { recall = -0.35 }\nlo_mastery_delta = -0.05\nlocal_severity_gain = 1.5\n\n[error_impacts.arithmetic_slip]\nfamilies = { numeric = -0.05 }\nlo_mastery_delta = 0.0\nlocal_severity_gain = 0.35\n\n# Cross-LO propagation gates per error type (spec §\"Error-type gate\").\n[cross_lo_propagation.default]\nmax_depth = 3\nhop_decay = 0.5\ntotal_propagated_weight_cap = 0.7\n\n[cross_lo_propagation.error_gates.recall_failure]\nmean_factor = 0.0 # forgetting a definition is not evidence prereqs are weak\nvariance_factor = 0.25\nscope = \"all\"\n\n[cross_lo_propagation.error_gates.scaffold_failure]\nmean_factor = 0.0\nvariance_factor = 0.35\nscope = \"all\"\n\n[cross_lo_propagation.error_gates.arithmetic_slip]\nmean_factor = 0.0\nvariance_factor = 0.10\nscope = \"all\"\n\n[recall_coverage.severity_examples.first_dont_know]\nattempt_type = \"dont_know\"\nhints_used = 0\ncorrectness = 0.0\nexpected_correctness = 0.65\neffective_coverage = 0.85\nexpected_error_type = \"recall_failure\"\nexpected_severity_band = [0.70, 0.82]\n\n[recall_coverage.severity_examples.second_same_item_dont_know]\nattempt_type = \"dont_know\"\nhints_used = 0\ncorrectness = 0.0\nexpected_correctness = 0.65\neffective_coverage = 0.85\nrecent_same_item_failures = 1\nexpected_error_type = \"recall_failure\"\nexpected_severity_band = [0.95, 1.00]\n\n[recall_coverage.severity_examples.second_same_facet_dont_know]\nattempt_type = \"dont_know\"\nhints_used = 0\ncorrectness = 0.0\nexpected_correctness = 0.65\neffective_coverage = 0.85\nrecent_same_facet_failures = 1\nexpected_error_type = \"recall_failure\"\nexpected_severity_band = [0.80, 1.00]\n\n[recall_coverage.severity_examples.hinted_dont_know]\nattempt_type = \"dont_know\"\nhints_used = 2\ncorrectness = 0.0\nexpected_correctness = 0.65\neffective_coverage = 0.80\nexpected_error_type = \"scaffold_failure\"\nexpected_severity_band = [0.85, 0.95]\n\n[recall_coverage.severity_examples.arithmetic_slip]\nattempt_type = \"independent_attempt\"\ncorrectness = 0.75\nexpected_correctness = 0.70\neffective_coverage = 0.85\ntarget_error_type = \"arithmetic_slip\"\nexpected_error_type = \"arithmetic_slip\"\nexpected_severity_band = [0.25, 0.35]\n\n[recall_coverage.severity_examples.ambiguous_item]\nattempt_type = \"independent_attempt\"\ncorrectness = 0.0\nexpected_correctness = 0.70\neffective_coverage = 0.85\nbad_item_suspicion = 0.70\nexpected_error_type = \"recall_failure\"\nexpected_severity_band = [0.45, 0.75]\n"}, "b48c1ee9be4bc2a4ff5612870d8bf38391e7061b": {"t": 1785750320.7751112, "n": 6330, "h": "7ab240b4649f2836", "c": "schema_version = 1\n\n[storage]\nsqlite_path = \"state.sqlite\"\n\n[algorithms]\nalgorithm_version = \"mvp-0.4\"\n\n[scheduler]\nforgetting_risk_weight = 1.0\nactive_goal_weight = 0.35\nrecent_error_weight = 0.50\nprobe_eig_weight = 0.25\nshort_session_minutes = 20\n# Seeded exploration over near-tie candidates so logged slates carry non-degenerate\n# selection propensities (off-policy learnability). See architecture_pivot.md Stage 0.\nselection_exploration_rate = 0.1\nselection_exploration_reward_window = 0.15\n\n[scheduler.surprise]\ntheta_pos = 1.5\ntheta_neg = 1.5\nalpha_interval = 0.3\nf_min = 0.5\nf_max = 1.5\nepsilon_error_surprise = 0.05\n\n[scheduler.followup]\ntau_followup_nats = 0.05\ngamma_min = 0.5\n\n[mastery]\nbase_observation_variance = 1.0\nsigma2_drift = 0.01\np_max = 4.0\n\n# IRT 2PL difficulty-aware mastery update (spec_irt_difficulty.md §4).\n# enabled = false restores the legacy logit-space Kalman update bit-for-bit.\n[mastery.irt]\nenabled = true\ndiscrimination_default = 1.0\ndifficulty_default = 0.0\ndifficulty_from_prior = true\ndifficulty_prior_scale = 2.5\nb_abs_max = 4.0\np_clip = 1e-4\nmu_abs_max = 5.0\nmax_logit_step = 4.0\n\n[probe]\nattempts_target_default = 3\nattempts_target_with_strong_claim = 1\nclaim_skip_threshold = 0.75\nvariance_convergence_threshold = 0.10\nhypothesis_set_max_size = 5\n\n# IRT difficulty-aware probe conditionals (spec_irt_difficulty.md §5).\n[probe.irt]\ntheta_mastered = 2.0\ntheta_unfamiliar = -2.0\ncut_mid = -1.0\ncut_high = 1.0\nunfamiliar_error_leak = 0.20\nerr_low_frac = 0.80\nerr_mid_frac = 0.50\n\n# Learner self-attributed misconception probe coverage (spec_irt_difficulty.md §12).\n[probe.self_tag]\nw_base = 0.5\nw_max = 0.7\ntarget_degree = 2.0\npromotion_threshold = 3\n\n[ingest]\nwindow_char_cap = 150000\nmin_content_chars = 400\ndefault_goal_priority = 0.5\nallow_auto_captions = false\n\n[ai]\nactive_provider = \"codex\"\nfallback_provider = \"\"\ntimeout_seconds = 60\n\n[ai.routing]\ngrading = \"codex\"\ncanonical_ingest = \"codex\"\ncanonical_ingest_retry = \"\"\nauthoring = \"codex\"\n\n[ai.providers.codex]\ntype = \"codex_sdk\"\nmodel = \"gpt-5.5\"\ncheckout_path = \"/home/chloe/Documents/thinking/learnanything/codex\"\nrevision = \"<pinned-commit>\"\nstartup_command = \"\"\nstartup_timeout_seconds = 20\nhealthcheck_timeout_seconds = 5\nauth_mode = \"chatgpt\"\nreasoning_effort = \"medium\"\nreasoning_summary = \"none\"\nsdk_python_path = \"sdk/python/src\"\nsdk_codex_bin = \"\"\nsdk_launch_command = \"\"\nbase_url = \"http://127.0.0.1:8765\"\nhealthcheck_path = \"/health\"\nauthoring_path = \"/authoring-proposal\"\ncanonical_ingest_path = \"/canonical-ingest\"\ngrading_path = \"/grading-proposal\"\n\n[ai.providers.deepseek_flash]\ntype = \"openai_chat\"\nbase_url = \"https://api.deepseek.com\"\napi_key_env = \"DEEPSEEK_API_KEY\"\nmodel = \"deepseek-v4-flash\"\nresponse_format = \"json_object\"\nthinking = \"disabled\"\nmax_tokens = 8192\ntimeout_seconds = 90\n\n[ai.providers.deepseek_pro]\ntype = \"openai_chat\"\nbase_url = \"https://api.deepseek.com\"\napi_key_env = \"DEEPSEEK_API_KEY\"\nmodel = \"deepseek-v4-pro\"\nresponse_format = \"json_object\"\nthinking = \"enabled\"\nreasoning_effort = \"high\"\nmax_tokens = 16384\ntimeout_seconds = 180\n\n[codex]\nprovider = \"sdk\"\ncheckout_path = \"/home/chloe/Documents/thinking/learnanything/codex\"\nrevision = \"<pinned-commit>\"\nstartup_command = \"\"\nstartup_timeout_seconds = 20\nhealthcheck_timeout_seconds = 5\nauth_mode = \"chatgpt\"\nmodel = \"gpt-5.5\"\nreasoning_effort = \"medium\"\nreasoning_summary = \"none\"\nsdk_python_path = \"sdk/python/src\"\nsdk_codex_bin = \"\"\nsdk_launch_command = \"\"\nbase_url = \"http://127.0.0.1:8765\"\nhealthcheck_path = \"/health\"\nauthoring_path = \"/authoring-proposal\"\ncanonical_ingest_path = \"/canonical-ingest\"\ngrading_path = \"/grading-proposal\"\n\n# Family-keyed mastery damage per error type (spec §\"Error-aware updates\").\n# recall_failure is the deterministic attribution for `dont_know` attempts.\n[error_impacts]\nmax_sharpening = 3.0\n\n[error_impacts.recall_failure]\nfamilies = { recall = -0.25 }\nlo_mastery_delta = -0.05\nlocal_severity_gain = 0.8\n\n[error_impacts.scaffold_failure]\nfamilies = { recall = -0.35 }\nlo_mastery_delta = -0.05\nlocal_severity_gain = 1.5\n\n[error_impacts.arithmetic_slip]\nfamilies = { numeric = -0.05 }\nlo_mastery_delta = 0.0\nlocal_severity_gain = 0.35\n\n# Cross-LO propagation gates per error type (spec §\"Error-type gate\").\n[cross_lo_propagation.default]\nmax_depth = 3\nhop_decay = 0.5\ntotal_propagated_weight_cap = 0.7\n\n[cross_lo_propagation.error_gates.recall_failure]\nmean_factor = 0.0 # forgetting a definition is not evidence prereqs are weak\nvariance_factor = 0.25\nscope = \"all\"\n\n[cross_lo_propagation.error_gates.scaffold_failure]\nmean_factor = 0.0\nvariance_factor = 0.35\nscope = \"all\"\n\n[cross_lo_propagation.error_gates.arithmetic_slip]\nmean_factor = 0.0\nvariance_factor = 0.10\nscope = \"all\"\n\n[recall_coverage.severity_examples.first_dont_know]\nattempt_type = \"dont_know\"\nhints_used = 0\ncorrectness = 0.0\nexpected_correctness = 0.65\neffective_coverage = 0.85\nexpected_error_type = \"recall_failure\"\nexpected_severity_band = [0.70, 0.82]\n\n[recall_coverage.severity_examples.second_same_item_dont_know]\nattempt_type = \"dont_know\"\nhints_used = 0\ncorrectness = 0.0\nexpected_correctness = 0.65\neffective_coverage = 0.85\nrecent_same_item_failures = 1\nexpected_error_type = \"recall_failure\"\nexpected_severity_band = [0.95, 1.00]\n\n[recall_coverage.severity_examples.second_same_facet_dont_know]\nattempt_type = \"dont_know\"\nhints_used = 0\ncorrectness = 0.0\nexpected_correctness = 0.65\neffective_coverage = 0.85\nrecent_same_facet_failures = 1\nexpected_error_type = \"recall_failure\"\nexpected_severity_band = [0.80, 1.00]\n\n[recall_coverage.severity_examples.hinted_dont_know]\nattempt_type = \"dont_know\"\nhints_used = 2\ncorrectness = 0.0\nexpected_correctness = 0.65\neffective_coverage = 0.80\nexpected_error_type = \"scaffold_failure\"\nexpected_severity_band = [0.85, 0.95]\n\n[recall_coverage.severity_examples.arithmetic_slip]\nattempt_type = \"independent_attempt\"\ncorrectness = 0.75\nexpected_correctness = 0.70\neffective_coverage = 0.85\ntarget_error_type = \"arithmetic_slip\"\nexpected_error_type = \"arithmetic_slip\"\nexpected_severity_band = [0.25, 0.35]\n\n[recall_coverage.severity_examples.ambiguous_item]\nattempt_type = \"independent_attempt\"\ncorrectness = 0.0\nexpected_correctness = 0.70\neffective_coverage = 0.85\nbad_item_suspicion = 0.70\nexpected_error_type = \"recall_failure\"\nexpected_severity_band = [0.45, 0.75]\n"}, "a02b11ed403a376167112e21192c7de7692fdf17": {"t": 1785750321.9089544, "n": 6330, "h": "1c29d512b6c90312", "c": "schema_version = 1\n\n[storage]\nsqlite_path = \"state.sqlite\"\n\n[algorithms]\nalgorithm_version = \"mvp-0.3\"\n\n[scheduler]\nforgetting_risk_weight = 1.0\nactive_goal_weight = 0.35\nrecent_error_weight = 0.50\nprobe_eig_weight = 0.25\nshort_session_minutes = 20\n# Seeded exploration over near-tie candidates so logged slates carry non-degenerate\n# selection propensities (off-policy learnability). See architecture_pivot.md Stage 0.\nselection_exploration_rate = 0.1\nselection_exploration_reward_window = 0.15\n\n[scheduler.surprise]\ntheta_pos = 1.5\ntheta_neg = 1.5\nalpha_interval = 0.3\nf_min = 0.5\nf_max = 1.5\nepsilon_error_surprise = 0.05\n\n[scheduler.followup]\ntau_followup_nats = 0.05\ngamma_min = 0.5\n\n[mastery]\nbase_observation_variance = 1.0\nsigma2_drift = 0.01\np_max = 4.0\n\n# IRT 2PL difficulty-aware mastery update (spec_irt_difficulty.md §4).\n# enabled = false restores the legacy logit-space Kalman update bit-for-bit.\n[mastery.irt]\nenabled = true\ndiscrimination_default = 1.0\ndifficulty_default = 0.0\ndifficulty_from_prior = true\ndifficulty_prior_scale = 2.5\nb_abs_max = 4.0\np_clip = 1e-4\nmu_abs_max = 5.0\nmax_logit_step = 4.0\n\n[probe]\nattempts_target_default = 3\nattempts_target_with_strong_claim = 1\nclaim_skip_threshold = 0.75\nvariance_convergence_threshold = 0.10\nhypothesis_set_max_size = 5\n\n# IRT difficulty-aware probe conditionals (spec_irt_difficulty.md §5).\n[probe.irt]\ntheta_mastered = 2.0\ntheta_unfamiliar = -2.0\ncut_mid = -1.0\ncut_high = 1.0\nunfamiliar_error_leak = 0.20\nerr_low_frac = 0.80\nerr_mid_frac = 0.50\n\n# Learner self-attributed misconception probe coverage (spec_irt_difficulty.md §12).\n[probe.self_tag]\nw_base = 0.5\nw_max = 0.7\ntarget_degree = 2.0\npromotion_threshold = 3\n\n[ingest]\nwindow_char_cap = 150000\nmin_content_chars = 400\ndefault_goal_priority = 0.5\nallow_auto_captions = false\n\n[ai]\nactive_provider = \"codex\"\nfallback_provider = \"\"\ntimeout_seconds = 60\n\n[ai.routing]\ngrading = \"codex\"\ncanonical_ingest = \"codex\"\ncanonical_ingest_retry = \"\"\nauthoring = \"codex\"\n\n[ai.providers.codex]\ntype = \"codex_sdk\"\nmodel = \"gpt-5.5\"\ncheckout_path = \"/home/chloe/Documents/thinking/learnanything/codex\"\nrevision = \"<pinned-commit>\"\nstartup_command = \"\"\nstartup_timeout_seconds = 20\nhealthcheck_timeout_seconds = 5\nauth_mode = \"chatgpt\"\nreasoning_effort = \"medium\"\nreasoning_summary = \"none\"\nsdk_python_path = \"sdk/python/src\"\nsdk_codex_bin = \"\"\nsdk_launch_command = \"\"\nbase_url = \"http://127.0.0.1:8765\"\nhealthcheck_path = \"/health\"\nauthoring_path = \"/authoring-proposal\"\ncanonical_ingest_path = \"/canonical-ingest\"\ngrading_path = \"/grading-proposal\"\n\n[ai.providers.deepseek_flash]\ntype = \"openai_chat\"\nbase_url = \"https://api.deepseek.com\"\napi_key_env = \"DEEPSEEK_API_KEY\"\nmodel = \"deepseek-v4-flash\"\nresponse_format = \"json_object\"\nthinking = \"disabled\"\nmax_tokens = 8192\ntimeout_seconds = 90\n\n[ai.providers.deepseek_pro]\ntype = \"openai_chat\"\nbase_url = \"https://api.deepseek.com\"\napi_key_env = \"DEEPSEEK_API_KEY\"\nmodel = \"deepseek-v4-pro\"\nresponse_format = \"json_object\"\nthinking = \"enabled\"\nreasoning_effort = \"high\"\nmax_tokens = 16384\ntimeout_seconds = 180\n\n[codex]\nprovider = \"sdk\"\ncheckout_path = \"/home/chloe/Documents/thinking/learnanything/codex\"\nrevision = \"<pinned-commit>\"\nstartup_command = \"\"\nstartup_timeout_seconds = 20\nhealthcheck_timeout_seconds = 5\nauth_mode = \"chatgpt\"\nmodel = \"gpt-5.5\"\nreasoning_effort = \"medium\"\nreasoning_summary = \"none\"\nsdk_python_path = \"sdk/python/src\"\nsdk_codex_bin = \"\"\nsdk_launch_command = \"\"\nbase_url = \"http://127.0.0.1:8765\"\nhealthcheck_path = \"/health\"\nauthoring_path = \"/authoring-proposal\"\ncanonical_ingest_path = \"/canonical-ingest\"\ngrading_path = \"/grading-proposal\"\n\n# Family-keyed mastery damage per error type (spec §\"Error-aware updates\").\n# recall_failure is the deterministic attribution for `dont_know` attempts.\n[error_impacts]\nmax_sharpening = 3.0\n\n[error_impacts.recall_failure]\nfamilies = { recall = -0.25 }\nlo_mastery_delta = -0.05\nlocal_severity_gain = 0.8\n\n[error_impacts.scaffold_failure]\nfamilies = { recall = -0.35 }\nlo_mastery_delta = -0.05\nlocal_severity_gain = 1.5\n\n[error_impacts.arithmetic_slip]\nfamilies = { numeric = -0.05 }\nlo_mastery_delta = 0.0\nlocal_severity_gain = 0.35\n\n# Cross-LO propagation gates per error type (spec §\"Error-type gate\").\n[cross_lo_propagation.default]\nmax_depth = 3\nhop_decay = 0.5\ntotal_propagated_weight_cap = 0.7\n\n[cross_lo_propagation.error_gates.recall_failure]\nmean_factor = 0.0 # forgetting a definition is not evidence prereqs are weak\nvariance_factor = 0.25\nscope = \"all\"\n\n[cross_lo_propagation.error_gates.scaffold_failure]\nmean_factor = 0.0\nvariance_factor = 0.35\nscope = \"all\"\n\n[cross_lo_propagation.error_gates.arithmetic_slip]\nmean_factor = 0.0\nvariance_factor = 0.10\nscope = \"all\"\n\n[recall_coverage.severity_examples.first_dont_know]\nattempt_type = \"dont_know\"\nhints_used = 0\ncorrectness = 0.0\nexpected_correctness = 0.65\neffective_coverage = 0.85\nexpected_error_type = \"recall_failure\"\nexpected_severity_band = [0.70, 0.82]\n\n[recall_coverage.severity_examples.second_same_item_dont_know]\nattempt_type = \"dont_know\"\nhints_used = 0\ncorrectness = 0.0\nexpected_correctness = 0.65\neffective_coverage = 0.85\nrecent_same_item_failures = 1\nexpected_error_type = \"recall_failure\"\nexpected_severity_band = [0.95, 1.00]\n\n[recall_coverage.severity_examples.second_same_facet_dont_know]\nattempt_type = \"dont_know\"\nhints_used = 0\ncorrectness = 0.0\nexpected_correctness = 0.65\neffective_coverage = 0.85\nrecent_same_facet_failures = 1\nexpected_error_type = \"recall_failure\"\nexpected_severity_band = [0.80, 1.00]\n\n[recall_coverage.severity_examples.hinted_dont_know]\nattempt_type = \"dont_know\"\nhints_used = 2\ncorrectness = 0.0\nexpected_correctness = 0.65\neffective_coverage = 0.80\nexpected_error_type = \"scaffold_failure\"\nexpected_severity_band = [0.85, 0.95]\n\n[recall_coverage.severity_examples.arithmetic_slip]\nattempt_type = \"independent_attempt\"\ncorrectness = 0.75\nexpected_correctness = 0.70\neffective_coverage = 0.85\ntarget_error_type = \"arithmetic_slip\"\nexpected_error_type = \"arithmetic_slip\"\nexpected_severity_band = [0.25, 0.35]\n\n[recall_coverage.severity_examples.ambiguous_item]\nattempt_type = \"independent_attempt\"\ncorrectness = 0.0\nexpected_correctness = 0.70\neffective_coverage = 0.85\nbad_item_suspicion = 0.70\nexpected_error_type = \"recall_failure\"\nexpected_severity_band = [0.45, 0.75]\n"}, "a742f898acd99e0bd5c263aa0e287d013fba7c04": {"t": 1785750323.0089746, "n": 6330, "h": "8c63c11f8573ba46", "c": "schema_version = 1\n\n[storage]\nsqlite_path = \"state.sqlite\"\n\n[algorithms]\nalgorithm_version = \"mvp-0.2\"\n\n[scheduler]\nforgetting_risk_weight = 1.0\nactive_goal_weight = 0.35\nrecent_error_weight = 0.50\nprobe_eig_weight = 0.25\nshort_session_minutes = 20\n# Seeded exploration over near-tie candidates so logged slates carry non-degenerate\n# selection propensities (off-policy learnability). See architecture_pivot.md Stage 0.\nselection_exploration_rate = 0.1\nselection_exploration_reward_window = 0.15\n\n[scheduler.surprise]\ntheta_pos = 1.5\ntheta_neg = 1.5\nalpha_interval = 0.3\nf_min = 0.5\nf_max = 1.5\nepsilon_error_surprise = 0.05\n\n[scheduler.followup]\ntau_followup_nats = 0.05\ngamma_min = 0.5\n\n[mastery]\nbase_observation_variance = 1.0\nsigma2_drift = 0.01\np_max = 4.0\n\n# IRT 2PL difficulty-aware mastery update (spec_irt_difficulty.md §4).\n# enabled = false restores the legacy logit-space Kalman update bit-for-bit.\n[mastery.irt]\nenabled = true\ndiscrimination_default = 1.0\ndifficulty_default = 0.0\ndifficulty_from_prior = true\ndifficulty_prior_scale = 2.5\nb_abs_max = 4.0\np_clip = 1e-4\nmu_abs_max = 5.0\nmax_logit_step = 4.0\n\n[probe]\nattempts_target_default = 3\nattempts_target_with_strong_claim = 1\nclaim_skip_threshold = 0.75\nvariance_convergence_threshold = 0.10\nhypothesis_set_max_size = 5\n\n# IRT difficulty-aware probe conditionals (spec_irt_difficulty.md §5).\n[probe.irt]\ntheta_mastered = 2.0\ntheta_unfamiliar = -2.0\ncut_mid = -1.0\ncut_high = 1.0\nunfamiliar_error_leak = 0.20\nerr_low_frac = 0.80\nerr_mid_frac = 0.50\n\n# Learner self-attributed misconception probe coverage (spec_irt_difficulty.md §12).\n[probe.self_tag]\nw_base = 0.5\nw_max = 0.7\ntarget_degree = 2.0\npromotion_threshold = 3\n\n[ingest]\nwindow_char_cap = 150000\nmin_content_chars = 400\ndefault_goal_priority = 0.5\nallow_auto_captions = false\n\n[ai]\nactive_provider = \"codex\"\nfallback_provider = \"\"\ntimeout_seconds = 60\n\n[ai.routing]\ngrading = \"codex\"\ncanonical_ingest = \"codex\"\ncanonical_ingest_retry = \"\"\nauthoring = \"codex\"\n\n[ai.providers.codex]\ntype = \"codex_sdk\"\nmodel = \"gpt-5.5\"\ncheckout_path = \"/home/chloe/Documents/thinking/learnanything/codex\"\nrevision = \"<pinned-commit>\"\nstartup_command = \"\"\nstartup_timeout_seconds = 20\nhealthcheck_timeout_seconds = 5\nauth_mode = \"chatgpt\"\nreasoning_effort = \"medium\"\nreasoning_summary = \"none\"\nsdk_python_path = \"sdk/python/src\"\nsdk_codex_bin = \"\"\nsdk_launch_command = \"\"\nbase_url = \"http://127.0.0.1:8765\"\nhealthcheck_path = \"/health\"\nauthoring_path = \"/authoring-proposal\"\ncanonical_ingest_path = \"/canonical-ingest\"\ngrading_path = \"/grading-proposal\"\n\n[ai.providers.deepseek_flash]\ntype = \"openai_chat\"\nbase_url = \"https://api.deepseek.com\"\napi_key_env = \"DEEPSEEK_API_KEY\"\nmodel = \"deepseek-v4-flash\"\nresponse_format = \"json_object\"\nthinking = \"disabled\"\nmax_tokens = 8192\ntimeout_seconds = 90\n\n[ai.providers.deepseek_pro]\ntype = \"openai_chat\"\nbase_url = \"https://api.deepseek.com\"\napi_key_env = \"DEEPSEEK_API_KEY\"\nmodel = \"deepseek-v4-pro\"\nresponse_format = \"json_object\"\nthinking = \"enabled\"\nreasoning_effort = \"high\"\nmax_tokens = 16384\ntimeout_seconds = 180\n\n[codex]\nprovider = \"sdk\"\ncheckout_path = \"/home/chloe/Documents/thinking/learnanything/codex\"\nrevision = \"<pinned-commit>\"\nstartup_command = \"\"\nstartup_timeout_seconds = 20\nhealthcheck_timeout_seconds = 5\nauth_mode = \"chatgpt\"\nmodel = \"gpt-5.5\"\nreasoning_effort = \"medium\"\nreasoning_summary = \"none\"\nsdk_python_path = \"sdk/python/src\"\nsdk_codex_bin = \"\"\nsdk_launch_command = \"\"\nbase_url = \"http://127.0.0.1:8765\"\nhealthcheck_path = \"/health\"\nauthoring_path = \"/authoring-proposal\"\ncanonical_ingest_path = \"/canonical-ingest\"\ngrading_path = \"/grading-proposal\"\n\n# Family-keyed mastery damage per error type (spec §\"Error-aware updates\").\n# recall_failure is the deterministic attribution for `dont_know` attempts.\n[error_impacts]\nmax_sharpening = 3.0\n\n[error_impacts.recall_failure]\nfamilies = { recall = -0.25 }\nlo_mastery_delta = -0.05\nlocal_severity_gain = 0.8\n\n[error_impacts.scaffold_failure]\nfamilies = { recall = -0.35 }\nlo_mastery_delta = -0.05\nlocal_severity_gain = 1.5\n\n[error_impacts.arithmetic_slip]\nfamilies = { numeric = -0.05 }\nlo_mastery_delta = 0.0\nlocal_severity_gain = 0.35\n\n# Cross-LO propagation gates per error type (spec §\"Error-type gate\").\n[cross_lo_propagation.default]\nmax_depth = 3\nhop_decay = 0.5\ntotal_propagated_weight_cap = 0.7\n\n[cross_lo_propagation.error_gates.recall_failure]\nmean_factor = 0.0 # forgetting a definition is not evidence prereqs are weak\nvariance_factor = 0.25\nscope = \"all\"\n\n[cross_lo_propagation.error_gates.scaffold_failure]\nmean_factor = 0.0\nvariance_factor = 0.35\nscope = \"all\"\n\n[cross_lo_propagation.error_gates.arithmetic_slip]\nmean_factor = 0.0\nvariance_factor = 0.10\nscope = \"all\"\n\n[recall_coverage.severity_examples.first_dont_know]\nattempt_type = \"dont_know\"\nhints_used = 0\ncorrectness = 0.0\nexpected_correctness = 0.65\neffective_coverage = 0.85\nexpected_error_type = \"recall_failure\"\nexpected_severity_band = [0.70, 0.82]\n\n[recall_coverage.severity_examples.second_same_item_dont_know]\nattempt_type = \"dont_know\"\nhints_used = 0\ncorrectness = 0.0\nexpected_correctness = 0.65\neffective_coverage = 0.85\nrecent_same_item_failures = 1\nexpected_error_type = \"recall_failure\"\nexpected_severity_band = [0.95, 1.00]\n\n[recall_coverage.severity_examples.second_same_facet_dont_know]\nattempt_type = \"dont_know\"\nhints_used = 0\ncorrectness = 0.0\nexpected_correctness = 0.65\neffective_coverage = 0.85\nrecent_same_facet_failures = 1\nexpected_error_type = \"recall_failure\"\nexpected_severity_band = [0.80, 1.00]\n\n[recall_coverage.severity_examples.hinted_dont_know]\nattempt_type = \"dont_know\"\nhints_used = 2\ncorrectness = 0.0\nexpected_correctness = 0.65\neffective_coverage = 0.80\nexpected_error_type = \"scaffold_failure\"\nexpected_severity_band = [0.85, 0.95]\n\n[recall_coverage.severity_examples.arithmetic_slip]\nattempt_type = \"independent_attempt\"\ncorrectness = 0.75\nexpected_correctness = 0.70\neffective_coverage = 0.85\ntarget_error_type = \"arithmetic_slip\"\nexpected_error_type = \"arithmetic_slip\"\nexpected_severity_band = [0.25, 0.35]\n\n[recall_coverage.severity_examples.ambiguous_item]\nattempt_type = \"independent_attempt\"\ncorrectness = 0.0\nexpected_correctness = 0.70\neffective_coverage = 0.85\nbad_item_suspicion = 0.70\nexpected_error_type = \"recall_failure\"\nexpected_severity_band = [0.45, 0.75]\n"}, "993e225d944e7516c2b632891ad508efd11d3f71": {"t": 1785750324.0898502, "n": 6083, "h": "00e062aa82b7797e", "c": "schema_version = 1\n\n[storage]\nsqlite_path = \"state.sqlite\"\n\n[algorithms]\nalgorithm_version = \"mvp-0.2\"\n\n[scheduler]\nforgetting_risk_weight = 1.0\nactive_goal_weight = 0.35\nrecent_error_weight = 0.50\nprobe_eig_weight = 0.25\nshort_session_minutes = 20\n\n[scheduler.surprise]\ntheta_pos = 1.5\ntheta_neg = 1.5\nalpha_interval = 0.3\nf_min = 0.5\nf_max = 1.5\nepsilon_error_surprise = 0.05\n\n[scheduler.followup]\ntau_followup_nats = 0.05\ngamma_min = 0.5\n\n[mastery]\nbase_observation_variance = 1.0\nsigma2_drift = 0.01\np_max = 4.0\n\n# IRT 2PL difficulty-aware mastery update (spec_irt_difficulty.md §4).\n# enabled = false restores the legacy logit-space Kalman update bit-for-bit.\n[mastery.irt]\nenabled = true\ndiscrimination_default = 1.0\ndifficulty_default = 0.0\ndifficulty_from_prior = true\ndifficulty_prior_scale = 2.5\nb_abs_max = 4.0\np_clip = 1e-4\nmu_abs_max = 5.0\nmax_logit_step = 4.0\n\n[probe]\nattempts_target_default = 3\nattempts_target_with_strong_claim = 1\nclaim_skip_threshold = 0.75\nvariance_convergence_threshold = 0.10\nhypothesis_set_max_size = 5\n\n# IRT difficulty-aware probe conditionals (spec_irt_difficulty.md §5).\n[probe.irt]\ntheta_mastered = 2.0\ntheta_unfamiliar = -2.0\ncut_mid = -1.0\ncut_high = 1.0\nunfamiliar_error_leak = 0.20\nerr_low_frac = 0.80\nerr_mid_frac = 0.50\n\n# Learner self-attributed misconception probe coverage (spec_irt_difficulty.md §12).\n[probe.self_tag]\nw_base = 0.5\nw_max = 0.7\ntarget_degree = 2.0\npromotion_threshold = 3\n\n[ingest]\nwindow_char_cap = 150000\nmin_content_chars = 400\ndefault_goal_priority = 0.5\nallow_auto_captions = false\n\n[ai]\nactive_provider = \"codex\"\nfallback_provider = \"\"\ntimeout_seconds = 60\n\n[ai.routing]\ngrading = \"codex\"\ncanonical_ingest = \"codex\"\ncanonical_ingest_retry = \"\"\nauthoring = \"codex\"\n\n[ai.providers.codex]\ntype = \"codex_sdk\"\nmodel = \"gpt-5.5\"\ncheckout_path = \"/home/chloe/Documents/thinking/learnanything/codex\"\nrevision = \"<pinned-commit>\"\nstartup_command = \"\"\nstartup_timeout_seconds = 20\nhealthcheck_timeout_seconds = 5\nauth_mode = \"chatgpt\"\nreasoning_effort = \"medium\"\nreasoning_summary = \"none\"\nsdk_python_path = \"sdk/python/src\"\nsdk_codex_bin = \"\"\nsdk_launch_command = \"\"\nbase_url = \"http://127.0.0.1:8765\"\nhealthcheck_path = \"/health\"\nauthoring_path = \"/authoring-proposal\"\ncanonical_ingest_path = \"/canonical-ingest\"\ngrading_path = \"/grading-proposal\"\n\n[ai.providers.deepseek_flash]\ntype = \"openai_chat\"\nbase_url = \"https://api.deepseek.com\"\napi_key_env = \"DEEPSEEK_API_KEY\"\nmodel = \"deepseek-v4-flash\"\nresponse_format = \"json_object\"\nthinking = \"disabled\"\nmax_tokens = 8192\ntimeout_seconds = 90\n\n[ai.providers.deepseek_pro]\ntype = \"openai_chat\"\nbase_url = \"https://api.deepseek.com\"\napi_key_env = \"DEEPSEEK_API_KEY\"\nmodel = \"deepseek-v4-pro\"\nresponse_format = \"json_object\"\nthinking = \"enabled\"\nreasoning_effort = \"high\"\nmax_tokens = 16384\ntimeout_seconds = 180\n\n[codex]\nprovider = \"sdk\"\ncheckout_path = \"/home/chloe/Documents/thinking/learnanything/codex\"\nrevision = \"<pinned-commit>\"\nstartup_command = \"\"\nstartup_timeout_seconds = 20\nhealthcheck_timeout_seconds = 5\nauth_mode = \"chatgpt\"\nmodel = \"gpt-5.5\"\nreasoning_effort = \"medium\"\nreasoning_summary = \"none\"\nsdk_python_path = \"sdk/python/src\"\nsdk_codex_bin = \"\"\nsdk_launch_command = \"\"\nbase_url = \"http://127.0.0.1:8765\"\nhealthcheck_path = \"/health\"\nauthoring_path = \"/authoring-proposal\"\ncanonical_ingest_path = \"/canonical-ingest\"\ngrading_path = \"/grading-proposal\"\n\n# Family-keyed mastery damage per error type (spec §\"Error-aware updates\").\n# recall_failure is the deterministic attribution for `dont_know` attempts.\n[error_impacts]\nmax_sharpening = 3.0\n\n[error_impacts.recall_failure]\nfamilies = { recall = -0.25 }\nlo_mastery_delta = -0.05\nlocal_severity_gain = 0.8\n\n[error_impacts.scaffold_failure]\nfamilies = { recall = -0.35 }\nlo_mastery_delta = -0.05\nlocal_severity_gain = 1.5\n\n[error_impacts.arithmetic_slip]\nfamilies = { numeric = -0.05 }\nlo_mastery_delta = 0.0\nlocal_severity_gain = 0.35\n\n# Cross-LO propagation gates per error type (spec §\"Error-type gate\").\n[cross_lo_propagation.default]\nmax_depth = 3\nhop_decay = 0.5\ntotal_propagated_weight_cap = 0.7\n\n[cross_lo_propagation.error_gates.recall_failure]\nmean_factor = 0.0 # forgetting a definition is not evidence prereqs are weak\nvariance_factor = 0.25\nscope = \"all\"\n\n[cross_lo_propagation.error_gates.scaffold_failure]\nmean_factor = 0.0\nvariance_factor = 0.35\nscope = \"all\"\n\n[cross_lo_propagation.error_gates.arithmetic_slip]\nmean_factor = 0.0\nvariance_factor = 0.10\nscope = \"all\"\n\n[recall_coverage.severity_examples.first_dont_know]\nattempt_type = \"dont_know\"\nhints_used = 0\ncorrectness = 0.0\nexpected_correctness = 0.65\neffective_coverage = 0.85\nexpected_error_type = \"recall_failure\"\nexpected_severity_band = [0.70, 0.82]\n\n[recall_coverage.severity_examples.second_same_item_dont_know]\nattempt_type = \"dont_know\"\nhints_used = 0\ncorrectness = 0.0\nexpected_correctness = 0.65\neffective_coverage = 0.85\nrecent_same_item_failures = 1\nexpected_error_type = \"recall_failure\"\nexpected_severity_band = [0.95, 1.00]\n\n[recall_coverage.severity_examples.second_same_facet_dont_know]\nattempt_type = \"dont_know\"\nhints_used = 0\ncorrectness = 0.0\nexpected_correctness = 0.65\neffective_coverage = 0.85\nrecent_same_facet_failures = 1\nexpected_error_type = \"recall_failure\"\nexpected_severity_band = [0.80, 1.00]\n\n[recall_coverage.severity_examples.hinted_dont_know]\nattempt_type = \"dont_know\"\nhints_used = 2\ncorrectness = 0.0\nexpected_correctness = 0.65\neffective_coverage = 0.80\nexpected_error_type = \"scaffold_failure\"\nexpected_severity_band = [0.85, 0.95]\n\n[recall_coverage.severity_examples.arithmetic_slip]\nattempt_type = \"independent_attempt\"\ncorrectness = 0.75\nexpected_correctness = 0.70\neffective_coverage = 0.85\ntarget_error_type = \"arithmetic_slip\"\nexpected_error_type = \"arithmetic_slip\"\nexpected_severity_band = [0.25, 0.35]\n\n[recall_coverage.severity_examples.ambiguous_item]\nattempt_type = \"independent_attempt\"\ncorrectness = 0.0\nexpected_correctness = 0.70\neffective_coverage = 0.85\nbad_item_suspicion = 0.70\nexpected_error_type = \"recall_failure\"\nexpected_severity_band = [0.45, 0.75]\n"}}, "fixtures/conic-sections/learnloop.toml": {"d7f5830f824d7636193af334e950c1d2ffc477c4": {"t": 1785745366.7049499, "n": 6304, "h": "e2eff264c84890f3", "c": "schema_version = 1\n\n[storage]\nsqlite_path = \"state.sqlite\"\n\n[algorithms]\nalgorithm_version = \"mvp-0.6\"\n\n[scheduler]\nforgetting_risk_weight = 1.0\nrecent_error_weight = 0.50\nprobe_eig_weight = 0.25\nshort_session_minutes = 20\n# Seeded exploration over near-tie candidates so logged slates carry non-degenerate\n# selection propensities (off-policy learnability). See architecture_pivot.md Stage 0.\nselection_exploration_rate = 0.1\nselection_exploration_reward_window = 0.15\n\n[scheduler.surprise]\ntheta_pos = 1.5\ntheta_neg = 1.5\nalpha_interval = 0.3\nf_min = 0.5\nf_max = 1.5\nepsilon_error_surprise = 0.05\n\n[scheduler.followup]\ntau_followup_nats = 0.05\ngamma_min = 0.5\n\n[mastery]\nbase_observation_variance = 1.0\nsigma2_drift = 0.01\np_max = 4.0\n\n# IRT 2PL difficulty-aware mastery update (spec_irt_difficulty.md §4).\n# enabled = false restores the legacy logit-space Kalman update bit-for-bit.\n[mastery.irt]\nenabled = true\ndiscrimination_default = 1.0\ndifficulty_default = 0.0\ndifficulty_from_prior = true\ndifficulty_prior_scale = 2.5\nb_abs_max = 4.0\np_clip = 1e-4\nmu_abs_max = 5.0\nmax_logit_step = 4.0\n\n[probe]\nattempts_target_default = 3\nattempts_target_with_strong_claim = 1\nclaim_skip_threshold = 0.75\nvariance_convergence_threshold = 0.10\nhypothesis_set_max_size = 5\n\n# IRT difficulty-aware probe conditionals (spec_irt_difficulty.md §5).\n[probe.irt]\ntheta_mastered = 2.0\ntheta_unfamiliar = -2.0\ncut_mid = -1.0\ncut_high = 1.0\nunfamiliar_error_leak = 0.20\nerr_low_frac = 0.80\nerr_mid_frac = 0.50\n\n# Learner self-attributed misconception probe coverage (spec_irt_difficulty.md §12).\n[probe.self_tag]\nw_base = 0.5\nw_max = 0.7\ntarget_degree = 2.0\npromotion_threshold = 3\n\n[ingest]\nwindow_char_cap = 150000\nmin_content_chars = 400\ndefault_goal_priority = 0.5\nallow_auto_captions = false\n\n[ai]\nactive_provider = \"codex\"\nfallback_provider = \"\"\ntimeout_seconds = 60\n\n[ai.routing]\ngrading = \"codex\"\ncanonical_ingest = \"codex\"\ncanonical_ingest_retry = \"\"\nauthoring = \"codex\"\n\n[ai.providers.codex]\ntype = \"codex_sdk\"\nmodel = \"gpt-5.5\"\ncheckout_path = \"/home/chloe/Documents/thinking/learnanything/codex\"\nrevision = \"<pinned-commit>\"\nstartup_command = \"\"\nstartup_timeout_seconds = 20\nhealthcheck_timeout_seconds = 5\nauth_mode = \"chatgpt\"\nreasoning_effort = \"medium\"\nreasoning_summary = \"none\"\nsdk_python_path = \"sdk/python/src\"\nsdk_codex_bin = \"\"\nsdk_launch_command = \"\"\nbase_url = \"http://127.0.0.1:8765\"\nhealthcheck_path = \"/health\"\nauthoring_path = \"/authoring-proposal\"\ncanonical_ingest_path = \"/canonical-ingest\"\ngrading_path = \"/grading-proposal\"\n\n[ai.providers.deepseek_flash]\ntype = \"openai_chat\"\nbase_url = \"https://api.deepseek.com\"\napi_key_env = \"DEEPSEEK_API_KEY\"\nmodel = \"deepseek-v4-flash\"\nresponse_format = \"json_object\"\nthinking = \"disabled\"\nmax_tokens = 8192\ntimeout_seconds = 90\n\n[ai.providers.deepseek_pro]\ntype = \"openai_chat\"\nbase_url = \"https://api.deepseek.com\"\napi_key_env = \"DEEPSEEK_API_KEY\"\nmodel = \"deepseek-v4-pro\"\nresponse_format = \"json_object\"\nthinking = \"enabled\"\nreasoning_effort = \"high\"\nmax_tokens = 16384\ntimeout_seconds = 180\n\n[codex]\nprovider = \"sdk\"\ncheckout_path = \"/home/chloe/Documents/thinking/learnanything/codex\"\nrevision = \"<pinned-commit>\"\nstartup_command = \"\"\nstartup_timeout_seconds = 20\nhealthcheck_timeout_seconds = 5\nauth_mode = \"chatgpt\"\nmodel = \"gpt-5.5\"\nreasoning_effort = \"medium\"\nreasoning_summary = \"none\"\nsdk_python_path = \"sdk/python/src\"\nsdk_codex_bin = \"\"\nsdk_launch_command = \"\"\nbase_url = \"http://127.0.0.1:8765\"\nhealthcheck_path = \"/health\"\nauthoring_path = \"/authoring-proposal\"\ncanonical_ingest_path = \"/canonical-ingest\"\ngrading_path = \"/grading-proposal\"\n\n# Family-keyed mastery damage per error type (spec §\"Error-aware updates\").\n# recall_failure is the deterministic attribution for `dont_know` attempts.\n[error_impacts]\nmax_sharpening = 3.0\n\n[error_impacts.recall_failure]\nfamilies = { recall = -0.25 }\nlo_mastery_delta = -0.05\nlocal_severity_gain = 0.8\n\n[error_impacts.scaffold_failure]\nfamilies = { recall = -0.35 }\nlo_mastery_delta = -0.05\nlocal_severity_gain = 1.5\n\n[error_impacts.arithmetic_slip]\nfamilies = { numeric = -0.05 }\nlo_mastery_delta = 0.0\nlocal_severity_gain = 0.35\n\n# Cross-LO propagation gates per error type (spec §\"Error-type gate\").\n[cross_lo_propagation.default]\nmax_depth = 3\nhop_decay = 0.5\ntotal_propagated_weight_cap = 0.7\n\n[cross_lo_propagation.error_gates.recall_failure]\nmean_factor = 0.0 # forgetting a definition is not evidence prereqs are weak\nvariance_factor = 0.25\nscope = \"all\"\n\n[cross_lo_propagation.error_gates.scaffold_failure]\nmean_factor = 0.0\nvariance_factor = 0.35\nscope = \"all\"\n\n[cross_lo_propagation.error_gates.arithmetic_slip]\nmean_factor = 0.0\nvariance_factor = 0.10\nscope = \"all\"\n\n[recall_coverage.severity_examples.first_dont_know]\nattempt_type = \"dont_know\"\nhints_used = 0\ncorrectness = 0.0\nexpected_correctness = 0.65\neffective_coverage = 0.85\nexpected_error_type = \"recall_failure\"\nexpected_severity_band = [0.70, 0.82]\n\n[recall_coverage.severity_examples.second_same_item_dont_know]\nattempt_type = \"dont_know\"\nhints_used = 0\ncorrectness = 0.0\nexpected_correctness = 0.65\neffective_coverage = 0.85\nrecent_same_item_failures = 1\nexpected_error_type = \"recall_failure\"\nexpected_severity_band = [0.95, 1.00]\n\n[recall_coverage.severity_examples.second_same_facet_dont_know]\nattempt_type = \"dont_know\"\nhints_used = 0\ncorrectness = 0.0\nexpected_correctness = 0.65\neffective_coverage = 0.85\nrecent_same_facet_failures = 1\nexpected_error_type = \"recall_failure\"\nexpected_severity_band = [0.80, 1.00]\n\n[recall_coverage.severity_examples.hinted_dont_know]\nattempt_type = \"dont_know\"\nhints_used = 2\ncorrectness = 0.0\nexpected_correctness = 0.65\neffective_coverage = 0.80\nexpected_error_type = \"scaffold_failure\"\nexpected_severity_band = [0.85, 0.95]\n\n[recall_coverage.severity_examples.arithmetic_slip]\nattempt_type = \"independent_attempt\"\ncorrectness = 0.75\nexpected_correctness = 0.70\neffective_coverage = 0.85\ntarget_error_type = \"arithmetic_slip\"\nexpected_error_type = \"arithmetic_slip\"\nexpected_severity_band = [0.25, 0.35]\n\n[recall_coverage.severity_examples.ambiguous_item]\nattempt_type = \"independent_attempt\"\ncorrectness = 0.0\nexpected_correctness = 0.70\neffective_coverage = 0.85\nbad_item_suspicion = 0.70\nexpected_error_type = \"recall_failure\"\nexpected_severity_band = [0.45, 0.75]\n"}, "b19e81d9993c28e995049da1aa16f8d316d56d68": {"t": 1785750314.8176203, "n": 6304, "h": "e2eff264c84890f3", "c": "schema_version = 1\n\n[storage]\nsqlite_path = \"state.sqlite\"\n\n[algorithms]\nalgorithm_version = \"mvp-0.6\"\n\n[scheduler]\nforgetting_risk_weight = 1.0\nrecent_error_weight = 0.50\nprobe_eig_weight = 0.25\nshort_session_minutes = 20\n# Seeded exploration over near-tie candidates so logged slates carry non-degenerate\n# selection propensities (off-policy learnability). See architecture_pivot.md Stage 0.\nselection_exploration_rate = 0.1\nselection_exploration_reward_window = 0.15\n\n[scheduler.surprise]\ntheta_pos = 1.5\ntheta_neg = 1.5\nalpha_interval = 0.3\nf_min = 0.5\nf_max = 1.5\nepsilon_error_surprise = 0.05\n\n[scheduler.followup]\ntau_followup_nats = 0.05\ngamma_min = 0.5\n\n[mastery]\nbase_observation_variance = 1.0\nsigma2_drift = 0.01\np_max = 4.0\n\n# IRT 2PL difficulty-aware mastery update (spec_irt_difficulty.md §4).\n# enabled = false restores the legacy logit-space Kalman update bit-for-bit.\n[mastery.irt]\nenabled = true\ndiscrimination_default = 1.0\ndifficulty_default = 0.0\ndifficulty_from_prior = true\ndifficulty_prior_scale = 2.5\nb_abs_max = 4.0\np_clip = 1e-4\nmu_abs_max = 5.0\nmax_logit_step = 4.0\n\n[probe]\nattempts_target_default = 3\nattempts_target_with_strong_claim = 1\nclaim_skip_threshold = 0.75\nvariance_convergence_threshold = 0.10\nhypothesis_set_max_size = 5\n\n# IRT difficulty-aware probe conditionals (spec_irt_difficulty.md §5).\n[probe.irt]\ntheta_mastered = 2.0\ntheta_unfamiliar = -2.0\ncut_mid = -1.0\ncut_high = 1.0\nunfamiliar_error_leak = 0.20\nerr_low_frac = 0.80\nerr_mid_frac = 0.50\n\n# Learner self-attributed misconception probe coverage (spec_irt_difficulty.md §12).\n[probe.self_tag]\nw_base = 0.5\nw_max = 0.7\ntarget_degree = 2.0\npromotion_threshold = 3\n\n[ingest]\nwindow_char_cap = 150000\nmin_content_chars = 400\ndefault_goal_priority = 0.5\nallow_auto_captions = false\n\n[ai]\nactive_provider = \"codex\"\nfallback_provider = \"\"\ntimeout_seconds = 60\n\n[ai.routing]\ngrading = \"codex\"\ncanonical_ingest = \"codex\"\ncanonical_ingest_retry = \"\"\nauthoring = \"codex\"\n\n[ai.providers.codex]\ntype = \"codex_sdk\"\nmodel = \"gpt-5.5\"\ncheckout_path = \"/home/chloe/Documents/thinking/learnanything/codex\"\nrevision = \"<pinned-commit>\"\nstartup_command = \"\"\nstartup_timeout_seconds = 20\nhealthcheck_timeout_seconds = 5\nauth_mode = \"chatgpt\"\nreasoning_effort = \"medium\"\nreasoning_summary = \"none\"\nsdk_python_path = \"sdk/python/src\"\nsdk_codex_bin = \"\"\nsdk_launch_command = \"\"\nbase_url = \"http://127.0.0.1:8765\"\nhealthcheck_path = \"/health\"\nauthoring_path = \"/authoring-proposal\"\ncanonical_ingest_path = \"/canonical-ingest\"\ngrading_path = \"/grading-proposal\"\n\n[ai.providers.deepseek_flash]\ntype = \"openai_chat\"\nbase_url = \"https://api.deepseek.com\"\napi_key_env = \"DEEPSEEK_API_KEY\"\nmodel = \"deepseek-v4-flash\"\nresponse_format = \"json_object\"\nthinking = \"disabled\"\nmax_tokens = 8192\ntimeout_seconds = 90\n\n[ai.providers.deepseek_pro]\ntype = \"openai_chat\"\nbase_url = \"https://api.deepseek.com\"\napi_key_env = \"DEEPSEEK_API_KEY\"\nmodel = \"deepseek-v4-pro\"\nresponse_format = \"json_object\"\nthinking = \"enabled\"\nreasoning_effort = \"high\"\nmax_tokens = 16384\ntimeout_seconds = 180\n\n[codex]\nprovider = \"sdk\"\ncheckout_path = \"/home/chloe/Documents/thinking/learnanything/codex\"\nrevision = \"<pinned-commit>\"\nstartup_command = \"\"\nstartup_timeout_seconds = 20\nhealthcheck_timeout_seconds = 5\nauth_mode = \"chatgpt\"\nmodel = \"gpt-5.5\"\nreasoning_effort = \"medium\"\nreasoning_summary = \"none\"\nsdk_python_path = \"sdk/python/src\"\nsdk_codex_bin = \"\"\nsdk_launch_command = \"\"\nbase_url = \"http://127.0.0.1:8765\"\nhealthcheck_path = \"/health\"\nauthoring_path = \"/authoring-proposal\"\ncanonical_ingest_path = \"/canonical-ingest\"\ngrading_path = \"/grading-proposal\"\n\n# Family-keyed mastery damage per error type (spec §\"Error-aware updates\").\n# recall_failure is the deterministic attribution for `dont_know` attempts.\n[error_impacts]\nmax_sharpening = 3.0\n\n[error_impacts.recall_failure]\nfamilies = { recall = -0.25 }\nlo_mastery_delta = -0.05\nlocal_severity_gain = 0.8\n\n[error_impacts.scaffold_failure]\nfamilies = { recall = -0.35 }\nlo_mastery_delta = -0.05\nlocal_severity_gain = 1.5\n\n[error_impacts.arithmetic_slip]\nfamilies = { numeric = -0.05 }\nlo_mastery_delta = 0.0\nlocal_severity_gain = 0.35\n\n# Cross-LO propagation gates per error type (spec §\"Error-type gate\").\n[cross_lo_propagation.default]\nmax_depth = 3\nhop_decay = 0.5\ntotal_propagated_weight_cap = 0.7\n\n[cross_lo_propagation.error_gates.recall_failure]\nmean_factor = 0.0 # forgetting a definition is not evidence prereqs are weak\nvariance_factor = 0.25\nscope = \"all\"\n\n[cross_lo_propagation.error_gates.scaffold_failure]\nmean_factor = 0.0\nvariance_factor = 0.35\nscope = \"all\"\n\n[cross_lo_propagation.error_gates.arithmetic_slip]\nmean_factor = 0.0\nvariance_factor = 0.10\nscope = \"all\"\n\n[recall_coverage.severity_examples.first_dont_know]\nattempt_type = \"dont_know\"\nhints_used = 0\ncorrectness = 0.0\nexpected_correctness = 0.65\neffective_coverage = 0.85\nexpected_error_type = \"recall_failure\"\nexpected_severity_band = [0.70, 0.82]\n\n[recall_coverage.severity_examples.second_same_item_dont_know]\nattempt_type = \"dont_know\"\nhints_used = 0\ncorrectness = 0.0\nexpected_correctness = 0.65\neffective_coverage = 0.85\nrecent_same_item_failures = 1\nexpected_error_type = \"recall_failure\"\nexpected_severity_band = [0.95, 1.00]\n\n[recall_coverage.severity_examples.second_same_facet_dont_know]\nattempt_type = \"dont_know\"\nhints_used = 0\ncorrectness = 0.0\nexpected_correctness = 0.65\neffective_coverage = 0.85\nrecent_same_facet_failures = 1\nexpected_error_type = \"recall_failure\"\nexpected_severity_band = [0.80, 1.00]\n\n[recall_coverage.severity_examples.hinted_dont_know]\nattempt_type = \"dont_know\"\nhints_used = 2\ncorrectness = 0.0\nexpected_correctness = 0.65\neffective_coverage = 0.80\nexpected_error_type = \"scaffold_failure\"\nexpected_severity_band = [0.85, 0.95]\n\n[recall_coverage.severity_examples.arithmetic_slip]\nattempt_type = \"independent_attempt\"\ncorrectness = 0.75\nexpected_correctness = 0.70\neffective_coverage = 0.85\ntarget_error_type = \"arithmetic_slip\"\nexpected_error_type = \"arithmetic_slip\"\nexpected_severity_band = [0.25, 0.35]\n\n[recall_coverage.severity_examples.ambiguous_item]\nattempt_type = \"independent_attempt\"\ncorrectness = 0.0\nexpected_correctness = 0.70\neffective_coverage = 0.85\nbad_item_suspicion = 0.70\nexpected_error_type = \"recall_failure\"\nexpected_severity_band = [0.45, 0.75]\n"}, "565100878e11bc9ac281139570040c118fbaf1a5": {"t": 1785750315.893314, "n": 6304, "h": "5a3d223da6708acc", "c": "schema_version = 1\n\n[storage]\nsqlite_path = \"state.sqlite\"\n\n[algorithms]\nalgorithm_version = \"mvp-0.5\"\n\n[scheduler]\nforgetting_risk_weight = 1.0\nrecent_error_weight = 0.50\nprobe_eig_weight = 0.25\nshort_session_minutes = 20\n# Seeded exploration over near-tie candidates so logged slates carry non-degenerate\n# selection propensities (off-policy learnability). See architecture_pivot.md Stage 0.\nselection_exploration_rate = 0.1\nselection_exploration_reward_window = 0.15\n\n[scheduler.surprise]\ntheta_pos = 1.5\ntheta_neg = 1.5\nalpha_interval = 0.3\nf_min = 0.5\nf_max = 1.5\nepsilon_error_surprise = 0.05\n\n[scheduler.followup]\ntau_followup_nats = 0.05\ngamma_min = 0.5\n\n[mastery]\nbase_observation_variance = 1.0\nsigma2_drift = 0.01\np_max = 4.0\n\n# IRT 2PL difficulty-aware mastery update (spec_irt_difficulty.md §4).\n# enabled = false restores the legacy logit-space Kalman update bit-for-bit.\n[mastery.irt]\nenabled = true\ndiscrimination_default = 1.0\ndifficulty_default = 0.0\ndifficulty_from_prior = true\ndifficulty_prior_scale = 2.5\nb_abs_max = 4.0\np_clip = 1e-4\nmu_abs_max = 5.0\nmax_logit_step = 4.0\n\n[probe]\nattempts_target_default = 3\nattempts_target_with_strong_claim = 1\nclaim_skip_threshold = 0.75\nvariance_convergence_threshold = 0.10\nhypothesis_set_max_size = 5\n\n# IRT difficulty-aware probe conditionals (spec_irt_difficulty.md §5).\n[probe.irt]\ntheta_mastered = 2.0\ntheta_unfamiliar = -2.0\ncut_mid = -1.0\ncut_high = 1.0\nunfamiliar_error_leak = 0.20\nerr_low_frac = 0.80\nerr_mid_frac = 0.50\n\n# Learner self-attributed misconception probe coverage (spec_irt_difficulty.md §12).\n[probe.self_tag]\nw_base = 0.5\nw_max = 0.7\ntarget_degree = 2.0\npromotion_threshold = 3\n\n[ingest]\nwindow_char_cap = 150000\nmin_content_chars = 400\ndefault_goal_priority = 0.5\nallow_auto_captions = false\n\n[ai]\nactive_provider = \"codex\"\nfallback_provider = \"\"\ntimeout_seconds = 60\n\n[ai.routing]\ngrading = \"codex\"\ncanonical_ingest = \"codex\"\ncanonical_ingest_retry = \"\"\nauthoring = \"codex\"\n\n[ai.providers.codex]\ntype = \"codex_sdk\"\nmodel = \"gpt-5.5\"\ncheckout_path = \"/home/chloe/Documents/thinking/learnanything/codex\"\nrevision = \"<pinned-commit>\"\nstartup_command = \"\"\nstartup_timeout_seconds = 20\nhealthcheck_timeout_seconds = 5\nauth_mode = \"chatgpt\"\nreasoning_effort = \"medium\"\nreasoning_summary = \"none\"\nsdk_python_path = \"sdk/python/src\"\nsdk_codex_bin = \"\"\nsdk_launch_command = \"\"\nbase_url = \"http://127.0.0.1:8765\"\nhealthcheck_path = \"/health\"\nauthoring_path = \"/authoring-proposal\"\ncanonical_ingest_path = \"/canonical-ingest\"\ngrading_path = \"/grading-proposal\"\n\n[ai.providers.deepseek_flash]\ntype = \"openai_chat\"\nbase_url = \"https://api.deepseek.com\"\napi_key_env = \"DEEPSEEK_API_KEY\"\nmodel = \"deepseek-v4-flash\"\nresponse_format = \"json_object\"\nthinking = \"disabled\"\nmax_tokens = 8192\ntimeout_seconds = 90\n\n[ai.providers.deepseek_pro]\ntype = \"openai_chat\"\nbase_url = \"https://api.deepseek.com\"\napi_key_env = \"DEEPSEEK_API_KEY\"\nmodel = \"deepseek-v4-pro\"\nresponse_format = \"json_object\"\nthinking = \"enabled\"\nreasoning_effort = \"high\"\nmax_tokens = 16384\ntimeout_seconds = 180\n\n[codex]\nprovider = \"sdk\"\ncheckout_path = \"/home/chloe/Documents/thinking/learnanything/codex\"\nrevision = \"<pinned-commit>\"\nstartup_command = \"\"\nstartup_timeout_seconds = 20\nhealthcheck_timeout_seconds = 5\nauth_mode = \"chatgpt\"\nmodel = \"gpt-5.5\"\nreasoning_effort = \"medium\"\nreasoning_summary = \"none\"\nsdk_python_path = \"sdk/python/src\"\nsdk_codex_bin = \"\"\nsdk_launch_command = \"\"\nbase_url = \"http://127.0.0.1:8765\"\nhealthcheck_path = \"/health\"\nauthoring_path = \"/authoring-proposal\"\ncanonical_ingest_path = \"/canonical-ingest\"\ngrading_path = \"/grading-proposal\"\n\n# Family-keyed mastery damage per error type (spec §\"Error-aware updates\").\n# recall_failure is the deterministic attribution for `dont_know` attempts.\n[error_impacts]\nmax_sharpening = 3.0\n\n[error_impacts.recall_failure]\nfamilies = { recall = -0.25 }\nlo_mastery_delta = -0.05\nlocal_severity_gain = 0.8\n\n[error_impacts.scaffold_failure]\nfamilies = { recall = -0.35 }\nlo_mastery_delta = -0.05\nlocal_severity_gain = 1.5\n\n[error_impacts.arithmetic_slip]\nfamilies = { numeric = -0.05 }\nlo_mastery_delta = 0.0\nlocal_severity_gain = 0.35\n\n# Cross-LO propagation gates per error type (spec §\"Error-type gate\").\n[cross_lo_propagation.default]\nmax_depth = 3\nhop_decay = 0.5\ntotal_propagated_weight_cap = 0.7\n\n[cross_lo_propagation.error_gates.recall_failure]\nmean_factor = 0.0 # forgetting a definition is not evidence prereqs are weak\nvariance_factor = 0.25\nscope = \"all\"\n\n[cross_lo_propagation.error_gates.scaffold_failure]\nmean_factor = 0.0\nvariance_factor = 0.35\nscope = \"all\"\n\n[cross_lo_propagation.error_gates.arithmetic_slip]\nmean_factor = 0.0\nvariance_factor = 0.10\nscope = \"all\"\n\n[recall_coverage.severity_examples.first_dont_know]\nattempt_type = \"dont_know\"\nhints_used = 0\ncorrectness = 0.0\nexpected_correctness = 0.65\neffective_coverage = 0.85\nexpected_error_type = \"recall_failure\"\nexpected_severity_band = [0.70, 0.82]\n\n[recall_coverage.severity_examples.second_same_item_dont_know]\nattempt_type = \"dont_know\"\nhints_used = 0\ncorrectness = 0.0\nexpected_correctness = 0.65\neffective_coverage = 0.85\nrecent_same_item_failures = 1\nexpected_error_type = \"recall_failure\"\nexpected_severity_band = [0.95, 1.00]\n\n[recall_coverage.severity_examples.second_same_facet_dont_know]\nattempt_type = \"dont_know\"\nhints_used = 0\ncorrectness = 0.0\nexpected_correctness = 0.65\neffective_coverage = 0.85\nrecent_same_facet_failures = 1\nexpected_error_type = \"recall_failure\"\nexpected_severity_band = [0.80, 1.00]\n\n[recall_coverage.severity_examples.hinted_dont_know]\nattempt_type = \"dont_know\"\nhints_used = 2\ncorrectness = 0.0\nexpected_correctness = 0.65\neffective_coverage = 0.80\nexpected_error_type = \"scaffold_failure\"\nexpected_severity_band = [0.85, 0.95]\n\n[recall_coverage.severity_examples.arithmetic_slip]\nattempt_type = \"independent_attempt\"\ncorrectness = 0.75\nexpected_correctness = 0.70\neffective_coverage = 0.85\ntarget_error_type = \"arithmetic_slip\"\nexpected_error_type = \"arithmetic_slip\"\nexpected_severity_band = [0.25, 0.35]\n\n[recall_coverage.severity_examples.ambiguous_item]\nattempt_type = \"independent_attempt\"\ncorrectness = 0.0\nexpected_correctness = 0.70\neffective_coverage = 0.85\nbad_item_suspicion = 0.70\nexpected_error_type = \"recall_failure\"\nexpected_severity_band = [0.45, 0.75]\n"}, "b48c1ee9be4bc2a4ff5612870d8bf38391e7061b": {"t": 1785750317.0053184, "n": 6330, "h": "7ab240b4649f2836", "c": "schema_version = 1\n\n[storage]\nsqlite_path = \"state.sqlite\"\n\n[algorithms]\nalgorithm_version = \"mvp-0.4\"\n\n[scheduler]\nforgetting_risk_weight = 1.0\nactive_goal_weight = 0.35\nrecent_error_weight = 0.50\nprobe_eig_weight = 0.25\nshort_session_minutes = 20\n# Seeded exploration over near-tie candidates so logged slates carry non-degenerate\n# selection propensities (off-policy learnability). See architecture_pivot.md Stage 0.\nselection_exploration_rate = 0.1\nselection_exploration_reward_window = 0.15\n\n[scheduler.surprise]\ntheta_pos = 1.5\ntheta_neg = 1.5\nalpha_interval = 0.3\nf_min = 0.5\nf_max = 1.5\nepsilon_error_surprise = 0.05\n\n[scheduler.followup]\ntau_followup_nats = 0.05\ngamma_min = 0.5\n\n[mastery]\nbase_observation_variance = 1.0\nsigma2_drift = 0.01\np_max = 4.0\n\n# IRT 2PL difficulty-aware mastery update (spec_irt_difficulty.md §4).\n# enabled = false restores the legacy logit-space Kalman update bit-for-bit.\n[mastery.irt]\nenabled = true\ndiscrimination_default = 1.0\ndifficulty_default = 0.0\ndifficulty_from_prior = true\ndifficulty_prior_scale = 2.5\nb_abs_max = 4.0\np_clip = 1e-4\nmu_abs_max = 5.0\nmax_logit_step = 4.0\n\n[probe]\nattempts_target_default = 3\nattempts_target_with_strong_claim = 1\nclaim_skip_threshold = 0.75\nvariance_convergence_threshold = 0.10\nhypothesis_set_max_size = 5\n\n# IRT difficulty-aware probe conditionals (spec_irt_difficulty.md §5).\n[probe.irt]\ntheta_mastered = 2.0\ntheta_unfamiliar = -2.0\ncut_mid = -1.0\ncut_high = 1.0\nunfamiliar_error_leak = 0.20\nerr_low_frac = 0.80\nerr_mid_frac = 0.50\n\n# Learner self-attributed misconception probe coverage (spec_irt_difficulty.md §12).\n[probe.self_tag]\nw_base = 0.5\nw_max = 0.7\ntarget_degree = 2.0\npromotion_threshold = 3\n\n[ingest]\nwindow_char_cap = 150000\nmin_content_chars = 400\ndefault_goal_priority = 0.5\nallow_auto_captions = false\n\n[ai]\nactive_provider = \"codex\"\nfallback_provider = \"\"\ntimeout_seconds = 60\n\n[ai.routing]\ngrading = \"codex\"\ncanonical_ingest = \"codex\"\ncanonical_ingest_retry = \"\"\nauthoring = \"codex\"\n\n[ai.providers.codex]\ntype = \"codex_sdk\"\nmodel = \"gpt-5.5\"\ncheckout_path = \"/home/chloe/Documents/thinking/learnanything/codex\"\nrevision = \"<pinned-commit>\"\nstartup_command = \"\"\nstartup_timeout_seconds = 20\nhealthcheck_timeout_seconds = 5\nauth_mode = \"chatgpt\"\nreasoning_effort = \"medium\"\nreasoning_summary = \"none\"\nsdk_python_path = \"sdk/python/src\"\nsdk_codex_bin = \"\"\nsdk_launch_command = \"\"\nbase_url = \"http://127.0.0.1:8765\"\nhealthcheck_path = \"/health\"\nauthoring_path = \"/authoring-proposal\"\ncanonical_ingest_path = \"/canonical-ingest\"\ngrading_path = \"/grading-proposal\"\n\n[ai.providers.deepseek_flash]\ntype = \"openai_chat\"\nbase_url = \"https://api.deepseek.com\"\napi_key_env = \"DEEPSEEK_API_KEY\"\nmodel = \"deepseek-v4-flash\"\nresponse_format = \"json_object\"\nthinking = \"disabled\"\nmax_tokens = 8192\ntimeout_seconds = 90\n\n[ai.providers.deepseek_pro]\ntype = \"openai_chat\"\nbase_url = \"https://api.deepseek.com\"\napi_key_env = \"DEEPSEEK_API_KEY\"\nmodel = \"deepseek-v4-pro\"\nresponse_format = \"json_object\"\nthinking = \"enabled\"\nreasoning_effort = \"high\"\nmax_tokens = 16384\ntimeout_seconds = 180\n\n[codex]\nprovider = \"sdk\"\ncheckout_path = \"/home/chloe/Documents/thinking/learnanything/codex\"\nrevision = \"<pinned-commit>\"\nstartup_command = \"\"\nstartup_timeout_seconds = 20\nhealthcheck_timeout_seconds = 5\nauth_mode = \"chatgpt\"\nmodel = \"gpt-5.5\"\nreasoning_effort = \"medium\"\nreasoning_summary = \"none\"\nsdk_python_path = \"sdk/python/src\"\nsdk_codex_bin = \"\"\nsdk_launch_command = \"\"\nbase_url = \"http://127.0.0.1:8765\"\nhealthcheck_path = \"/health\"\nauthoring_path = \"/authoring-proposal\"\ncanonical_ingest_path = \"/canonical-ingest\"\ngrading_path = \"/grading-proposal\"\n\n# Family-keyed mastery damage per error type (spec §\"Error-aware updates\").\n# recall_failure is the deterministic attribution for `dont_know` attempts.\n[error_impacts]\nmax_sharpening = 3.0\n\n[error_impacts.recall_failure]\nfamilies = { recall = -0.25 }\nlo_mastery_delta = -0.05\nlocal_severity_gain = 0.8\n\n[error_impacts.scaffold_failure]\nfamilies = { recall = -0.35 }\nlo_mastery_delta = -0.05\nlocal_severity_gain = 1.5\n\n[error_impacts.arithmetic_slip]\nfamilies = { numeric = -0.05 }\nlo_mastery_delta = 0.0\nlocal_severity_gain = 0.35\n\n# Cross-LO propagation gates per error type (spec §\"Error-type gate\").\n[cross_lo_propagation.default]\nmax_depth = 3\nhop_decay = 0.5\ntotal_propagated_weight_cap = 0.7\n\n[cross_lo_propagation.error_gates.recall_failure]\nmean_factor = 0.0 # forgetting a definition is not evidence prereqs are weak\nvariance_factor = 0.25\nscope = \"all\"\n\n[cross_lo_propagation.error_gates.scaffold_failure]\nmean_factor = 0.0\nvariance_factor = 0.35\nscope = \"all\"\n\n[cross_lo_propagation.error_gates.arithmetic_slip]\nmean_factor = 0.0\nvariance_factor = 0.10\nscope = \"all\"\n\n[recall_coverage.severity_examples.first_dont_know]\nattempt_type = \"dont_know\"\nhints_used = 0\ncorrectness = 0.0\nexpected_correctness = 0.65\neffective_coverage = 0.85\nexpected_error_type = \"recall_failure\"\nexpected_severity_band = [0.70, 0.82]\n\n[recall_coverage.severity_examples.second_same_item_dont_know]\nattempt_type = \"dont_know\"\nhints_used = 0\ncorrectness = 0.0\nexpected_correctness = 0.65\neffective_coverage = 0.85\nrecent_same_item_failures = 1\nexpected_error_type = \"recall_failure\"\nexpected_severity_band = [0.95, 1.00]\n\n[recall_coverage.severity_examples.second_same_facet_dont_know]\nattempt_type = \"dont_know\"\nhints_used = 0\ncorrectness = 0.0\nexpected_correctness = 0.65\neffective_coverage = 0.85\nrecent_same_facet_failures = 1\nexpected_error_type = \"recall_failure\"\nexpected_severity_band = [0.80, 1.00]\n\n[recall_coverage.severity_examples.hinted_dont_know]\nattempt_type = \"dont_know\"\nhints_used = 2\ncorrectness = 0.0\nexpected_correctness = 0.65\neffective_coverage = 0.80\nexpected_error_type = \"scaffold_failure\"\nexpected_severity_band = [0.85, 0.95]\n\n[recall_coverage.severity_examples.arithmetic_slip]\nattempt_type = \"independent_attempt\"\ncorrectness = 0.75\nexpected_correctness = 0.70\neffective_coverage = 0.85\ntarget_error_type = \"arithmetic_slip\"\nexpected_error_type = \"arithmetic_slip\"\nexpected_severity_band = [0.25, 0.35]\n\n[recall_coverage.severity_examples.ambiguous_item]\nattempt_type = \"independent_attempt\"\ncorrectness = 0.0\nexpected_correctness = 0.70\neffective_coverage = 0.85\nbad_item_suspicion = 0.70\nexpected_error_type = \"recall_failure\"\nexpected_severity_band = [0.45, 0.75]\n"}, "6442b066d8fe25097acf955919827263ff54add1": {"t": 1785750318.1133091, "n": 6330, "h": "1c29d512b6c90312", "c": "schema_version = 1\n\n[storage]\nsqlite_path = \"state.sqlite\"\n\n[algorithms]\nalgorithm_version = \"mvp-0.3\"\n\n[scheduler]\nforgetting_risk_weight = 1.0\nactive_goal_weight = 0.35\nrecent_error_weight = 0.50\nprobe_eig_weight = 0.25\nshort_session_minutes = 20\n# Seeded exploration over near-tie candidates so logged slates carry non-degenerate\n# selection propensities (off-policy learnability). See architecture_pivot.md Stage 0.\nselection_exploration_rate = 0.1\nselection_exploration_reward_window = 0.15\n\n[scheduler.surprise]\ntheta_pos = 1.5\ntheta_neg = 1.5\nalpha_interval = 0.3\nf_min = 0.5\nf_max = 1.5\nepsilon_error_surprise = 0.05\n\n[scheduler.followup]\ntau_followup_nats = 0.05\ngamma_min = 0.5\n\n[mastery]\nbase_observation_variance = 1.0\nsigma2_drift = 0.01\np_max = 4.0\n\n# IRT 2PL difficulty-aware mastery update (spec_irt_difficulty.md §4).\n# enabled = false restores the legacy logit-space Kalman update bit-for-bit.\n[mastery.irt]\nenabled = true\ndiscrimination_default = 1.0\ndifficulty_default = 0.0\ndifficulty_from_prior = true\ndifficulty_prior_scale = 2.5\nb_abs_max = 4.0\np_clip = 1e-4\nmu_abs_max = 5.0\nmax_logit_step = 4.0\n\n[probe]\nattempts_target_default = 3\nattempts_target_with_strong_claim = 1\nclaim_skip_threshold = 0.75\nvariance_convergence_threshold = 0.10\nhypothesis_set_max_size = 5\n\n# IRT difficulty-aware probe conditionals (spec_irt_difficulty.md §5).\n[probe.irt]\ntheta_mastered = 2.0\ntheta_unfamiliar = -2.0\ncut_mid = -1.0\ncut_high = 1.0\nunfamiliar_error_leak = 0.20\nerr_low_frac = 0.80\nerr_mid_frac = 0.50\n\n# Learner self-attributed misconception probe coverage (spec_irt_difficulty.md §12).\n[probe.self_tag]\nw_base = 0.5\nw_max = 0.7\ntarget_degree = 2.0\npromotion_threshold = 3\n\n[ingest]\nwindow_char_cap = 150000\nmin_content_chars = 400\ndefault_goal_priority = 0.5\nallow_auto_captions = false\n\n[ai]\nactive_provider = \"codex\"\nfallback_provider = \"\"\ntimeout_seconds = 60\n\n[ai.routing]\ngrading = \"codex\"\ncanonical_ingest = \"codex\"\ncanonical_ingest_retry = \"\"\nauthoring = \"codex\"\n\n[ai.providers.codex]\ntype = \"codex_sdk\"\nmodel = \"gpt-5.5\"\ncheckout_path = \"/home/chloe/Documents/thinking/learnanything/codex\"\nrevision = \"<pinned-commit>\"\nstartup_command = \"\"\nstartup_timeout_seconds = 20\nhealthcheck_timeout_seconds = 5\nauth_mode = \"chatgpt\"\nreasoning_effort = \"medium\"\nreasoning_summary = \"none\"\nsdk_python_path = \"sdk/python/src\"\nsdk_codex_bin = \"\"\nsdk_launch_command = \"\"\nbase_url = \"http://127.0.0.1:8765\"\nhealthcheck_path = \"/health\"\nauthoring_path = \"/authoring-proposal\"\ncanonical_ingest_path = \"/canonical-ingest\"\ngrading_path = \"/grading-proposal\"\n\n[ai.providers.deepseek_flash]\ntype = \"openai_chat\"\nbase_url = \"https://api.deepseek.com\"\napi_key_env = \"DEEPSEEK_API_KEY\"\nmodel = \"deepseek-v4-flash\"\nresponse_format = \"json_object\"\nthinking = \"disabled\"\nmax_tokens = 8192\ntimeout_seconds = 90\n\n[ai.providers.deepseek_pro]\ntype = \"openai_chat\"\nbase_url = \"https://api.deepseek.com\"\napi_key_env = \"DEEPSEEK_API_KEY\"\nmodel = \"deepseek-v4-pro\"\nresponse_format = \"json_object\"\nthinking = \"enabled\"\nreasoning_effort = \"high\"\nmax_tokens = 16384\ntimeout_seconds = 180\n\n[codex]\nprovider = \"sdk\"\ncheckout_path = \"/home/chloe/Documents/thinking/learnanything/codex\"\nrevision = \"<pinned-commit>\"\nstartup_command = \"\"\nstartup_timeout_seconds = 20\nhealthcheck_timeout_seconds = 5\nauth_mode = \"chatgpt\"\nmodel = \"gpt-5.5\"\nreasoning_effort = \"medium\"\nreasoning_summary = \"none\"\nsdk_python_path = \"sdk/python/src\"\nsdk_codex_bin = \"\"\nsdk_launch_command = \"\"\nbase_url = \"http://127.0.0.1:8765\"\nhealthcheck_path = \"/health\"\nauthoring_path = \"/authoring-proposal\"\ncanonical_ingest_path = \"/canonical-ingest\"\ngrading_path = \"/grading-proposal\"\n\n# Family-keyed mastery damage per error type (spec §\"Error-aware updates\").\n# recall_failure is the deterministic attribution for `dont_know` attempts.\n[error_impacts]\nmax_sharpening = 3.0\n\n[error_impacts.recall_failure]\nfamilies = { recall = -0.25 }\nlo_mastery_delta = -0.05\nlocal_severity_gain = 0.8\n\n[error_impacts.scaffold_failure]\nfamilies = { recall = -0.35 }\nlo_mastery_delta = -0.05\nlocal_severity_gain = 1.5\n\n[error_impacts.arithmetic_slip]\nfamilies = { numeric = -0.05 }\nlo_mastery_delta = 0.0\nlocal_severity_gain = 0.35\n\n# Cross-LO propagation gates per error type (spec §\"Error-type gate\").\n[cross_lo_propagation.default]\nmax_depth = 3\nhop_decay = 0.5\ntotal_propagated_weight_cap = 0.7\n\n[cross_lo_propagation.error_gates.recall_failure]\nmean_factor = 0.0 # forgetting a definition is not evidence prereqs are weak\nvariance_factor = 0.25\nscope = \"all\"\n\n[cross_lo_propagation.error_gates.scaffold_failure]\nmean_factor = 0.0\nvariance_factor = 0.35\nscope = \"all\"\n\n[cross_lo_propagation.error_gates.arithmetic_slip]\nmean_factor = 0.0\nvariance_factor = 0.10\nscope = \"all\"\n\n[recall_coverage.severity_examples.first_dont_know]\nattempt_type = \"dont_know\"\nhints_used = 0\ncorrectness = 0.0\nexpected_correctness = 0.65\neffective_coverage = 0.85\nexpected_error_type = \"recall_failure\"\nexpected_severity_band = [0.70, 0.82]\n\n[recall_coverage.severity_examples.second_same_item_dont_know]\nattempt_type = \"dont_know\"\nhints_used = 0\ncorrectness = 0.0\nexpected_correctness = 0.65\neffective_coverage = 0.85\nrecent_same_item_failures = 1\nexpected_error_type = \"recall_failure\"\nexpected_severity_band = [0.95, 1.00]\n\n[recall_coverage.severity_examples.second_same_facet_dont_know]\nattempt_type = \"dont_know\"\nhints_used = 0\ncorrectness = 0.0\nexpected_correctness = 0.65\neffective_coverage = 0.85\nrecent_same_facet_failures = 1\nexpected_error_type = \"recall_failure\"\nexpected_severity_band = [0.80, 1.00]\n\n[recall_coverage.severity_examples.hinted_dont_know]\nattempt_type = \"dont_know\"\nhints_used = 2\ncorrectness = 0.0\nexpected_correctness = 0.65\neffective_coverage = 0.80\nexpected_error_type = \"scaffold_failure\"\nexpected_severity_band = [0.85, 0.95]\n\n[recall_coverage.severity_examples.arithmetic_slip]\nattempt_type = \"independent_attempt\"\ncorrectness = 0.75\nexpected_correctness = 0.70\neffective_coverage = 0.85\ntarget_error_type = \"arithmetic_slip\"\nexpected_error_type = \"arithmetic_slip\"\nexpected_severity_band = [0.25, 0.35]\n\n[recall_coverage.severity_examples.ambiguous_item]\nattempt_type = \"independent_attempt\"\ncorrectness = 0.0\nexpected_correctness = 0.70\neffective_coverage = 0.85\nbad_item_suspicion = 0.70\nexpected_error_type = \"recall_failure\"\nexpected_severity_band = [0.45, 0.75]\n"}}, "fixtures/physical_therapy/learnloop.toml": {"d7f5830f824d7636193af334e950c1d2ffc477c4": {"t": 1785745371.5467293, "n": 6335, "h": "f229f60aca5fc45c", "c": "schema_version = 1\n\n[storage]\nsqlite_path = \"state.sqlite\"\n\n[algorithms]\nalgorithm_version = \"mvp-0.6\"\n\n[scheduler]\nforgetting_risk_weight = 1.0\nrecent_error_weight = 0.50\nprobe_eig_weight = 0.25\nshort_session_minutes = 20\n# Seeded exploration over near-tie candidates so logged slates carry non-degenerate\n# selection propensities (off-policy learnability). See architecture_pivot.md Stage 0.\nselection_exploration_rate = 0.1\nselection_exploration_reward_window = 0.15\n\n[scheduler.surprise]\ntheta_pos = 1.5\ntheta_neg = 1.5\nalpha_interval = 0.3\nf_min = 0.5\nf_max = 1.5\nepsilon_error_surprise = 0.05\n\n[scheduler.followup]\ntau_followup_nats = 0.05\ngamma_min = 0.5\nmin_target_facet_overlap = 0.5\n\n[mastery]\nbase_observation_variance = 1.0\nsigma2_drift = 0.01\np_max = 4.0\n\n# IRT 2PL difficulty-aware mastery update (spec_irt_difficulty.md §4).\n# enabled = false restores the legacy logit-space Kalman update bit-for-bit.\n[mastery.irt]\nenabled = true\ndiscrimination_default = 1.0\ndifficulty_default = 0.0\ndifficulty_from_prior = true\ndifficulty_prior_scale = 2.5\nb_abs_max = 4.0\np_clip = 1e-4\nmu_abs_max = 5.0\nmax_logit_step = 4.0\n\n[probe]\nattempts_target_default = 3\nattempts_target_with_strong_claim = 1\nclaim_skip_threshold = 0.75\nvariance_convergence_threshold = 0.10\nhypothesis_set_max_size = 5\n\n# IRT difficulty-aware probe conditionals (spec_irt_difficulty.md §5).\n[probe.irt]\ntheta_mastered = 2.0\ntheta_unfamiliar = -2.0\ncut_mid = -1.0\ncut_high = 1.0\nunfamiliar_error_leak = 0.20\nerr_low_frac = 0.80\nerr_mid_frac = 0.50\n\n# Learner self-attributed misconception probe coverage (spec_irt_difficulty.md §12).\n[probe.self_tag]\nw_base = 0.5\nw_max = 0.7\ntarget_degree = 2.0\npromotion_threshold = 3\n\n[ingest]\nwindow_char_cap = 150000\nmin_content_chars = 400\ndefault_goal_priority = 0.5\nallow_auto_captions = false\n\n[ai]\nactive_provider = \"codex\"\nfallback_provider = \"\"\ntimeout_seconds = 60\n\n[ai.routing]\ngrading = \"codex\"\ncanonical_ingest = \"codex\"\ncanonical_ingest_retry = \"\"\nauthoring = \"codex\"\n\n[ai.providers.codex]\ntype = \"codex_sdk\"\nmodel = \"gpt-5.5\"\ncheckout_path = \"/home/chloe/Documents/thinking/learnanything/codex\"\nrevision = \"<pinned-commit>\"\nstartup_command = \"\"\nstartup_timeout_seconds = 20\nhealthcheck_timeout_seconds = 5\nauth_mode = \"chatgpt\"\nreasoning_effort = \"medium\"\nreasoning_summary = \"none\"\nsdk_python_path = \"sdk/python/src\"\nsdk_codex_bin = \"\"\nsdk_launch_command = \"\"\nbase_url = \"http://127.0.0.1:8765\"\nhealthcheck_path = \"/health\"\nauthoring_path = \"/authoring-proposal\"\ncanonical_ingest_path = \"/canonical-ingest\"\ngrading_path = \"/grading-proposal\"\n\n[ai.providers.deepseek_flash]\ntype = \"openai_chat\"\nbase_url = \"https://api.deepseek.com\"\napi_key_env = \"DEEPSEEK_API_KEY\"\nmodel = \"deepseek-v4-flash\"\nresponse_format = \"json_object\"\nthinking = \"disabled\"\nmax_tokens = 8192\ntimeout_seconds = 90\n\n[ai.providers.deepseek_pro]\ntype = \"openai_chat\"\nbase_url = \"https://api.deepseek.com\"\napi_key_env = \"DEEPSEEK_API_KEY\"\nmodel = \"deepseek-v4-pro\"\nresponse_format = \"json_object\"\nthinking = \"enabled\"\nreasoning_effort = \"high\"\nmax_tokens = 16384\ntimeout_seconds = 180\n\n[codex]\nprovider = \"sdk\"\ncheckout_path = \"/home/chloe/Documents/thinking/learnanything/codex\"\nrevision = \"<pinned-commit>\"\nstartup_command = \"\"\nstartup_timeout_seconds = 20\nhealthcheck_timeout_seconds = 5\nauth_mode = \"chatgpt\"\nmodel = \"gpt-5.5\"\nreasoning_effort = \"medium\"\nreasoning_summary = \"none\"\nsdk_python_path = \"sdk/python/src\"\nsdk_codex_bin = \"\"\nsdk_launch_command = \"\"\nbase_url = \"http://127.0.0.1:8765\"\nhealthcheck_path = \"/health\"\nauthoring_path = \"/authoring-proposal\"\ncanonical_ingest_path = \"/canonical-ingest\"\ngrading_path = \"/grading-proposal\"\n\n# Family-keyed mastery damage per error type (spec §\"Error-aware updates\").\n# recall_failure is the deterministic attribution for `dont_know` attempts.\n[error_impacts]\nmax_sharpening = 3.0\n\n[error_impacts.recall_failure]\nfamilies = { recall = -0.25 }\nlo_mastery_delta = -0.05\nlocal_severity_gain = 0.8\n\n[error_impacts.scaffold_failure]\nfamilies = { recall = -0.35 }\nlo_mastery_delta = -0.05\nlocal_severity_gain = 1.5\n\n[error_impacts.arithmetic_slip]\nfamilies = { numeric = -0.05 }\nlo_mastery_delta = 0.0\nlocal_severity_gain = 0.35\n\n# Cross-LO propagation gates per error type (spec §\"Error-type gate\").\n[cross_lo_propagation.default]\nmax_depth = 3\nhop_decay = 0.5\ntotal_propagated_weight_cap = 0.7\n\n[cross_lo_propagation.error_gates.recall_failure]\nmean_factor = 0.0 # forgetting a definition is not evidence prereqs are weak\nvariance_factor = 0.25\nscope = \"all\"\n\n[cross_lo_propagation.error_gates.scaffold_failure]\nmean_factor = 0.0\nvariance_factor = 0.35\nscope = \"all\"\n\n[cross_lo_propagation.error_gates.arithmetic_slip]\nmean_factor = 0.0\nvariance_factor = 0.10\nscope = \"all\"\n\n[recall_coverage.severity_examples.first_dont_know]\nattempt_type = \"dont_know\"\nhints_used = 0\ncorrectness = 0.0\nexpected_correctness = 0.65\neffective_coverage = 0.85\nexpected_error_type = \"recall_failure\"\nexpected_severity_band = [0.70, 0.82]\n\n[recall_coverage.severity_examples.second_same_item_dont_know]\nattempt_type = \"dont_know\"\nhints_used = 0\ncorrectness = 0.0\nexpected_correctness = 0.65\neffective_coverage = 0.85\nrecent_same_item_failures = 1\nexpected_error_type = \"recall_failure\"\nexpected_severity_band = [0.95, 1.00]\n\n[recall_coverage.severity_examples.second_same_facet_dont_know]\nattempt_type = \"dont_know\"\nhints_used = 0\ncorrectness = 0.0\nexpected_correctness = 0.65\neffective_coverage = 0.85\nrecent_same_facet_failures = 1\nexpected_error_type = \"recall_failure\"\nexpected_severity_band = [0.80, 1.00]\n\n[recall_coverage.severity_examples.hinted_dont_know]\nattempt_type = \"dont_know\"\nhints_used = 2\ncorrectness = 0.0\nexpected_correctness = 0.65\neffective_coverage = 0.80\nexpected_error_type = \"scaffold_failure\"\nexpected_severity_band = [0.85, 0.95]\n\n[recall_coverage.severity_examples.arithmetic_slip]\nattempt_type = \"independent_attempt\"\ncorrectness = 0.75\nexpected_correctness = 0.70\neffective_coverage = 0.85\ntarget_error_type = \"arithmetic_slip\"\nexpected_error_type = \"arithmetic_slip\"\nexpected_severity_band = [0.25, 0.35]\n\n[recall_coverage.severity_examples.ambiguous_item]\nattempt_type = \"independent_attempt\"\ncorrectness = 0.0\nexpected_correctness = 0.70\neffective_coverage = 0.85\nbad_item_suspicion = 0.70\nexpected_error_type = \"recall_failure\"\nexpected_severity_band = [0.45, 0.75]\n"}, "b19e81d9993c28e995049da1aa16f8d316d56d68": {"t": 1785750320.2721786, "n": 6335, "h": "f229f60aca5fc45c", "c": "schema_version = 1\n\n[storage]\nsqlite_path = \"state.sqlite\"\n\n[algorithms]\nalgorithm_version = \"mvp-0.6\"\n\n[scheduler]\nforgetting_risk_weight = 1.0\nrecent_error_weight = 0.50\nprobe_eig_weight = 0.25\nshort_session_minutes = 20\n# Seeded exploration over near-tie candidates so logged slates carry non-degenerate\n# selection propensities (off-policy learnability). See architecture_pivot.md Stage 0.\nselection_exploration_rate = 0.1\nselection_exploration_reward_window = 0.15\n\n[scheduler.surprise]\ntheta_pos = 1.5\ntheta_neg = 1.5\nalpha_interval = 0.3\nf_min = 0.5\nf_max = 1.5\nepsilon_error_surprise = 0.05\n\n[scheduler.followup]\ntau_followup_nats = 0.05\ngamma_min = 0.5\nmin_target_facet_overlap = 0.5\n\n[mastery]\nbase_observation_variance = 1.0\nsigma2_drift = 0.01\np_max = 4.0\n\n# IRT 2PL difficulty-aware mastery update (spec_irt_difficulty.md §4).\n# enabled = false restores the legacy logit-space Kalman update bit-for-bit.\n[mastery.irt]\nenabled = true\ndiscrimination_default = 1.0\ndifficulty_default = 0.0\ndifficulty_from_prior = true\ndifficulty_prior_scale = 2.5\nb_abs_max = 4.0\np_clip = 1e-4\nmu_abs_max = 5.0\nmax_logit_step = 4.0\n\n[probe]\nattempts_target_default = 3\nattempts_target_with_strong_claim = 1\nclaim_skip_threshold = 0.75\nvariance_convergence_threshold = 0.10\nhypothesis_set_max_size = 5\n\n# IRT difficulty-aware probe conditionals (spec_irt_difficulty.md §5).\n[probe.irt]\ntheta_mastered = 2.0\ntheta_unfamiliar = -2.0\ncut_mid = -1.0\ncut_high = 1.0\nunfamiliar_error_leak = 0.20\nerr_low_frac = 0.80\nerr_mid_frac = 0.50\n\n# Learner self-attributed misconception probe coverage (spec_irt_difficulty.md §12).\n[probe.self_tag]\nw_base = 0.5\nw_max = 0.7\ntarget_degree = 2.0\npromotion_threshold = 3\n\n[ingest]\nwindow_char_cap = 150000\nmin_content_chars = 400\ndefault_goal_priority = 0.5\nallow_auto_captions = false\n\n[ai]\nactive_provider = \"codex\"\nfallback_provider = \"\"\ntimeout_seconds = 60\n\n[ai.routing]\ngrading = \"codex\"\ncanonical_ingest = \"codex\"\ncanonical_ingest_retry = \"\"\nauthoring = \"codex\"\n\n[ai.providers.codex]\ntype = \"codex_sdk\"\nmodel = \"gpt-5.5\"\ncheckout_path = \"/home/chloe/Documents/thinking/learnanything/codex\"\nrevision = \"<pinned-commit>\"\nstartup_command = \"\"\nstartup_timeout_seconds = 20\nhealthcheck_timeout_seconds = 5\nauth_mode = \"chatgpt\"\nreasoning_effort = \"medium\"\nreasoning_summary = \"none\"\nsdk_python_path = \"sdk/python/src\"\nsdk_codex_bin = \"\"\nsdk_launch_command = \"\"\nbase_url = \"http://127.0.0.1:8765\"\nhealthcheck_path = \"/health\"\nauthoring_path = \"/authoring-proposal\"\ncanonical_ingest_path = \"/canonical-ingest\"\ngrading_path = \"/grading-proposal\"\n\n[ai.providers.deepseek_flash]\ntype = \"openai_chat\"\nbase_url = \"https://api.deepseek.com\"\napi_key_env = \"DEEPSEEK_API_KEY\"\nmodel = \"deepseek-v4-flash\"\nresponse_format = \"json_object\"\nthinking = \"disabled\"\nmax_tokens = 8192\ntimeout_seconds = 90\n\n[ai.providers.deepseek_pro]\ntype = \"openai_chat\"\nbase_url = \"https://api.deepseek.com\"\napi_key_env = \"DEEPSEEK_API_KEY\"\nmodel = \"deepseek-v4-pro\"\nresponse_format = \"json_object\"\nthinking = \"enabled\"\nreasoning_effort = \"high\"\nmax_tokens = 16384\ntimeout_seconds = 180\n\n[codex]\nprovider = \"sdk\"\ncheckout_path = \"/home/chloe/Documents/thinking/learnanything/codex\"\nrevision = \"<pinned-commit>\"\nstartup_command = \"\"\nstartup_timeout_seconds = 20\nhealthcheck_timeout_seconds = 5\nauth_mode = \"chatgpt\"\nmodel = \"gpt-5.5\"\nreasoning_effort = \"medium\"\nreasoning_summary = \"none\"\nsdk_python_path = \"sdk/python/src\"\nsdk_codex_bin = \"\"\nsdk_launch_command = \"\"\nbase_url = \"http://127.0.0.1:8765\"\nhealthcheck_path = \"/health\"\nauthoring_path = \"/authoring-proposal\"\ncanonical_ingest_path = \"/canonical-ingest\"\ngrading_path = \"/grading-proposal\"\n\n# Family-keyed mastery damage per error type (spec §\"Error-aware updates\").\n# recall_failure is the deterministic attribution for `dont_know` attempts.\n[error_impacts]\nmax_sharpening = 3.0\n\n[error_impacts.recall_failure]\nfamilies = { recall = -0.25 }\nlo_mastery_delta = -0.05\nlocal_severity_gain = 0.8\n\n[error_impacts.scaffold_failure]\nfamilies = { recall = -0.35 }\nlo_mastery_delta = -0.05\nlocal_severity_gain = 1.5\n\n[error_impacts.arithmetic_slip]\nfamilies = { numeric = -0.05 }\nlo_mastery_delta = 0.0\nlocal_severity_gain = 0.35\n\n# Cross-LO propagation gates per error type (spec §\"Error-type gate\").\n[cross_lo_propagation.default]\nmax_depth = 3\nhop_decay = 0.5\ntotal_propagated_weight_cap = 0.7\n\n[cross_lo_propagation.error_gates.recall_failure]\nmean_factor = 0.0 # forgetting a definition is not evidence prereqs are weak\nvariance_factor = 0.25\nscope = \"all\"\n\n[cross_lo_propagation.error_gates.scaffold_failure]\nmean_factor = 0.0\nvariance_factor = 0.35\nscope = \"all\"\n\n[cross_lo_propagation.error_gates.arithmetic_slip]\nmean_factor = 0.0\nvariance_factor = 0.10\nscope = \"all\"\n\n[recall_coverage.severity_examples.first_dont_know]\nattempt_type = \"dont_know\"\nhints_used = 0\ncorrectness = 0.0\nexpected_correctness = 0.65\neffective_coverage = 0.85\nexpected_error_type = \"recall_failure\"\nexpected_severity_band = [0.70, 0.82]\n\n[recall_coverage.severity_examples.second_same_item_dont_know]\nattempt_type = \"dont_know\"\nhints_used = 0\ncorrectness = 0.0\nexpected_correctness = 0.65\neffective_coverage = 0.85\nrecent_same_item_failures = 1\nexpected_error_type = \"recall_failure\"\nexpected_severity_band = [0.95, 1.00]\n\n[recall_coverage.severity_examples.second_same_facet_dont_know]\nattempt_type = \"dont_know\"\nhints_used = 0\ncorrectness = 0.0\nexpected_correctness = 0.65\neffective_coverage = 0.85\nrecent_same_facet_failures = 1\nexpected_error_type = \"recall_failure\"\nexpected_severity_band = [0.80, 1.00]\n\n[recall_coverage.severity_examples.hinted_dont_know]\nattempt_type = \"dont_know\"\nhints_used = 2\ncorrectness = 0.0\nexpected_correctness = 0.65\neffective_coverage = 0.80\nexpected_error_type = \"scaffold_failure\"\nexpected_severity_band = [0.85, 0.95]\n\n[recall_coverage.severity_examples.arithmetic_slip]\nattempt_type = \"independent_attempt\"\ncorrectness = 0.75\nexpected_correctness = 0.70\neffective_coverage = 0.85\ntarget_error_type = \"arithmetic_slip\"\nexpected_error_type = \"arithmetic_slip\"\nexpected_severity_band = [0.25, 0.35]\n\n[recall_coverage.severity_examples.ambiguous_item]\nattempt_type = \"independent_attempt\"\ncorrectness = 0.0\nexpected_correctness = 0.70\neffective_coverage = 0.85\nbad_item_suspicion = 0.70\nexpected_error_type = \"recall_failure\"\nexpected_severity_band = [0.45, 0.75]\n"}, "565100878e11bc9ac281139570040c118fbaf1a5": {"t": 1785750321.3507855, "n": 6335, "h": "e78a38cdd6d12483", "c": "schema_version = 1\n\n[storage]\nsqlite_path = \"state.sqlite\"\n\n[algorithms]\nalgorithm_version = \"mvp-0.5\"\n\n[scheduler]\nforgetting_risk_weight = 1.0\nrecent_error_weight = 0.50\nprobe_eig_weight = 0.25\nshort_session_minutes = 20\n# Seeded exploration over near-tie candidates so logged slates carry non-degenerate\n# selection propensities (off-policy learnability). See architecture_pivot.md Stage 0.\nselection_exploration_rate = 0.1\nselection_exploration_reward_window = 0.15\n\n[scheduler.surprise]\ntheta_pos = 1.5\ntheta_neg = 1.5\nalpha_interval = 0.3\nf_min = 0.5\nf_max = 1.5\nepsilon_error_surprise = 0.05\n\n[scheduler.followup]\ntau_followup_nats = 0.05\ngamma_min = 0.5\nmin_target_facet_overlap = 0.5\n\n[mastery]\nbase_observation_variance = 1.0\nsigma2_drift = 0.01\np_max = 4.0\n\n# IRT 2PL difficulty-aware mastery update (spec_irt_difficulty.md §4).\n# enabled = false restores the legacy logit-space Kalman update bit-for-bit.\n[mastery.irt]\nenabled = true\ndiscrimination_default = 1.0\ndifficulty_default = 0.0\ndifficulty_from_prior = true\ndifficulty_prior_scale = 2.5\nb_abs_max = 4.0\np_clip = 1e-4\nmu_abs_max = 5.0\nmax_logit_step = 4.0\n\n[probe]\nattempts_target_default = 3\nattempts_target_with_strong_claim = 1\nclaim_skip_threshold = 0.75\nvariance_convergence_threshold = 0.10\nhypothesis_set_max_size = 5\n\n# IRT difficulty-aware probe conditionals (spec_irt_difficulty.md §5).\n[probe.irt]\ntheta_mastered = 2.0\ntheta_unfamiliar = -2.0\ncut_mid = -1.0\ncut_high = 1.0\nunfamiliar_error_leak = 0.20\nerr_low_frac = 0.80\nerr_mid_frac = 0.50\n\n# Learner self-attributed misconception probe coverage (spec_irt_difficulty.md §12).\n[probe.self_tag]\nw_base = 0.5\nw_max = 0.7\ntarget_degree = 2.0\npromotion_threshold = 3\n\n[ingest]\nwindow_char_cap = 150000\nmin_content_chars = 400\ndefault_goal_priority = 0.5\nallow_auto_captions = false\n\n[ai]\nactive_provider = \"codex\"\nfallback_provider = \"\"\ntimeout_seconds = 60\n\n[ai.routing]\ngrading = \"codex\"\ncanonical_ingest = \"codex\"\ncanonical_ingest_retry = \"\"\nauthoring = \"codex\"\n\n[ai.providers.codex]\ntype = \"codex_sdk\"\nmodel = \"gpt-5.5\"\ncheckout_path = \"/home/chloe/Documents/thinking/learnanything/codex\"\nrevision = \"<pinned-commit>\"\nstartup_command = \"\"\nstartup_timeout_seconds = 20\nhealthcheck_timeout_seconds = 5\nauth_mode = \"chatgpt\"\nreasoning_effort = \"medium\"\nreasoning_summary = \"none\"\nsdk_python_path = \"sdk/python/src\"\nsdk_codex_bin = \"\"\nsdk_launch_command = \"\"\nbase_url = \"http://127.0.0.1:8765\"\nhealthcheck_path = \"/health\"\nauthoring_path = \"/authoring-proposal\"\ncanonical_ingest_path = \"/canonical-ingest\"\ngrading_path = \"/grading-proposal\"\n\n[ai.providers.deepseek_flash]\ntype = \"openai_chat\"\nbase_url = \"https://api.deepseek.com\"\napi_key_env = \"DEEPSEEK_API_KEY\"\nmodel = \"deepseek-v4-flash\"\nresponse_format = \"json_object\"\nthinking = \"disabled\"\nmax_tokens = 8192\ntimeout_seconds = 90\n\n[ai.providers.deepseek_pro]\ntype = \"openai_chat\"\nbase_url = \"https://api.deepseek.com\"\napi_key_env = \"DEEPSEEK_API_KEY\"\nmodel = \"deepseek-v4-pro\"\nresponse_format = \"json_object\"\nthinking = \"enabled\"\nreasoning_effort = \"high\"\nmax_tokens = 16384\ntimeout_seconds = 180\n\n[codex]\nprovider = \"sdk\"\ncheckout_path = \"/home/chloe/Documents/thinking/learnanything/codex\"\nrevision = \"<pinned-commit>\"\nstartup_command = \"\"\nstartup_timeout_seconds = 20\nhealthcheck_timeout_seconds = 5\nauth_mode = \"chatgpt\"\nmodel = \"gpt-5.5\"\nreasoning_effort = \"medium\"\nreasoning_summary = \"none\"\nsdk_python_path = \"sdk/python/src\"\nsdk_codex_bin = \"\"\nsdk_launch_command = \"\"\nbase_url = \"http://127.0.0.1:8765\"\nhealthcheck_path = \"/health\"\nauthoring_path = \"/authoring-proposal\"\ncanonical_ingest_path = \"/canonical-ingest\"\ngrading_path = \"/grading-proposal\"\n\n# Family-keyed mastery damage per error type (spec §\"Error-aware updates\").\n# recall_failure is the deterministic attribution for `dont_know` attempts.\n[error_impacts]\nmax_sharpening = 3.0\n\n[error_impacts.recall_failure]\nfamilies = { recall = -0.25 }\nlo_mastery_delta = -0.05\nlocal_severity_gain = 0.8\n\n[error_impacts.scaffold_failure]\nfamilies = { recall = -0.35 }\nlo_mastery_delta = -0.05\nlocal_severity_gain = 1.5\n\n[error_impacts.arithmetic_slip]\nfamilies = { numeric = -0.05 }\nlo_mastery_delta = 0.0\nlocal_severity_gain = 0.35\n\n# Cross-LO propagation gates per error type (spec §\"Error-type gate\").\n[cross_lo_propagation.default]\nmax_depth = 3\nhop_decay = 0.5\ntotal_propagated_weight_cap = 0.7\n\n[cross_lo_propagation.error_gates.recall_failure]\nmean_factor = 0.0 # forgetting a definition is not evidence prereqs are weak\nvariance_factor = 0.25\nscope = \"all\"\n\n[cross_lo_propagation.error_gates.scaffold_failure]\nmean_factor = 0.0\nvariance_factor = 0.35\nscope = \"all\"\n\n[cross_lo_propagation.error_gates.arithmetic_slip]\nmean_factor = 0.0\nvariance_factor = 0.10\nscope = \"all\"\n\n[recall_coverage.severity_examples.first_dont_know]\nattempt_type = \"dont_know\"\nhints_used = 0\ncorrectness = 0.0\nexpected_correctness = 0.65\neffective_coverage = 0.85\nexpected_error_type = \"recall_failure\"\nexpected_severity_band = [0.70, 0.82]\n\n[recall_coverage.severity_examples.second_same_item_dont_know]\nattempt_type = \"dont_know\"\nhints_used = 0\ncorrectness = 0.0\nexpected_correctness = 0.65\neffective_coverage = 0.85\nrecent_same_item_failures = 1\nexpected_error_type = \"recall_failure\"\nexpected_severity_band = [0.95, 1.00]\n\n[recall_coverage.severity_examples.second_same_facet_dont_know]\nattempt_type = \"dont_know\"\nhints_used = 0\ncorrectness = 0.0\nexpected_correctness = 0.65\neffective_coverage = 0.85\nrecent_same_facet_failures = 1\nexpected_error_type = \"recall_failure\"\nexpected_severity_band = [0.80, 1.00]\n\n[recall_coverage.severity_examples.hinted_dont_know]\nattempt_type = \"dont_know\"\nhints_used = 2\ncorrectness = 0.0\nexpected_correctness = 0.65\neffective_coverage = 0.80\nexpected_error_type = \"scaffold_failure\"\nexpected_severity_band = [0.85, 0.95]\n\n[recall_coverage.severity_examples.arithmetic_slip]\nattempt_type = \"independent_attempt\"\ncorrectness = 0.75\nexpected_correctness = 0.70\neffective_coverage = 0.85\ntarget_error_type = \"arithmetic_slip\"\nexpected_error_type = \"arithmetic_slip\"\nexpected_severity_band = [0.25, 0.35]\n\n[recall_coverage.severity_examples.ambiguous_item]\nattempt_type = \"independent_attempt\"\ncorrectness = 0.0\nexpected_correctness = 0.70\neffective_coverage = 0.85\nbad_item_suspicion = 0.70\nexpected_error_type = \"recall_failure\"\nexpected_severity_band = [0.45, 0.75]\n"}, "b48c1ee9be4bc2a4ff5612870d8bf38391e7061b": {"t": 1785750322.5602922, "n": 6361, "h": "3f2ad8055515ebc9", "c": "schema_version = 1\n\n[storage]\nsqlite_path = \"state.sqlite\"\n\n[algorithms]\nalgorithm_version = \"mvp-0.4\"\n\n[scheduler]\nforgetting_risk_weight = 1.0\nactive_goal_weight = 0.35\nrecent_error_weight = 0.50\nprobe_eig_weight = 0.25\nshort_session_minutes = 20\n# Seeded exploration over near-tie candidates so logged slates carry non-degenerate\n# selection propensities (off-policy learnability). See architecture_pivot.md Stage 0.\nselection_exploration_rate = 0.1\nselection_exploration_reward_window = 0.15\n\n[scheduler.surprise]\ntheta_pos = 1.5\ntheta_neg = 1.5\nalpha_interval = 0.3\nf_min = 0.5\nf_max = 1.5\nepsilon_error_surprise = 0.05\n\n[scheduler.followup]\ntau_followup_nats = 0.05\ngamma_min = 0.5\nmin_target_facet_overlap = 0.5\n\n[mastery]\nbase_observation_variance = 1.0\nsigma2_drift = 0.01\np_max = 4.0\n\n# IRT 2PL difficulty-aware mastery update (spec_irt_difficulty.md §4).\n# enabled = false restores the legacy logit-space Kalman update bit-for-bit.\n[mastery.irt]\nenabled = true\ndiscrimination_default = 1.0\ndifficulty_default = 0.0\ndifficulty_from_prior = true\ndifficulty_prior_scale = 2.5\nb_abs_max = 4.0\np_clip = 1e-4\nmu_abs_max = 5.0\nmax_logit_step = 4.0\n\n[probe]\nattempts_target_default = 3\nattempts_target_with_strong_claim = 1\nclaim_skip_threshold = 0.75\nvariance_convergence_threshold = 0.10\nhypothesis_set_max_size = 5\n\n# IRT difficulty-aware probe conditionals (spec_irt_difficulty.md §5).\n[probe.irt]\ntheta_mastered = 2.0\ntheta_unfamiliar = -2.0\ncut_mid = -1.0\ncut_high = 1.0\nunfamiliar_error_leak = 0.20\nerr_low_frac = 0.80\nerr_mid_frac = 0.50\n\n# Learner self-attributed misconception probe coverage (spec_irt_difficulty.md §12).\n[probe.self_tag]\nw_base = 0.5\nw_max = 0.7\ntarget_degree = 2.0\npromotion_threshold = 3\n\n[ingest]\nwindow_char_cap = 150000\nmin_content_chars = 400\ndefault_goal_priority = 0.5\nallow_auto_captions = false\n\n[ai]\nactive_provider = \"codex\"\nfallback_provider = \"\"\ntimeout_seconds = 60\n\n[ai.routing]\ngrading = \"codex\"\ncanonical_ingest = \"codex\"\ncanonical_ingest_retry = \"\"\nauthoring = \"codex\"\n\n[ai.providers.codex]\ntype = \"codex_sdk\"\nmodel = \"gpt-5.5\"\ncheckout_path = \"/home/chloe/Documents/thinking/learnanything/codex\"\nrevision = \"<pinned-commit>\"\nstartup_command = \"\"\nstartup_timeout_seconds = 20\nhealthcheck_timeout_seconds = 5\nauth_mode = \"chatgpt\"\nreasoning_effort = \"medium\"\nreasoning_summary = \"none\"\nsdk_python_path = \"sdk/python/src\"\nsdk_codex_bin = \"\"\nsdk_launch_command = \"\"\nbase_url = \"http://127.0.0.1:8765\"\nhealthcheck_path = \"/health\"\nauthoring_path = \"/authoring-proposal\"\ncanonical_ingest_path = \"/canonical-ingest\"\ngrading_path = \"/grading-proposal\"\n\n[ai.providers.deepseek_flash]\ntype = \"openai_chat\"\nbase_url = \"https://api.deepseek.com\"\napi_key_env = \"DEEPSEEK_API_KEY\"\nmodel = \"deepseek-v4-flash\"\nresponse_format = \"json_object\"\nthinking = \"disabled\"\nmax_tokens = 8192\ntimeout_seconds = 90\n\n[ai.providers.deepseek_pro]\ntype = \"openai_chat\"\nbase_url = \"https://api.deepseek.com\"\napi_key_env = \"DEEPSEEK_API_KEY\"\nmodel = \"deepseek-v4-pro\"\nresponse_format = \"json_object\"\nthinking = \"enabled\"\nreasoning_effort = \"high\"\nmax_tokens = 16384\ntimeout_seconds = 180\n\n[codex]\nprovider = \"sdk\"\ncheckout_path = \"/home/chloe/Documents/thinking/learnanything/codex\"\nrevision = \"<pinned-commit>\"\nstartup_command = \"\"\nstartup_timeout_seconds = 20\nhealthcheck_timeout_seconds = 5\nauth_mode = \"chatgpt\"\nmodel = \"gpt-5.5\"\nreasoning_effort = \"medium\"\nreasoning_summary = \"none\"\nsdk_python_path = \"sdk/python/src\"\nsdk_codex_bin = \"\"\nsdk_launch_command = \"\"\nbase_url = \"http://127.0.0.1:8765\"\nhealthcheck_path = \"/health\"\nauthoring_path = \"/authoring-proposal\"\ncanonical_ingest_path = \"/canonical-ingest\"\ngrading_path = \"/grading-proposal\"\n\n# Family-keyed mastery damage per error type (spec §\"Error-aware updates\").\n# recall_failure is the deterministic attribution for `dont_know` attempts.\n[error_impacts]\nmax_sharpening = 3.0\n\n[error_impacts.recall_failure]\nfamilies = { recall = -0.25 }\nlo_mastery_delta = -0.05\nlocal_severity_gain = 0.8\n\n[error_impacts.scaffold_failure]\nfamilies = { recall = -0.35 }\nlo_mastery_delta = -0.05\nlocal_severity_gain = 1.5\n\n[error_impacts.arithmetic_slip]\nfamilies = { numeric = -0.05 }\nlo_mastery_delta = 0.0\nlocal_severity_gain = 0.35\n\n# Cross-LO propagation gates per error type (spec §\"Error-type gate\").\n[cross_lo_propagation.default]\nmax_depth = 3\nhop_decay = 0.5\ntotal_propagated_weight_cap = 0.7\n\n[cross_lo_propagation.error_gates.recall_failure]\nmean_factor = 0.0 # forgetting a definition is not evidence prereqs are weak\nvariance_factor = 0.25\nscope = \"all\"\n\n[cross_lo_propagation.error_gates.scaffold_failure]\nmean_factor = 0.0\nvariance_factor = 0.35\nscope = \"all\"\n\n[cross_lo_propagation.error_gates.arithmetic_slip]\nmean_factor = 0.0\nvariance_factor = 0.10\nscope = \"all\"\n\n[recall_coverage.severity_examples.first_dont_know]\nattempt_type = \"dont_know\"\nhints_used = 0\ncorrectness = 0.0\nexpected_correctness = 0.65\neffective_coverage = 0.85\nexpected_error_type = \"recall_failure\"\nexpected_severity_band = [0.70, 0.82]\n\n[recall_coverage.severity_examples.second_same_item_dont_know]\nattempt_type = \"dont_know\"\nhints_used = 0\ncorrectness = 0.0\nexpected_correctness = 0.65\neffective_coverage = 0.85\nrecent_same_item_failures = 1\nexpected_error_type = \"recall_failure\"\nexpected_severity_band = [0.95, 1.00]\n\n[recall_coverage.severity_examples.second_same_facet_dont_know]\nattempt_type = \"dont_know\"\nhints_used = 0\ncorrectness = 0.0\nexpected_correctness = 0.65\neffective_coverage = 0.85\nrecent_same_facet_failures = 1\nexpected_error_type = \"recall_failure\"\nexpected_severity_band = [0.80, 1.00]\n\n[recall_coverage.severity_examples.hinted_dont_know]\nattempt_type = \"dont_know\"\nhints_used = 2\ncorrectness = 0.0\nexpected_correctness = 0.65\neffective_coverage = 0.80\nexpected_error_type = \"scaffold_failure\"\nexpected_severity_band = [0.85, 0.95]\n\n[recall_coverage.severity_examples.arithmetic_slip]\nattempt_type = \"independent_attempt\"\ncorrectness = 0.75\nexpected_correctness = 0.70\neffective_coverage = 0.85\ntarget_error_type = \"arithmetic_slip\"\nexpected_error_type = \"arithmetic_slip\"\nexpected_severity_band = [0.25, 0.35]\n\n[recall_coverage.severity_examples.ambiguous_item]\nattempt_type = \"independent_attempt\"\ncorrectness = 0.0\nexpected_correctness = 0.70\neffective_coverage = 0.85\nbad_item_suspicion = 0.70\nexpected_error_type = \"recall_failure\"\nexpected_severity_band = [0.45, 0.75]\n"}}}} |