Contributing
Contributions are welcome. Open an issue before a non-trivial change, keep the change focused, and run the checks below before you push.
Before you start
The repository is spec-driven: features of any size get a file in docs/spec/ first, and that file records the decisions behind the design. If you are changing behavior rather than fixing a bug, expect to write or update a spec.
Workflow
# 1. Fork, then branch from main
git checkout -b your-feature
# 2. Make the change, running the relevant checks as you go
ccheck
cargo test -p storage
# 3. Keep commits focused and rebased on main before you open the PR
git fetch origin && git rebase origin/mainChecks to run
| Command | What it verifies |
|---|---|
cargo check -p taskstream-desktop | The desktop app compiles. |
cargo test -p storage | Persistence and migration tests pass. |
ccheck | cargo check across the main workspace crates. |
tt | Run the Rust test suite (macOS adds signing/quarantine fixups). |
testdbg | Storage tests with debug logging when a failure needs more detail. |
pnpm typecheck | Typecheck all three JavaScript packages. |
pnpm test | Vitest: token integrity, WCAG contrast math, component rendering. |
pnpm test:e2e | Playwright: every showcase route loads, theming persists, axe finds no serious WCAG 2.1 AA violations. |
pnpm build:docs | This site still builds. |
The full test matrix, including the end-to-end suite, is described inlibs/web-design-system/DESIGN.md for the web packages. Playwright uses the locally installed Chrome, so no browser download is required.
Rust conventions
AGENTS.md at the repository root is the authoritative list. The short version:
- Correctness and clarity first; speed and efficiency are secondary unless the task says otherwise.
- No panicking shortcuts. Propagate with
?instead ofunwrap(), and be careful with indexing and slicing, which can panic. - Never silently discard an error. Propagate it, log it, or handle it explicitly —
let _ =on a fallible call hides bugs. - Async failures must reach the UI layer so users get meaningful feedback.
- New modules are
src/some_module.rs; do not createmod.rstrees. - Prefer descriptive names over abbreviations, and comments that explain why the code is shaped that way.
- Implement functionality in existing files unless it is a genuinely new component.
In GPUI tests, drive timeouts and delays with the GPUI executor (cx.background_executor().timer(...)) rather than an external timer, so run_until_parked() can pump the work.
Web conventions
Everything under libs/web-design-system, demos/design-system-showcase, andapps/docs-web follows DESIGN.md:
- Components consume semantic tokens (
accent.text,surface.subtle,fg.muted), never raw palette values, so a theme stays a token swap. - One component per file, PascalCase, with props extended from the underlying DOM props and split with
splitProps. - Hydration is opt-in and documented per wrapper:
client:only="solid"for Ark-based overlays,client:visiblefor simple stateful wrappers, pure.astrofor static sections. - Keep
hash,separator, andprefixidentical across all threepanda.config.tsfiles, and make each app'sincludeglobs cover the design system's source. - WCAG 2.1 AA is the floor: visible focus, labeled icon-only controls, keyboard-focusable scroll regions, and motion that collapses under
prefers-reduced-motion.
Vendoring a crate
When an upstream crate needs a patch, clone it into patched/ with clone-patch <crate>, edit it there, and point a [patch] entry in the root Cargo.toml at the checkout. Add a comment explaining why the fork exists and keep the revision in the entry in sync with the vendored Cargo.toml.
A vendored fork keeps its own license and copyright; note any behavioral change in the comment above the patch entry, as the existing cersei forks do.
Questions about a specific area are best asked in an issue, with the relevant spec file linked. The repository also lives at github.com/lofi-tools/todo-lofi.