ai-project-bootstrap
Docs / Contributing / Changing the engine

Changing the engine

If you are touching src/ rather than adding a module, one invariant governs everything.

No file under src/ names a specific technology

Builders iterate the resolved modules and read well-known filenames. They never branch on a module id. That constraint is what keeps adding a technology a content-only change — worth preserving deliberately when you are tempted to special-case one module's behaviour.

Setup

pnpm install
pnpm build
pnpm test
pnpm lint
pnpm typecheck

What CI runs

Lint, typecheck and test on every PR — plus a second job that generates a full-stack project from a fixture and runs its setup, doctor, lint, typecheck and tests. That proves the generator's output actually works, not just that the generator compiles.

Two tests worth knowing about

tests/moduleContract.test.ts iterates every directory under technologies/ and validates the file contract automatically.
tests/generate.test.ts exercises the full pipeline end-to-end against fixture selections, entirely in memory — which is what keeps 40+ end-to-end cases fast.

The one deliberate exception

claudeBuilder does not special-case any module, but it does synthesise Claude Code's required skill frontmatter from each module's manifest and its Cursor rule's glob line — so Cursor and Claude activate on the same files without a module author maintaining the glob list twice.

Commit style

Conventional Commits — feat:, fix:, chore:, docs:. Releases are tagged 'chore: release vX.Y.Z' commits. From 1.0.0 onward semver applies for real: a breaking change to the CLI's flags, exit codes, or the generated-project contract needs a major version bump, not a feat:.