Unified guidance for AI coding assistants (Copilot, Claude, others) collaborating on the VideoAnnotator project.
- Name: VideoAnnotator
- Current Release: v1.2.0 (API-first, production-ready base)
- Active Minor (In Progress): v1.2.1 (polish + pipeline specification/registry foundation)
- Next Major (Planned): v1.3.0 (advanced ML, multi-modal, plugins, enterprise)
- Primary Users: Individual researchers (90%) needing simple local installs.
- Secondary Users: Lab / enterprise research groups (10%).
- Core Pillars: Modular pipelines, standardized outputs, reproducibility, minimal friction.
AI agents MUST optimize for:
- Low-friction local usability (no mandatory external services).
- Predictable, non-breaking incremental improvements (especially in v1.2.x series).
- Standard formats first (COCO, WebVTT, RTTM) – no bespoke schema proliferation.
- Future extensibility (registry metadata now → adaptive routing/plugins later).
- Clear, ASCII-safe console / log output (Windows encoding constraint: NO emoji, no fancy unicode blocks that may fail in PowerShell).
| Concern | Rule | Rationale |
|---|---|---|
| Emoji / Unicode | Prohibited in console/log prints | Windows charmap crashes |
| Log Directory | Use setup_videoannotator_logging(); do not reinvent handlers |
Central consistency |
| Structured Logs | Prefer logger over print; CLI may still use typer.echo for UX |
Unified diagnostics |
| Error Prefix | Use [ERROR], [WARNING], [OK], [START] |
Consistency + plain ASCII |
| JSON Output | Provide optional --json for machine parsing (v1.2.1 introduction) |
Scripting support |
Minimal YAML-driven registry located at src/registry/metadata/ (to be added). Each file MUST define:
name: string (slug)
display_name: string
category: tracking|detection|analysis|segmentation|preprocessing
description: short sentence
outputs:
- format: COCO|RTTM|WebVTT|JSON
types: [list of semantic output types]
config_schema: { field_name: { type, default, description } }
examples: optional list (cli / api usage)
version: integer schema version
Assistant tasks involving pipelines should:
- Load via registry once implemented rather than hard-coding.
- Offer graceful degradation if metadata missing (warn, skip).
- Avoid adding advanced fields early (resources, capabilities) unless explicitly approved (those are v1.3.0 targets).
| Aspect | Convention |
|---|---|
| CLI Base Command | videoannotator (Typer app) |
| Job Submission | videoannotator job submit |
| Pipelines Listing | videoannotator pipelines --detailed (backed by registry) |
| Config Validation | videoannotator config --validate path/to.yaml |
| Health Check | /health (enriched incrementally) |
| Pipeline Endpoint | /api/v1/pipelines dynamic (replace mock) |
When adding new CLI commands:
- Provide
--jsonif the output lists entities. - Fail fast with exit codes; include a suggestion line for common errors.
- Single version source in
src/version.py(no duplicated literals). - Registry metadata includes its own
version(schema evolution). - Generated docs (pipeline specs) MUST be reproducible – diffs trigger CI failure.
- For v1.2.x the public API reports the package version; plan to introduce a dedicated API semantic version constant in v1.3.0.
| Tier | Path | Goal | Runtime |
|---|---|---|---|
| Unit | tests/unit/ |
Fast logic validation | < 1 min total |
| Integration | tests/integration/ |
Cross-component behaviors | ~5 min |
| Pipelines | tests/pipelines/ |
Real or simulated model runs | Longer |
Assistant-created code MUST include at least minimal tests for:
- Registry loader integrity.
- API pipeline endpoint parity with registry.
- Markdown generation (smoke: file contains each pipeline name).
Workspace Configuration:
- All terminals open in
/workspaces/VideoAnnotatorby default (dev container). - No need to prefix commands with
cd /workspaces/VideoAnnotator &&. - Use
uvfor all Python operations (see section 21 for details).
Command Patterns:
# Correct (terminal is already in workspace)
uv run pytest tests/unit/
# Incorrect (unnecessary)
cd /workspaces/VideoAnnotator && uv run pytest tests/unit/File Paths:
- Use absolute paths when required by tools:
/workspaces/VideoAnnotator/src/... - Relative paths work naturally since terminal CWD is the workspace root.
- Plugin execution sandbox
- Multi-modal correlation graph engine
- Active learning feedback store
- Real-time streaming/WebRTC stack
- RBAC / SSO / multi-tenancy / audit log frameworks
- Complex resource scheduling or autoscaling logic
- Rich TUI or progress bar framework
- Favor lazy initialization; avoid loading heavy models outside
initialize(). - Avoid hidden network calls during import time.
- Annotate any model download operations with explicit logging.
- Provide timing logs (execution time context manager available in
logging_config).
- Never log raw PII (e.g., full file system paths of user home beyond what’s already necessary).
- Validate file existence before processing.
- Reject unsupported video formats with clear error messages.
- Avoid embedding secrets or tokens in code or docs.
| Action | Required Practice |
|---|---|
| File Edits | Small, atomic patches with rationale |
| New Features | Add tests + docs stub in same PR scope |
| Refactors | Preserve public CLI/API unless release notes updated |
| Docs Generation | Provide script, never hand-edit generated file |
| Logging Additions | Use existing logger categories (api, pipelines, requests, database) |
Standard error envelope (foundation for future):
{
"error": {
"code": "PIPELINE_NOT_FOUND",
"message": "Pipeline 'xyz' not registered",
"hint": "Run 'videoannotator pipelines --detailed' to list available pipelines"
}
}
Assistant changes touching API endpoints should migrate ad hoc responses toward this structure (without breaking existing clients unless major release).
Before approving output that touches user-visible text:
- No emojis or fancy unicode
- Paths use
Pathabstractions not hard-coded separators - Avoid color control chars (future optional feature)
| Category | v1.2.1 Expectation | v1.3.0 Expansion |
|---|---|---|
| Registry | Minimal YAML + loader | Capability & resource aware, plugin aware |
| Config Validation | Presence & primitive types | Full schema + templates + precedence engine |
| Health | Basic enrichment (registry, GPU flag) | Deep performance & scaling metrics |
| Errors | Simple envelope | Taxonomy + GraphQL alignment |
| Docs | Generated pipeline specs | Marketplace + plugin publishing |
| CLI | JSON option & consistent formatting | Color/TUI, adaptive suggestions |
- Is the change needed for v1.2.1 scope? If not, defer.
- Can it be undone easily if incorrect? If not, request human confirmation.
- Does it introduce silent behavior change? If yes, add explicit note to changelog.
- Is there a testable seam? Add or extend a test BEFORE large refactor.
- Implement class in
src/pipelines/<name>/ - Provide metadata YAML
- Update tests (registry presence)
- Regenerate docs (script) → commit
- Propose field (resources/capabilities) → doc it in metadata README
- Add parsing with backward-compatible default
- Update one metadata file as exemplar
- Add validation + tests
- Adding model downloads in global import scope
- Introducing new colorized/emoji output prematurely
- Creating parallel config systems instead of extending registry
- Hard-coding pipeline lists in multiple places
- Adding advanced multi-modal logic in v1.2.1 timeframe
- No emoji / unicode hazards
- Registry unaffected OR metadata updated
- Tests added/updated (if feature code)
- Docs regenerated (if pipeline changes)
- Logging consistent & non-duplicative
- Version not duplicated outside
version.py
Use labels/phrases to keep scope controlled:
scope:v1.2.1-foundationdefer:v1.3.0needs:registry-extensiontype:docs-generationtype:cli-ux
If generating Azure deployment or infra code:
The project STANDARD is to use uv (https://github.com/astral-sh/uv) for all Python dependency resolution, execution, and testing. Assistants MUST NOT rely on a pre-activated conda / venv environment when giving commands or running tests.
Required practices:
- Installation / Sync
- To sync the environment exactly to
pyproject.toml+uv.lock:uv sync(never manuallypip installinside the venv for project deps)
- Adding / Removing Dependencies
- Add runtime dependency:
uv add <package> - Add dev/test dependency:
uv add --dev <package> - Remove:
uv remove <package> - After changes: commit updated
uv.lock.
- Running Code
- Module / script:
uv run python -m videoannotator ... - CLI entry (if defined):
uv run videoannotator ...
- Tests & Quality
- Full test suite:
uv run pytest -q(or with markers/coverage flags) - Ruff lint (if configured):
uv run ruff check . - Mypy (if configured):
uv run mypy src/
- REPL / One-off
uv run python(never rely on external shell’s site-packages)
- Caching & Performance
- Let
uvmanage wheels; do not manually clear caches unless diagnosing a build issue.
- Consistency Enforcement
- If guidance or scripts previously referenced bare
pytest/python, update them touv runform. - Any test failure reproduction steps in issues/PR descriptions MUST use
uv run.
- CI Alignment
- CI should mirror:
uv syncthenuv run pytest .... Do not introduce alternative installers.
Common Anti-Patterns to Avoid (uv):
- Using
pip install -e .directly (useuv syncinstead). - Activating a conda environment and running
pytestwithoutuv run. - Editing
requirements.txt(the project is pyproject+lock driven; no requirements.txt unless generated artifact).
Assistant Heuristic Update:
- Before running tests, always ensure commands are prefixed with
uv rununless explicitly operating inside a scriptedmaketarget that already does so. - If a user asks for install instructions, default to
uvcommands.
Quick Reference:
uv sync # create/update environment
uv run pytest -q # run tests
uv add requests # add runtime dep
uv add --dev pytest-cov # add dev dep
uv run videoannotator --help
If any discrepancy between an active shell environment and uv run behavior is suspected, treat the uv run result as canonical.
The project uses pre-commit hooks (ruff, ruff-format, mypy, trailing-whitespace) that run automatically on git commit. Understanding their behavior reduces iteration cycles.
The project has DIFFERENT mypy strictness for different modules (see pyproject.toml):
Strict modules (src/api/*, tests/api/*, tests/integration/test_api_integration):
check_untyped_defs = truedisallow_incomplete_defs = trueno_implicit_optional = true
Relaxed modules (pipelines, storage, utils, exporters, schemas):
- Excluded from strict checking (reduces noise from ML/storage deps)
-
Pydantic Model Config Classes (RUF012)
- Use
json_schema_extra: ClassVar[dict[str, Any]] = {...} - Import:
from typing import ClassVar, Any
- Use
-
Exception Subclass Attributes
- Use inline annotations in
__init__:self.code: str = code - Avoid class-level annotations on Exception subclasses
- Use inline annotations in
-
Mixed-Type Dictionaries
- Declare explicit type upfront:
detail: dict[str, str | int] = {} - Mypy infers dict value type from first assignment
- Declare explicit type upfront:
-
Mypy Cache Staleness
- Clear cache when errors persist:
rm -rf .mypy_cache ~/.cache/pre-commit/mypy*
- Clear cache when errors persist:
Before committing:
uv run ruff format src/api/v1/ # Format first
uv run mypy src/api/ # Check types
uv run ruff check src/api/ # LintIf pre-commit fails:
- Auto-formatted files → re-stage:
git add <files> - Mypy cache stale → clear:
rm -rf .mypy_cache - After verifying fixes → last resort:
git commit --no-verify
Hook order: trailing-whitespace → end-of-file-fixer → ruff → ruff-format → mypy
Files modified by first 4 hooks require re-staging.
For new src/api/ modules:
- All parameters and returns typed
- Pydantic Config: use
ClassVarfor class attributes - Exceptions: inline type annotations in
__init__ - Mixed dicts: explicit
dict[str, str | int]hints - Import
ClassVar,Anyfromtyping
| Error | Fix |
|---|---|
| RUF012 mutable class attribute | ClassVar[dict[str, Any]] |
| dict type mismatch | Declare dict[str, str | int] upfront |
| Exception init type error | Inline: self.attr: type = value |
| Stale mypy errors | Clear .mypy_cache |
| Pre-commit formatting | Re-stage files |