{"components":{"schemas":{"AccumulativeAnalysis":{"description":"Accumulative analysis output: conditional conclusions showing how the\nverdict changes under different distinction conditions.","properties":{"conditional_conclusions":{"items":{"$ref":"#/components/schemas/ConditionalConclusionOutput"},"type":"array"}},"required":["conditional_conclusions"],"type":"object"},"ActorInput":{"properties":{"base_reliability":{"format":"double","type":["number","null"]},"competence":{"additionalProperties":{"format":"double","type":"number"},"description":"Per-predicate competence scores (0–1). Optional.\nEffective reliability = disposition × competence(predicate) × conflict_penalties.","propertyNames":{"type":"string"},"type":["object","null"]},"default_competence":{"description":"Fallback competence when no predicate-specific score exists. Defaults to 1.0.","format":"double","type":["number","null"]},"id":{"type":"string"},"name":{"type":"string"},"source_type":{"description":"Must match a SourceType variant name (case-insensitive).","type":"string"}},"required":["id","name","source_type"],"type":"object"},"ArgumentationSummary":{"properties":{"accepted_claims":{"description":"Claims that survive all challenges (internal IDs, kept for backwards compat).","items":{"type":"string"},"type":"array"},"alternative_interpretations":{"description":"Alternative coherent interpretations of the evidence (internal IDs, kept for backwards compat).","items":{"items":{"type":"string"},"type":"array"},"type":"array"},"causal_chains":{"items":{"$ref":"#/components/schemas/CausalChainSummary"},"type":"array"},"dispute_level":{"description":"How contested the narrative is (0 = consensus, higher = more disputed)","format":"double","type":"number"},"interpretations":{"description":"Rich interpretation trees: one per preferred extension, with full claim\ncontext, attack/support edges, and credibility opinions.","items":{"$ref":"#/components/schemas/InterpretationTree"},"type":"array"},"is_exact":{"description":"True if all interpretations were computed exhaustively.\nFalse if the analysis was too large and used an approximation.","type":"boolean"}},"required":["accepted_claims","alternative_interpretations","dispute_level","causal_chains","is_exact","interpretations"],"type":"object"},"AttackEdge":{"properties":{"attacker_claim_id":{"type":"string"},"description":{"type":"string"},"target_claim_id":{"type":"string"}},"required":["attacker_claim_id","target_claim_id","description"],"type":"object"},"CausalChainSummary":{"properties":{"argument_ids":{"items":{"type":"string"},"type":"array"}},"required":["argument_ids"],"type":"object"},"ClaimAnalysisSummary":{"properties":{"actor_id":{"type":"string"},"assertion_time":{"description":"When this claim was asserted (RFC 3339), if known.","type":["string","null"]},"below_credibility_floor":{"description":"True if the actor's reliability fell below the credibility floor.\nThe claim is visible but its evidence counts are zeroed.\n\nRef: Hansson et al. (2001), \"Credibility Limited Revision\"","type":"boolean"},"claim_id":{"type":"string"},"corroboration_count":{"description":"Number of valid corroboration events for this claim.","minimum":0,"type":"integer"},"decay_origin":{"description":"The time from which decay was computed (RFC 3339). Equals assertion_time\nif no corroboration; equals the most recent effective corroboration time\notherwise.","type":["string","null"]},"effective_half_life_days":{"description":"The effective half-life in days used for this specific claim's decay,\nafter applying claim-type and source-authority multipliers.","format":"double","type":"number"},"epistemic_status":{"description":"Epistemic lifecycle status: \"conjecture\", \"hypothesis\", \"theory\", \"law\",\n\"superseded\", \"retracted\".","type":"string"},"expected_probability":{"format":"double","type":"number"},"freshness_score":{"description":"Composite freshness score (0.0-1.0). Combines temporal decay (70%),\ncorroboration recency (20%), and epistemic status factor (10%).","format":"double","type":"number"},"last_corroborated":{"description":"Most recent corroboration time (RFC 3339), if any.","type":["string","null"]},"neutral_count":{"format":"int64","type":"integer"},"opposition":{"format":"double","type":"number"},"predicate":{"type":"string"},"refuting_count":{"format":"int64","type":"integer"},"suggested_epistemic_status":{"description":"System-suggested epistemic status based on evidence accumulation.\nOnly present when it differs from the current epistemic_status.","type":["string","null"]},"support":{"format":"double","type":"number"},"supporting_count":{"format":"int64","type":"integer"},"temporal_decay_factor":{"description":"Temporal decay multiplier applied to this claim's evidence weight.\n1.0 = recent claim (full weight); 0.5 = one half-life old.\nComputed using: `base_half_life × claim_type_mult × source_authority_mult`.","format":"double","type":"number"},"truth_status":{"description":"\"True\", \"False\", \"Both\" (contradicted), or \"Neither\" (no information)","type":"string"},"uncertainty":{"format":"double","type":"number"},"value":{"type":"string"}},"required":["claim_id","predicate","value","actor_id","truth_status","expected_probability","support","opposition","uncertainty","supporting_count","refuting_count","neutral_count","temporal_decay_factor","effective_half_life_days","epistemic_status","freshness_score"],"type":"object"},"ClaimInput":{"properties":{"actor_id":{"type":"string"},"assertion_time":{"description":"ISO 8601 / RFC 3339 timestamp (e.g. \"2024-01-15T09:30:00Z\").","type":["string","null"]},"claim_type":{"description":"\"Factual\", \"Predictive\", \"Evaluative\", \"Causal\", or \"Procedural\".\nDefaults to \"Factual\" if absent. Predictive/Evaluative/Causal claims\ncarry inherently more uncertainty.","type":["string","null"]},"content":{"type":"string"},"corroboration_events":{"description":"Corroboration events: independent confirmations of this claim at later times.\nEach resets the temporal decay clock (fully for independent sources, partially\nfor dependent sources controlled by `dependent_refresh_factor`).","items":{"$ref":"#/components/schemas/CorroborationEventInput"},"type":"array"},"decay_half_life_days":{"description":"Per-claim half-life override in days.  When set, bypasses the computed\n`base_half_life × claim_type_multiplier × source_authority_multiplier`.","format":"double","type":["number","null"]},"epistemic_status":{"description":"Epistemic lifecycle status. One of: \"conjecture\", \"hypothesis\" (default),\n\"theory\", \"law\", \"superseded\", \"retracted\". Affects temporal decay rate.","type":["string","null"]},"event_end_time":{"description":"ISO 8601 end of the event window; absent means open.","type":["string","null"]},"event_start_time":{"description":"ISO 8601 start of the event window; absent means open.","type":["string","null"]},"id":{"type":"string"},"predicate":{"type":"string"},"relationships":{"description":"Explicit relationships to other claims (by claim ID).\nEach entry is an object: `{\"type\": \"complements\"|\"refines\"|\"qualifies\"|\n\"supersedes\"|\"challenges_methodology\", \"target_claim_id\": \"...\"}`.","items":{"$ref":"#/components/schemas/ClaimRelationshipInput"},"type":["array","null"]},"scope":{"description":"Scope qualifier — disambiguates claims on the same predicate that\nmeasure different things.  Examples: \"global\", \"US\", \"nominal\",\n\"risk-adjusted\", \"top-quartile\".  Claims with different scopes on the\nsame predicate are not treated as contradictions.","type":["string","null"]},"subject_id":{"description":"Set for regular claims; empty / absent for meta-claims.","type":["string","null"]},"supersedes_claim_id":{"description":"ID of the claim this one supersedes. The superseded claim's epistemic status\nis automatically set to \"superseded\" and its effective half-life drops to 25%.","type":["string","null"]},"target_claim_id":{"description":"Set for meta-claims; empty / absent for regular claims.","type":["string","null"]},"valence":{"description":"\"Supports\", \"Refutes\", or \"Neutral\". Defaults to \"Neutral\" if absent.","type":["string","null"]},"value":{"type":"string"}},"required":["id","actor_id","predicate","value","content"],"type":"object"},"ClaimRelationshipInput":{"properties":{"relationship_type":{"description":"One of: \"complements\", \"refines\", \"qualifies\", \"supersedes\",\n\"challenges_methodology\".","type":"string"},"target_claim_id":{"description":"The ID of the related claim.","type":"string"}},"required":["relationship_type","target_claim_id"],"type":"object"},"ConditionalConclusionOutput":{"description":"A single conditional conclusion from a distinction.","properties":{"condition":{"type":"string"},"distinction_id":{"type":"string"},"expected_probability":{"format":"double","type":"number"},"favored_claim_id":{"type":"string"},"opinion":{"$ref":"#/components/schemas/OpinionSummary"}},"required":["distinction_id","condition","favored_claim_id","expected_probability","opinion"],"type":"object"},"CorroboratedClaim":{"properties":{"claim_id":{"type":"string"},"corroboration_count":{"minimum":0,"type":"integer"},"freshness_score":{"format":"double","type":"number"},"last_corroborated":{"type":"string"}},"required":["claim_id","corroboration_count","last_corroborated","freshness_score"],"type":"object"},"CorroborationEventInput":{"properties":{"actor_id":{"description":"ID of the actor who corroborated. Must differ from the claim's actor_id.","type":"string"},"description":{"description":"Description of the corroborating evidence.","type":"string"},"time":{"description":"When the corroboration occurred (ISO 8601 / RFC 3339).","type":"string"}},"required":["time","actor_id"],"type":"object"},"CreateSessionRequest":{"properties":{"name":{"description":"Required session name: non-empty, max 2000 chars.","type":"string"},"payload":{"oneOf":[{"type":"null"},{"$ref":"#/components/schemas/InvestigationInput","description":"Initial investigation payload. Defaults to an empty investigation."}]},"session_id":{"description":"Unicode session ID. Auto-generated if omitted.","type":["string","null"]}},"required":["name"],"type":"object"},"CreateSessionResponse":{"properties":{"session_id":{"type":"string"}},"required":["session_id"],"type":"object"},"DistinctionInput":{"description":"A distinction between two conflicting arguments.","properties":{"argument_a":{"description":"First argument (claim ID, user-supplied).","type":"string"},"argument_b":{"description":"Second argument (claim ID, user-supplied).","type":"string"},"condition_a":{"description":"Condition under which argument_a applies.","type":"string"},"condition_b":{"description":"Condition under which argument_b applies.","type":"string"},"description":{"type":["string","null"]},"feature":{"description":"The feature that differentiates the cases (e.g. \"scope\", \"timeframe\").","type":"string"},"id":{"type":"string"}},"required":["id","argument_a","argument_b","feature","condition_a","condition_b"],"type":"object"},"ErrorResponse":{"description":"Error response returned when a request fails.","properties":{"error":{"type":"string"}},"required":["error"],"type":"object"},"EvidenceGap":{"description":"A single evidence gap: a subject-predicate pair where additional data would\nmost reduce uncertainty or resolve contestation.","properties":{"discriminating_claims":{"description":"Claims that appear in some but not all preferred extensions — the locus\nof narrative disagreement.  Evidence targeting these claims would best\ndiscriminate between competing interpretations.\n\nRef: Good (1985) \"Weight of Evidence\"; Schum (1994) \"Evidential Foundations\"","items":{"type":"string"},"type":"array"},"expected_probability":{"description":"Current expected probability.","format":"double","type":"number"},"is_contested":{"description":"Whether this predicate is contested (multiple conflicting interpretations).","type":"boolean"},"potential_shift":{"description":"Estimated probability shift if one strong confirming evidence were added.\nComputed by simulating +1 evidence count and re-fusing.","format":"double","type":"number"},"predicate":{"type":"string"},"subject_id":{"type":"string"},"suggestion":{"description":"Human-readable suggestion for what evidence would be most valuable.","type":"string"},"uncertainty":{"description":"Current uncertainty level (0 = certain, 1 = no evidence).","format":"double","type":"number"}},"required":["subject_id","predicate","uncertainty","expected_probability","potential_shift","is_contested","suggestion"],"type":"object"},"EvidenceInput":{"properties":{"claim_id":{"type":"string"},"content":{"type":"string"},"id":{"type":"string"},"valence":{"description":"\"Supports\", \"Refutes\", or \"Neutral\" (case-insensitive).","type":"string"},"weight":{"format":"double","type":["number","null"]}},"required":["id","claim_id","content","valence"],"type":"object"},"GetDocsInput":{"description":"Input shape for `get_docs`.  Lives here rather than in `mcp.rs` so the\ntool's schema and dispatch dispatch sit next to the registry entry that\ndescribes it.","properties":{"tool":{"description":"Name of a specific tool to fetch detailed documentation for\n(e.g. `submit_investigation`, `create_investigation_session`).\nOmit to list every tool with its one-line summary.","type":["string","null"]}},"type":"object"},"InferenceInput":{"description":"An inference argument: a derived conclusion from premise claims via a\ntyped inference rule.","properties":{"description":{"type":["string","null"]},"id":{"type":"string"},"predicate":{"description":"The predicate this inference applies to.","type":"string"},"premise_claim_ids":{"description":"Premise claim IDs (user-supplied, resolved to internal IDs).","items":{"type":"string"},"type":"array"},"rule_param":{"description":"Rule-specific parameter: ordering (a_fortiori), shared_feature\n(analogy), exemplar (generalization), description (default),\nname (custom).","type":["string","null"]},"rule_param2":{"description":"Secondary parameter for custom rules (description).","type":["string","null"]},"rule_type":{"description":"One of: \"a_fortiori\", \"analogy\", \"generalization\",\n\"expert_testimony\", \"default\", \"temporal_precedence\", \"custom\".","type":"string"},"subject_id":{"description":"The subject this inference applies to.","type":"string"}},"required":["id","subject_id","predicate","premise_claim_ids","rule_type"],"type":"object"},"InterpretationClaim":{"properties":{"actor_id":{"description":"Which actor made this claim.","type":"string"},"actor_name":{"description":"The actor's name.","type":"string"},"belief":{"description":"Credibility opinion for this claim.","format":"double","type":"number"},"claim_id":{"description":"The user-supplied claim ID (not internal).","type":"string"},"content":{"description":"The claim content/description.","type":"string"},"disbelief":{"format":"double","type":"number"},"expected_probability":{"format":"double","type":"number"},"predicate":{"description":"What they claimed (predicate = value).","type":"string"},"truth_status":{"description":"Belnap status.","type":"string"},"uncertainty":{"format":"double","type":"number"},"value":{"type":"string"}},"required":["claim_id","actor_id","actor_name","predicate","value","content","belief","disbelief","uncertainty","expected_probability","truth_status"],"type":"object"},"InterpretationResponse":{"properties":{"interpretation":{"type":["string","null"]},"interpretation_updated_at":{"type":["string","null"]},"session_id":{"type":"string"}},"required":["session_id"],"type":"object"},"InterpretationTree":{"description":"A coherent interpretation of the evidence — one preferred extension rendered\nwith full claim context, edge info, and credibility opinions.","properties":{"accepted_claims":{"description":"The claims accepted in this interpretation, with full context.","items":{"$ref":"#/components/schemas/InterpretationClaim"},"type":"array"},"attacks":{"description":"Attack edges within this interpretation context.","items":{"$ref":"#/components/schemas/AttackEdge"},"type":"array"},"coherence_score":{"description":"Narrative coherence score (0.0-1.0): how well this interpretation\nhangs together as a story.  Combines evidential coverage (25%),\ninternal support density (25%), and mean credibility (50%).\n\nRef: Thagard (2000) \"Coherence in Thought and Action\" (ECHO);\n     Bex (2011) \"Arguments, Stories and Criminal Evidence\"","format":"double","type":"number"},"label":{"description":"Human-readable label: \"Interpretation 1\", \"Interpretation 2\", etc.","type":"string"},"supports":{"description":"Support edges within this interpretation context.","items":{"$ref":"#/components/schemas/SupportEdge"},"type":"array"}},"required":["label","coherence_score","accepted_claims","attacks","supports"],"type":"object"},"InvestigationInput":{"properties":{"actors":{"items":{"$ref":"#/components/schemas/ActorInput"},"type":"array"},"claims":{"items":{"$ref":"#/components/schemas/ClaimInput"},"type":"array"},"decay_half_life_days":{"description":"Explicit temporal half-life in days, overriding the domain default.\nA claim this many days old has half its original evidence weight.","format":"double","type":["number","null"]},"dependent_refresh_factor":{"description":"Factor (0.0-1.0) controlling how much dependent-source corroboration\nrefreshes the temporal decay clock. 0.0 = no refresh, 0.5 = halfway\nrefresh (default), 1.0 = full refresh (same as independent).","format":"double","type":["number","null"]},"distinctions":{"description":"Distinctions between conflicting arguments.  When registered, the\nattack between the pair is suppressed and both survive under their\nrespective conditions.  Their presence is the sole trigger for\naccumulative analysis — no separate flag is required.","items":{"$ref":"#/components/schemas/DistinctionInput"},"type":"array"},"domain":{"description":"Knowledge domain that sets the default temporal half-life for claims.\nOne of: \"Finance\" (180d), \"News\" (90d), \"Technology\" (365d),\n\"Geopolitics\" (2yr), \"Medicine\" (10yr), \"Science\" (25yr),\n\"Legal\" (20yr), \"General\" (180d). Case-insensitive. Defaults to \"General\".","type":["string","null"]},"evidence":{"items":{"$ref":"#/components/schemas/EvidenceInput"},"type":["array","null"]},"inferences":{"description":"Inference arguments: derived conclusions from premise claims via\ntyped inference rules.  Optional; when absent, the investigation\nproceeds with flat (premise-only) argumentation as before.","items":{"$ref":"#/components/schemas/InferenceInput"},"type":"array"},"research_question":{"type":"string"},"subjects":{"items":{"$ref":"#/components/schemas/SubjectInput"},"type":"array"},"summary_mode":{"description":"When true, returns a compact output: top findings, top contested claims,\ntop evidence gaps, and a one-paragraph synthesis.  The full output is\nomitted.  Designed for LLM consumers with limited context windows.","type":"boolean"}},"required":["research_question","actors","subjects","claims"],"type":"object"},"InvestigationResult":{"properties":{"accumulative_analysis":{"oneOf":[{"type":"null"},{"$ref":"#/components/schemas/AccumulativeAnalysis","description":"Accumulative analysis: conditional conclusions per distinction.\nPresent whenever the input contains at least one distinction and the\nengine produced any conditional conclusions.  Omitted in `summary_mode`\n(a soft warning is emitted instead so callers know to drop summary_mode\nto retrieve them)."}]},"claim_analyses":{"items":{"$ref":"#/components/schemas/ClaimAnalysisSummary"},"type":"array"},"conflict_analysis":{"description":"Argumentation analysis for every (subject, predicate) pair.","items":{"$ref":"#/components/schemas/SubjectArgumentation"},"type":"array"},"decay_half_life_days":{"description":"The temporal half-life in days used for this investigation.","format":"double","type":"number"},"ranked_claims":{"description":"Claims ranked by net evidence strength (belief − disbelief), descending.","items":{"$ref":"#/components/schemas/RankedClaim"},"type":"array"},"research_question":{"type":"string"},"sensitivity_analysis":{"$ref":"#/components/schemas/SensitivityAnalysis","description":"Sensitivity analysis: which evidence gaps would most shift conclusions.\nEnables abductive reasoning — \"what should I look for next?\""},"subject_results":{"items":{"$ref":"#/components/schemas/SubjectResult"},"type":"array"},"temporal_analysis":{"oneOf":[{"type":"null"},{"$ref":"#/components/schemas/TemporalAnalysis","description":"Temporal analysis: freshness report, supersession chains, and\ncorroboration summary. Present when any claim uses temporal features\n(corroboration, epistemic status, or supersession)."}]},"warnings":{"description":"Soft warnings about potentially inconsistent inputs (e.g. a Troll with\n0.95 reliability).  Empty when all inputs look reasonable.","items":{"type":"string"},"type":"array"}},"required":["research_question","decay_half_life_days","subject_results","conflict_analysis","claim_analyses","ranked_claims","sensitivity_analysis"],"type":"object"},"JudgeOverride":{"additionalProperties":false,"description":"One-shot overrides applied to a session's investigation payload before\njudging.  Overrides do **not** persist back to the stored session — they\nonly affect the current run.\n\nToday, `summary_mode` is the sole runtime mode flag the engine accepts\n(see `InvestigationInput::summary_mode` in `investigation_runner`).\nAccumulative analysis (the \"distinctions\" mode referenced in #823) is\nautomatic whenever the payload contains distinctions; there is no\nseparate flag to toggle it.  The struct is shaped so additional\noverride fields can be added later without breaking the wire format.","properties":{"summary_mode":{"description":"Override the session's `summary_mode` for this run only.  When `true`,\nthe engine returns the compact output (top findings, top contested\nclaims, top evidence gaps) and omits `accumulative_analysis`.","type":["boolean","null"]}},"type":"object"},"JudgeResponse":{"properties":{"result":{"$ref":"#/components/schemas/InvestigationResult"},"session_id":{"type":"string"}},"required":["session_id","result"],"type":"object"},"JudgementMeta":{"description":"List-view metadata for a single judgement run. Omits large fields\n(input_snapshot, result) so list responses stay compact.","properties":{"duration_ms":{"format":"int32","type":["integer","null"]},"id":{"type":"string"},"judged_at":{"format":"date-time","type":"string"},"session_id":{"type":"string"}},"required":["id","session_id","judged_at"],"type":"object"},"JudgementRecord":{"description":"Full judgement record including the input snapshot and engine result.","properties":{"duration_ms":{"format":"int32","type":["integer","null"]},"id":{"type":"string"},"input_snapshot":{},"judged_at":{"format":"date-time","type":"string"},"result":{},"session_id":{"type":"string"}},"required":["id","session_id","judged_at","input_snapshot","result"],"type":"object"},"McpActorRefInput":{"description":"Reference to one actor within a session (get / delete).","properties":{"actor_id":{"description":"The actor's id.","type":"string"},"session_id":{"description":"The session that owns the actor.","type":"string"}},"required":["session_id","actor_id"],"type":"object"},"McpActorUpsertInput":{"description":"Upsert payload for an actor (add / replace).","properties":{"actor":{"$ref":"#/components/schemas/ActorInput","description":"The full actor object (its `id` is the upsert/replace key)."},"session_id":{"description":"The session to write into.","type":"string"}},"required":["session_id","actor"],"type":"object"},"McpClaimRefInput":{"description":"Reference to one claim within a session (get / delete).","properties":{"claim_id":{"description":"The claim's id.","type":"string"},"session_id":{"description":"The session that owns the claim.","type":"string"}},"required":["session_id","claim_id"],"type":"object"},"McpClaimUpsertInput":{"description":"Upsert payload for a claim (add / replace).","properties":{"claim":{"$ref":"#/components/schemas/ClaimInput","description":"The full claim object (its `id` is the upsert/replace key)."},"session_id":{"description":"The session to write into.","type":"string"}},"required":["session_id","claim"],"type":"object"},"McpCreateSessionInput":{"description":"Input shape for the `create_investigation_session` MCP tool.  Mirrors\n[`CreateSessionRequest`] but `name` is optional (defaults to \"Untitled\"\nwhen called via MCP for ergonomic LLM use).","properties":{"name":{"description":"Session name (non-empty, max 2000 chars). Defaults to \"Untitled\".","type":["string","null"]},"payload":{"oneOf":[{"type":"null"},{"$ref":"#/components/schemas/InvestigationInput","description":"Initial investigation payload (same schema as `submit_investigation`).\nOmit to start with an empty session.  When the payload contains\ndistinctions, judging automatically produces conditional conclusions —\nthere is no separate flag."}]},"session_id":{"description":"Custom Unicode session ID. Auto-generated if omitted.","type":["string","null"]}},"type":"object"},"McpDistinctionRefInput":{"description":"Reference to one distinction within a session (get / delete).","properties":{"distinction_id":{"description":"The distinction's id.","type":"string"},"session_id":{"description":"The session that owns the distinction.","type":"string"}},"required":["session_id","distinction_id"],"type":"object"},"McpDistinctionUpsertInput":{"description":"Upsert payload for a distinction (add / replace).","properties":{"distinction":{"$ref":"#/components/schemas/DistinctionInput","description":"The full distinction object (its `id` is the upsert/replace key)."},"session_id":{"description":"The session to write into.","type":"string"}},"required":["session_id","distinction"],"type":"object"},"McpEvidenceRefInput":{"description":"Reference to one evidence item within a session (get / delete).","properties":{"evidence_id":{"description":"The evidence item's id.","type":"string"},"session_id":{"description":"The session that owns the evidence item.","type":"string"}},"required":["session_id","evidence_id"],"type":"object"},"McpEvidenceUpsertInput":{"description":"Upsert payload for an evidence item (add / replace).","properties":{"evidence":{"$ref":"#/components/schemas/EvidenceInput","description":"The full evidence object (its `id` is the upsert/replace key)."},"session_id":{"description":"The session to write into.","type":"string"}},"required":["session_id","evidence"],"type":"object"},"McpGetShareInput":{"description":"Input shape for `get_investigation_session_share` — looks up the share\nrecord for a session owned by the caller.","properties":{"session_id":{"description":"The session whose share to inspect.","type":"string"}},"required":["session_id"],"type":"object"},"McpInferenceRefInput":{"description":"Reference to one inference within a session (get / delete).","properties":{"inference_id":{"description":"The inference's id.","type":"string"},"session_id":{"description":"The session that owns the inference.","type":"string"}},"required":["session_id","inference_id"],"type":"object"},"McpInferenceUpsertInput":{"description":"Upsert payload for an inference (add / replace).","properties":{"inference":{"$ref":"#/components/schemas/InferenceInput","description":"The full inference object (its `id` is the upsert/replace key)."},"session_id":{"description":"The session to write into.","type":"string"}},"required":["session_id","inference"],"type":"object"},"McpJudgeSessionInput":{"description":"Input shape for the `judge_investigation_session` MCP tool.  Pairs the\npath-param `session_id` with the same one-shot overrides accepted by\nREST `POST /api/v1/sessions/{id}/judge`.  `summary_mode` is the only\noverride the engine currently honours; see [`JudgeOverride`].","properties":{"session_id":{"description":"The session to judge.","type":"string"},"summary_mode":{"description":"One-shot override of the session's `summary_mode` for this run only.\n`true` → compact output, `accumulative_analysis` omitted.\n`false` → full output.  Omit to use the stored payload value.","type":["boolean","null"]}},"required":["session_id"],"type":"object"},"McpJudgementIdInput":{"description":"Input shape for MCP tools that target a specific judgement.","properties":{"judgement_id":{"description":"The judgement UUID to retrieve.","type":"string"},"session_id":{"description":"The session that owns the judgement.","type":"string"}},"required":["session_id","judgement_id"],"type":"object"},"McpLatestJudgementInput":{"description":"Input shape for the `get_latest_session_judgement` MCP tool.","properties":{"session_id":{"description":"The session to fetch the latest judgement for.","type":"string"}},"required":["session_id"],"type":"object"},"McpListJudgementsInput":{"description":"Input shape for the `list_session_judgements` MCP tool.","properties":{"session_id":{"description":"The session whose judgements to list.","type":"string"}},"required":["session_id"],"type":"object"},"McpListSessionsInput":{"description":"Input shape for `list_investigation_sessions` — accepts optional filters\nand pagination parameters. All fields are optional; omitting them returns\nthe full list ordered by `updated_at DESC` (same as the legacy behaviour).","properties":{"has_result":{"description":"When `true`, return only sessions that have been judged at least once.\nWhen `false`, return only sessions that have never been judged.\nOmit to return all sessions regardless of judge status.","type":["boolean","null"]},"limit":{"description":"Maximum number of sessions to return (1–200, default 50).","format":"int64","type":["integer","null"]},"name_filter":{"description":"Case-insensitive substring filter on session name.","type":["string","null"]},"offset":{"description":"Pagination offset (default 0).","format":"int64","type":["integer","null"]},"sort":{"description":"Sort key. One of `updated_at` (default, descending), `created_at`\n(descending), or `name` (ascending).","type":["string","null"]},"updated_after":{"description":"ISO 8601 timestamp: only return sessions last updated after this time.","type":["string","null"]},"updated_before":{"description":"ISO 8601 timestamp: only return sessions last updated before this time.","type":["string","null"]}},"type":"object"},"McpListSharesInput":{"description":"Input shape for `list_investigation_session_shares` — takes no args.","type":"object"},"McpSessionIdInput":{"description":"Input shape for `get_investigation_session` / `delete_investigation_session`\nMCP tools — both take only a `session_id`.","properties":{"session_id":{"description":"The session to retrieve / delete.","type":"string"}},"required":["session_id"],"type":"object"},"McpSetInterpretationInput":{"description":"Input shape for the `set_session_interpretation` MCP tool.","properties":{"interpretation":{"description":"Analyst commentary text. Pass `null` to clear. Session must have been judged first.","type":["string","null"]},"session_id":{"description":"The session to update.","type":"string"}},"required":["session_id"],"type":"object"},"McpShareSessionInput":{"description":"Input shape for the `share_investigation_session` MCP tool.  Combines\nthe REST path-param `session_id` with the body of [`SetShareRequest`].","properties":{"preferred_pane":{"description":"The default pane viewers land on. All panes remain visible — this is\njust the initial tab. Allowed values: \"overview\", \"timeline\", \"mesh\",\n\"distinctions\", \"audit\".","type":"string"},"public":{"description":"Whether the share should be visible to anyone with the link.","type":"boolean"},"session_id":{"description":"The session to share.","type":"string"},"slug":{"description":"Human-readable display name for the URL (e.g. 'q3-tesla-analysis').\nLowercased and sanitized server-side; non-alphanumerics become\nhyphens; max 64 chars.","type":"string"}},"required":["session_id","public","slug","preferred_pane"],"type":"object"},"McpSubjectRefInput":{"description":"Reference to one subject within a session (get / delete).","properties":{"session_id":{"description":"The session that owns the subject.","type":"string"},"subject_id":{"description":"The subject's id.","type":"string"}},"required":["session_id","subject_id"],"type":"object"},"McpSubjectUpsertInput":{"description":"Upsert payload for a subject (add / replace).","properties":{"session_id":{"description":"The session to write into.","type":"string"},"subject":{"$ref":"#/components/schemas/SubjectInput","description":"The full subject object (its `id` is the upsert/replace key)."}},"required":["session_id","subject"],"type":"object"},"McpUpdateSessionInput":{"allOf":[{"description":"Partial update to a session's investigation payload.","properties":{"actors":{"items":{"$ref":"#/components/schemas/ActorInput"},"type":["array","null"]},"claims":{"items":{"$ref":"#/components/schemas/ClaimInput"},"type":["array","null"]},"decay_half_life_days":{"format":"double","type":["number","null"]},"dependent_refresh_factor":{"format":"double","type":["number","null"]},"distinctions":{"items":{"$ref":"#/components/schemas/DistinctionInput"},"type":["array","null"]},"domain":{"type":["string","null"]},"evidence":{"items":{"$ref":"#/components/schemas/EvidenceInput"},"type":["array","null"]},"inferences":{"items":{"$ref":"#/components/schemas/InferenceInput"},"type":["array","null"]},"remove_actor_ids":{"description":"Actor IDs to remove (applied after merging).","items":{"type":"string"},"type":["array","null"]},"remove_claim_ids":{"description":"Claim IDs to remove.","items":{"type":"string"},"type":["array","null"]},"remove_distinction_ids":{"description":"Distinction IDs to remove.","items":{"type":"string"},"type":["array","null"]},"remove_evidence_ids":{"description":"Evidence IDs to remove.","items":{"type":"string"},"type":["array","null"]},"remove_inference_ids":{"description":"Inference IDs to remove.","items":{"type":"string"},"type":["array","null"]},"remove_subject_ids":{"description":"Subject IDs to remove.","items":{"type":"string"},"type":["array","null"]},"research_question":{"type":["string","null"]},"subjects":{"items":{"$ref":"#/components/schemas/SubjectInput"},"type":["array","null"]},"summary_mode":{"type":["boolean","null"]}},"type":"object"},{"properties":{"name":{"description":"Rename the session.","type":["string","null"]},"session_id":{"description":"The session to update.","type":"string"}},"required":["session_id"],"type":"object"}],"description":"Input shape for the `update_investigation_session` MCP tool.  Same\nmerge semantics as REST `PATCH /api/v1/sessions/{id}`, plus the path\nparameter `session_id` as a flattened field."},"OpinionSummary":{"properties":{"base_rate":{"format":"double","type":"number"},"opposition":{"format":"double","type":"number"},"support":{"format":"double","type":"number"},"uncertainty":{"format":"double","type":"number"}},"required":["support","opposition","uncertainty","base_rate"],"type":"object"},"RankedClaim":{"description":"A claim ranked by net evidence strength.","properties":{"actor_id":{"type":"string"},"belief":{"format":"double","type":"number"},"category":{"description":"\"strong\", \"moderate\", \"contested\", \"weak\", or \"refuted\"","type":"string"},"claim_id":{"type":"string"},"disbelief":{"format":"double","type":"number"},"expected_probability":{"format":"double","type":"number"},"predicate":{"type":"string"},"rank":{"minimum":0,"type":"integer"},"uncertainty":{"format":"double","type":"number"},"value":{"type":"string"}},"required":["rank","claim_id","actor_id","predicate","value","category","expected_probability","belief","disbelief","uncertainty"],"type":"object"},"SensitivityAnalysis":{"description":"Identifies the highest-value missing evidence — claims or subject-predicates\nwhere additional data would most shift the conclusions.  This is the\nabductive reasoning layer: \"what would best explain the remaining uncertainty?\"","properties":{"evidence_gaps":{"description":"Per-subject evidence gaps, ordered by potential impact (highest first).","items":{"$ref":"#/components/schemas/EvidenceGap"},"type":"array"}},"required":["evidence_gaps"],"type":"object"},"SessionMeta":{"description":"List-view metadata for investigation sessions.  Exposed as the schema\n`SessionMeta` in the OpenAPI document via [`utoipa::ToSchema`]; the\n`list_sessions` handler returns `Vec<SessionMeta>` directly so the\ndocumented shape matches the wire bytes by construction.","properties":{"created_at":{"format":"date-time","type":"string"},"id":{"type":"string"},"judged_at":{"format":"date-time","type":"string"},"name":{"type":"string"},"updated_at":{"format":"date-time","type":"string"}},"required":["id","name","created_at","updated_at","judged_at"],"type":"object"},"SessionResponse":{"properties":{"created_at":{"type":"string"},"interpretation":{"description":"Free-text interpretation written by an LLM or user.","type":["string","null"]},"interpretation_updated_at":{"type":["string","null"]},"judged_at":{"type":["string","null"]},"last_result":{"oneOf":[{"type":"null"},{"$ref":"#/components/schemas/InvestigationResult"}]},"name":{"type":"string"},"payload":{"$ref":"#/components/schemas/InvestigationInput"},"session_id":{"type":"string"},"updated_at":{"type":"string"}},"required":["session_id","name","payload","created_at","updated_at"],"type":"object"},"SetInterpretationRequest":{"properties":{"interpretation":{"description":"Analyst commentary text. Pass `null` or omit to clear.","type":["string","null"]}},"type":"object"},"SetShareRequest":{"properties":{"preferred_pane":{"description":"Pane the public viewer opens to (\"overview\" | \"timeline\" | \"mesh\"\n| \"distinctions\" | \"audit\"). All panes remain visible — this just\nchooses the default tab.","type":"string"},"public":{"description":"Whether the session should be publicly accessible. Default false.","type":"boolean"},"slug":{"description":"Caller-supplied display name; sanitized server-side.","type":"string"}},"required":["public","slug","preferred_pane"],"type":"object"},"ShareListItemResponse":{"properties":{"is_public":{"type":"boolean"},"preferred_pane":{"type":"string"},"session_id":{"type":"string"},"session_name":{"type":"string"},"share_uuid":{"format":"uuid","type":"string"},"slug":{"type":"string"},"snapshot_taken_at":{"type":["string","null"]},"updated_at":{"type":"string"},"url":{"type":"string"}},"required":["session_id","session_name","share_uuid","slug","preferred_pane","is_public","url","updated_at"],"type":"object"},"ShareResponse":{"properties":{"is_public":{"type":"boolean"},"preferred_pane":{"type":"string"},"share_uuid":{"format":"uuid","type":"string"},"slug":{"type":"string"},"snapshot_taken_at":{"type":["string","null"]},"updated_at":{"type":"string"},"url":{"type":"string"},"url_path":{"type":"string"}},"required":["share_uuid","slug","preferred_pane","is_public","url_path","url","updated_at"],"type":"object"},"StaleClaim":{"properties":{"age_days":{"format":"double","type":"number"},"claim_id":{"type":"string"},"decay_factor":{"format":"double","type":"number"},"recommendation":{"type":"string"}},"required":["claim_id","age_days","decay_factor","recommendation"],"type":"object"},"SubjectArgumentation":{"allOf":[{"$ref":"#/components/schemas/ArgumentationSummary"},{"properties":{"predicate":{"type":"string"},"subject_id":{"type":"string"}},"required":["subject_id","predicate"],"type":"object"}],"description":"Argumentation results for a single (subject, predicate) pair."},"SubjectInput":{"properties":{"id":{"type":"string"},"name":{"type":"string"},"subject_type":{"type":"string"}},"required":["id","name","subject_type"],"type":"object"},"SubjectResult":{"properties":{"confidence":{"$ref":"#/components/schemas/OpinionSummary"},"expected_probability":{"format":"double","type":"number"},"predicate":{"type":"string"},"subject_id":{"type":"string"},"subject_name":{"type":"string"},"truth_status":{"description":"\"True\", \"False\", \"Both\" (contradicted), or \"Neither\" (no information)","type":"string"}},"required":["subject_id","subject_name","predicate","truth_status","confidence","expected_probability"],"type":"object"},"SupersessionChainSummary":{"properties":{"claim_ids":{"description":"Claim IDs ordered oldest → newest.","items":{"type":"string"},"type":"array"},"current_claim_id":{"description":"The most recent (current) claim in the chain.","type":"string"}},"required":["claim_ids","current_claim_id"],"type":"object"},"SupportEdge":{"properties":{"supported_claim_id":{"type":"string"},"supporter_claim_id":{"type":"string"}},"required":["supporter_claim_id","supported_claim_id"],"type":"object"},"TemporalAnalysis":{"description":"Aggregate temporal analysis for the entire investigation.","properties":{"overall_freshness":{"description":"Overall investigation freshness (0.0-1.0): average of all claim freshness scores.","format":"double","type":"number"},"recently_corroborated":{"description":"Claims with recent corroboration, sorted most recent first.","items":{"$ref":"#/components/schemas/CorroboratedClaim"},"type":"array"},"stale_claims":{"description":"Claims past their effective half-life (decay < 0.25), sorted most stale first.","items":{"$ref":"#/components/schemas/StaleClaim"},"type":"array"},"supersession_chains":{"description":"Chains of superseding claims (oldest → newest).","items":{"$ref":"#/components/schemas/SupersessionChainSummary"},"type":"array"}},"required":["stale_claims","recently_corroborated","supersession_chains","overall_freshness"],"type":"object"},"UpdateSessionPayload":{"description":"Partial update to a session's investigation payload.","properties":{"actors":{"items":{"$ref":"#/components/schemas/ActorInput"},"type":["array","null"]},"claims":{"items":{"$ref":"#/components/schemas/ClaimInput"},"type":["array","null"]},"decay_half_life_days":{"format":"double","type":["number","null"]},"dependent_refresh_factor":{"format":"double","type":["number","null"]},"distinctions":{"items":{"$ref":"#/components/schemas/DistinctionInput"},"type":["array","null"]},"domain":{"type":["string","null"]},"evidence":{"items":{"$ref":"#/components/schemas/EvidenceInput"},"type":["array","null"]},"inferences":{"items":{"$ref":"#/components/schemas/InferenceInput"},"type":["array","null"]},"remove_actor_ids":{"description":"Actor IDs to remove (applied after merging).","items":{"type":"string"},"type":["array","null"]},"remove_claim_ids":{"description":"Claim IDs to remove.","items":{"type":"string"},"type":["array","null"]},"remove_distinction_ids":{"description":"Distinction IDs to remove.","items":{"type":"string"},"type":["array","null"]},"remove_evidence_ids":{"description":"Evidence IDs to remove.","items":{"type":"string"},"type":["array","null"]},"remove_inference_ids":{"description":"Inference IDs to remove.","items":{"type":"string"},"type":["array","null"]},"remove_subject_ids":{"description":"Subject IDs to remove.","items":{"type":"string"},"type":["array","null"]},"research_question":{"type":["string","null"]},"subjects":{"items":{"$ref":"#/components/schemas/SubjectInput"},"type":["array","null"]},"summary_mode":{"type":["boolean","null"]}},"type":"object"},"UpdateSessionRequest":{"allOf":[{"description":"Partial update to a session's investigation payload.","properties":{"actors":{"items":{"$ref":"#/components/schemas/ActorInput"},"type":["array","null"]},"claims":{"items":{"$ref":"#/components/schemas/ClaimInput"},"type":["array","null"]},"decay_half_life_days":{"format":"double","type":["number","null"]},"dependent_refresh_factor":{"format":"double","type":["number","null"]},"distinctions":{"items":{"$ref":"#/components/schemas/DistinctionInput"},"type":["array","null"]},"domain":{"type":["string","null"]},"evidence":{"items":{"$ref":"#/components/schemas/EvidenceInput"},"type":["array","null"]},"inferences":{"items":{"$ref":"#/components/schemas/InferenceInput"},"type":["array","null"]},"remove_actor_ids":{"description":"Actor IDs to remove (applied after merging).","items":{"type":"string"},"type":["array","null"]},"remove_claim_ids":{"description":"Claim IDs to remove.","items":{"type":"string"},"type":["array","null"]},"remove_distinction_ids":{"description":"Distinction IDs to remove.","items":{"type":"string"},"type":["array","null"]},"remove_evidence_ids":{"description":"Evidence IDs to remove.","items":{"type":"string"},"type":["array","null"]},"remove_inference_ids":{"description":"Inference IDs to remove.","items":{"type":"string"},"type":["array","null"]},"remove_subject_ids":{"description":"Subject IDs to remove.","items":{"type":"string"},"type":["array","null"]},"research_question":{"type":["string","null"]},"subjects":{"items":{"$ref":"#/components/schemas/SubjectInput"},"type":["array","null"]},"summary_mode":{"type":["boolean","null"]}},"type":"object"},{"properties":{"name":{"type":["string","null"]}},"type":"object"}]},"UpdateSessionStatus":{"description":"Returned by `PATCH /api/v1/sessions/{id}` and the\n`update_investigation_session` MCP tool.  Mirrors the shape returned to\nREST clients today (`{ session_id, status }`) so the typed handler and\nthe prior `Json<serde_json::Value>` body are byte-identical on the wire.","properties":{"session_id":{"type":"string"},"status":{"type":"string"}},"required":["session_id","status"],"type":"object"}}},"info":{"description":"REST API for the Arbiter reasoning engine. Submit claims from multiple sources and get scored verdicts, ranked claims, conflict analysis with interpretation trees, temporal decay tracking, corroboration refresh, epistemic status lifecycle, and supersession chain analysis.\n\n**Session API**: persistent investigation sessions allow incremental investigation building — create a session, add actors/subjects/claims over time, and call judge to run the engine whenever ready. Sessions are stored server-side and can be re-analyzed repeatedly.\n\n**Share API**: session owners can publish read-only snapshots of judged sessions; viewers see a stable copy at `/share/{uuid}/{slug}` even if the owner later edits the session.","title":"Arbiter Investigation API","version":"0.1.0"},"openapi":"3.1.0","paths":{"/api/v1/investigations/analyze":{"post":{"description":"Submit a full investigation to the Arbiter reasoning engine. The engine analyzes claims from multiple sources to detect contradictions, assess confidence, evaluate timelines, and identify causal weaknesses.\n\nINPUT INSTRUCTIONS:\n1. Extract distinct entities (Subjects), sources (Actors), assertions (Claims), and supporting/refuting data (Evidence) from the material.\n2. RELIABILITY: Set base_reliability between 0.01 and 0.99. The engine clamps values outside this range. Values inconsistent with source_type will produce warnings. Guidelines: 0.8-0.95 for regulators/auditors (e.g. SEC filing > anonymous tweet), 0.5-0.8 for analysts/experts, 0.1-0.3 for anonymous/social media, 0.01-0.3 for trolls.\n3. COMPETENCE: When a source has uneven expertise across topics, set per-predicate competence scores (0-1). A financial analyst might score 0.9 on 'valuation' but 0.3 on 'regulatory-risk'. The engine multiplies reliability × competence to get effective credibility per topic.\n4. VALENCE: Every claim MUST have a valence. Use 'Supports' when the actor affirms the predicate, 'Refutes' when the actor denies it. Without valence, the engine cannot distinguish affirmation from denial.\n5. CLAIM TYPE: Set claim_type to 'Predictive' for forecasts/guidance, 'Evaluative' for opinions/ratings, 'Causal' for cause-effect assertions, 'Factual' for verifiable statements, 'Procedural' for process/methodology claims, 'Methodological' for claims about research methods or analytical approaches. Non-factual claims carry more inherent uncertainty.\n6. TEMPORAL: Always provide assertion_time (when the claim was made). Provide event_start_time and event_end_time when the claim refers to a specific time window. Precise timestamps enable the engine to detect contradictions across overlapping or sequential time periods. event_start_time MUST be before event_end_time. Older claims are automatically down-weighted (see HALF-LIFE FORMULA below).\n7. DEDUPLICATION: Do not submit the same claim twice from the same actor. Duplicates are automatically dropped to prevent evidence amplification.\n8. NUMERIC VALUES: For financial predicates (revenue, price, etc.), use consistent numeric formats with K/M/B/T suffixes. The engine recognizes that '99M' and '100M' are close and will NOT treat them as contradictions.\n9. SCOPE: Claims can have a `scope` field to disambiguate same-predicate claims measuring different things (e.g. 'global' vs 'US', 'nominal' vs 'risk-adjusted'). Claims with different scopes on the same predicate are NOT treated as contradictions.\n10. RELATIONSHIPS: Claims can declare explicit relationships to other claims via the `relationships` array. See RELATIONSHIP TYPES below for the per-type semantics.\n11. INFERENCES: Top-level `inferences[]` array — derived conclusions from premise claims, each with `id`, `subject_id`, `predicate`, `premise_claim_ids[]`, `rule_type`, optional `rule_param`. See INFERENCE RULES below for the rule_type enum.\n12. DISTINCTIONS: Top-level `distinctions[]` array — pairs of claims that disagree only because they apply under different conditions. Required fields: `id`, `argument_a`, `argument_b`, `feature`, `condition_a`, `condition_b` (`description` optional). When BOTH arguments target the SAME predicate, judging produces a `conditional_conclusion` in `accumulative_analysis`; cross-predicate distinctions are accepted but inert (no conditional fires).\n13. SUMMARY MODE: Set `summary_mode: true` for compact output: top findings, top contested claims, top evidence gaps, one-paragraph synthesis. Full claim_analyses, temporal_analysis, and accumulative_analysis are omitted.\n\nRELATIONSHIP TYPES (`claim.relationships[].relationship_type`):\n- 'complements' — both claims hold and reinforce each other on the same predicate; adds a SUPPORT edge in the argumentation framework.\n- 'refines' — the source claim narrows or sharpens the target's predicate; adds a SUPPORT edge and slightly downweights the target where they overlap.\n- 'qualifies' — the source claim attaches a condition to the target (e.g. 'this holds only in X'); adds a SUPPORT edge under that condition.\n- 'supersedes' — equivalent to setting `supersedes_claim_id` on the source; the target's epistemic_status becomes 'superseded'.\n- 'challenges_methodology' — recorded for audit but does NOT draw an attack edge in the conflict graph. Use a 'Refutes' valence claim if you want the engine to count the critique as opposition.\n\nINFERENCE RULES (`inferences[].rule_type`, lowercase):\n- 'a_fortiori' — 'if A holds, B holds even more strongly'; `rule_param` is the ordering hint.\n- 'analogy' — 'A is like B in feature F'; `rule_param` is the shared feature.\n- 'generalization' — 'this exemplar implies the general case'; `rule_param` names the exemplar.\n- 'expert_testimony' — 'an expert says so'; no `rule_param` needed.\n- 'default' — 'absent contradicting evidence, conclude X'; `rule_param` carries the description.\n- 'temporal_precedence' — 'X happened before Y, therefore X caused Y'.\n- 'custom' — user-named rule; `rule_param` is the name, `rule_param2` the description.\n\nHALF-LIFE FORMULA: effective_half_life_days = domain_half_life × claim_type_multiplier × source_authority_multiplier × epistemic_status_multiplier (multipliers apply unless `claim.decay_half_life_days` is set explicitly, which bypasses the formula). The `claim_analyses[].decay_origin` field names whichever multiplier dominated.\n  - Domain defaults: Finance 180d, News 90d, Technology 365d, Geopolitics 730d, Medicine 3650d (10y), Science 9125d (25y), Legal 7300d (20y), General 180d.\n  - Epistemic multipliers: conjecture 0.5×, hypothesis 1× (default), theory 2×, law 100× (effectively immortal), superseded 0.25×, retracted 0×.\n  - Example: domain=Finance + epistemic_status=theory ⇒ 180 × 2 = 360d effective half-life. domain=Medicine + theory ⇒ 3650 × 2 = 7300d. The response shows the result in `decay_half_life_days`; multipliers stack, so a number larger than the raw domain default is expected, not a bug.\n\nOUTPUT GUIDE — the response contains these key sections:\n- subject_results: Per-subject verdicts with support/opposition/uncertainty scores that sum to 1.0, expected_probability (posterior), and truth status (True/False/Both/Neither).\n- ranked_claims: All claims ranked by net evidence strength (belief − disbelief). Categories: 'strong' (high belief, very low disbelief), 'moderate' (good belief, low disbelief), 'contested' (significant evidence both ways), 'weak' (low evidence or high uncertainty), 'refuted' (low belief, low uncertainty).\n- conflict_analysis: For EVERY subject+predicate pair, a full argumentation analysis with interpretation trees. Each InterpretationTree is a coherent reading of the evidence showing which claims are accepted, who made them, their credibility scores, and the attack/support relationships between them. coherence_score (0.0-1.0) measures narrative coherence (evidential coverage + internal support density + mean credibility).\n- claim_analyses: Per-claim breakdown with belief/disbelief/uncertainty, temporal_decay_factor (1.0 = no decay, 0.5 = claim lost half its weight), epistemic_status, freshness_score (0-1 composite), suggested_epistemic_status (when the engine recommends a change), decay_origin (which multiplier dominated — 'domain', 'claim_type', 'source_authority', 'epistemic_status', 'override'), corroboration_count (how many independent confirmations fired), and last_corroborated (ISO 8601 of most recent confirmation). below_credibility_floor=true when the actor's effective reliability fell below the floor (the claim is visible but evidence counts are zeroed).\n- sensitivity_analysis: Per-subject evidence gaps ordered by potential impact. Each gap shows current uncertainty, expected_probability, potential_shift, is_contested, discriminating_claims (claims in some but not all interpretations — targeting these best resolves disagreement), and a human-readable suggestion. Use for abductive reasoning — 'what should I look for next?'.\n- temporal_analysis: When temporal features are used (corroboration, epistemic status, supersession), provides stale_claims, recently_corroborated, supersession_chains[] — each entry has `claim_ids[]` (chronological order, oldest first) and `current_claim_id` (the surviving terminal claim) — and overall_freshness (0-1 average).\n- accumulative_analysis: Populated when the payload includes distinctions whose argument pair shares a predicate. Contains conditional_conclusions[] — each names the predicate, the differentiating feature, and which condition each branch holds under. Cross-predicate distinctions or empty distinctions list ⇒ this section is omitted.\n- warnings: Input validation issues. See WARNING CATALOG below.\n\nWARNING CATALOG (non-fatal; the run still produces results):\n- 'claim X: decay_half_life_days=V is out of range (0, 365000]; using default' — per-claim half-life override rejected.\n- 'claim X: epistemic_status \"law\" is unusual for a predictive claim' — epistemic mismatch with claim_type.\n- 'claim X: N corroboration events exceeds limit of 100 — truncating' — corroboration list capped.\n- 'claim X: corroboration by same actor Y — self-corroboration is ignored' — same actor cannot corroborate themselves.\n- 'claim X: corroboration at T is before assertion at T0 — will be ignored' — corroboration must post-date the claim.\n- 'claim X: supersedes_claim_id Y not found in input claims' — supersession target missing.\n- 'claim X: N relationships exceeds limit; truncating' / 'relationship target Y not found' — relationships list capped or referent missing.\n- 'inference X: dropped (requires at least one premise)' / 'unknown premise claim_id(s)' / rule-specific error — inference rejected.\n- 'distinction X: argument_a and argument_b must differ — dropped' — distinction self-loops are rejected.\n- 'Claim X from actor Y: below credibility floor (V < 0.15). Evidence acknowledged but not counted in fusion.' — below CREDIBILITY FLOOR.\n- 'decay_half_life_days=V is not positive; using domain default' / 'dependent_refresh_factor=V outside [0,1]; clamping' — investigation-level scalars out of range.\nEach warning names the field and input value at fault; fix them to improve analysis quality.\n\nCORROBORATION: When a claim has been independently confirmed at a later date, add corroboration_events with the confirming actor's ID and the confirmation time. Independent corroboration (different citation chain) fully resets the temporal decay clock; dependent-source corroboration provides partial refresh controlled by dependent_refresh_factor (default 0.5). This is critical for long-running investigations where early claims may otherwise appear stale. The number of confirmations and the most recent timestamp surface as `claim_analyses[].corroboration_count` and `.last_corroborated` so you can see the mechanism firing.\n\nEPISTEMIC STATUS: Set epistemic_status to reflect the claim's lifecycle:\n- 'conjecture' — untested assertion, decays 2× faster\n- 'hypothesis' — consistent with data (default), standard decay\n- 'theory' — validated by evidence, decays 2× slower\n- 'law' — established across all known ramifications, near-zero decay\n- 'superseded' — replaced by newer claim, decays 4× faster\n- 'retracted' — explicitly withdrawn, zero weight\n\nSUPERSESSION: When a newer claim replaces an older one (e.g., revised earnings estimate), set supersedes_claim_id on the newer claim (or a `relationships` entry with type 'supersedes'). The older claim's epistemic status is automatically set to 'superseded'. Chains are reported in `temporal_analysis.supersession_chains[]`: `claim_ids[]` lists every link in chronological order; `current_claim_id` is the surviving terminal claim.\n\nCREDIBILITY FLOOR: When an actor's effective reliability (base_reliability × competence) drops below CREDIBILITY_FLOOR = 0.15, the claim is acknowledged in the output but its evidence counts are zeroed in fusion. A `below_credibility_floor: true` flag appears on the corresponding `claim_analyses[]` entry, and a warning is emitted.\n\nFOR ITERATIVE INVESTIGATIONS — when you expect to update claims, add corroboration, or iterate on a hypothesis over multiple turns — prefer the session API: `create_investigation_session` → `update_investigation_session` (add/replace by ID, or remove by `remove_*_ids`) → `judge_investigation_session` → `share_investigation_session` (to publish a snapshot). Sessions persist server-side; submit_investigation is for one-shot analyses only.","operationId":"submit_investigation","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/InvestigationInput"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/InvestigationResult"}}},"description":"Investigation completed successfully"},"422":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Invalid investigation input"},"500":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Internal engine error"},"504":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Investigation timed out"}},"security":[{"api_key":[]},{"bearer":[]}],"summary":"Submit an investigation for analysis.","tags":["investigations"]}},"/api/v1/sessions":{"get":{"description":"List all investigation sessions for the current user. Returns session IDs, names, last-updated times, and whether each session has been judged.","operationId":"list_investigation_sessions","parameters":[{"description":"Case-insensitive name substring filter","in":"query","name":"name","required":false,"schema":{"type":"string"}},{"description":"Filter by judged (true) or unjudged (false) status","in":"query","name":"has_result","required":false,"schema":{"type":"boolean"}},{"description":"ISO 8601 lower bound on updated_at","in":"query","name":"updated_after","required":false,"schema":{"type":"string"}},{"description":"ISO 8601 upper bound on updated_at","in":"query","name":"updated_before","required":false,"schema":{"type":"string"}},{"description":"Sort key: updated_at (default), created_at, or name","in":"query","name":"sort","required":false,"schema":{"type":"string"}},{"description":"Page size (1–200, default 50)","in":"query","name":"limit","required":false,"schema":{"format":"int64","type":"integer"}},{"description":"Pagination offset (default 0)","in":"query","name":"offset","required":false,"schema":{"format":"int64","type":"integer"}}],"responses":{"200":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/SessionMeta"},"type":"array"}}},"description":"Session metadata array"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"User-scoped credential required"},"500":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Internal store error"}},"security":[{"api_key":[]},{"bearer":[]}],"summary":"List all investigation sessions for the authenticated user.","tags":["sessions"]},"post":{"description":"Create a new persistent investigation session. Sessions let you build an investigation incrementally — add actors, subjects, and claims over time, then judge (analyze) whenever you're ready. Use update_investigation_session to modify actors, subjects, claims, domain, research_question, or any other field after creation. You can tweak and re-judge as many times as needed.\n\nSession IDs are Unicode strings — you can provide a meaningful name like 'tsla-q4-2025' or let the server auto-generate one.\n\nLimits: max 1024 sessions per user, max 10 MB payload, sessions expire after 365 days of inactivity. Names are required (non-empty, max 2000 chars).","operationId":"create_investigation_session","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateSessionRequest"}}},"required":true},"responses":{"201":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateSessionResponse"}}},"description":"Session created"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Invalid input (empty name, bad session_id, malformed payload)"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"User-scoped credential required"},"409":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Session ID already exists"},"413":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Payload exceeds size limit"},"429":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Per-user session limit reached"}},"security":[{"api_key":[]},{"bearer":[]}],"summary":"Create a new persistent investigation session.","tags":["sessions"]}},"/api/v1/sessions/{id}":{"delete":{"description":"Permanently delete an investigation session and its stored results.","operationId":"delete_investigation_session","parameters":[{"description":"Session ID","in":"path","name":"id","required":true,"schema":{"type":"string"}}],"responses":{"204":{"description":"Session deleted"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"User-scoped credential required"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Session not found"},"500":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Internal store error"}},"security":[{"api_key":[]},{"bearer":[]}],"summary":"Permanently delete a session and its stored results.","tags":["sessions"]},"get":{"description":"Retrieve a session's current state: the investigation payload (actors, subjects, claims, evidence) and the last judgment result (if any). Use this to review the session before making updates or to retrieve previously computed results.","operationId":"get_investigation_session","parameters":[{"description":"Session ID","in":"path","name":"id","required":true,"schema":{"type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SessionResponse"}}},"description":"Session state"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"User-scoped credential required"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Session not found"},"500":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Corrupt session data"}},"security":[{"api_key":[]},{"bearer":[]}],"summary":"Retrieve a session's current payload and last judgment result.","tags":["sessions"]},"patch":{"description":"Update a persistent investigation session — use this to change domain, research_question, add/replace actors/subjects/claims/evidence/inferences/distinctions, or rename the session. Merges changes into the existing payload:\n- Actors/subjects/claims/evidence/inferences/distinctions with matching IDs are replaced; new IDs are appended.\n- Use remove_*_ids to delete specific items.\n- Scalar fields (research_question, domain, etc.) are replaced if provided.\n- Adding distinctions automatically enables conditional conclusions on the next judge — no separate flag.\n\nChanges take effect on the next judge run.","operationId":"update_investigation_session","parameters":[{"description":"Session ID","in":"path","name":"id","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateSessionRequest"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateSessionStatus"}}},"description":"Session updated"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Invalid name"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"User-scoped credential required"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Session not found"},"413":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Payload exceeds size limit after merge"},"500":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Internal store / serialization error"}},"security":[{"api_key":[]},{"bearer":[]}],"summary":"Update a session's payload and/or name.","tags":["sessions"]}},"/api/v1/sessions/{id}/actors":{"get":{"description":"List every actor in a session's payload. Returns the full actor objects. To edit one actor without resending the whole payload, use add_session_actor / replace_session_actor / delete_session_actor; to bulk-edit many fields at once, use update_investigation_session.","operationId":"list_session_actors","parameters":[{"description":"Session ID","in":"path","name":"id","required":true,"schema":{"type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ActorInput"},"type":"array"}}},"description":"Actor list"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"User-scoped credential required"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Session not found"},"500":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Internal error"}},"security":[{"api_key":[]},{"bearer":[]}],"summary":"List all actors in a session's payload.","tags":["sessions"]},"post":{"description":"Add an actor to a session, or replace the existing actor with the same id (upsert). The actor's `id` field is the key. Use this to append a single actor; for editing many elements at once prefer update_investigation_session. Changes take effect on the next judge run.","operationId":"post_session_actor","parameters":[{"description":"Session ID","in":"path","name":"id","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ActorInput"}}},"required":true},"responses":{"201":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ActorInput"}}},"description":"Actor created or replaced"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"User-scoped credential required"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Session not found"},"413":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Payload too large after update"},"500":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Internal error"}},"security":[{"api_key":[]},{"bearer":[]}],"summary":"Add or replace an actor in a session's payload (upsert by id).","tags":["sessions"]}},"/api/v1/sessions/{id}/actors/{actor_id}":{"delete":{"description":"Remove one actor from a session by id. Returns 404 if the session or actor does not exist.","operationId":"delete_session_actor","parameters":[{"description":"Session ID","in":"path","name":"id","required":true,"schema":{"type":"string"}},{"description":"Actor ID","in":"path","name":"actor_id","required":true,"schema":{"type":"string"}}],"responses":{"204":{"description":"Actor deleted"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"User-scoped credential required"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Session or actor not found"},"500":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Internal error"}},"security":[{"api_key":[]},{"bearer":[]}],"summary":"Delete an actor from a session's payload.","tags":["sessions"]},"get":{"description":"Fetch one actor from a session by its id. Returns 404 if the session or actor does not exist. Use list_session_actors to discover actor ids.","operationId":"get_session_actor","parameters":[{"description":"Session ID","in":"path","name":"id","required":true,"schema":{"type":"string"}},{"description":"Actor ID","in":"path","name":"actor_id","required":true,"schema":{"type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ActorInput"}}},"description":"Actor"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"User-scoped credential required"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Session or actor not found"},"500":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Internal error"}},"security":[{"api_key":[]},{"bearer":[]}],"summary":"Retrieve a single actor by ID.","tags":["sessions"]},"put":{"description":"Replace an actor that already exists. The actor's `id` must match the target and the actor must already be present (returns 404 otherwise — use add_session_actor to create). Changes take effect on the next judge run.","operationId":"put_session_actor","parameters":[{"description":"Session ID","in":"path","name":"id","required":true,"schema":{"type":"string"}},{"description":"Actor ID","in":"path","name":"actor_id","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ActorInput"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ActorInput"}}},"description":"Actor replaced"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Actor id does not match path"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"User-scoped credential required"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Session or actor not found"},"413":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Payload too large after update"},"500":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Internal error"}},"security":[{"api_key":[]},{"bearer":[]}],"summary":"Replace an actor. The actor must already exist (PUT semantics).","tags":["sessions"]}},"/api/v1/sessions/{id}/claims":{"get":{"description":"List every claim in a session's payload. Returns the full claim objects. To edit one claim without resending the whole payload, use add_session_claim / replace_session_claim / delete_session_claim; to bulk-edit many fields at once, use update_investigation_session.","operationId":"list_session_claims","parameters":[{"description":"Session ID","in":"path","name":"id","required":true,"schema":{"type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ClaimInput"},"type":"array"}}},"description":"Claim list"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"User-scoped credential required"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Session not found"},"500":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Internal error"}},"security":[{"api_key":[]},{"bearer":[]}],"summary":"List all claims in a session's payload.","tags":["sessions"]},"post":{"description":"Add a claim to a session, or replace the existing claim with the same id (upsert). The claim's `id` field is the key. Use this to append a single claim; for editing many elements at once prefer update_investigation_session. Changes take effect on the next judge run.","operationId":"post_session_claim","parameters":[{"description":"Session ID","in":"path","name":"id","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ClaimInput"}}},"required":true},"responses":{"201":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ClaimInput"}}},"description":"Claim created or replaced"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"User-scoped credential required"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Session not found"},"413":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Payload too large"},"500":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Internal error"}},"security":[{"api_key":[]},{"bearer":[]}],"summary":"Add or replace a claim in a session's payload.","tags":["sessions"]}},"/api/v1/sessions/{id}/claims/{claim_id}":{"delete":{"description":"Remove one claim from a session by id. Returns 404 if the session or claim does not exist.","operationId":"delete_session_claim","parameters":[{"description":"Session ID","in":"path","name":"id","required":true,"schema":{"type":"string"}},{"description":"Claim ID","in":"path","name":"claim_id","required":true,"schema":{"type":"string"}}],"responses":{"204":{"description":"Claim deleted"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"User-scoped credential required"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Session or claim not found"},"500":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Internal error"}},"security":[{"api_key":[]},{"bearer":[]}],"summary":"Delete a claim from a session's payload.","tags":["sessions"]},"get":{"description":"Fetch one claim from a session by its id. Returns 404 if the session or claim does not exist. Use list_session_claims to discover claim ids.","operationId":"get_session_claim","parameters":[{"description":"Session ID","in":"path","name":"id","required":true,"schema":{"type":"string"}},{"description":"Claim ID","in":"path","name":"claim_id","required":true,"schema":{"type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ClaimInput"}}},"description":"Claim"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"User-scoped credential required"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Session or claim not found"},"500":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Internal error"}},"security":[{"api_key":[]},{"bearer":[]}],"summary":"Retrieve a single claim by ID.","tags":["sessions"]},"put":{"description":"Replace a claim that already exists. The claim's `id` must match the target and the claim must already be present (returns 404 otherwise — use add_session_claim to create). Changes take effect on the next judge run.","operationId":"put_session_claim","parameters":[{"description":"Session ID","in":"path","name":"id","required":true,"schema":{"type":"string"}},{"description":"Claim ID","in":"path","name":"claim_id","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ClaimInput"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ClaimInput"}}},"description":"Claim replaced"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"ID mismatch"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"User-scoped credential required"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Session or claim not found"},"413":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Payload too large"},"500":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Internal error"}},"security":[{"api_key":[]},{"bearer":[]}],"summary":"Replace a claim. The claim must already exist.","tags":["sessions"]}},"/api/v1/sessions/{id}/distinctions":{"get":{"description":"List every distinction in a session's payload. Distinctions enable conditional/accumulative analysis on the next judge run. Returns the full distinction objects. To edit one distinction without resending the whole payload, use add_session_distinction / replace_session_distinction / delete_session_distinction.","operationId":"list_session_distinctions","parameters":[{"description":"Session ID","in":"path","name":"id","required":true,"schema":{"type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/DistinctionInput"},"type":"array"}}},"description":"Distinction list"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"User-scoped credential required"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Session not found"},"500":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Internal error"}},"security":[{"api_key":[]},{"bearer":[]}],"summary":"List all distinctions in a session's payload.","tags":["sessions"]},"post":{"description":"Add a distinction to a session, or replace the existing distinction with the same id (upsert). Adding distinctions automatically enables accumulative analysis on the next judge run — no separate flag required. Changes take effect on the next judge run.","operationId":"post_session_distinction","parameters":[{"description":"Session ID","in":"path","name":"id","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/DistinctionInput"}}},"required":true},"responses":{"201":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/DistinctionInput"}}},"description":"Distinction created or replaced"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"User-scoped credential required"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Session not found"},"413":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Payload too large"},"500":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Internal error"}},"security":[{"api_key":[]},{"bearer":[]}],"summary":"Add or replace a distinction in a session's payload.","tags":["sessions"]}},"/api/v1/sessions/{id}/distinctions/{distinction_id}":{"delete":{"description":"Remove one distinction from a session by id. Returns 404 if the session or distinction does not exist. Removing all distinctions disables accumulative analysis on the next judge run.","operationId":"delete_session_distinction","parameters":[{"description":"Session ID","in":"path","name":"id","required":true,"schema":{"type":"string"}},{"description":"Distinction ID","in":"path","name":"distinction_id","required":true,"schema":{"type":"string"}}],"responses":{"204":{"description":"Distinction deleted"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"User-scoped credential required"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Session or distinction not found"},"500":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Internal error"}},"security":[{"api_key":[]},{"bearer":[]}],"summary":"Delete a distinction from a session's payload.","tags":["sessions"]},"get":{"description":"Fetch one distinction from a session by its id. Returns 404 if the session or distinction does not exist. Use list_session_distinctions to discover distinction ids.","operationId":"get_session_distinction","parameters":[{"description":"Session ID","in":"path","name":"id","required":true,"schema":{"type":"string"}},{"description":"Distinction ID","in":"path","name":"distinction_id","required":true,"schema":{"type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/DistinctionInput"}}},"description":"Distinction"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"User-scoped credential required"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Session or distinction not found"},"500":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Internal error"}},"security":[{"api_key":[]},{"bearer":[]}],"summary":"Retrieve a single distinction by ID.","tags":["sessions"]},"put":{"description":"Replace a distinction that already exists. The distinction's `id` must match the target and must already be present (returns 404 otherwise — use add_session_distinction to create). Changes take effect on the next judge run.","operationId":"put_session_distinction","parameters":[{"description":"Session ID","in":"path","name":"id","required":true,"schema":{"type":"string"}},{"description":"Distinction ID","in":"path","name":"distinction_id","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/DistinctionInput"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/DistinctionInput"}}},"description":"Distinction replaced"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"ID mismatch"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"User-scoped credential required"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Session or distinction not found"},"413":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Payload too large"},"500":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Internal error"}},"security":[{"api_key":[]},{"bearer":[]}],"summary":"Replace a distinction. The distinction must already exist.","tags":["sessions"]}},"/api/v1/sessions/{id}/evidence":{"get":{"description":"List every evidence item in a session's payload. Returns the full evidence objects. To edit one item without resending the whole payload, use add_session_evidence / replace_session_evidence / delete_session_evidence; to bulk-edit many fields at once, use update_investigation_session.","operationId":"list_session_evidence","parameters":[{"description":"Session ID","in":"path","name":"id","required":true,"schema":{"type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/EvidenceInput"},"type":"array"}}},"description":"Evidence list"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"User-scoped credential required"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Session not found"},"500":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Internal error"}},"security":[{"api_key":[]},{"bearer":[]}],"summary":"List all evidence items in a session's payload.","tags":["sessions"]},"post":{"description":"Add an evidence item to a session, or replace the existing item with the same id (upsert). The evidence's `id` field is the key. Works even when the session has no evidence yet (None → first insert). Changes take effect on the next judge run.","operationId":"post_session_evidence","parameters":[{"description":"Session ID","in":"path","name":"id","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/EvidenceInput"}}},"required":true},"responses":{"201":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/EvidenceInput"}}},"description":"Evidence created or replaced"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"User-scoped credential required"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Session not found"},"413":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Payload too large"},"500":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Internal error"}},"security":[{"api_key":[]},{"bearer":[]}],"summary":"Add or replace an evidence item in a session's payload.","tags":["sessions"]}},"/api/v1/sessions/{id}/evidence/{evidence_id}":{"delete":{"description":"Remove one evidence item from a session by id. Returns 404 if the session or evidence item does not exist.","operationId":"delete_session_evidence","parameters":[{"description":"Session ID","in":"path","name":"id","required":true,"schema":{"type":"string"}},{"description":"Evidence ID","in":"path","name":"evidence_id","required":true,"schema":{"type":"string"}}],"responses":{"204":{"description":"Evidence deleted"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"User-scoped credential required"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Session or evidence not found"},"500":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Internal error"}},"security":[{"api_key":[]},{"bearer":[]}],"summary":"Delete an evidence item from a session's payload.","tags":["sessions"]},"get":{"description":"Fetch one evidence item from a session by its id. Returns 404 if the session or evidence item does not exist. Use list_session_evidence to discover evidence ids.","operationId":"get_session_evidence","parameters":[{"description":"Session ID","in":"path","name":"id","required":true,"schema":{"type":"string"}},{"description":"Evidence ID","in":"path","name":"evidence_id","required":true,"schema":{"type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/EvidenceInput"}}},"description":"Evidence item"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"User-scoped credential required"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Session or evidence not found"},"500":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Internal error"}},"security":[{"api_key":[]},{"bearer":[]}],"summary":"Retrieve a single evidence item by ID.","tags":["sessions"]},"put":{"description":"Replace an evidence item that already exists. The evidence's `id` must match the target and the item must already be present (returns 404 otherwise — use add_session_evidence to create). Changes take effect on the next judge run.","operationId":"put_session_evidence","parameters":[{"description":"Session ID","in":"path","name":"id","required":true,"schema":{"type":"string"}},{"description":"Evidence ID","in":"path","name":"evidence_id","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/EvidenceInput"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/EvidenceInput"}}},"description":"Evidence item replaced"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"ID mismatch"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"User-scoped credential required"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Session or evidence not found"},"413":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Payload too large"},"500":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Internal error"}},"security":[{"api_key":[]},{"bearer":[]}],"summary":"Replace an evidence item. The item must already exist.","tags":["sessions"]}},"/api/v1/sessions/{id}/inferences":{"get":{"description":"List every inference in a session's payload. Returns the full inference objects. To edit one inference without resending the whole payload, use add_session_inference / replace_session_inference / delete_session_inference; to bulk-edit many fields at once, use update_investigation_session.","operationId":"list_session_inferences","parameters":[{"description":"Session ID","in":"path","name":"id","required":true,"schema":{"type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/InferenceInput"},"type":"array"}}},"description":"Inference list"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"User-scoped credential required"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Session not found"},"500":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Internal error"}},"security":[{"api_key":[]},{"bearer":[]}],"summary":"List all inferences in a session's payload.","tags":["sessions"]},"post":{"description":"Add an inference to a session, or replace the existing inference with the same id (upsert). The inference's `id` field is the key. Changes take effect on the next judge run.","operationId":"post_session_inference","parameters":[{"description":"Session ID","in":"path","name":"id","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/InferenceInput"}}},"required":true},"responses":{"201":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/InferenceInput"}}},"description":"Inference created or replaced"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"User-scoped credential required"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Session not found"},"413":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Payload too large"},"500":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Internal error"}},"security":[{"api_key":[]},{"bearer":[]}],"summary":"Add or replace an inference in a session's payload.","tags":["sessions"]}},"/api/v1/sessions/{id}/inferences/{inference_id}":{"delete":{"description":"Remove one inference from a session by id. Returns 404 if the session or inference does not exist.","operationId":"delete_session_inference","parameters":[{"description":"Session ID","in":"path","name":"id","required":true,"schema":{"type":"string"}},{"description":"Inference ID","in":"path","name":"inference_id","required":true,"schema":{"type":"string"}}],"responses":{"204":{"description":"Inference deleted"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"User-scoped credential required"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Session or inference not found"},"500":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Internal error"}},"security":[{"api_key":[]},{"bearer":[]}],"summary":"Delete an inference from a session's payload.","tags":["sessions"]},"get":{"description":"Fetch one inference from a session by its id. Returns 404 if the session or inference does not exist. Use list_session_inferences to discover inference ids.","operationId":"get_session_inference","parameters":[{"description":"Session ID","in":"path","name":"id","required":true,"schema":{"type":"string"}},{"description":"Inference ID","in":"path","name":"inference_id","required":true,"schema":{"type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/InferenceInput"}}},"description":"Inference"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"User-scoped credential required"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Session or inference not found"},"500":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Internal error"}},"security":[{"api_key":[]},{"bearer":[]}],"summary":"Retrieve a single inference by ID.","tags":["sessions"]},"put":{"description":"Replace an inference that already exists. The inference's `id` must match the target and must already be present (returns 404 otherwise — use add_session_inference to create). Changes take effect on the next judge run.","operationId":"put_session_inference","parameters":[{"description":"Session ID","in":"path","name":"id","required":true,"schema":{"type":"string"}},{"description":"Inference ID","in":"path","name":"inference_id","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/InferenceInput"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/InferenceInput"}}},"description":"Inference replaced"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"ID mismatch"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"User-scoped credential required"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Session or inference not found"},"413":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Payload too large"},"500":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Internal error"}},"security":[{"api_key":[]},{"bearer":[]}],"summary":"Replace an inference. The inference must already exist.","tags":["sessions"]}},"/api/v1/sessions/{id}/judge":{"post":{"description":"Run the Arbiter reasoning engine on the current session payload and persist the results. Returns the full investigation analysis (same output as submit_investigation). The result is also stored on the session for later retrieval via get_investigation_session.\n\n**Modes:**\n- *Default (full)*: full claim_analyses, temporal_analysis, and — when the payload has distinctions — accumulative_analysis with conditional conclusions.\n- *summary_mode=true*: compact output (top findings, top contested claims, top evidence gaps); accumulative_analysis is omitted.\n- *Accumulative analysis*: produced automatically whenever the payload contains distinctions. There is no separate flag — add distinctions via update_investigation_session and re-judge.\n\nMode overrides set here are one-shot — they do not persist back to the stored session.\n\nCan be called repeatedly after updates; each run overwrites the previous result.","operationId":"judge_investigation_session","parameters":[{"description":"Session ID","in":"path","name":"id","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/JudgeOverride"}}},"description":"Optional one-shot overrides; omit body entirely to use stored payload defaults","required":true},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/JudgeResponse"}}},"description":"Analysis complete"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"User-scoped credential required"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Session not found"},"422":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Invalid investigation payload"},"500":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Internal engine / store error"},"504":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Investigation timed out"}},"security":[{"api_key":[]},{"bearer":[]}],"summary":"Run the reasoning engine on the session's stored payload.","tags":["sessions"]}},"/api/v1/sessions/{id}/judgements":{"get":{"description":"List the audit trail of every judge run for a session, ordered newest-first. Returns compact metadata (id, judged_at, duration_ms) without the bulky input_snapshot or result payload — use get_session_judgement or get_latest_session_judgement to fetch the full record.","operationId":"list_session_judgements","parameters":[{"description":"Session ID","in":"path","name":"id","required":true,"schema":{"type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/JudgementMeta"},"type":"array"}}},"description":"Judgement metadata list"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"User-scoped credential required"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Session not found"},"500":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Internal store error"}},"security":[{"api_key":[]},{"bearer":[]}],"summary":"List all judgement records for a session (metadata only, newest first).","tags":["sessions"]}},"/api/v1/sessions/{id}/judgements/latest":{"get":{"description":"Convenience shortcut for the newest judgement in a session's audit trail. Returns the same full JudgementRecord as get_session_judgement but resolves the latest-by-time automatically. Returns 404 when the session has never been judged.","operationId":"get_latest_session_judgement","parameters":[{"description":"Session ID","in":"path","name":"id","required":true,"schema":{"type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/JudgementRecord"}}},"description":"Latest judgement record"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"User-scoped credential required"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Session not found or no judgements yet"},"500":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Internal store error"}},"security":[{"api_key":[]},{"bearer":[]}],"summary":"Retrieve the most recent judgement for a session (full record).","tags":["sessions"]}},"/api/v1/sessions/{id}/judgements/{judgement_id}":{"get":{"description":"Retrieve a specific judgement by its UUID. Returns the full record: id, session_id, judged_at, duration_ms, input_snapshot (the payload as it was at judge time, after any one-shot overrides), and result (the complete InvestigationResult). Use list_session_judgements to discover available judgement IDs.","operationId":"get_session_judgement","parameters":[{"description":"Session ID","in":"path","name":"id","required":true,"schema":{"type":"string"}},{"description":"Judgement UUID","in":"path","name":"judgement_id","required":true,"schema":{"type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/JudgementRecord"}}},"description":"Judgement record"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Invalid judgement_id UUID"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"User-scoped credential required"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Session or judgement not found"},"500":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Internal store error"}},"security":[{"api_key":[]},{"bearer":[]}],"summary":"Retrieve a specific judgement by its UUID (full record with input snapshot).","tags":["sessions"]}},"/api/v1/sessions/{id}/share":{"get":{"description":"Return the current share state for an owned session: share_uuid, slug, preferred_pane, is_public, public URL, and snapshot timestamp. Returns an error if the session has never been shared.","operationId":"get_investigation_session_share","parameters":[{"description":"Session ID","in":"path","name":"id","required":true,"schema":{"type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ShareResponse"}}},"description":"Share state"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"User-scoped credential required"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"No share record for this session"},"500":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Internal store error"}},"security":[{"api_key":[]},{"bearer":[]}],"summary":"Return the current share state for an owned session.","tags":["shares"]},"put":{"description":"Toggle public sharing on an investigation session. When `public: true` the server takes a fresh, datetime-stamped snapshot of the session payload and last judgement; viewers see exactly that snapshot via a URL of the form `https://arbiter.housecarl.cloud/share/<uuid>/<slug>`. Sharing again with `public: false` hides the page and clears the snapshot — but the share_uuid is preserved, so calling with `public: true` later restores the same URL. Use this when the user asks you to publish an analysis, post results, generate a sharable link, or take it back down. Returns the public URL and the share metadata.\n\nWhen public, all claims, evidence, actor identities, and audit data are world-readable.","operationId":"share_investigation_session","parameters":[{"description":"Session ID","in":"path","name":"id","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SetShareRequest"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ShareResponse"}}},"description":"Share state updated"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Invalid slug or preferred_pane"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"User-scoped credential required"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Session not found"},"500":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Internal store error"}},"security":[{"api_key":[]},{"bearer":[]}],"summary":"Toggle the public-share flag and snapshot the current session state.","tags":["shares"]}},"/api/v1/sessions/{id}/subjects":{"get":{"description":"List every subject in a session's payload. Returns the full subject objects. To edit one subject without resending the whole payload, use add_session_subject / replace_session_subject / delete_session_subject; to bulk-edit many fields at once, use update_investigation_session.","operationId":"list_session_subjects","parameters":[{"description":"Session ID","in":"path","name":"id","required":true,"schema":{"type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/SubjectInput"},"type":"array"}}},"description":"Subject list"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"User-scoped credential required"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Session not found"},"500":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Internal error"}},"security":[{"api_key":[]},{"bearer":[]}],"summary":"List all subjects in a session's payload.","tags":["sessions"]},"post":{"description":"Add a subject to a session, or replace the existing subject with the same id (upsert). The subject's `id` field is the key. Use this to append a single subject; for editing many elements at once prefer update_investigation_session. Changes take effect on the next judge run.","operationId":"post_session_subject","parameters":[{"description":"Session ID","in":"path","name":"id","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SubjectInput"}}},"required":true},"responses":{"201":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SubjectInput"}}},"description":"Subject created or replaced"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"User-scoped credential required"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Session not found"},"413":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Payload too large"},"500":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Internal error"}},"security":[{"api_key":[]},{"bearer":[]}],"summary":"Add or replace a subject in a session's payload.","tags":["sessions"]}},"/api/v1/sessions/{id}/subjects/{subject_id}":{"delete":{"description":"Remove one subject from a session by id. Returns 404 if the session or subject does not exist.","operationId":"delete_session_subject","parameters":[{"description":"Session ID","in":"path","name":"id","required":true,"schema":{"type":"string"}},{"description":"Subject ID","in":"path","name":"subject_id","required":true,"schema":{"type":"string"}}],"responses":{"204":{"description":"Subject deleted"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"User-scoped credential required"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Session or subject not found"},"500":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Internal error"}},"security":[{"api_key":[]},{"bearer":[]}],"summary":"Delete a subject from a session's payload.","tags":["sessions"]},"get":{"description":"Fetch one subject from a session by its id. Returns 404 if the session or subject does not exist. Use list_session_subjects to discover subject ids.","operationId":"get_session_subject","parameters":[{"description":"Session ID","in":"path","name":"id","required":true,"schema":{"type":"string"}},{"description":"Subject ID","in":"path","name":"subject_id","required":true,"schema":{"type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SubjectInput"}}},"description":"Subject"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"User-scoped credential required"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Session or subject not found"},"500":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Internal error"}},"security":[{"api_key":[]},{"bearer":[]}],"summary":"Retrieve a single subject by ID.","tags":["sessions"]},"put":{"description":"Replace a subject that already exists. The subject's `id` must match the target and the subject must already be present (returns 404 otherwise — use add_session_subject to create). Changes take effect on the next judge run.","operationId":"put_session_subject","parameters":[{"description":"Session ID","in":"path","name":"id","required":true,"schema":{"type":"string"}},{"description":"Subject ID","in":"path","name":"subject_id","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SubjectInput"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SubjectInput"}}},"description":"Subject replaced"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"ID mismatch"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"User-scoped credential required"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Session or subject not found"},"413":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Payload too large"},"500":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Internal error"}},"security":[{"api_key":[]},{"bearer":[]}],"summary":"Replace a subject. The subject must already exist.","tags":["sessions"]}},"/api/v1/shares":{"get":{"description":"List every share record owned by the calling user. Returns session_id, session name, share_uuid, slug, public URL, is_public, preferred_pane, and timestamps for each. Useful for auditing what's currently public, finding old links, or batch-toggling visibility.","operationId":"list_investigation_session_shares","responses":{"200":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ShareListItemResponse"},"type":"array"}}},"description":"Array of share records"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"User-scoped credential required"},"500":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Internal store error"}},"security":[{"api_key":[]},{"bearer":[]}],"summary":"List every share record owned by the calling user.","tags":["shares"]}}},"security":[{"api_key":[]},{"bearer":[]}]}