scitex_todo — Python API

scitex-todo: a canonical YAML task store with pluggable adapters.

The task store (YAML, top-level tasks: list) is the single source of truth. Adapters render or import it; the mermaid adapter (YAML -> dependency PNG) ships today. See the project roadmap for org and Web-UI adapters.

Quick Start

>>> import scitex_todo as todo
>>> tasks = todo.load_tasks("tasks.yaml")
>>> src = todo.build_mermaid(tasks)
>>> todo.render(src, "tasks.png")
'mmdc'
exception scitex_todo.TaskValidationError[source]

Bases: ValueError

Raised when a task store fails structural validation.

exception scitex_todo.RenderError[source]

Bases: RuntimeError

Raised when every render path (mmdc, kroki) fails.

scitex_todo.build_mermaid(tasks)[source]

Render the task list as a mermaid flowchart TB source string.

Parameters:

tasks (list[dict]) – Validated tasks, typically from scitex_todo.load_tasks().

Returns:

Mermaid flowchart TB source, newline-terminated. Includes node labels, depends_on and blocks edges, and per-status classDef styling.

Return type:

str

Notes

Edges referencing an unknown task id are skipped with a warning on stderr rather than raising — a partial graph is more useful than none.

Examples

>>> src = build_mermaid([{"id": "a", "title": "A", "status": "done"}])
>>> src.startswith("flowchart TB")
True
scitex_todo.bundled_example()[source]

Path to the generic example task store shipped inside the wheel.

Return type:

Path

scitex_todo.find_chromium()[source]

Locate a puppeteer- or playwright-cached chromium for headless render.

Resolution order: $PUPPETEER_EXECUTABLE_PATH, then the puppeteer cache, then the playwright cache. Snap chromium is excluded.

Returns:

Path to a chromium executable, or None if none is found.

Return type:

str | None

scitex_todo.load_tasks(path)[source]

Load and validate the task list from a YAML store.

Parameters:

path (str | Path) – Path to the YAML task store. The document must have a top-level tasks: list.

Returns:

The validated task mappings, in document order.

Return type:

list[dict]

Raises:
  • FileNotFoundError – If path does not exist.

  • TaskValidationError – If the store is structurally invalid: tasks is not a list, a task is missing id or title, an id is duplicated, a status is not in VALID_STATUSES, or a priority is present but not an integer.

Examples

>>> tasks = load_tasks("tasks.yaml")
>>> tasks[0]["id"]
'design'
scitex_todo.save_tasks(tasks, path)[source]

Validate then write a task list back to a YAML store, preserving comments.

Re-runs the same validation gate as load_tasks() before touching disk, so a malformed mutation can never corrupt the store. Uses ruamel.yaml round-trip mode so hand-written comments and key layout in the existing store survive the rewrite.

Parameters:
  • tasks (list[dict]) – The (already-mutated) task mappings to persist. Validated first.

  • path (str | Path) – Destination store. If it already exists, its comments + structure are preserved and only the tasks: payload is updated; otherwise a fresh document is written.

Raises:

TaskValidationError – If tasks fails structural validation (nothing is written).

Return type:

None

Examples

>>> tasks = load_tasks("tasks.yaml")
>>> tasks[0]["priority"] = 1
>>> save_tasks(tasks, "tasks.yaml")
scitex_todo.render(mermaid_src, out_png)[source]

Render mermaid source to PNG, mmdc-first with kroki fallback.

Parameters:
Returns:

The engine that produced the output: "mmdc" or "kroki".

Return type:

str

Raises:

RenderError – If both the mmdc and kroki render paths fail.

scitex_todo.render_with_kroki(mermaid_src, out_png)[source]

Fallback: render via kroki.io.

Returns:

True on success, False on any network/HTTP failure.

Return type:

bool

scitex_todo.render_with_mmdc(mermaid_src, out_png)[source]

Render via mermaid-cli.

Returns:

True on success, False to allow the caller to fall back.

Return type:

bool

scitex_todo.resolve_tasks_path(explicit=None)[source]

Resolve which task store to use, following the precedence chain.

Parameters:

explicit (str | Path | None) – An explicit path (e.g. a CLI --tasks flag). When given and it exists, it wins outright.

Returns:

The first existing task store in precedence order. Falls back to the bundled generic example if no personal store is found.

Return type:

Path

Examples

>>> p = resolve_tasks_path()
>>> p.name
'tasks.yaml'