| name | ai4s-task-harness |
| description | Use when starting any AI4S analysis task (bioinformatics pipeline, model training, benchmark, data integration) to build a task-specific harness BEFORE writing analysis code. Symptoms - about to run a multi-step experiment, need reproducible results, want to prevent metric drift or story drift, setting up a new analysis phase. |
AI4S Task Harness Builder
Overview
Build a task-specific harness before writing analysis code, so Claude orchestrates the task with contracts, sanity checks, and evidence generation โ not just free-form coding. The harness is the scaffolding that prevents silent metric drift, story drift, and irreproducibility.
Core idea from Anthropic's dynamic workflows: Claude's default coding harness works for general tasks, but AI4S tasks need domain-specific guardrails โ data contracts, statistical sanity, evidence locking, and negative controls. This skill builds those guardrails per-task.
When to Use
- Starting a new analysis phase (e.g. "run differential expression", "build a classifier", "benchmark against SILVA")
- Any task that will produce numbers cited in a manuscript
- Multi-step pipelines where intermediate results feed downstream
- Tasks involving HPC submission, large-scale benchmarking, or cross-dataset validation
When NOT to Use
- Pure writing tasks (use
ml-paper-writing)
- One-off exploratory plots that won't appear in the paper
- Project-level scaffolding from scratch (use
/init_ai4s instead)
The Harness Stack
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ STORY_LOCK.md โ which sub-question? โ โ narrative anchor
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโค
โ HYPOTHESIS.md โ falsifiable claim โ โ scientific rigor
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโค
โ harness/contracts/ โ input schemas โ โ data integrity
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโค
โ harness/sanity/ โ negative controls โ โ anti-artifact
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโค
โ harness/benchmarks/ โ metric capture โ โ evidence lock
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโค
โ harness/registry.py โ phase object โ โ orchestration
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโค
โ tests/test_contracts/ โ locked numbers โ โ drift guard
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโค
โ Workflow script (optional) โ parallel โ โ scale & verify
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
Build Process (follow in order)
Step 1: Anchor to the story
Before any code, answer:
- Which sub-question in
plan/STORY_LOCK.md does this task serve?
- What evidence tier will it produce? (Causal / Inferential / Correlative / Descriptive)
- Main text or extended data?
If no sub-question fits, stop โ the task may be scope creep.
Step 2: Write HYPOTHESIS.md
## Hypothesis
<one falsifiable sentence>
## Null hypothesis
<what we expect if the effect is absent>
## Variables
- Independent: ...
- Dependent: ...
- Controlled: ...
## Statistical test (pre-registered)
<test name, correction method, threshold>
## Sample size / power
<n per group, expected effect size, power>
## Seed
<from configs/, never hardcoded>
Run bash check_science.sh โ it must pass before proceeding.
Step 3: Write the data contract
Create harness/contracts/<task_name>.py:
def check_<task_name>_inputs() -> None:
"""Assert input data matches expected schema."""
Step 4: Write the sanity check
Create harness/sanity/<task_name>.py with at least ONE negative control:
| Task type | Negative control |
|---|
| Classification | Shuffled labels โ accuracy ~ chance |
| Clustering | Random features โ no structure |
| Differential expression | Permuted groups โ no significant genes |
| Dimensionality reduction | Uniform random โ no clusters |
| Benchmark comparison | Null classifier โ floor metric |
Step 5: Register the phase
@register_phase("phase_<task_name>")
class Phase<TaskName>(Phase):
inputs = [PROJECT_ROOT / "data" / "..."]
outputs = [PROJECT_ROOT / "results" / "phase_<task_name>" / "..."]
seed = cfg.seed
def run(self):
from src.<module> import run_<task_name>
run_<task_name>(self.inputs, self.outputs, seed=self.seed)
def benchmark(self):
return {"accuracy": ..., "f1": ..., "n_samples": ...}
def sanity(self):
from harness.sanity.<task_name> import check_shuffled
return [lambda: check_shuffled(seed=self.seed)]
Step 6: Lock the evidence (after first successful run)
Add to tests/test_contracts/test_evidence_constants.py:
def test_<task_name>_accuracy():
assert 0.85 <= result["accuracy"] <= 0.95, "accuracy drifted"
Step 7: (Optional) Build a workflow for scale
For tasks needing parallelism, adversarial verification, or multi-dataset benchmarking, write a Claude Code workflow script. Pick from these AI4S patterns:
AI4S Workflow Patterns
Pattern A: Fan-Out Benchmark
Run the same pipeline across N datasets in parallel, then synthesize.
datasets โโโฌโโ agent(dataset_1) โโโ
โโโ agent(dataset_2) โโโคโโ synthesize metrics
โโโ agent(dataset_N) โโโ
Use when: benchmarking a method across multiple cohorts (e.g. 276 16S projects).
Pattern B: Adversarial Method Verification
One agent runs the analysis; separate agents try to break it.
run_analysis โโโฌโโ verify: shuffled labels
โโโ verify: held-out samples
โโโ verify: known-positive recovery
Use when: any result that will appear in main text. Prevents self-preferential bias.
Pattern C: Hypothesis Tournament
Generate competing explanations, judge each against evidence.
evidence โโโฌโโ hypothesis_1 โโโ
โโโ hypothesis_2 โโโคโโ judge panel โโ winner
โโโ hypothesis_3 โโโ
Use when: root-cause investigation, model selection, method comparison.
Pattern D: Pipeline-Then-Audit
Run the full pipeline, then audit every intermediate for biological sense.
pipeline(steps) โโ audit_agent(step_1_output)
audit_agent(step_2_output)
...
Use when: multi-step bioinformatics pipelines where each step can silently produce garbage.
Failure Modes This Prevents
| Failure mode | Without harness | With harness |
|---|
| Metric drift | Paper says 92%, code produces 89% | test_evidence_constants fails |
| Story drift | Manuscript claims X, code does Y | evidence_table.py auto-generates from code |
| Silent fallback | Method A fails, silently uses method B | Contract rejects; no silent fallback rule |
| Artifact survival | Shuffled labels still show signal | sanity/shuffled_labels.py catches it |
| Agentic laziness | Claude stops after step 2 of 5 | Workflow script enforces all steps |
| Self-preferential bias | Claude judges own output as "good" | Adversarial verification agents |
| Irreproducibility | Results differ on re-run | Seed locked, env pinned, manifest hashed |
Quick Reference: Harness Completeness Check
Before calling the task done, verify:
[ ] HYPOTHESIS.md written and check_science.sh passes
[ ] Data contract in harness/contracts/
[ ] At least one negative control in harness/sanity/
[ ] Phase registered in harness/registry.py
[ ] Benchmark metrics captured (flat dict, no nested)
[ ] Evidence constants locked in tests/test_contracts/
[ ] Seed from config, not hardcoded
[ ] `python -m harness.run_all` exits 0
[ ] `python -m harness.evidence_table` regenerates without diff
Common Mistakes
- Writing analysis code before the contract: the contract defines what "correct input" means โ without it, garbage-in is invisible.
- Skipping the negative control: "it works" means nothing without "it fails when it should fail."
- Hardcoding thresholds in tests: use tolerances that reflect actual pipeline variance, not wishes.
- Registering the phase before outputs exist: register only after the first successful run; until then the phase stays commented out.
- Using workflows for simple tasks: a single-dataset, single-method analysis doesn't need fan-out. Reserve workflows for genuine parallelism or adversarial verification.