{
  "manifest_version": "0.1",
  "work_slug": "modern-collagen-cn-fish-vs-mammal-glycine",
  "concept_ark_suffix": "dp-quality-control-for-modern-bone-collagen-stable-carbon-and-n",
  "protocol": "protocol:secondary-analysis 0.1",
  "module": "agent/tools.py",
  "analysis_unit": "analysis.py",
  "published_results": "results.json",
  "source_dataset_doi": "10.5061/dryad.ffbg79crm",
  "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 exposes its statistics (mwu, cliffs_delta, hl_boot_ci, bh_fdr) and loader (load_main, acquire_and_verify) as functions, and the tools call those. The group selection, group summaries, Spearman blocks, residue screen and robustness variants exist only as closures inside main(), so they are re-implemented here line for line, preserving row order because the HL bootstrap draws indices. The published-pointer calls prove the re-implementation reproduces results.json at the defaults. The parameters are the row selections the published run already makes (class groupings, the Material stratum, the per-taxon collapse) plus leave-one-study-out, the standard sensitivity for a compilation of 231 source studies.",
  "tools": [
    {
      "name": "data_integrity",
      "summary": "The md5 record of all five pinned source tables.",
      "unit": "analysis.acquire_and_verify (inputs fetched first through scripts/fetch_pinned.py into the analysis unit's data directory)",
      "parameters": [],
      "returns": "one record per file: file, url, bytes, md5_expected, md5_observed, verified",
      "supports_claims": [1, 2, 3, 4, 5],
      "deterministic": true
    },
    {
      "name": "dataset_summary",
      "summary": "Sample, taxon and class counts of the 436 populated Table S1 rows.",
      "unit": "analysis.load_main plus the dataset block of analysis.main (re-implemented)",
      "parameters": [],
      "returns": "n_samples_total, n_unique_taxa, n_rows_missing_taxon, n_actinopterygii, n_mammalia, class_counts",
      "supports_claims": [1, 2, 3, 5],
      "deterministic": true
    },
    {
      "name": "normality_check",
      "summary": "Shapiro-Wilk on C:N for each side of the contrast -- the stated reason for going nonparametric.",
      "unit": "analysis.main: normality_shapiro block (scipy.stats.shapiro over the T1 groups), re-implemented over the shared row selection",
      "parameters": [
        {"name": "fish_classes", "type": "array of string | null", "default": null, "range": "one or more Table S1 classes, disjoint from mammal_classes; null is [Actinopterygii]", "published_values": [null]},
        {"name": "mammal_classes", "type": "array of string | null", "default": null, "range": "one or more Table S1 classes, disjoint from fish_classes; null is [Mammalia]", "published_values": [null]},
        {"name": "material", "type": "integer | null", "default": null, "range": "1 | 2 | 3 | null (all rows)", "published_values": [null]},
        {"name": "collapse_taxa", "type": "boolean", "default": false, "range": "true applies main()'s R2 rule: one median row per named taxon, unnamed rows kept individually", "published_values": [false]},
        {"name": "exclude_references", "type": "array of string | null", "default": null, "range": "exact Reference strings of Table S1 (231 studies); unknown strings are rejected", "published_values": [null]},
        {
          "name": "max_cn",
          "type": "number | null",
          "default": null,
          "range": "> 0; drops samples whose C:N exceeds it before testing",
          "published_values": [null],
          "notes": "The published fish result (W = 0.89, p = 1.2e-13) contradicts the source's own Table S2 (fish n = 288, W = 0.9949, p = 0.4585). The difference is two samples, both from Rigby 1968 (C:N 3.56 and 3.58; the next-highest fish is 3.32). max_cn = 3.5 reproduces Table S2's row to its printed precision."
        }
      ],
      "returns": "cn_fish and cn_mammal, each with n, W and p",
      "supports_claims": [1, 4],
      "deterministic": true
    },
    {
      "name": "fish_vs_mammal_contrast",
      "summary": "Two-sided Mann-Whitney U on C:N between two class groups, with Cliff's delta and a bootstrapped Hodges-Lehmann shift (T1).",
      "unit": "analysis.mwu, analysis.cliffs_delta and analysis.hl_boot_ci over main()'s T1 group selection and grp_stats closure (re-implemented)",
      "parameters": [
        {"name": "fish_classes", "type": "array of string | null", "default": null, "range": "one or more Table S1 classes, disjoint from mammal_classes; null is [Actinopterygii]", "published_values": [null, ["Actinopterygii", "Elasmobranchii"]], "notes": "The second published value is R3. Group-summary keys are named from the pooled classes, so a broadened call reports group_fish_actinopterygii_elasmobranchii rather than mislabelling it."},
        {"name": "mammal_classes", "type": "array of string | null", "default": null, "range": "one or more Table S1 classes, disjoint from fish_classes; null is [Mammalia]", "published_values": [null, ["Mammalia", "Aves"]]},
        {
          "name": "material",
          "type": "integer | null",
          "default": null,
          "range": "1 | 2 | 3 | null (all rows); 2 holds fish only, so a contrast within it raises",
          "published_values": [null, 1, 3],
          "notes": "R1. The object calls Material an undocumented batch code. It is very probably tissue: Material = 1 reproduces Table S2's Bone rows for Mammalia and Elasmobranchii exactly (acceptance call normality-bone-stratum-table-s2), the Elasmobranchii counts equal Table S5's Bone/cartilage 6 and Skin 25, and Material = 2 holds only ray-finned fish, as scales would. But the ray-finned fish counts differ from Table S2's Bone/Scale/Skin rows by 1 to 3 in every stratum (51/50/189 against 50/49/186) and mammal Material = 3 differs from Skin by one (62 against 61), so this surface keeps the numeric code rather than renaming it."
        },
        {"name": "collapse_taxa", "type": "boolean", "default": false, "range": "true applies main()'s R2 rule: one median row per named taxon, unnamed rows kept individually", "published_values": [false, true]},
        {"name": "exclude_references", "type": "array of string | null", "default": null, "range": "exact Reference strings of Table S1 (231 studies); unknown strings are rejected", "published_values": [null], "notes": "Leave-one-study-out, which the published battery does not contain."},
        {"name": "n_boot", "type": "integer", "default": 10000, "range": ">= 100 bootstrap resamples", "published_values": [10000]},
        {"name": "seed", "type": "integer", "default": 0, "range": "any integer; each call seeds its own generator", "published_values": [0]}
      ],
      "returns": "test, U, p, cliffs_delta, hodges_lehmann_shift_fish_minus_mammal, hl_ci95, one grp_stats block per side (n, median, IQR, mean, sd, min, max, pct_in_archaeo_window), expected and observed direction",
      "supports_claims": [1, 4, 5],
      "deterministic": true
    },
    {
      "name": "robustness_battery",
      "summary": "The pre-registered T1 robustness battery exactly as published: primary, R1 per Material stratum, R2, R3 and R4.",
      "unit": "analysis.main: robustness block and its one() closure (re-implemented over the same contrast core as fish_vs_mammal_contrast)",
      "parameters": [],
      "returns": "R4_window_free_cliffs_delta_primary and the variants list (variant, n_fish, n_mammal, hl_shift, ci_lo, ci_hi, cliffs_delta, U, p, note)",
      "supports_claims": [4],
      "deterministic": true
    },
    {
      "name": "qc_window_pass_rate",
      "summary": "Share of samples a C:N acceptance window would pass, per side of the contrast and for the whole compilation.",
      "unit": "analysis.main: grp_stats pct_in_archaeo_window, with analysis.QC_LO and analysis.QC_HI as the defaults",
      "parameters": [
        {"name": "window_lo", "type": "number", "default": 2.9, "range": "< window_hi; inclusive", "published_values": [2.9]},
        {"name": "window_hi", "type": "number", "default": 3.6, "range": "> window_lo; inclusive", "published_values": [3.6], "notes": "Claim 5 says the class offset is not a pass/fail effect. That is true of the 2.9-3.6 window and depends on it: the stricter 3.1-3.5 window rejects 34 of 290 fish and passes every mammal (acceptance call window-3.1-3.5-off-reference)."},
        {"name": "fish_classes", "type": "array of string | null", "default": null, "range": "null is [Actinopterygii]", "published_values": [null]},
        {"name": "mammal_classes", "type": "array of string | null", "default": null, "range": "null is [Mammalia]", "published_values": [null]}
      ],
      "returns": "window, and fish, mammal and all_samples blocks with n, n_in_window and pct_in_window",
      "supports_claims": [5],
      "deterministic": true
    },
    {
      "name": "glycine_association",
      "summary": "Spearman rho of C:N against glycine over the whole selection and within each named class (T2).",
      "unit": "analysis.main: T2 spearman closure (re-implemented over the shared row selection)",
      "parameters": [
        {"name": "within_classes", "type": "array of string | null", "default": null, "range": "one or more Table S1 classes with at least 3 samples in the selection; null is [Actinopterygii, Mammalia]", "published_values": [null], "notes": "Naming a class the confirmatory test never used is an out-of-sample replication of the glycine mechanism."},
        {"name": "material", "type": "integer | null", "default": null, "range": "1 | 2 | 3 | null", "published_values": [null], "notes": "T2 was never stratified in the published run."},
        {"name": "collapse_taxa", "type": "boolean", "default": false, "range": "true applies the R2 per-taxon median to C:N and glycine", "published_values": [false], "notes": "The pseudoreplication guard was applied only to T1 in the published run."},
        {"name": "exclude_references", "type": "array of string | null", "default": null, "range": "exact Reference strings of Table S1", "published_values": [null]}
      ],
      "returns": "test, overall {rho, p, n}, one {rho, p, n} block per class keyed by its lower-cased name, expected_direction",
      "supports_claims": [2],
      "deterministic": true
    },
    {
      "name": "amino_acid_screen",
      "summary": "Spearman rho of every residue against C:N, with Benjamini-Hochberg over the tested family (T3).",
      "unit": "analysis.main: T3 residue loop with analysis.bh_fdr (re-implemented over the shared row selection)",
      "parameters": [
        {"name": "classes", "type": "array of string | null", "default": null, "range": "one or more Table S1 classes; null pools all ten", "published_values": [null], "notes": "The published screen pools classes that differ in both C:N and composition, so a residue can rank high because it separates fish from mammals. A single-class screen removes that."},
        {"name": "material", "type": "integer | null", "default": null, "range": "1 | 2 | 3 | null", "published_values": [null]},
        {"name": "collapse_taxa", "type": "boolean", "default": false, "range": "true applies the R2 per-taxon median to C:N and every residue", "published_values": [false]},
        {"name": "exclude_references", "type": "array of string | null", "default": null, "range": "exact Reference strings of Table S1", "published_values": [null]},
        {"name": "min_n", "type": "integer", "default": 10, "range": ">= 3 paired samples for a residue to enter the FDR family", "published_values": [10], "notes": "Cys is reported in 110 of 436 rows and Hyl in 347; min_n above 347 drops both from the family."},
        {"name": "fdr_q", "type": "number", "default": 0.05, "range": "(0, 1)", "published_values": [0.05], "notes": "Names the flag it sets, so the default reproduces significant_q<0.05."}
      ],
      "returns": "test, n_residues_tested, results (one row per residue sorted by rho: residue, residue_full, rho, p, n, q_bh, significance flag) and the glycine row",
      "supports_claims": [3],
      "deterministic": true
    }
  ]
}
