Manuscript Assembly Protocol
Purpose
Combine all drafted manuscript sections into a complete manuscript file with validation, metadata generation, and quality checks.
Prerequisites
Required files in {target_dir}:
abstract.md
introduction.md
methods.md
results.md
discussion.md
availability.md (optional)
Recommended:
literature_citations.bib - For citation validation
outline.md - For structure verification
Workflow
Phase 1: Pre-Assembly Validation
Check Required Sections:
cd {target_dir}
required_sections=("abstract.md" "introduction.md" "results.md" "discussion.md" "methods.md")
missing=()
for section in "${required_sections[@]}"; do
if [ ! -f "$section" ]; then
missing+=("$section")
fi
done
if [ ${#missing[@]} -gt 0 ]; then
echo "Error: Missing required sections: ${missing[*]}"
exit 1
fi
Verify Section Completion:
Check workflow state to ensure all sections are marked as completed:
import json
from pathlib import Path
state_file = Path("{target_dir}/.rrwrite/state.json")
if state_file.exists():
with open(state_file) as f:
state = json.load(f)
sections = state.get("workflow_status", {}).get("drafting", {}).get("sections", {})
incomplete = [s for s, data in sections.items() if data.get("status") != "completed"]
if incomplete:
print(f"Warning: Incomplete sections: {incomplete}")
Phase 2: Section Assembly
Combine Sections in Order:
For Nature format: Abstract → Introduction → Results → Discussion → Methods → Availability
cd {target_dir}
# Clear or create output file
> manuscript_full.md
# Add header
cat >> manuscript_full.md << 'EOF'
# MicroGrowAgents Manuscript
**Target Journal:** Nature
**Date:** $(date +%Y-%m-%d)
---
EOF
# Combine sections
echo "# Abstract" >> manuscript_full.md
echo "" >> manuscript_full.md
cat abstract.md >> manuscript_full.md
echo -e "\n\n---\n" >> manuscript_full.md
echo "# Introduction" >> manuscript_full.md
echo "" >> manuscript_full.md
cat introduction.md >> manuscript_full.md
echo -e "\n\n---\n" >> manuscript_full.md
echo "# Results" >> manuscript_full.md
echo "" >> manuscript_full.md
cat results.md >> manuscript_full.md
echo -e "\n\n---\n" >> manuscript_full.md
echo "# Discussion" >> manuscript_full.md
echo "" >> manuscript_full.md
cat discussion.md >> manuscript_full.md
echo -e "\n\n---\n" >> manuscript_full.md
echo "# Methods" >> manuscript_full.md
echo "" >> manuscript_full.md
cat methods.md >> manuscript_full.md
echo -e "\n\n---\n" >> manuscript_full.md
if [ -f "availability.md" ]; then
echo "# Data and Code Availability" >> manuscript_full.md
echo "" >> manuscript_full.md
cat availability.md >> manuscript_full.md
echo -e "\n\n---\n" >> manuscript_full.md
fi
# Add references section placeholder
echo "# References" >> manuscript_full.md
echo "" >> manuscript_full.md
echo "[References will be generated from literature_citations.bib]" >> manuscript_full.md
echo "✓ Manuscript assembled: manuscript_full.md"
Phase 3: Metadata Generation
- Calculate Statistics:
import re
from pathlib import Path
from datetime import datetime
import json
target_dir = Path("{target_dir}")
manuscript_file = target_dir / "manuscript_full.md"
# Read manuscript
with open(manuscript_file) as f:
content = f.read()
# Count words (exclude markdown headers, code blocks)
text_only = re.sub(r'```.*?```', '', content, flags=re.DOTALL)
text_only = re.sub(r'^#.*$', '', text_only, flags=re.MULTILINE)
text_only = re.sub(r'\[.*?\]', '', text_only)
words = len(text_only.split())
# Count citations
citations = re.findall(r'\[([a-zA-Z0-9,\s]+)\]', content)
unique_citations = set()
for cite_group in citations:
for cite in cite_group.split(','):
cite = cite.strip()
if cite and cite[0].islower(): # Citation keys start with lowercase
unique_citations.add(cite)
# Count sections
sections = re.findall(r'^# (.+)$', content, flags=re.MULTILINE)
# Section word counts
section_words = {}
current_section = None
current_text = []
for line in content.split('\n'):
if line.startswith('# '):
if current_section:
section_text = ' '.join(current_text)
section_text = re.sub(r'\[.*?\]', '', section_text)
section_words[current_section] = len(section_text.split())
current_section = line[2:].strip()
current_text = []
else:
current_text.append(line)
if current_section:
section_text = ' '.join(current_text)
section_text = re.sub(r'\[.*?\]', '', section_text)
section_words[current_section] = len(section_text.split())
# Generate manifest
manifest = {
"version": "1.0",
"generated": datetime.now().isoformat(),
"manuscript_file": "manuscript_full.md",
"statistics": {
"total_words": words,
"total_sections": len(sections),
"unique_citations": len(unique_citations),
"section_breakdown": section_words
},
"sections_included": sections,
"validation": {
"all_required_sections": True,
"word_count_target": 3000, # Nature
"within_limit": words <= 3500
}
}
# Save manifest
manifest_file = target_dir / "manifest.json"
with open(manifest_file, 'w') as f:
json.dump(manifest, f, indent=2)
print(f"✓ Generated manifest: {manifest_file}")
print(f" Total words: {words}")
print(f" Citations: {len(unique_citations)}")
print(f" Sections: {len(sections)}")
Phase 4: Quality Checks
Check Citation Validity:
import re
from pathlib import Path
target_dir = Path("{target_dir}")
manuscript_file = target_dir / "manuscript_full.md"
bib_file = target_dir / "literature_citations.bib"
# Extract citations from manuscript
with open(manuscript_file) as f:
content = f.read()
cited_keys = set()
for cite_group in re.findall(r'\[([a-zA-Z0-9,\s]+)\]', content):
for cite in cite_group.split(','):
cite = cite.strip()
if cite and cite[0].islower():
cited_keys.add(cite)
# Extract citation keys from .bib file
if bib_file.exists():
with open(bib_file) as f:
bib_content = f.read()
bib_keys = set(re.findall(r'@\w+\{([^,]+),', bib_content))
# Check for missing citations
missing = cited_keys - bib_keys
if missing:
print(f"⚠ Warning: Citations not in .bib file: {missing}")
else:
print(f"✓ All {len(cited_keys)} citations found in .bib file")
else:
print("⚠ Warning: No literature_citations.bib file found")
Check Word Count Compliance:
import json
from pathlib import Path
target_dir = Path("{target_dir}")
manifest_file = target_dir / "manifest.json"
with open(manifest_file) as f:
manifest = json.load(f)
total_words = manifest["statistics"]["total_words"]
target = manifest["validation"]["word_count_target"]
if total_words > target * 1.2: # 20% over
print(f"⚠ Warning: Manuscript is {total_words - target} words over target ({total_words}/{target})")
print(f" Recommendation: Trim {total_words - target} words before submission")
elif total_words < target * 0.8: # 20% under
print(f"⚠ Warning: Manuscript is {target - total_words} words under target ({total_words}/{target})")
else:
print(f"✓ Word count within acceptable range: {total_words}/{target}")
Phase 5: State Update
- Update Workflow State:
import sys
from pathlib import Path
sys.path.insert(0, str(Path('scripts').resolve()))
from rrwrite_state_manager import StateManager
import json
target_dir = "{target_dir}"
manager = StateManager(output_dir=target_dir, enable_git=False)
# Load manifest for statistics
manifest_file = Path(target_dir) / "manifest.json"
with open(manifest_file) as f:
manifest = json.load(f)
# Update assembly stage
manager.update_workflow_stage(
"assembly",
status="completed",
file=f"{target_dir}/manuscript_full.md",
manifest_file=f"{target_dir}/manifest.json",
sections_included=manifest["statistics"]["total_sections"],
total_word_count=manifest["statistics"]["total_words"],
validation_warnings=0 # TODO: count actual warnings
)
print("✓ Workflow state updated")
Output Files
The assembly process generates:
{target_dir}/manuscript_full.md
- Complete manuscript with all sections
- Section headers and separators
- References placeholder
{target_dir}/manifest.json
- Assembly metadata
- Word counts per section
- Citation statistics
- Validation results
Validation Criteria
The manuscript is considered successfully assembled if:
✅ All required sections present and combined
✅ Word count statistics calculated
✅ Citations extracted and validated against .bib file
✅ Manifest generated with complete metadata
✅ Workflow state updated to mark assembly as completed
Display Summary
After successful assembly, display:
============================================================
MANUSCRIPT ASSEMBLY COMPLETE
============================================================
Output: {target_dir}/manuscript_full.md
Statistics:
• Total words: [X]
• Target: [Y] (Nature: 3000 words)
• Status: [Within limit / Over by X words]
• Citations: [N] unique citations
• Sections: [M] sections included
Section Breakdown:
• Abstract: [X] words
• Introduction: [X] words
• Results: [X] words
• Discussion: [X] words
• Methods: [X] words
• Availability: [X] words
Next Steps:
1. Review manuscript_full.md
2. Run critique:
/rrwrite-critique-manuscript --target-dir {target_dir} --file manuscript_full.md
3. Address critique feedback
4. Trim to target word count if needed
============================================================
Error Handling
Missing sections:
Error: Missing required sections: [list]
Please draft all sections before assembly:
/rrwrite-draft-section --target-dir {target_dir} --section [name]
No sections found:
Error: No manuscript sections found in {target_dir}
Expected files: abstract.md, introduction.md, results.md, discussion.md, methods.md
Invalid target directory:
Error: Target directory not found: {target_dir}
Please specify a valid manuscript directory
Notes
- Assembly does NOT modify individual section files
- Original sections remain unchanged in {target_dir}
- Manifest can be regenerated by re-running assembly
- Word counts exclude markdown formatting and citations
- Nature format uses Abstract → Intro → Results → Discussion → Methods order
- For other journals (PLOS, Bioinformatics), adjust section order as needed
Converted and distributed by TomeVault — claim your Tome and manage your conversions.
1---2name: rrwrite-assemble3description: Output directory containing manuscript sections Use when this capability is needed.4---5# Manuscript Assembly Protocol67## Purpose8Combine all drafted manuscript sections into a complete manuscript file with validation, metadata generation, and quality checks.910## Prerequisites11**Required files in {target_dir}:**12- `abstract.md`13- `introduction.md`14- `methods.md`15- `results.md`16- `discussion.md`17- `availability.md` (optional)1819**Recommended:**20- `literature_citations.bib` - For citation validation21- `outline.md` - For structure verification2223## Workflow2425### Phase 1: Pre-Assembly Validation26271. **Check Required Sections:**28 ```bash29 cd {target_dir}3031 required_sections=("abstract.md" "introduction.md" "results.md" "discussion.md" "methods.md")32 missing=()3334 for section in "${required_sections[@]}"; do35 if [ ! -f "$section" ]; then36 missing+=("$section")37 fi38 done3940 if [ ${#missing[@]} -gt 0 ]; then41 echo "Error: Missing required sections: ${missing[*]}"42 exit 143 fi44 ```45462. **Verify Section Completion:**47 Check workflow state to ensure all sections are marked as completed:48 ```python49 import json50 from pathlib import Path5152 state_file = Path("{target_dir}/.rrwrite/state.json")53 if state_file.exists():54 with open(state_file) as f:55 state = json.load(f)5657 sections = state.get("workflow_status", {}).get("drafting", {}).get("sections", {})58 incomplete = [s for s, data in sections.items() if data.get("status") != "completed"]5960 if incomplete:61 print(f"Warning: Incomplete sections: {incomplete}")62 ```6364### Phase 2: Section Assembly65661. **Combine Sections in Order:**6768 **For Nature format:** Abstract → Introduction → Results → Discussion → Methods → Availability6970 ```bash71 cd {target_dir}7273 # Clear or create output file74 > manuscript_full.md7576 # Add header77 cat >> manuscript_full.md << 'EOF'78 # MicroGrowAgents Manuscript7980 **Target Journal:** Nature81 **Date:** $(date +%Y-%m-%d)8283 ---8485 EOF8687 # Combine sections88 echo "# Abstract" >> manuscript_full.md89 echo "" >> manuscript_full.md90 cat abstract.md >> manuscript_full.md91 echo -e "\n\n---\n" >> manuscript_full.md9293 echo "# Introduction" >> manuscript_full.md94 echo "" >> manuscript_full.md95 cat introduction.md >> manuscript_full.md96 echo -e "\n\n---\n" >> manuscript_full.md9798 echo "# Results" >> manuscript_full.md99 echo "" >> manuscript_full.md100 cat results.md >> manuscript_full.md101 echo -e "\n\n---\n" >> manuscript_full.md102103 echo "# Discussion" >> manuscript_full.md104 echo "" >> manuscript_full.md105 cat discussion.md >> manuscript_full.md106 echo -e "\n\n---\n" >> manuscript_full.md107108 echo "# Methods" >> manuscript_full.md109 echo "" >> manuscript_full.md110 cat methods.md >> manuscript_full.md111 echo -e "\n\n---\n" >> manuscript_full.md112113 if [ -f "availability.md" ]; then114 echo "# Data and Code Availability" >> manuscript_full.md115 echo "" >> manuscript_full.md116 cat availability.md >> manuscript_full.md117 echo -e "\n\n---\n" >> manuscript_full.md118 fi119120 # Add references section placeholder121 echo "# References" >> manuscript_full.md122 echo "" >> manuscript_full.md123 echo "[References will be generated from literature_citations.bib]" >> manuscript_full.md124125 echo "✓ Manuscript assembled: manuscript_full.md"126 ```127128### Phase 3: Metadata Generation1291301. **Calculate Statistics:**131 ```python132 import re133 from pathlib import Path134 from datetime import datetime135 import json136137 target_dir = Path("{target_dir}")138 manuscript_file = target_dir / "manuscript_full.md"139140 # Read manuscript141 with open(manuscript_file) as f:142 content = f.read()143144 # Count words (exclude markdown headers, code blocks)145 text_only = re.sub(r'```.*?```', '', content, flags=re.DOTALL)146 text_only = re.sub(r'^#.*$', '', text_only, flags=re.MULTILINE)147 text_only = re.sub(r'\[.*?\]', '', text_only)148 words = len(text_only.split())149150 # Count citations151 citations = re.findall(r'\[([a-zA-Z0-9,\s]+)\]', content)152 unique_citations = set()153 for cite_group in citations:154 for cite in cite_group.split(','):155 cite = cite.strip()156 if cite and cite[0].islower(): # Citation keys start with lowercase157 unique_citations.add(cite)158159 # Count sections160 sections = re.findall(r'^# (.+)$', content, flags=re.MULTILINE)161162 # Section word counts163 section_words = {}164 current_section = None165 current_text = []166167 for line in content.split('\n'):168 if line.startswith('# '):169 if current_section:170 section_text = ' '.join(current_text)171 section_text = re.sub(r'\[.*?\]', '', section_text)172 section_words[current_section] = len(section_text.split())173 current_section = line[2:].strip()174 current_text = []175 else:176 current_text.append(line)177178 if current_section:179 section_text = ' '.join(current_text)180 section_text = re.sub(r'\[.*?\]', '', section_text)181 section_words[current_section] = len(section_text.split())182183 # Generate manifest184 manifest = {185 "version": "1.0",186 "generated": datetime.now().isoformat(),187 "manuscript_file": "manuscript_full.md",188 "statistics": {189 "total_words": words,190 "total_sections": len(sections),191 "unique_citations": len(unique_citations),192 "section_breakdown": section_words193 },194 "sections_included": sections,195 "validation": {196 "all_required_sections": True,197 "word_count_target": 3000, # Nature198 "within_limit": words <= 3500199 }200 }201202 # Save manifest203 manifest_file = target_dir / "manifest.json"204 with open(manifest_file, 'w') as f:205 json.dump(manifest, f, indent=2)206207 print(f"✓ Generated manifest: {manifest_file}")208 print(f" Total words: {words}")209 print(f" Citations: {len(unique_citations)}")210 print(f" Sections: {len(sections)}")211 ```212213### Phase 4: Quality Checks2142151. **Check Citation Validity:**216 ```python217 import re218 from pathlib import Path219220 target_dir = Path("{target_dir}")221 manuscript_file = target_dir / "manuscript_full.md"222 bib_file = target_dir / "literature_citations.bib"223224 # Extract citations from manuscript225 with open(manuscript_file) as f:226 content = f.read()227228 cited_keys = set()229 for cite_group in re.findall(r'\[([a-zA-Z0-9,\s]+)\]', content):230 for cite in cite_group.split(','):231 cite = cite.strip()232 if cite and cite[0].islower():233 cited_keys.add(cite)234235 # Extract citation keys from .bib file236 if bib_file.exists():237 with open(bib_file) as f:238 bib_content = f.read()239240 bib_keys = set(re.findall(r'@\w+\{([^,]+),', bib_content))241242 # Check for missing citations243 missing = cited_keys - bib_keys244 if missing:245 print(f"⚠ Warning: Citations not in .bib file: {missing}")246 else:247 print(f"✓ All {len(cited_keys)} citations found in .bib file")248 else:249 print("⚠ Warning: No literature_citations.bib file found")250 ```2512522. **Check Word Count Compliance:**253 ```python254 import json255 from pathlib import Path256257 target_dir = Path("{target_dir}")258 manifest_file = target_dir / "manifest.json"259260 with open(manifest_file) as f:261 manifest = json.load(f)262263 total_words = manifest["statistics"]["total_words"]264 target = manifest["validation"]["word_count_target"]265266 if total_words > target * 1.2: # 20% over267 print(f"⚠ Warning: Manuscript is {total_words - target} words over target ({total_words}/{target})")268 print(f" Recommendation: Trim {total_words - target} words before submission")269 elif total_words < target * 0.8: # 20% under270 print(f"⚠ Warning: Manuscript is {target - total_words} words under target ({total_words}/{target})")271 else:272 print(f"✓ Word count within acceptable range: {total_words}/{target}")273 ```274275### Phase 5: State Update2762771. **Update Workflow State:**278 ```python279 import sys280 from pathlib import Path281 sys.path.insert(0, str(Path('scripts').resolve()))282 from rrwrite_state_manager import StateManager283 import json284285 target_dir = "{target_dir}"286 manager = StateManager(output_dir=target_dir, enable_git=False)287288 # Load manifest for statistics289 manifest_file = Path(target_dir) / "manifest.json"290 with open(manifest_file) as f:291 manifest = json.load(f)292293 # Update assembly stage294 manager.update_workflow_stage(295 "assembly",296 status="completed",297 file=f"{target_dir}/manuscript_full.md",298 manifest_file=f"{target_dir}/manifest.json",299 sections_included=manifest["statistics"]["total_sections"],300 total_word_count=manifest["statistics"]["total_words"],301 validation_warnings=0 # TODO: count actual warnings302 )303304 print("✓ Workflow state updated")305 ```306307## Output Files308309The assembly process generates:3103111. **`{target_dir}/manuscript_full.md`**312 - Complete manuscript with all sections313 - Section headers and separators314 - References placeholder3153162. **`{target_dir}/manifest.json`**317 - Assembly metadata318 - Word counts per section319 - Citation statistics320 - Validation results321322## Validation Criteria323324The manuscript is considered successfully assembled if:325326✅ All required sections present and combined327✅ Word count statistics calculated328✅ Citations extracted and validated against .bib file329✅ Manifest generated with complete metadata330✅ Workflow state updated to mark assembly as completed331332## Display Summary333334After successful assembly, display:335336```337============================================================338MANUSCRIPT ASSEMBLY COMPLETE339============================================================340341Output: {target_dir}/manuscript_full.md342343Statistics:344 • Total words: [X]345 • Target: [Y] (Nature: 3000 words)346 • Status: [Within limit / Over by X words]347 • Citations: [N] unique citations348 • Sections: [M] sections included349350Section Breakdown:351 • Abstract: [X] words352 • Introduction: [X] words353 • Results: [X] words354 • Discussion: [X] words355 • Methods: [X] words356 • Availability: [X] words357358Next Steps:359 1. Review manuscript_full.md360 2. Run critique:361 /rrwrite-critique-manuscript --target-dir {target_dir} --file manuscript_full.md362 3. Address critique feedback363 4. Trim to target word count if needed364365============================================================366```367368## Error Handling369370**Missing sections:**371```372Error: Missing required sections: [list]373Please draft all sections before assembly:374 /rrwrite-draft-section --target-dir {target_dir} --section [name]375```376377**No sections found:**378```379Error: No manuscript sections found in {target_dir}380Expected files: abstract.md, introduction.md, results.md, discussion.md, methods.md381```382383**Invalid target directory:**384```385Error: Target directory not found: {target_dir}386Please specify a valid manuscript directory387```388389## Notes390391- Assembly does NOT modify individual section files392- Original sections remain unchanged in {target_dir}393- Manifest can be regenerated by re-running assembly394- Word counts exclude markdown formatting and citations395- Nature format uses Abstract → Intro → Results → Discussion → Methods order396- For other journals (PLOS, Bioinformatics), adjust section order as needed397398---399> Converted and distributed by [TomeVault](https://tomevault.io/claim/realmarcin) — claim your Tome and manage your conversions.400<!-- tomevault:4.0:skill_md:2026-04-13 -->