03 — contribute
Contributing
> welcome. the machine proposes — you dispose.
Ethos
cancri is a read-only live-portfolio terminal with a strong point of view: colour and motion carry meaning, the terminal is honest about its data, and humans confirm everything. Contributions that respect that ethos are very welcome.
Ground rules
English artifacts
Code, comments, commits, PRs, docs, and ADRs are English. Chat with the maintainer happens in their language; the repo speaks English.
Decisions go in smADRs
Architecture decisions live in docs/decisions/ as Structured MADRs — not in code comments or prose.
No secrets, ever
Source access and key-touching calls run server-side. The client only subscribes to normalised ticks. Never commit .env, keys, or tokens.
Propose, don't dispose
No silent adoption, no auto-merge — for the LLM inventory and the self-heal PR alike. A human always confirms.
The dev loop
Everything runs in a node:26 container; the host only needs Docker — no Node, no
Firebase project, no secrets. See Quickstart for the one-shot.
scripts/dev.sh # run the terminal with a mock feed → http://localhost:5173
scripts/build.sh # typecheck every package + production-build the web app
The dev build ships the dev-only // review bar to jump between every screen and
dashboard state. No backend needed.
Repo map
apps/web/ the terminal SPA (Vite, vanilla TS, single rAF loop)
services/feed-engine/ always-on Cloud Run: L&S + Yahoo taps, oracle, FSM, sole RTDB writer
services/selfheal/ Cloud Run Job: capture-and-diff → gated PR
functions/ Gemini normalise/confirm + logo (Vertex AI, IAM, no keys)
packages/data-contracts/ the one shared seam: Tick, SourceAdapter, inventory schema
packages/ls-protocol/ the L&S break surface + deterministic replay (self-heal target)
packages/selfheal-core/ pure fix-search + replay gate + fixture corpus
packages/sim-source/ in-browser mock feed (drives local dev with zero backend)
tools/tokens/ design tokens generated from design/cancri.handover.json
config/ firestore.rules · database.rules.json · indexes
design/ the Claude Design handover — source of truth for all UI
Tests & CI
Each package has a vitest suite. The security rules, persistence, and tick-bus run against the
Firebase Emulator Suite (needs a JDK; the containerised flow handles it). Please keep PRs green.
| check | what it runs |
|---|---|
| CI / verify | typecheck (all) + web build + non-emulator unit tests. |
| CI / rules | security rules + persistence + tick-bus on the emulators. |
| Validate ADRs | smADR schema check on docs/decisions/. |
| ls replay regression | the self-heal merge gate + bounded-surface check. |
| Security Review | OAuth-authenticated review of the diff. |
Run the security review locally before pushing security-relevant changes — in Claude Code:
/security-review.
Architecture decisions (smADR)
Architecture lives in docs/decisions/ as Structured MADR. Write an ADR when a decision:
- is hard to reverse, or
- spans multiple layers, a public interface, or a contract, or
- pins an invariant, a provider, or a stack building block, or
- displaces a plausible alternative worth recording.
Don't write an ADR for implementation details, local refactors, naming, helpers, or
test layout. When unsure, open one in proposed status. ADRs are append-only — once
accepted, supersede instead of editing.
# in Claude Code
/adr-new
# …or copy the template by hand
cp docs/decisions/adr-template.md docs/decisions/00NN-your-decision.md
Branching & PRs
-
Branch off
mainOpen the PR against
main. Don't stack PRs — a merge lands in the PR's base, so stacked bases never reachmain. -
Conventional-commit-ish titles
feat(...),fix(...),docs(...),chore(...). -
Fill the PR template honestly
Especially the Architecture impact checklist: does this need an ADR? Is one added? Or is it an implementation detail?
-
Keep it green
Run
scripts/build.shlocally; for security-relevant changes run/security-reviewbefore pushing.
Code style
- TypeScript, strict. No
any— useunknown+ a guard or a concrete type. Honour the sharedtsconfig.base.json(noUncheckedIndexedAccess,verbatimModuleSyntax, …). - The
design/handover is the source of truth for everything visual. UI tokens are generated fromdesign/cancri.handover.json— never hand-edit the generated files; re-runpnpm tokens. - The
data-contractspackage is the only seam between client and server. Nothing source-specific (Lightstreamer frames, protobuf, internal ids) may cross it. - Match the surrounding code; keep diffs minimal and focused.
Editing the docs site (this site lives in site/)? It's hand-authored static
HTML/CSS — no build step. Open the files directly or serve the folder, push to main, and the
Pages workflow publishes it. Keep using the cancri tokens in
site/assets/cancri.css so the optics stay consistent.
Good first contributions
A logo provider
Behind resolveLogo's injected fetcher (functions/src/logo.ts). Monogram-only until then.
Protocol fixtures
More fixtures for the L&S corpus / additional decode edge cases.
Accessibility passes
Focus order, reduced-motion parity on the terminal UI.
Yahoo venue coverage
More venue suffixes and PricingData schema hardening.
By contributing you agree to the Code of Conduct and that your work is licensed under the MIT License. The canonical text is CONTRIBUTING.md.