Contributing
Contributing
Section titled “Contributing”Follow these guidelines when contributing to Sencai.
Where to look first
Section titled “Where to look first”Before making changes, read these — they are the current, living references (not this page’s prose):
.claude/AGENTS.md— agent roles and autonomy boundaries.claude/context/— architecture, glossary, onboarding, audit patterns, code review checklistPHASE-5-PLAN.md/PHASE-6-PLAN.md(repo root) — the current phase plans (PHASE-5 is gate-overridden and in active local execution, PHASE-6 is prep-stage);PHASE-2-PLAN.md,PHASE-3-PLAN.md, andPHASE-4-PLAN.mdhave all been archived underai-context-staging/phase-2/,phase-3/, andphase-4/respectively, now that those phases are implementation-complete
Git workflow
Section titled “Git workflow”Sencai’s monorepo is a polyrepo: each service (sencai.space, api-manager, cloud-connector, sencai-web, and roughly 30 others) is its own independent Git repository with its own remote — there is no single root repository tying them together.
There is no main branch in any of these repos. Every active repository has exactly one long-lived branch, dev, and that is what CI builds from. A handful of older repos (ai-context-staging, auth-service-consumer, bootstrap, graphql-gateway) still carry a leftover master branch from before the dev-only convention was settled, but none of them use it as an integration target — dev is the branch that matters everywhere.
There is also no evidence of feature-branch workflows in any repo’s history — real practice is Conventional Commits landing directly on dev:
git checkout devgit pull origin dev# ...make changes...git add .git commit -m "fix(security): account-limit-guard invite bypass"git push origin devA main-based Git Flow model with feature/* branches, PR review, and tag-triggered releases does not exist in this codebase today. If you’ve seen that model described elsewhere (including in .claude/skills/release.md — see note below), treat it as aspirational, not current practice.
Committing changes
Section titled “Committing changes”Use Conventional Commits, as a single-line message:
git commit -m "feat(billing): add overview endpoint"Per the root CLAUDE.md: one sentence, no trailing period, no commit body/footer conventions like Closes #42 are in use.
Hard rule — no exceptions: commits must never include Co-Authored-By, Signed-off-by, or any mention of Claude/AI, in the message or in code/comments. This is enforced project-wide. (Note: a small number of early historical commits predate this rule being enforced — do not use them as a precedent.)
Commit types
Section titled “Commit types”| Type | Description |
|---|---|
feat | New feature |
fix | Bug fix |
docs | Documentation |
chore | Build, deps, tooling |
refactor | Refactoring (no behavior change) |
test | Add/modify tests |
ci | CI/CD pipeline changes |
perf | Performance improvement |
Pull Request process
Section titled “Pull Request process”There is currently no PR-based review process in day-to-day use: no PULL_REQUEST_TEMPLATE.md, no CODEOWNERS file, and no pull_request-triggered CI workflow exist across the repos for the primary lint/test/build gate (ci.yml) — it runs on push to dev only. If a PR-and-review workflow is introduced in the future, this section will be updated to match; until then, treat any PR/branch/squash-merge process described here or elsewhere as aspirational, not current practice.
CHANGELOG updates
Section titled “CHANGELOG updates”Every change must update the affected service’s CHANGELOG under ## [Unreleased].
Format
Section titled “Format”Use Keep a Changelog:
## [Unreleased]
### Added- New feature
### Changed- Changed behavior
### Fixed- Fixed bug
### Removed- Removed endpointExample
Section titled “Example”## [Unreleased]
### Added- GET /api/billing/overview endpoint- Monthly cost aggregation
### Fixed- Keycloak sync loop issueDatabase migrations
Section titled “Database migrations”Migration discipline differs by service — see .claude/skills/db-migration.md for the full per-service breakdown. The two most common patterns:
- Strapi (
sencai.space) — Knex migrations underdatabase/migrations/. Never modify or delete an existing migration file; always add a new one. Migrations run automatically on Strapi startup. For content-type field changes,schema.jsonupdates usually generate the migration automatically. - Cloud Connector (
cloud-connector) — TypeORM entity sync, not file-based migrations. Schema changes are made directly to entity definitions undersrc/database/entities/; in dev, TypeORM’ssynchronize: trueapplies the schema, and production changes go throughtypeorm migration:generate. This is a different discipline from Strapi’s — don’t assume Knex-style migration files exist here.
Never delete or modify existing Knex migrations, regardless of service.
Testing
Section titled “Testing”Running tests
Section titled “Running tests”# Backendcd sencai.space && npm test
# Frontendcd sencai.space-frontend && npm test
# Microservicescd api-manager && npm testCI runs on every push to dev (not on pull requests — there is no PR trigger for the primary pipeline). The core ci.yml gate typically runs:
- Lint — ESLint + Prettier
- Type check — TypeScript
- Tests — Jest/Vitest
- Build — Production build
Two additional gates run independently of ci.yml, on a schedule as well as on push:
- Dependency Audit (
dependency-audit.yml) —npm audit(blocking on high/critical), runs on push todevand nightly via a0 4 * * *cron. - Secret scanning (
gitleaks.yml) — scans for committed secrets; several repos run this via thegacts/gitleaksaction (a license-gate-free wrapper around the same OSS gitleaks scanner, adopted aftergitleaks/gitleaks-action@v2started requiring a paid license for org repos).
All gates must pass before changes are considered mergeable/deployable in practice, even without a formal PR review step enforcing it.
Documentation
Section titled “Documentation”Update README
Section titled “Update README”If adding features or services:
service-name/├── README.md ← add documentation├── CLAUDE.md ← context for Claude Code├── CHANGELOG.md ← Keep a Changelog format└── .env.example ← all ENV variablesRequired files in new services
Section titled “Required files in new services”README.md— description, tech stack, how to runCLAUDE.md— context for Claude CodeCHANGELOG.md— Keep a Changelog format.env.example— all environment variablesDockerfile— containerization.dockerignore— exclude build files
Exception: purely config-only directories with no application code of their own — auth-service/, git-service/, sencai-mq/, k8s-agent/ — don’t need a Dockerfile/.dockerignore/.env.example, since their runtime image comes from an upstream project (Keycloak, Gitea, RabbitMQ) rather than being built here. infra-gcp/ (CDKTF infrastructure-as-code) is likewise exempt from the Dockerfile/.dockerignore requirement, since it’s not a running service.
Release process
Section titled “Release process”Move [Unreleased] in each service’s CHANGELOG.md to a dated version section when cutting a release:
## [1.2.0] - 2026-04-20
### Added- Billing overview
### Fixed- Keycloak syncThen bump the version in package.json:
{ "version": "1.2.0"}That part of the workflow is real and current practice.
What is not current practice: there is no main branch to merge into, no git tag v1.2.0 step, and no tag-triggered release pipeline. The only image tagging scheme actually observed in the repos is dev-latest — the Docker image is rebuilt and pushed to ghcr.io under that single tag on every push to dev. Versioned image tags (ghcr.io/...:v1.2.0) and GitHub Releases are not part of the current pipeline.
.claude/skills/release.mdcurrently documents the same unsupporteddev→main→ tagged-release flow described above as removed from this page. That skill file should eventually be corrected to match thedev-only,dev-latest-tag reality, but updating it is out of scope for this content fix.
Security rules
Section titled “Security rules”- Never commit
.env— use.env.example - Never commit unencrypted secrets — API keys, tokens, passwords
- Validate input — always
- Use parameterized queries — prevent SQL injection
- Configure CORS/CSRF — properly
Common mistakes
Section titled “Common mistakes”| Issue | Cause | Solution |
|---|---|---|
| CI “push” failed | Lint error | Run npm run lint:fix locally before pushing |
| Tests don’t pass | Missing fixture | Check test setup |
| Dependency Audit fails | High/critical npm audit finding | Fix the dependency or document in the service’s audit allowlist with notes + expiry |
| CHANGELOG missing | Forgot to update [Unreleased] | Update CHANGELOG.md before considering the change done |
Questions
Section titled “Questions”For onboarding and architecture questions, start with .claude/AGENTS.md and .claude/context/onboarding.md rather than generic community channels — this is an internal platform without public GitHub Issues/Discussions or a community chat set up for contribution questions.
See each service’s .github/workflows/ for its actual CI/CD gates.