{
  "manifest_version": "0.1",
  "work_slug": "icme-radial-field-scaling",
  "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.6356420.v24",
  "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"
  },
  "surface_note": "analysis.py is partly decomposed: loglog_ols, bootstrap_slope_ci and bh_correct are named functions and the tools call them; the row filter, T1, T3 and all three confound guards live only in main(), so tools.py re-implements them line for line and the eight published-pointer calls prove the re-implementation reproduces results.json. The pinned file is fetched through scripts/fetch_pinned.py with analysis.py's own URL and md5. The one parameter family every tool shares is the sample -- a heliocentric-distance window and a set of excluded spacecraft -- because the narrative's usage notes send readers to refit on a subset, and that refit is where the single global exponent stops describing the subsets: OLS gives 1.595 inside 1.1 AU and 1.262 beyond, with non-overlapping bootstrap CIs.",
  "tools": [
    {
      "name": "dataset_summary",
      "summary": "Pinned catalogue identity, the row filter's counts, and the distance span.",
      "unit": "analysis.DATA_URL and analysis.DATA_MD5 (fetched via scripts/fetch_pinned.py), then main()'s row filter: mo_bmean > 0, mo_sc_heliodistance > 0, complete cases",
      "parameters": [],
      "returns": "source_doi, source_file, source_md5, n_total_rows, n_analysis_rows, n_dropped, heliodistance_min_AU, heliodistance_max_AU, n_spacecraft",
      "supports_claims": [1, 2],
      "deterministic": true
    },
    {
      "name": "radial_correlation",
      "summary": "Two-sided Spearman rank correlation of magnetic-obstacle field strength against heliocentric distance (T1).",
      "unit": "main() T1 block (scipy.stats.spearmanr on the filtered rows), re-implemented",
      "parameters": [
        {
          "name": "exclude_spacecraft",
          "type": "array of string | null",
          "default": null,
          "range": "any of BepiColombo, Juno, MAVEN, MESSENGER, PSP, STEREO-A, STEREO-B, SolarOrbiter, ULYSSES, VEX, Wind; at least 3 events and 2 distinct distances must remain",
          "published_values": [null]
        },
        {
          "name": "r_min_au",
          "type": "number | null",
          "default": null,
          "range": "inclusive lower bound on mo_sc_heliodistance in AU; the data span 0.0685-5.4246",
          "published_values": [null]
        },
        {
          "name": "r_max_au",
          "type": "number | null",
          "default": null,
          "range": "inclusive upper bound on mo_sc_heliodistance in AU; must exceed r_min_au",
          "published_values": [null]
        }
      ],
      "returns": "test, statistic_rho, p_value, effect_size, effect_size_value, n",
      "supports_claims": [1],
      "deterministic": true
    },
    {
      "name": "powerlaw_fit",
      "summary": "Log-log OLS power law B ~ r^-alpha with a percentile bootstrap 95% CI on the slope and alpha (T2).",
      "unit": "analysis.loglog_ols and analysis.bootstrap_slope_ci (main() T2 block)",
      "parameters": [
        {
          "name": "exclude_spacecraft",
          "type": "array of string | null",
          "default": null,
          "range": "any of the eleven spacecraft; at least 3 events and 2 distinct distances must remain",
          "published_values": [null]
        },
        {
          "name": "r_min_au",
          "type": "number | null",
          "default": null,
          "range": "inclusive lower bound in AU",
          "published_values": [null]
        },
        {
          "name": "r_max_au",
          "type": "number | null",
          "default": null,
          "range": "inclusive upper bound in AU; must exceed r_min_au",
          "published_values": [null]
        },
        {
          "name": "n_boot",
          "type": "integer",
          "default": 10000,
          "range": ">= 100 bootstrap resamples",
          "published_values": [10000]
        },
        {
          "name": "seed",
          "type": "integer",
          "default": 42,
          "range": "any integer; seeds a fresh numpy default_rng per call",
          "published_values": [42],
          "notes": "The published run's generator is seeded 42 and consumed only by this bootstrap, so a fresh default_rng(42) per call reproduces its interval exactly."
        }
      ],
      "returns": "test, statistic_slope, alpha, slope_ci95, alpha_ci95, intercept, r2, p_value, effect_size, effect_size_value, n",
      "supports_claims": [2, 3],
      "deterministic": true
    },
    {
      "name": "robust_powerlaw_fit",
      "summary": "Theil-Sen robust slope of log10 field on log10 distance, with its 95% CI (T3).",
      "unit": "main() T3 block (scipy.stats.theilslopes on log10 data), re-implemented",
      "parameters": [
        {
          "name": "exclude_spacecraft",
          "type": "array of string | null",
          "default": null,
          "range": "any of the eleven spacecraft; at least 3 events and 2 distinct distances must remain",
          "published_values": [null]
        },
        {
          "name": "r_min_au",
          "type": "number | null",
          "default": null,
          "range": "inclusive lower bound in AU",
          "published_values": [null]
        },
        {
          "name": "r_max_au",
          "type": "number | null",
          "default": null,
          "range": "inclusive upper bound in AU; must exceed r_min_au",
          "published_values": [null]
        }
      ],
      "returns": "test, statistic_slope, alpha, intercept, slope_ci95, alpha_ci95, effect_size, effect_size_value, n",
      "supports_claims": [2],
      "deterministic": true
    },
    {
      "name": "leave_one_spacecraft_out",
      "summary": "Refit the log-log OLS exponent once per spacecraft in the sample, each time without it (guard b).",
      "unit": "main() guard (b) loop over analysis.loglog_ols, re-implemented",
      "parameters": [
        {
          "name": "exclude_spacecraft",
          "type": "array of string | null",
          "default": null,
          "range": "spacecraft removed from the base sample before the leave-one-out loop; at least two must remain",
          "published_values": [null]
        },
        {
          "name": "r_min_au",
          "type": "number | null",
          "default": null,
          "range": "inclusive lower bound on the base sample in AU",
          "published_values": [null]
        },
        {
          "name": "r_max_au",
          "type": "number | null",
          "default": null,
          "range": "inclusive upper bound on the base sample in AU; must exceed r_min_au",
          "published_values": [null]
        }
      ],
      "returns": "test, alpha_min, alpha_max, alpha_range, full_alpha, and per_exclusion rows of excluded_sc, alpha, slope, n",
      "supports_claims": [3],
      "deterministic": true
    },
    {
      "name": "perspacecraft_slopes",
      "summary": "Per-spacecraft log-log slope and Spearman test, BH-corrected over the guard family, widest radial baseline first (guard a).",
      "unit": "main() guard (a) with analysis.loglog_ols and analysis.bh_correct, re-implemented",
      "parameters": [
        {
          "name": "min_n",
          "type": "integer",
          "default": 30,
          "range": ">= 3; spacecraft with fewer events are not tested. MAVEN (n = 10) is the only spacecraft below the published 30",
          "published_values": [30]
        },
        {
          "name": "within_targets",
          "type": "array of string | null",
          "default": null,
          "range": "spacecraft whose within-spacecraft tests join the BH family; null uses the published PSP, Juno, ULYSSES; [] corrects over the per-spacecraft tests alone",
          "published_values": [null],
          "notes": "The published family counts PSP, Juno and Ulysses twice, so the corrected p-values here depend on this choice."
        },
        {
          "name": "within_min_n",
          "type": "integer",
          "default": 10,
          "range": ">= 3; a named within target with fewer events raises rather than being skipped",
          "published_values": [10]
        }
      ],
      "returns": "test, spacecraft rows (sc_insitu, n, r_min, r_max, r_span_AU, slope, alpha, r2, spearman_rho, spearman_p, spearman_p_bh), n_spacecraft_tested, multiple_comparison_correction",
      "supports_claims": [5],
      "deterministic": true
    },
    {
      "name": "within_spacecraft",
      "summary": "Within-instrument Spearman and log-log slope for chosen spacecraft, BH-corrected over the guard family (guard c).",
      "unit": "main() guard (c) with analysis.loglog_ols and analysis.bh_correct, re-implemented",
      "parameters": [
        {
          "name": "within_targets",
          "type": "array of string | null",
          "default": null,
          "range": "any spacecraft with at least within_min_n events; null uses the published PSP, Juno, ULYSSES",
          "published_values": [null]
        },
        {
          "name": "min_n",
          "type": "integer",
          "default": 30,
          "range": ">= 3; sets which per-spacecraft tests share the BH family",
          "published_values": [30]
        },
        {
          "name": "within_min_n",
          "type": "integer",
          "default": 10,
          "range": ">= 3",
          "published_values": [10]
        }
      ],
      "returns": "test and target rows (sc_insitu, n, r_min, r_max, spearman_rho, spearman_p, ols_slope, ols_alpha, r2, spearman_p_bh)",
      "supports_claims": [4],
      "deterministic": true
    },
    {
      "name": "guard_family",
      "summary": "The guard test family with raw and Benjamini-Hochberg-corrected p-values, in main()'s order.",
      "unit": "main() guard-family construction and analysis.bh_correct, re-implemented",
      "parameters": [
        {
          "name": "min_n",
          "type": "integer",
          "default": 30,
          "range": ">= 3",
          "published_values": [30]
        },
        {
          "name": "within_targets",
          "type": "array of string | null",
          "default": null,
          "range": "null uses the published PSP, Juno, ULYSSES; [] gives the de-duplicated per-spacecraft family",
          "published_values": [null]
        },
        {
          "name": "within_min_n",
          "type": "integer",
          "default": 10,
          "range": ">= 3",
          "published_values": [10]
        }
      ],
      "returns": "one row per test: test, p_raw, p_bh",
      "supports_claims": [4, 5],
      "deterministic": true
    }
  ]
}
