| name | generate-research-plan |
| description | Planner stage — operationalize the decisive test into ONE flat, runnable item list plus a column-and-formula-precise plan + a metadata-feasibility verdict. Topic-agnostic; the data is whatever the data-metadata docs (data/INDEX.md + registers/<slug>.md) describe. Owns the group-free manifest contract (plan.md + manifest.json + feasibility.json) and the numbers-are-cited rule. Feasibility is metadata/design-level (no data bytes): confirm columns exist + a documented join path, never a measured rate. |
generate-research-plan
The Planner stage. Turn the hypothesis's research arc into something a researcher could RUN: ONE flat experimental-item list + a column-precise design per item, plus the feasibility verdict. Engineering, not taste. There is NO group split — the first-order question, the second-order extensions, and the robustness perturbations are all items in ONE manifest. You PRODUCE the plan; there is no committee in this isolated build — do not self-accept.
The data is not hardcoded: it is whatever the run-context --data-dir docs describe (data/INDEX.md is the catalog; data/registers/<slug>.md are the per-register schemas, each variable citable as [data:<slug>.<VAR>]). Feasibility is metadata-only — you have no data bytes, so you confirm what the docs STATE.
Inputs (read from the run context)
workspace/stage-frame/hypothesis/hypothesis.md — the research arc (first-order question, second-order extend/defend/boundary, robustness sketch). Turn the WHOLE arc into one flat item list.
workspace/stage-frame/data/review.md + workspace/stage-frame/literature/review.md — the Proposer's grounding.
- The
--data-dir register docs (feasibility) + the --papers-dir corpus (method grounding).
Orchestration (depth-1 sub-agents via Task)
literature-specialist — ground each item's estimator / identification strategy with corpus exemplars + their transferability to the available data.
data-specialist — the metadata-feasibility role: column-precise grading of the draft plan against the register docs + the GREEN/YELLOW/RED verdict (it writes the feasibility contract below). The author never grades its own feasibility.
If Task is unavailable, run these inline as strictly-separated passes and note DEGRADED: no-subagents in feasibility.md.
Design method
- ONE item per arc question / perturbation. The bar: two non-communicating researchers implementing the item independently should land inside each other's confidence intervals.
- Identification first: pick the design template from the corpus / reviews (natural experiment, leniency/assignment IV, staggered-DiD, event study, bunching, matched-DiD) and write WHY it transfers to the available administrative records (lean on the
literature-specialist).
- Controls: for each, why control / why not over-control. State the expected effect + the minimum detectable effect (MDE) before "running" anything — as
[design] assumptions (there is no data to measure against).
- Item taxonomy in the ONE flat list: the first-order headline item; ≥3 second-order items (extend / defend / boundary), each conditioned on the realized first-order case; ≥6 robustness-perturbation items of the locked model — leave-one-group-out / alt outcome / alt clustering / placebo timing / window shift / alt fixed effects / winsorization — each a one-criterion item (e.g. "main coefficient must not flip sign; |Δβ|/β < 0.5").
- A pre-registered branch tree (per first-order item: CASE-A/B/C decision thresholds + second-order expansions + a holdout time barrier that kills spec-search) belongs in
plan.md prose.
Feasibility (metadata-only — the gate reads this)
Run an in-skill FEAS⇄PLAN loop (≤3 rounds, maker/checker): draft the plan, then dispatch a FRESH read-only data-specialist sub-agent (subagent_type=data-specialist) that grades the current draft against the register docs and returns the verdict. The grader checks:
- Dim A (columns): every
[data:<id>] the plan cites EXISTS in a register doc and MEANS what the plan assumes (row-semantics); coverage red-lines respected (e.g. the hours window). A cited field absent from the docs is a blocker.
- Dim B (linkage): name the join key(s) the design needs (
PNR, an FK, spell dates); classify each deterministic (exact register key — the norm) vs crosswalk-needed; assess key coverage from the docs. A non-deterministic join whose match rate is unconfirmable from metadata caps the verdict at YELLOW (an unmeasured_assumption), never blocks.
- Verdict: GREEN (cited columns confirmed + a documented deterministic/covered join path + red-lines respected) → finalize; YELLOW (adapt explicitly — shrink sample / swap outcome / restrict window — and re-check, or it rests on an unmeasured join) ; RED (a required column or join path is not in the docs, or a red-line kills the design) → write the verdict and STOP.
The data-specialist writes workspace/stage-frame/data/feasibility.json:
{ "verdict":"GREEN|YELLOW|RED", "confidence":"metadata-only",
"required_columns_confirmed": true, "linkage_block_present": true,
"joins":[{"from":"<reg>","to":"<reg>","key":"PNR","kind":"deterministic","coverage":"[data:...]"}],
"unmeasured_assumptions":[ "<match rate / NA rate assumed; confirm against data>" ],
"blocked_reason": null, "rounds": N }
plus the prose to workspace/stage-frame/data/feasibility.md. The gate gives no GREEN without required_columns_confirmed AND linkage_block_present both true.
Gate-checked outputs (the postcondition greps these — exact paths)
workspace/stage-research/manifest.json — the flat DEFAULT-FAIL contract (≥1 item; each id+spec+≥1 criterion id+desc; every pass:false, every verdict:null; unique ids):
{ "conditioned_on": null,
"items": [
{ "id": "<item-id>", "spec": "<the item's question or perturbation>",
"criteria": [ { "id":"C1", "kind":"data|identification|robustness",
"desc":"<mechanically verifiable acceptance item>",
"verify":"<evidence location>", "pass": false, "evidence": null } ],
"status": "pending", "verdict": null } ] }
workspace/stage-research/plan.md — opens with ## HEADLINE / ## QUESTION-MAP / ## ESTIMAND / ## CENSORING / ## SELECTION, then one ### <item-id> block per item with - UNIT: / - DATA: / - SAMPLE: / - MODEL: / - LIT: / - EXPECT: / - OUTPUT:. The branch tree (CASE thresholds + holdout barrier) goes here.
workspace/stage-frame/data/feasibility.json + feasibility.md — the verdict (above).
Constraints
- NUMBERS ARE CITED, NEVER INVENTED: every numeric claim in plan.md and feasibility.md carries
[data:<id>] (a register field/coverage fact) or [design] (a design assumption) ON THE SAME LINE. There is no data to query → no [calc:].
- DEFAULT-FAIL: write criteria you would accept being held to; all
pass:false / verdict:null now.
- Metadata-only honesty: never claim a measured match rate / NA% / N — those are
[design] assumptions to confirm against data later; record them in unmeasured_assumptions.
- Write ONLY under
workspace/stage-research/ and workspace/stage-frame/data/; never write outside the session.