{
  "manifest_version": "0.1",
  "work_slug": "bodo-endosymbiont-metabolic-complementarity",
  "concept_ark_suffix": "dp-bodo-endosymbiont",
  "protocol": "protocol:secondary-analysis 0.1",
  "module": "agent/tools.py",
  "analysis_unit": "analysis.py",
  "published_results": "results.json",
  "source_dataset_doi": "10.6084/m9.figshare.31362613",
  "environment": {
    "language": "python",
    "tested_version": "3.13",
    "requirements": "requirements-reproduction.txt",
    "network": "deny-except-pinned-inputs"
  },
  "execution": {
    "boundary": "docs/72-reproduction-contract.md",
    "live_invocation": "not connected; the sandboxed runner gates execution over MCP"
  },
  "tools": [
    {
      "name": "shared_modules",
      "summary": "Size and identity of the KEGG module set both genomes share.",
      "unit": "analysis.main: merge of Supplementary Files 12 and 13 on module_accession",
      "parameters": [],
      "returns": "n_shared_modules, the host and symbiont completeness columns, and the seven single-cell pair ids",
      "supports_claims": [1, 2, 3],
      "deterministic": true
    },
    {
      "name": "classify_modules",
      "summary": "Classify every shared module by which genome clears a completeness threshold.",
      "unit": "analysis.classify",
      "parameters": [
        {
          "name": "threshold",
          "type": "number",
          "default": 67,
          "range": "[0, 100] completeness percent",
          "published_values": [50, 67, 80],
          "notes": "The classification is threshold-generic; the published run reports three values."
        }
      ],
      "returns": "the echoed threshold and counts of both, host_only, symbiont_only, neither",
      "supports_claims": [2],
      "deterministic": true
    },
    {
      "name": "paired_completeness_test",
      "summary": "Wilcoxon signed-rank test of host versus endosymbiont module completeness (T1).",
      "unit": "analysis.main: scipy.stats.wilcoxon over the paired completeness vectors",
      "parameters": [
        {
          "name": "alternative",
          "type": "string",
          "default": "two-sided",
          "range": "two-sided | greater | less",
          "published_values": ["two-sided"],
          "notes": "The pre-registered test is two-sided; the one-sided forms are exposed for sensitivity checks."
        }
      ],
      "returns": "statistic, p_value, median_host_minus_symbiont, and the win/tie counts",
      "supports_claims": [1],
      "deterministic": true
    },
    {
      "name": "equivalence_test",
      "summary": "Two one-sided t-tests bounding the paired completeness gap (T1 equivalence).",
      "unit": "analysis.main: TOST block over host minus symbiont",
      "parameters": [
        {
          "name": "margin_pp",
          "type": "number",
          "default": 10.0,
          "range": "> 0 percentage points",
          "published_values": [10.0],
          "notes": "The equivalence margin is the scientifically interesting knob and is the reason this tool is parameterised."
        }
      ],
      "returns": "margin_pp, mean_diff_pp, diff_ci95_pp, p_tost, equivalent_within_margin",
      "supports_claims": [1, 4],
      "deterministic": true
    },
    {
      "name": "mcnemar_asymmetry",
      "summary": "Exact McNemar test on discordant module categories at a threshold (T2).",
      "unit": "analysis.main: binomtest over the discordant pair counts from analysis.classify",
      "parameters": [
        {
          "name": "threshold",
          "type": "number",
          "default": 67,
          "range": "[0, 100] completeness percent",
          "published_values": [67],
          "notes": "The published run reports the test only at the primary threshold."
        }
      ],
      "returns": "host_only, symbiont_only, their ratio, and the exact two-sided p_value",
      "supports_claims": [2],
      "deterministic": true
    },
    {
      "name": "per_cell_consistency",
      "summary": "Host-only versus symbiont-only module fractions in each single-cell pair (T3).",
      "unit": "analysis.main: per-cell loop over analysis.classify",
      "parameters": [
        {
          "name": "threshold",
          "type": "number",
          "default": 67,
          "range": "[0, 100] completeness percent",
          "published_values": [67]
        },
        {
          "name": "cells",
          "type": "array of string | null",
          "default": null,
          "range": "any non-empty subset of F10, B7, A8, A10, B2, G10, H10",
          "published_values": [null],
          "notes": "Subsetting supports the leave-one-out checks the published run does not report but the data support."
        }
      ],
      "returns": "per_cell fractions and counts, plus the mean and (for more than one cell) the sd of each fraction",
      "supports_claims": [3],
      "deterministic": true
    }
  ]
}
