Skip to content

## Implement manuscript subpackage in notio: schema, assembly, render, figures,

Implement manuscript subpackage in notio: schema, assembly, render, figures, validate

Implement the manuscript subpackage at packages/notio/src/notio/manuscript/.

Prerequisites

  • Read the design spec at docs/explanation/manuscript-design-spec.md (written by prior task) — it has the full architecture.
  • Read existing notio code: packages/notio/src/notio/core.py, query.py, config.py, mcp/server.py.
  • Read figio schema: packages/figio/src/figio/schema.py (for FigureSpec/caption structure).
  • Read pixecog's manuscript audit: worklog_read_file(project_id="pixecog", path="docs/how-to/doc/manuscript-system-audit.md").

Deliverables

1. manuscript/__init__.py

Public API exports: init_manuscript, list_manuscripts, manuscript_status, assemble, render, validate_manuscript, ManuscriptSpec

2. manuscript/schema.py

Pydantic models: - SectionRef(order: int, path: str, title: str) - FigureBinding(figure_id: str, spec_path: str, caption_override: str | None) - RenderConfig(pdf_engine: str = "xelatex", csl: str = "", bibliography: str = "", extra_args: list[str] = []) - ManuscriptSpec(name: str, title: str, authors: list[str], sections: list[SectionRef], figures: list[FigureBinding], render: RenderConfig, output_dir: str = "_build") - from_yaml(path) / to_yaml(path) class methods

3. manuscript/assembly.py

  • assemble(root: Path, spec: ManuscriptSpec) -> str
  • Read each section file in order
  • Prepend YAML metadata block (title, author, date)
  • Insert \newpage between sections (configurable)
  • Resolve figure references: {fig:figure_id}![caption](path){#fig:id}
  • Write assembled output to <output_dir>/md/<name>-assembled.md
  • Return the assembled text

4. manuscript/render.py

  • render(root: Path, spec: ManuscriptSpec, format: str = "pdf") -> RenderResult
  • Run assembly first if assembled file doesn't exist or is stale
  • Build pandoc command: pandoc <assembled.md> --citeproc --bibliography=<bib> --csl=<csl> --pdf-engine=<engine> -o <output>
  • Format support: pdf, latex, md (gfm, no citeproc), html
  • subprocess.run with capture of stderr for warnings
  • Return RenderResult(success: bool, output_path: Path, warnings: list[str], stderr: str)

5. manuscript/figures.py

  • extract_caption(spec_path: Path) -> str | None — read figio FigureSpec YAML, find caption annotation, return text
  • resolve_figure_paths(root: Path, bindings: list[FigureBinding]) -> dict[str, Path] — map figure_id to built SVG/PDF path
  • insert_figure_markdown(figure_id: str, caption: str, path: Path) -> str — return ![caption](path){#fig:id} markdown

6. manuscript/validate.py

  • validate_manuscript(root: Path, spec: ManuscriptSpec) -> ValidationResult
  • Check all section files exist
  • Check order field has no gaps/duplicates
  • Scan sections for [@citekey] patterns, verify each exists in bibliography .bib file
  • Check figure bindings have corresponding figio spec files
  • Check pandoc is in PATH
  • Return ValidationResult(valid: bool, errors: list[str], warnings: list[str])

7. Extend notio/core.py

  • Add a section note type to DEFAULT_CONFIG with template including order and manuscript fields
  • Section template:
    ---
    title: ${title}
    order: ${order}
    series: manuscript-${manuscript}
    manuscript: ${manuscript}
    date: ${date}
    ---
    

8. Extend notio/config.py

  • Add [manuscript] section support in notio.toml parsing
  • Fields: default_csl, default_engine, bib_path, output_dir

9. manuscript/init.py (or in init)

  • init_manuscript(root: Path, name: str, template: str = "generic") -> ManuscriptSpec
  • Create docs/manuscript/<name>/ directory
  • Create manuscript.yml with defaults
  • Create starter sections: 00-cover.md, 01-abstract.md, 02-introduction.md, 03-methods.md, 04-results.md, 05-discussion.md, 06-conclusions.md
  • Each section created as a notio note with appropriate frontmatter

10. Tests

  • tests/test_manuscript_schema.py — ManuscriptSpec YAML round-trip
  • tests/test_manuscript_assembly.py — section ordering and concatenation (use tmp_path, no pandoc needed)
  • tests/test_manuscript_validate.py — validation logic with fixture sections

Notes

  • Keep pandoc as an optional system dependency — render functions should check for it and raise clear errors.
  • Don't modify notio's existing tests — add new test files.
  • Use pathlib throughout, not os.path.
  • Section files live at docs/manuscript/<name>/sections/NN-slug.md (not in docs/log/ like regular notes).
  • The section note type in notio.toml uses a custom note_dir pointing to manuscript directories, not the default docs/log/section/ path.
  • [[task-arash-20260331-175617-644481.md]] — Design spec task for manuscript as a notio subpackage — direct prerequisite
  • [[task-arash-20260331-175313-566067.md]] — manuscripto architecture and API surface design — closely related design work
  • [[task-arash-20260331-175439-058148.md]] — Parallel implementation task for manuscripto core: assembly, render, notio section type
  • [[task-arash-20260331-175356-958039.md]] — Scaffolding manuscripto package — prerequisite infrastructure
  • [[task-arash-20260331-175508-399347.md]] — Registering manuscripto in projio MCP/submodule — downstream integration step

Batch Result

  • status: done
  • batch queue_id: 3e973e87bee2
  • session: f9189029-1adf-43a6-aa5f-93edf57dfe17
  • batch duration: 494.6s