Pre-Commit Check
Run proportional local checks for the files being changed, catching relevant
issues before pushing without defaulting to the full test suite.
When to Use
- Before creating a commit or PR
- User says "check my changes", "pre-commit", "verify before commit", "ready to push"
- After making any code changes to
.py files
Steps
1. Identify Changed Files
git diff --name-only HEAD
git diff --name-only --cached
git status --short
Collect all changed/added .py files.
Classify the change by affected area: workflow, docs, agent skill, packaged
configuration, isolated Python module, package-wide behavior, or cross-cutting
infrastructure.
2. Run Black Formatting Check
This is the first CI gate and will cause immediate failure:
black --check --diff --color ./
If it fails, run black . and review the formatting changes.
3. Check Public API Documentation Coverage
Run the same read-only gate used by CI:
python docs/scripts/check_api_docs.py
If it reports missing exports, use $update-api-docs to add useful Sphinx
entries and descriptions. Do not change __all__ solely to make this check
pass.
4. Check Apache 2.0 Copyright Header
Every .py file must begin with the 15-line copyright block. For each changed/new .py file, verify the first line is:
# ----------------------------------------------------------------------------
The full header template:
# ----------------------------------------------------------------------------
# Copyright (c) 2021-2026 DexForce Technology Co., Ltd.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
# ----------------------------------------------------------------------------
5. Check from __future__ import annotations
Every .py file must have this import (after the header, before other imports). This enables A | B syntax and forward references.
6. Check __all__ in Public Modules
For any new or modified module under embodichain/, verify it defines __all__ listing all public symbols. Example:
__all__ = ["MyClass", "my_function"]
Skip this check for __init__.py files that only re-export via from . import *.
7. Check Docstrings on Public APIs
For any new public function, class, or method:
- Must have a Google-style docstring
- Must include
Args: section if it takes parameters
- Must include
Returns: section if it returns a value
- Use
.. attention:: or .. tip:: directives for non-obvious behavior
8. Check Type Annotations
For any new public API:
- All parameters must have type hints
- Return type must be annotated
- Use
A | B over Union[A, B]
- Use
TYPE_CHECKING guard for imports that would cause circular dependencies
9. Check @configclass Usage
For any new configuration class:
- Must use
@configclass decorator (not bare @dataclass)
- Must use
from dataclasses import MISSING for required fields
- Import from
embodichain.utils import configclass
10. Select and Run Relevant Tests
Do not treat the CI test job as a requirement to run pytest tests locally for
every change. Choose the smallest command set that exercises the affected
behavior:
| Change scope | Default validation |
|---|
.github/workflows/** only | actionlint on changed workflows; run related script tests only when workflow scripts changed |
| Human-facing docs content only | Relevant Sphinx build or docs-specific tests |
agent_context/** or its routing helper | Run context.py check and tests/test_agent_context_{map,tools}.py; use advisory stats --base REF and representative overview-to-owner lookups when restructuring; exercise representative routes when routing changes |
.agents/skills/** and thin adapters | Run quick_validate.py for each changed canonical skill; compile/run any bundled scripts |
| Task Program components/deployments | Run the $add-task-program static deployment inspector plus the closest configured-integration/package-data tests |
| Other packaged JSON/YAML | Parse through the production loader and run the closest config/layout tests |
| One Python module | Matching tests/**/test_<module>.py |
| One package/subsystem | Tests for that package plus focused integration tests |
| Packaging/release code | Package build and artifact validation |
| Shared core, global test config, or multiple subsystems | Broader affected tests; full suite only when narrow coverage is not credible |
Skip runtime tests when no executable behavior is affected, but still run the
appropriate syntax or configuration validator. Run the full suite only when:
- the change affects shared core behavior used throughout the repository;
- global dependencies, test configuration, or environment initialization changed;
- several subsystems are modified together;
- a release-critical behavior cannot be validated narrowly; or
- the user explicitly requests it.
For changes identified as performance-sensitive during task analysis, follow
implement-performance and select focused
correctness checks for the algorithm, batch, memory or concurrency contracts
being changed. Validate material performance claims using
benchmark, comparing equivalent workloads and quality
settings, including relevant small-batch behavior and peak memory. Report
measured gains, tradeoffs and regressions with hardware and timing scope. If
required hardware is unavailable, state what remains unvalidated; passing CPU
tests does not establish GPU performance. Ordinary edits do not require a
benchmark run.
Before starting a command likely to take more than two minutes, report the
selected scope and why narrower validation is insufficient. Honor explicit user
instructions to skip or narrow tests.
For canonical skill directories, use:
python "${CODEX_HOME:-$HOME/.codex}/skills/.system/skill-creator/scripts/quick_validate.py" \
.agents/skills/<skill>
If the personal skill installation differs, locate the available skill-creator
validator through the session skill catalog instead of assuming a username.
Thin .claude/skills/ and .github/copilot/ adapters should point back to
the canonical .agents/skills/<skill>/SKILL.md; do not duplicate the full
instructions in adapters.
11. Check Test Coverage and Necessity
Apply the shared
test necessity review to the changed
behavior and any added or extended cases. Confirm that observable behavior and
real regressions have meaningful coverage; reuse sufficient existing tests
without requiring a new test file for every public module or function.
Report an actual unverified contract or regression when coverage is missing.
Review additions for redundancy and verification value, and briefly identify
the existing coverage relied upon or why runtime tests are unnecessary. Check
test file headers with the other changed Python files in step 4.
12. Summary Report
Output a pass/fail summary:
Pre-Commit Check Results
========================
[PASS] Black formatting
[PASS] Public API docs coverage
[PASS] Apache 2.0 headers (5/5 files)
[FAIL] from __future__ import annotations — missing in: foo.py
[PASS] __all__ exports
[PASS] Docstrings on public APIs
[PASS] Type annotations
[PASS] @configclass usage
[PASS] Targeted tests — tests/foo/test_bar.py
[N/A] Full test suite — isolated change covered by targeted tests
[PASS] Coverage and test necessity — existing coverage reused; no redundant additions
Fix the above issues before committing.
What CI Checks
The project's CI pipeline (.github/workflows/main.yml) runs:
- lint job:
black --check --diff --color ./
- lint job:
python docs/scripts/check_api_docs.py
- test job: proportional pytest groups after lint passes
- build job: Sphinx docs build after lint passes
This skill always covers the relevant lint and structural checks, then selects
tests proportionally. It does not require reproducing the entire CI pipeline for
every local change.
Common Mistakes
| Mistake | Fix |
|---|
Running black on only one file | Run black . on the whole project — CI checks everything |
| Forgetting test Apache header | Test files also need the 15-line copyright block |
Using Union[A, B] | Use A | B (with from __future__ import annotations) |
Using bare @dataclass | Use @configclass from embodichain.utils |
Missing __all__ in new module | Add __all__ with all public symbols |
Quick Reference
| Check | Command/Method |
|---|
| Black formatting | black --check --diff --color ./ |
| Auto-fix formatting | black . |
| Public API docs | python docs/scripts/check_api_docs.py |
| Header check | Verify first line is # ---...--- |
__future__ import | Grep for from __future__ import annotations |
__all__ export | Grep for __all__ in module |
| Run targeted tests | pytest tests/<affected-path> |
| Run full tests | pytest tests only when the full-suite criteria above apply |