Implement quarto-reports phase 1 (report_init + report_build)¶
Goal¶
(promoted from note)
Context¶
(see source note)
Prompt¶
Fix the issue described below (source: /storage2/arash/projects/projio/docs/log/issue/issue-arash-20260420-025311-537046.md). Understand the problem, then implement the proposed fix.
Implement quarto-reports phase 1: report_init + report_build MCP tools.
Spec: docs/specs/quarto-reports.md (drafted 2026-04-18/19, all open questions resolved in §12).
Phase 1 scope:
1. New module src/projio/mcp/report.py exposing:
- report_init(name, template) — scaffold docs/deliverables/reports/quarto render report.qmd --to <format> inside project compute env, return build path + log.
2. Register both tools in src/projio/mcp/server.py alongside present_ tools.
3. Preflight validation per §5c: parse .qmd for {{< embed >}} shortcodes and image refs, verify notebook files exist + are executed + cell labels resolve, verify bibliography path resolves. Report actionable errors.
4. Add .projio/render/quarto.yml scaffold via projio sync (min_version field, CSL/bib inheritance from render.yml).
5. projio sync adds _freeze/ and _files/ under docs/deliverables/reports// to the managed gitignore block per §12c.
6. Runtime quarto --version check in report_build; error with install URL if below min_version per §12a.
Out of scope for phase 1: cross-project notebook imports (§12b deferred to phase 2), report_list / report_status / report_validate (sketch only in §6), report_refresh_import / report_freeze_import.
Related: spec's rejected options (in-report regeneration, dedicated report notebooks) are recorded in §5 and §10 — do not implement these even if they seem tempting during coding.
Testing: add a pixecog-style fixture in tests/ with a minimal executed .ipynb and a report that embeds one cell. Verify report_build produces valid HTML and that preflight catches missing labels.
Dependency: independent of the questio.py scanner fix issue (issue-arash-20260419-212250-953561). Can run in parallel.
Related Notes¶
- issue-arash-20260419-212250-953561.md — report_init fills frontmatter from questio_status; _scan_deliverables shares the deliverables/ boundary this feature writes to
- issue-arash-20260414-030010-945964.md — report_build uses the same pixi/conda runner resolution pattern as pipeio_run — env resolution bugs there are directly applicable
- issue-arash-20260411-173902-670919.md — report_build inherits CSL/bib from render.yml; cross-project biblio sharing affects what bibliography paths resolve in quarto renders
- issue-arash-20260410-000346-439918.md — reports embed notebooks via {{< embed >}} shortcodes — notebook move/path issues directly break report preflight validation
- issue-arash-20260411-173854-577193.md — report_init scaffolds docs/deliverables/reports/
/ — overlaps with study profile layout decisions in projio_init
Acceptance Criteria¶
- [ ]
Result¶
Completed in 576.4s (1 steps, model: opus)
Session: 97cf4949-c480-4348-8ad1-237f3dc2b8d5
Result note: /storage2/arash/worklog/workflow/captures/20260420-030709-d36b0f/note.md
Output¶
Phase 1 of quarto-reports is complete. Summary of changes:
**New module** `src/projio/mcp/report.py`:
- `report_init(name, template)` — scaffolds `docs/deliverables/reports/<name>/report.qmd` with frontmatter preamble (title/date/bibliography/CSL/questions/results/source_flows) seeded from `questio_status`, `docs/log/result/result-*.md`, and `.projio/pipeio/registry.yml`. Templates: `progress`, `update`, `milestone`.
- `report_build(name, format="html")` — locates report, splits frontmatter, runs §5c preflight (embed shortcodes verified against executed `.ipynb` + `#| label:` resolution; image refs checked; bibliography verified), resolves `quarto` via §8 chain (`code.envs.report` → `code.envs.default` → PATH), runs `quarto --version` with in-process cache against `min_version` from `.projio/render/quarto.yml`, then `quarto render`. Returns build path + log.
**Server registration** `src/projio/mcp/server.py`: added `report_init` + `report_build` tools alongside the present_* block.
**projio sync** `src/projio/sync.py`: new `_sync_quarto_config()` creates `.projio/render/quarto.yml` with `min_version: "1.5"` when missing; wired into `sync_workspace` after `_sync_render_config`.
**projio init** `src/projio/init.py`: added `docs/deliverables/reports/*/_freeze/` and `docs/deliverables/reports/*/_files/` to the managed gitignore block.
**Tests**: `tests/test_mcp_report.py` (27 tests covering version parsing, frontmatter splitting, notebook embed validation, preflight happy path + each failure mode, runner resolution for pixi/conda/PATH/missing, `report_init` scaffolding + overwrite guard + result-note preamble, and `report_build` integration with quarto mocked); `tests/test_sync.py` + `tests/test_init.py` extended. Full suite: 514 passing.
## Next Steps
1. Implement phase 2 of quarto-reports: `report_list`, `report_status` (staleness vs. embedded notebook mtimes), and `report_validate` (dry-run preflight without `quarto render`).
2. Write the `report-build` skill a