* ci: enforce the file-size ceiling on pull requests `check-added-large-files` only ran in pre-commit, so the ceiling was absent from CI: an unhooked clone or `--no-verify` bypassed it entirely, and the hook is weaker than it looks even locally — it inspects only files being *added*, so an existing fixture that grows never trips it. Add `scripts/check_file_sizes.py`, wired into `make lint` and therefore the required `lint` check. It diffs against the base branch's merge base and measures additions, modifications and renames, leaving files already committed above the ceiling alone so no pull request fails for something it did not touch. An unresolvable base is a hard failure rather than a silent pass. The `lint` job now checks out with `fetch-depth: 0` to provide it. Lower the hook's `--maxkb` from 1024 to 640 to match, and pin the two limits equal in a unit test so they cannot drift back apart. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * ci: catch untracked oversized files in the size gate `git diff` cannot see a newly created file until it is staged, so a local `make check-file-sizes` passed a brand-new 700 KB file — verified against the real script, not reasoned about. CI was unaffected (its checkout has everything committed), but the docstring claimed the local run covered uncommitted work, which was only true for edits to already-tracked files. Union in `git ls-files --others --exclude-standard`, which respects .gitignore, and pin both the untracked and the ignored case in tests. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * ci: exempt the generated search-seed corpora from the size ceiling tests/fixtures/search_seed/ holds embedded corpora regenerated by _dump_search_seed.py. Two of them are already near 1 MB and grew ~60% in one release, so the next refresh would have hit the 640 KB ceiling and the cheapest fix would have been raising it for the whole repository — a gate that teaches people to edit the gate. Exempt that one directory by path prefix instead. Outside it the largest tracked file is ~300 KB, so 640 KB still binds where it matters, including the examples/ case that prompted this work. Three tests pin the carve-out: a sibling of the exempt directory is still caught, the list itself is asserted verbatim so growth shows up in review, and every prefix must name a directory that actually exists. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> --------- Co-authored-by: zhanghui <zhanghui@shanda.com> Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
6.3 KiB
Engineering Reference
Companion docs: system design lives in architecture.md; coding rules live in ../.claude/rules/. This document is the contributor-facing reference for building, testing, and shipping a change — the toolchain, the CI gates, and the branch / commit conventions your pull request must satisfy.
Toolchain
| Tool | Role |
|---|---|
| uv | sole package manager (uv sync; do not use pip install) |
| hatchling | wheel build backend (src layout under src/everos) |
| ruff | lint + format (replaces black / isort / flake8) |
| import-linter | enforces the DDD layer dependency direction |
| pytest | unit + integration tests |
| pre-commit | local gate run before each commit |
Makefile |
single entry point for every command — CI invokes the same targets |
All tool configuration lives in a single pyproject.toml (ruff, pytest,
coverage, and the import-linter layer contracts) — there are no separate
pylintrc / pytest.ini / .isort.cfg files.
Local development
make install # uv sync --frozen
make format # ruff fix + format
make lint # ruff check + format-check + import-linter + datetime/asset/name guards
make test # pytest tests/unit
make integration # pytest tests/integration
make cov # unit + integration with coverage (gate: 80%)
make ci # lint + test + integration — run this before pushing
make help # list every target
CI runs the same make targets, so a green make ci locally predicts a
green pipeline.
Configuration
Settings load in ascending priority:
src/everos/config/default.toml— shipped with the package (lowest)<memory-root>/everos.toml— user config (optional)EVEROS_*environment variables (highest)
Run everos init to generate starter config and everos config show to
inspect the effective result. Full reference: configuration.md.
Quality gates
Each stage can independently fail a change; there is no --no-verify bypass.
1. Editor ruff (lint + format) on save
2. pre-commit ruff, trailing-whitespace / EOF, yaml & toml checks,
file-size & private-key guards, merge-conflict check,
and gitlint (commit-msg stage) — see "Commits" below
3. make ci lint + unit + integration — run before pushing
4. GitHub CI re-runs the same make targets on every pull request
5. Review 1 approval + all conversations resolved + all checks green
Stage 2 runs only on machines that ran make install, so CI cannot rely on it.
Where a pre-commit guard must hold for every pull request it has a make
counterpart re-run by CI.
File-size ceiling — 640 KB. Enforced locally by check-added-large-files
and on every pull request by
scripts/check_file_sizes.py
(make check-file-sizes, wired into make lint). The two limits are pinned
equal by a unit test; change them in the same commit. The CI gate is the
stronger of the two in scope: the local hook only inspects files being
added, so it cannot catch an existing file that grows, while the gate diffs
against the base branch and covers additions, modifications and renames
alike. Files already committed above the ceiling are out of scope — the gate
never fails a pull request for something it did not touch. Because it needs a
merge base, the lint job checks out with fetch-depth: 0.
One directory is exempt: tests/fixtures/search_seed/, whose search corpora
are regenerated by tests/fixtures/_dump_search_seed.py and already approach
1 MB. Outside it the largest tracked file is ~300 KB, so the ceiling stays
meaningful. Prefer adding a directory to EXEMPT_PREFIXES over raising
MAX_KB for the whole repository; a unit test pins the list so it cannot grow
unnoticed.
Continuous integration
CI runs on GitHub Actions (.github/workflows/). Every
pull request into main must pass:
| Check | Command | Guards |
|---|---|---|
| lint | make lint |
ruff style, DDD layer direction (import-linter), datetime discipline, asset, file-size & deprecated-name guards |
| unit tests | make test |
tests/unit |
| integration tests | make integration |
tests/integration |
| package build | make package |
the wheel builds and imports cleanly |
| docs | make docs-check |
Markdown and internal-link validity |
| commit messages / PR title | make check-commits / make check-pr-title |
Conventional Commits format |
main is a protected branch: no direct pushes; changes land through a
reviewed pull request with all checks green.
Contributing workflow
- Branch off
main, then open a pull request back intomain. - Commits and the PR title follow
Conventional Commits:
type(scope): subject, with the subject ≤ 72 characters and no leading emoji. Allowed types:feat,fix,refactor,test,docs,style,perf,chore,build,ci,revert. This is enforced both locally (gitlint, commit-msg stage) and in CI. - Pull requests use .github/PULL_REQUEST_TEMPLATE.md (changes / scope / API impact / tests / checklist).
- Issues use the templates under .github/ISSUE_TEMPLATE/.
See CONTRIBUTING.md for the full onboarding walkthrough.
This repository also ships Claude Code configuration — coding rules under
.claude/rules/and slash-command workflows under.claude/skills/— that encode the conventions above. It is optional convenience tooling: using Claude Code is not required to contribute, and the CI gates remain the source of truth.
References
- Architecture: architecture.md
- Coding rules: ../.claude/rules/
- Contributor onboarding: ../CONTRIBUTING.md
- uv · ruff · import-linter · pre-commit · Conventional Commits