Skip to content

Development and Tooling

The development environment for ppt-craft relies on a standardized toolchain managed through pyproject.toml and hatchling, with strict quality gates enforced via vendored scripts and Git hooks. Configuration is centralized in the project root, while development utilities handle everything from local TLS certificate provisioning to prose hygiene and file-size ceilings. This section details the setup required to run the server, lint the codebase, and validate changes before they are committed.

The project uses hatchling as the build backend, requiring Python 3.14 or higher 1. Dependencies are pinned to specific versions to ensure reproducibility, including fastapi, uvicorn, and python-pptx. Development dependencies such as ruff, mypy, and pytest are installed via the dev optional dependency group.

Ruff is configured to target Python 3.14 with a line length of 120 characters. It enforces a specific set of linting rules (E, F, W, I, UP, B) while ignoring specific codes like E501 (line too long) and F841 (unused variable). The isort tool is configured to recognize ppt_craft as a known first-party package.

Pytest is configured to look for tests in the tests directory and includes src in the Python path. The project exposes a CLI entry point ppt-craft mapped to ppt_craft.cli:cli.

Quality is enforced through two primary vendored scripts and a Git pre-push hook.

The script tools/check_file_ceiling.py enforces a maximum of 1,000 lines for hand-authored code files 2. It scans tracked files for languages including Python, Go, JavaScript, TypeScript, Astro, Shell, CSS, and HTML. Binary files, generated lockfiles, and common cache directories (e.g., __pycache__, .venv) are excluded from this check. The script exits with a non-zero status if any file exceeds the limit, printing the offenders sorted by line count.

The script operates in two modes:

  1. Gate (Default): Reports offenders and exits non-zero if any are found 3.
  2. Fix (--fix): Automatically replaces dashes with hyphens and removes decorative emoji. AI-speak phrases are reported for manual rewording but are not auto-fixed.

Files can opt out of these checks by including the marker prose-hygiene: allow.

The .githooks/pre-push script runs automatically if core.hooksPath is set to .githooks 4. It executes two checks:

  1. Runs tools/check_file_ceiling.py to enforce the 1,000-line limit.
  2. Runs the pytest suite (python3 -m pytest -q) to ensure parity with local tests.

Bypassing these checks requires git push --no-verify.

diagram

Local development requires HTTPS for the Office.js taskpane. The module src/ppt_craft/tls.py manages this using mkcert 5.

  1. Cert Issuance: The system issues a SAN certificate covering localhost, 127.0.0.1, gb10.local, and the machine’s hostname (and .local alias).
  2. Storage: Certificates are stored in ~/.local/share/ppt-craft/tls/ with permissions 0o700 for the directory and 0o600 for the key.

The mkcert binary is located via shutil.which or by checking common paths like mise shims, Homebrew, or /usr/local/bin. If mkcert is not found, a SddcError is raised with installation instructions.

diagram

scripts/smoke_live.py provides an end-to-end smoke test for the agent loop 6. It boots the ppt-craft server in a background thread, connects via WebSocket, and sends a draft request.

The script:

  • Accepts arguments for --host, --port, --intent, --slides, and --theme.
  • Waits for the server to start (up to 5 seconds).
  • Listens for WebSocket events (log, model_resolved, storyline_ready, slide_ready, preview_ready, deck_ready, error).
  • Times out after a configurable --deadline (default 300 seconds).

.gitignore excludes Python caches (__pycache__, .venv), build artifacts (dist, build), and generated theme assets (*.pptx, *.theme.json) 7. It also ignores HTTPS certificates in certs/ and generated wiki build outputs (wiki-site/node_modules, wiki-site/dist).