Use this guide for consistent formatting, naming, and conventions across all vCon repositories. When a repository has its own style config (e.g., pyproject.toml, .eslintrc), follow it; this document defines the ecosystem baseline.
| Element | Convention | Examples |
|---|---|---|
| Database columns | snake_case | created_at, vcon_version, tenant_id |
| Python modules | snake_case | vcon_redis.py, llm_client.py |
| Python classes | PascalCase | Vcon, Storage, VConPeeWee |
| Python functions | snake_case | get_vcon(), add_tag() |
| TypeScript types | PascalCase | VCon, Dialog, Analysis |
| TypeScript functions | camelCase | getVcon(), addAnalysis() |
| MCP tool names | snake_case | create_vcon, search_vcons_semantic |
| API endpoints | RESTful snake_case | /vcon/{uuid}/analysis |
| Environment vars | UPPER_SNAKE_CASE | REDIS_URL, SUPABASE_URL |
| Config keys | snake_case | ingress_lists, api_key |
| Docker services | lowercase hyphenated | conserver, redis-stack |
| IETF/vCon fields | snake_case | created_at, content_hash, party_history |
- Formatter: black
- Line length: 120 characters
- Linters: flake8, ruff
- Import order: isort (stdlib, third-party, local)
# Standard module layout
"""Module docstring."""
from __future__ import annotations
import logging
from typing import Optional
from lib.vcon_redis import VconRedis
from lib.logging_utils import init_logger
logger = init_logger(__name__)
default_options = {"model": "default"}
async def run(vcon_uuid: str, link_config: dict) -> str | None:
"""Process a vCon. Return uuid to continue, None to stop."""
pass- Use
init_logger(__name__)fromlib.logging_utils - Structured logging: key-value pairs, not string interpolation
- Always include
vcon_uuidin log entries for vCon processing
logger.info("Processing vCon", extra={"vcon_uuid": uuid, "chain": chain_name})
logger.error("vCon not found", extra={"vcon_uuid": uuid})- Use type hints for public functions and link/storage interfaces
- Prefer
str | NoneoverOptional[str](Python 3.10+) - Use
dictandlistfor generic collections (Python 3.9+)
- Use Google-style or NumPy-style consistently within a repo
- Document Args, Returns, Raises for public functions
- Include at least a one-line summary for link
run()functions
- Module system: ES modules (
"type": "module") - Build target: ES2022
- Strict mode: Enabled
- Linter: ESLint with TypeScript plugin
// Standard module layout
import { z } from 'zod';
import { logger } from './observability/logger.js';
const inputSchema = z.object({
uuid: z.string().uuid(),
});
export async function createVcon(input: z.infer<typeof inputSchema>) {
logger.info({ uuid: input.uuid }, 'Creating vCon');
// ...
}- Use Zod for input validation
- Validate at API boundaries before processing
- Return clear error messages for invalid params
- Use pino with structured fields
- Include context (vconUuid, tool name) in log objects
logger.info({ vconUuid: uuid, tool: 'create_vcon' }, 'Creating vCon');These are non-negotiable. Violations are spec-breaking:
- Analysis: Use
schema, notschema_version.vendoris REQUIRED. - Analysis body: Always a string type, even when content is JSON.
- Attachment: Use
purpose(nottypein core).partyanddialogare REQUIRED. - Tags: Stored as attachments with
purpose: "tags", JSON body. Useparty: 0,dialog: 0for vCon-level tags. - External references: MUST have both
urlandcontent_hash(sha512-base64url). - Timestamps: ISO 8601 with timezone (e.g.,
2025-01-15T10:30:00Z). - UUIDs: Accept with or without dashes. Generate v8 in vcon-lib.
base64url: Audio, video, binary inline contentjson: Structured data (tags, analysis body)none: Plain text
- Return
Noneto stop pipeline (non-fatal, e.g., vCon not found) - Push to Dead Letter Queue for fatal errors
- Log with context before returning or raising
if not vcon:
logger.warning("vCon not found", extra={"vcon_uuid": vcon_uuid})
return None
try:
result = await process(vcon)
except Exception as e:
logger.error("Processing failed", extra={"vcon_uuid": vcon_uuid}, exc_info=True)
await dlq.push(vcon_uuid, str(e))
return None- Use
McpErrorwithErrorCodefor MCP protocol errors - Validate with Zod; throw
McpError(ErrorCode.InvalidParams, message)on failure
- Framework: pytest, pytest-asyncio
- Markers:
@pytest.mark.slow,@pytest.mark.integration,@pytest.mark.anyio - Fixtures: Use
conftest.pyfor shared setup - Mock vCons: Use
generate_mock_vcon()or equivalent
- Framework: vitest
- Config: Node environment, dotenv, v8 coverage
- E2E: Separate script (
test:e2e)
Before submitting a PR:
- Code follows naming conventions for the language
- Logging uses structured format with context
- vCon fields use correct names (
schema,vendor,purpose) - Tests pass
- No new lint violations