Context
While running /scholar:research:recap --sync on a research repo (me-exposure-recall, the M2b
manuscript), I needed a one-shot R script (make_table1.R) to aggregate a finished simulation grid
(simulation_results/sim_exposure_summary.csv, 144 cells) into the §5.2 manuscript table body.
Writing it to code/ on the draft branch was blocked by craft's branch-guard.sh (smart mode,
MEDIUM): "New code files on draft should go in a feature branch."
This is not a bug
The guard behaved correctly per the research draft-as-dev convention
(~/.claude/rules/draft-as-dev-research.md). On draft: new .md, extension-less files, and edits
to existing files are all allowed (LOW); only new code files (extension in
py sh js ts jsx tsx json yml yaml toml cfg ini r R zsh) are MEDIUM-confirmed and steered to a
feature/* branch. Enforcement lives in craft/scripts/branch-guard.sh:636-695. It's also MEDIUM
(confirmable), not a hard block. So nothing is broken — filing this as an enhancement about the
workflow friction it exposes, not a fix for a defect.
The genuine friction
Research/manuscript work legitimately happens on draft, and reproducible analysis scripts
— table/figure generators that turn simulation_results/*.csv into a \begin{table*} body — are part
of that work, not separable "features." Today such a script has two homes, both poor for a one-shot:
- A
feature/* branch — convention-correct, but heavyweight ceremony for a 30-line aggregation,
and the manuscript edit it feeds (index.qmd) lives on draft, so the change splits across two
branches for no real isolation benefit.
/tmp (what I did) — sidesteps the guard cleanly, but the script that computed a published
table is then untracked → reproducibility gap. The table is in version control; the code that
produced it is not.
Proposed options (for discussion — pick one)
- (Recommended) Path-scoped allowance on research
draft. Permit new code files under a
designated analysis dir (e.g. code/ or scripts/) on draft in research repos, while keeping the
block for new code elsewhere. Matches how research repos actually work and keeps table/figure
generators version-controlled next to the manuscript they serve.
- Scholar-side "promote script" helper. A small command (or a step in the simulation / recap
workflow) that lifts a /tmp analysis script onto a feature/* branch and opens the PR — making the
reproducible path one step instead of manual worktree ceremony.
- Doc-only. Document the sanctioned pattern (one-shot →
/tmp; reproducible → feature branch) in
scholar's simulation/manuscript workflow docs and surface it in the recap output, so users aren't
surprised by the block. Cheapest, but does not close the reproducibility gap.
Where the fix lives
Enforcement is craft's (branch-guard.sh), so option 1 is an upstream craft change that scholar
would track/depend on; options 2–3 are scholar-side. Filed here per request — cross-link to a craft
issue if option 1 is chosen.
Repro
- Repo: research
me-exposure-recall, branch draft.
Write code/make_table1.R → blocked MEDIUM by branch-guard smart mode.
- Workaround used: wrote
/tmp/make_table1.R, ran it, pasted the LaTeX output into index.qmd
(existing file → allowed). Reproducibility of that table now depends on an untracked /tmp file.
Context
While running
/scholar:research:recap --syncon a research repo (me-exposure-recall, the M2bmanuscript), I needed a one-shot R script (
make_table1.R) to aggregate a finished simulation grid(
simulation_results/sim_exposure_summary.csv, 144 cells) into the §5.2 manuscript table body.Writing it to
code/on thedraftbranch was blocked by craft'sbranch-guard.sh(smart mode,MEDIUM): "New code files on draft should go in a feature branch."
This is not a bug
The guard behaved correctly per the research
draft-as-devconvention(
~/.claude/rules/draft-as-dev-research.md). Ondraft: new.md, extension-less files, and editsto existing files are all allowed (LOW); only new code files (extension in
py sh js ts jsx tsx json yml yaml toml cfg ini r R zsh) are MEDIUM-confirmed and steered to afeature/*branch. Enforcement lives incraft/scripts/branch-guard.sh:636-695. It's also MEDIUM(confirmable), not a hard block. So nothing is broken — filing this as an enhancement about the
workflow friction it exposes, not a fix for a defect.
The genuine friction
Research/manuscript work legitimately happens on
draft, and reproducible analysis scripts— table/figure generators that turn
simulation_results/*.csvinto a\begin{table*}body — are partof that work, not separable "features." Today such a script has two homes, both poor for a one-shot:
feature/*branch — convention-correct, but heavyweight ceremony for a 30-line aggregation,and the manuscript edit it feeds (
index.qmd) lives ondraft, so the change splits across twobranches for no real isolation benefit.
/tmp(what I did) — sidesteps the guard cleanly, but the script that computed a publishedtable is then untracked → reproducibility gap. The table is in version control; the code that
produced it is not.
Proposed options (for discussion — pick one)
draft. Permit new code files under adesignated analysis dir (e.g.
code/orscripts/) ondraftin research repos, while keeping theblock for new code elsewhere. Matches how research repos actually work and keeps table/figure
generators version-controlled next to the manuscript they serve.
workflow) that lifts a
/tmpanalysis script onto afeature/*branch and opens the PR — making thereproducible path one step instead of manual worktree ceremony.
/tmp; reproducible → feature branch) inscholar's simulation/manuscript workflow docs and surface it in the recap output, so users aren't
surprised by the block. Cheapest, but does not close the reproducibility gap.
Where the fix lives
Enforcement is craft's (
branch-guard.sh), so option 1 is an upstream craft change that scholarwould track/depend on; options 2–3 are scholar-side. Filed here per request — cross-link to a craft
issue if option 1 is chosen.
Repro
me-exposure-recall, branchdraft.Write code/make_table1.R→ blocked MEDIUM by branch-guard smart mode./tmp/make_table1.R, ran it, pasted the LaTeX output intoindex.qmd(existing file → allowed). Reproducibility of that table now depends on an untracked
/tmpfile.