Development¶
This page orients contributors working in the sase repository. It covers local setup, verification, source layout, and
documentation publishing paths.
Setup¶
Requirements:
uv venv .venv
source .venv/bin/activate
just install
sase --help
just install installs the package in editable mode with development dependencies. When a sibling ../sase-core
checkout is present and cargo is available, it also builds and installs the local sase_core_rs extension before
resolving Python dependencies.
Verification Commands¶
just install # Install with dev deps
just fmt # Auto-format code and Markdown
just lint # Run ruff, mypy, pyvision, keep-sorted, and SDD validation
just test # Fast parallel test run, including PNG visual snapshots
just test-slow # Slow pytest subset only
just test-visual # ACE PNG visual regression snapshots only
just test-terminal-smoke # Optional real-terminal ACE smoke test
just test-cov # Parallel test run with coverage + 50% gate, including visual snapshots
just check # CI-style checks: formatting, lint, SDD validation, tests
just test-tox # Test across Python 3.12, 3.13, 3.14
just clean # Remove build artifacts
just build # Build wheel and sdist
just test, just test-slow, just test-visual, and just test-cov size the pytest-xdist worker pool from local CPU
count, capped at 16. Set SASE_PYTEST_WORKERS=<N> to override that value. Test selectors are normalized from the
directory where just was invoked, so this works the same from the repository root or a subdirectory:
just test tests/main/test_parser.py::test_example
just lint and just fix-keep-sorted bootstrap a project-local keep-sorted executable into .venv/bin/ from PATH,
or by running go install github.com/google/keep-sorted@v0.8.0 when Go is available. If neither keep-sorted nor Go is
installed, those recipes fail with a setup error before linting YAML keep-sorted blocks.
Default test runs exclude slow and terminal_smoke markers but include the ACE PNG snapshot regression tests. Use
just test-visual for focused visual-snapshot work; both recipes install the optional PNG rasterizer dependencies when
they are missing. Direct pytest runs still inherit the repository pyproject.toml default marker expression, which
excludes slow, terminal_smoke, and visual unless you pass your own -m selector.
Use just test-terminal-smoke only when you need to verify the ACE startup path through a real PTY. It installs
pexpect and pyte, runs the optional terminal_smoke marker, and stays out of default tests and CI until that path
has proved stable.
Visual Snapshot Workflow¶
ACE visual tests live under tests/ace/tui/visual/ and compare deterministic Textual screenshots against committed PNG
goldens. Run them normally first:
just test-visual
When a visual test fails, inspect the artifacts under .pytest_cache/sase-visual/<node>/<snapshot>/. Each failure
directory contains the actual PNG capture and, when a golden exists, the expected PNG plus a diff PNG, a human-readable
summary.txt, and a structured failure.json sidecar. The sidecar carries the test source location, repo-relative
golden path, and pixel-diff stats so tooling can map a failure back to the test and the committed golden. Accept
intentional visual changes only by rerunning the relevant test with the explicit update flag:
just test-visual -- --sase-update-visual-snapshots tests/ace/tui/visual/test_ace_png_snapshots.py
Review changed PNG files as normal test data. Do not pass --sase-update-visual-snapshots to just check, just fmt,
or broad CI-style commands.
PNG comparison tolerance is environment-gated. Dedicated local visual runs require exact pixel equality against the
committed golden; any drift there is a real regression that needs investigation, not relaxation. Broad commands that
include visual tests, such as just test and just test-cov, set SASE_VISUAL_PNG_MAX_DIFF_RATIO=0.001 so tiny
font/rasterizer jitter does not break the full local suite. Runs in GitHub Actions allow a small ratio-only
renderer-drift tolerance for the same reason. Treat a just test-visual failure as a true regression even if the same
test passes in CI, and accept new goldens only with --sase-update-visual-snapshots after inspecting the diff PNG
locally.
Visual Failure Report¶
tools/render_visual_snapshot_failure_report consumes the failure.json sidecars and writes
.pytest_cache/sase-visual-report/:
visual-failure-report.html- self-contained HTML with PNG/SVG embedded as data URIs, one anchored section per failure.summary.md- compact table for$GITHUB_STEP_SUMMARYwith links into the report and to the committed golden.annotations.sh- escaped::error file=...,line=...workflow commands.manifest.jsonl- aggregate of every loadedfailure.jsonfor ad-hoc inspection.
Run it locally against a failed run with
tools/render_visual_snapshot_failure_report --repo <owner/repo> --sha <commit> and open the HTML file directly. The
script is safe to run when there are no failures; it exits 0 without writing artifacts.
In GitHub Actions the visual-test job invokes the renderer twice on failure: once to build the report before upload,
then again after upload with --report-url "$VISUAL_REPORT_URL" so the summary and annotations point at the freshly
uploaded artifact. The HTML is uploaded via actions/upload-artifact@v7 with archive: false, which is what makes the
per-failure anchors browsable directly from the Actions UI. Expected links point at the immutable
https://github.com/<repo>/blob/<sha>/<expected_repo_path> URL; actual/diff links point at the report artifact rather
than a public PNG URL because the raw PNGs are only uploaded as a zipped ace-visual-artifacts bundle and have no
stable per-file URL.
Add a visual test when the risk is layout, styling, focus highlighting, modal composition, or a regression that is hard to express as state. Prefer a plain state/widget test when the behavior can be asserted through model state, rendered text, selection identity, key handling, or a small widget contract.
Required Rust Core¶
Ported sase.core operations are served by the required Rust extension sase_core_rs, distributed as the
sase-core-rs package and built from the sibling ../sase-core repo during source development. Normal installs pull a
prebuilt wheel; local source installs can build the extension with just install or just rust-install.
There is no pure-Python fallback for ported operations. Use the health check after install changes:
sase core health
See the Rust backend reference for the Python/Rust boundary, shipped Rust-backed operations, source build path, and benchmark expectations.
Source Map¶
The repository is organized around the CLI entry point, operational subsystems, provider boundaries, and docs/tests:
| Path | Purpose |
|---|---|
src/sase/main/ |
CLI parser registration and subcommand handlers. |
src/sase/ace/ |
ACE TUI, ChangeSpec rendering, query integration, actions, widgets, and TUI state. |
src/sase/agent/ |
Agent launch, detached spawn, prompt fan-out, running-agent metadata, artifact lookup, and naming. |
src/sase/axe/ |
Axe orchestrator, lumberjacks, chop execution, scheduled jobs, maintenance mode, and automation state. |
src/sase/xprompt/ |
XPrompt expansion, directives, workflow loading, execution, tracing, explaining, and graphing. |
src/sase/xprompts/ |
Bundled xprompt templates, workflows, and schemas shipped with the package. |
src/sase/workflows/ |
Change lifecycle workflows for commit, mentor, CRS, accept, and rewind operations. |
src/sase/memory/ |
Memory inventory, audited read logs, and proposal write/review flows. |
src/sase/core/ |
Python facade and stable wire records for operations served by sase_core_rs. |
src/sase/bead/ |
Python host layer for bead storage discovery, CLI integration, and epic/legend launch flow. |
src/sase/sdd/ |
Spec-driven development file and bead integration helpers. |
src/sase/llm_provider/ |
Built-in LLM providers and provider registry. |
src/sase/vcs_provider/ |
VCS provider hook specs, plugin registry, and built-in git provider. |
src/sase/workspace_provider/ |
Workspace provider hook specs, plugin registry, #cd, and bare-git workspace support. |
src/sase/running_field/ |
Workspace claim and slot-management helpers. |
src/sase/notifications/ |
Notification delivery and storage integration. |
src/sase/telemetry/ |
Prometheus metrics, health, dashboard, and monitoring export support. |
src/sase/version/ |
Runtime inventory collection and rendering for the sase version CLI command. |
src/sase/integrations/ |
Public helper APIs consumed by external plugins and editors. |
src/sase/scripts/ |
Packaged utility scripts used by axe chops and support commands. |
tests/ |
Python test suite, with subdirectories mirroring major src/sase/ areas. |
docs/ |
MkDocs Material site source. |
sdd/ |
Project-local prompt, tale, epic, legend, research, and bead artifacts. |
xprompts/ |
Repository-local xprompts and workflows for SASE maintenance agents. |
tools/ |
Development scripts used by just targets and CI checks. |
memory/ |
SASE memory files used by repository agents. |
Detailed subsystem pages often include narrower source-layout tables. Use this page for initial orientation, then jump to the specific reference for the area you are changing.
Repository XPrompts¶
The checkout's top-level xprompts/ directory is project-local to the sase repository. When SASE resolves prompts
from this project checkout, those entries are namespaced as sase/<name> so they do not collide with user or packaged
prompts. Use the catalog's insertion value to know whether an entry should be invoked with # or #!.
Useful visible entries include:
| Reference | Purpose |
|---|---|
#!sase/reads |
Fan out a reading-recommendation request across Antigravity, Claude, and Codex, then consolidate the final list. |
#sase/sync |
Sync the primary SASE workspace and restart axe. |
#!sase/reads accepts a required topic and an optional reference_query. By default, the workflow passes this
Dataview query to the research agents:
LIST WITHOUT ID title + " (" + url + ")"
FROM "ref"
WHERE
source_path AND url AND (
parent = [[ai_ref]]
OR parent.parent = [[ai_ref]]
OR parent.parent.parent = [[ai_ref]]
OR parent.parent.parent.parent = [[ai_ref]]
OR parent.parent.parent.parent.parent = [[ai_ref]]
)
SORT title
Each research agent is expected to use /bob_dataview to run that query against Bryan's Bob vault, treat every returned
title and URL entry as already-known, and only then search for new reading candidates. A normal invocation can rely on
the default query:
#!sase/reads(agent memory systems)
Some repository workflows are marked hidden: true because they are automation helpers, such as docs refresh, recent
bug/improvement audits, and Python line-limit splitting. That flag hides workflow run rows in ACE; it does not mean the
workflow is unavailable. Use sase xprompt list or the ACE xprompt browser from a source checkout when you need the
exact current catalog.
Documentation Workflow¶
The docs site is a MkDocs Material project:
| Path | Purpose |
|---|---|
mkdocs.yml |
Main docs site configuration, strict build, navigation, blog, RSS, and theme settings. |
mkdocs-pdf.yml |
PDF handbook build configuration, inheriting the main site config. |
docs/ |
Markdown, images, stylesheets, JavaScript, redirects, headers, and PDF templates. |
site/ |
Generated site output. It is rebuilt by docs commands and deployed as the static asset directory. |
Run the strict site build after changing docs navigation, links, images, or Markdown pages:
just docs-check
Run SASE validation when a change can affect generated initialization files or SDD frontmatter links. This is the same
validation lane used by just lint, so it can report user/home initialization drift as well as repository-local issues:
sase validate
Run the handbook build and validation when a change materially affects the public handbook, PDF styling, navigation, or generated-site assets:
just docs-pdf-check
just docs-check installs only MkDocs tooling, then runs mkdocs build --strict. just docs-pdf-check installs the
PDF tooling, installs Chromium for Playwright, builds mkdocs-pdf.yml in an isolated temporary site directory,
post-processes and validates the handbook there, and copies only downloads/sase-handbook.pdf back into site/.
Docs Deployment¶
Production docs are deployed by .github/workflows/docs-deploy.yml, not by a Cloudflare dashboard build command. The
workflow:
- Checks out the repo and installs
uv,just, and Python 3.12. - Runs
just docs-check. - Runs
just docs-pdf-check. - Verifies
site/index.html,site/_headers, the blog and series pages, andsite/downloads/sase-handbook.pdf. - Deploys the prebuilt
site/directory throughwrangler.jsonc. - Smoke-tests the deployed handbook PDF from the deployment URL and
https://sase.sh/.
The GitHub repository must provide a CLOUDFLARE_API_TOKEN Actions secret with permission to deploy the sase
Cloudflare Worker. Keep dashboard-managed Git builds disabled or unused for production so they cannot race the checked
in workflow's prebuilt artifact deploy.