Contributing
The test suite is the contract. Write the failing test first, then the code. The entire suite runs on fakes — no network, no gh, no claude.
Commands
From the Cue checkout:
bun test # full suite
bun run lint # oxlint (.oxlintrc.json)
bun run format # oxfmt — run after editing
bun run format:check
bun run check # lint + format:check + tests
bun run cue <cmd> # CLI against cwd (usually a target repo)tsconfig has noUncheckedIndexedAccess, so indexed access needs a guard or a deliberate !. Tests use bun test (the code depends on Bun APIs) — do not migrate them to another framework.
Always run bun run check before claiming a change works.
bun test always reports coverage (bunfig.toml) and writes coverage/lcov.info. The suite fails if any file drops below 95% lines or 80% functions (Bun's threshold is per-file). CI (.github/workflows/tests.yml) uploads that LCOV file as an artifact and to Codecov.
Tests and fakes
- Subprocess-touching code:
makeFakeExecintests/helpers/— scripted{ match, result }replay,"*"wildcards, prefix matching. - Agent-touching code:
makeFakeAdapter. tests/triage.test.tsexportsmakeCtx— the sharedStageContextfactory used by dev, review, replan, pipeline, cleanup, and integration tests. Extend it rather than duplicating setup.
TypeScript is strict. any is allowed only at gh / claude JSON parse boundaries, and is narrowed immediately. Errors throw with actionable messages.
What to keep in sync
If you change any of these, update all of them:
- Label names — code, tests, prompts, docs, real repos
PLAN_MARKER— defined once instages/triage.ts- Config fields — valibot schema in
src/config.tsand the defaults table
docs/superpowers/ is gitignored on purpose. Do not commit design specs or "fix" that ignore rule.
Dashboard
ui/ is excluded from the root tsconfig, oxlint, and oxfmt configs. It has its own:
bun run ui:build # after any change under ui/app/
bun run ui:dev
bun run ui:lint
bun run ui:format
bun run ui:check # tscbun run check does not cover the SPA — run both when you touch ui/.
The dashboard uses react-router in library mode (createBrowserRouter in app/main.tsx) on plain Vite with the React Compiler on. Do not reintroduce @react-router/dev.
RunEntry.result is polymorphic: older logs store a single result event as an object; newer ones store the whole event array. Anything reading a transcript must go through normalizeEvents in ui/app/lib/transcript.ts (re-exported by cue.ts and covered by the root test suite).
Docs
User and contributor docs are this VitePress site (docs/content/). The root README stays short and points here. Diagrams use fenced mermaid blocks (vitepress-plugin-mermaid).
bun run docs:dev
bun run docs:buildReleasing
- Land the change on
main. - Push a
v*tag (for examplev0.3.0). - CI (
.github/workflows/release.yml) builds binaries withscripts/build-binaries.shand attachesdist/cue-*pluschecksums.txt. - Users upgrade with the same
install.shone-liner, orCUE_VERSION=v0.3.0.
Do not commit src/ui-manifest.g.ts after a local binary build — the script restores the empty stub; leave it that way.