diff --git a/programming_gd/code_standards.yaml b/programming_gd/code_standards.yaml new file mode 100644 index 0000000..650b937 --- /dev/null +++ b/programming_gd/code_standards.yaml @@ -0,0 +1,34 @@ +apiVersion: conventions/v1 +version: 0.1.0 +updated: "2026-06-29" +name: code_standards +title: GDScript code standards +scope: gd +status: active +summary: Explicit static types everywhere, specific node types, EventBus for cross-system signals, scenes as skeletons, SRP scripts, observable errors. From v2 magic-civilization. +appliesTo: ["**/*.gd"] +rules: + - id: explicit_types + level: must + text: "Explicit type on every var (`var x: Type`); no bare `var x = v`, no inferred `:=`, no `Variant` escapes (except a typed EventBus payload)." + - id: specific_types + level: must + text: Use the specific type (`Node3D`, `AudioStreamPlayer`), never the general (`Node`). Typed arrays always (`Array[String]`, never bare `Array`). + - id: typed_signatures + level: must + text: Every function has typed params and a return type (`-> void` when none). + - id: refcounted_for_logic + level: should + text: "`RefCounted` for pure logic; `Node` only for scene-tree lifecycle. One script = one responsibility (no God Nodes)." + - id: signals + level: must + text: Cross-system communication goes through the EventBus autoload only; intra-tree parent↔child direct signals are fine. + - id: scenes_skeleton + level: should + text: ".tscn is structure/skeleton only; behavior is attached/wired at runtime in _ready()." + - id: observable_errors + level: must + text: "push_error()/push_warning() on failure paths; never silent returns or empty error handlers. Safe-cast with null check + log on mismatch." + - id: no_dead_code + level: must + text: "No `# TODO`, no `# gdlint:ignore`, no unused vars." diff --git a/programming_general/database_patterns.yaml b/programming_general/database_patterns.yaml new file mode 100644 index 0000000..bcf5024 --- /dev/null +++ b/programming_general/database_patterns.yaml @@ -0,0 +1,28 @@ +apiVersion: conventions/v1 +version: 0.1.0 +updated: "2026-06-29" +name: database_patterns +title: Database patterns +scope: general +status: active +summary: Schema-is-the-contract (forward-only migrations), one connection singleton, per-service role isolation, pgBouncer transaction-mode constraints. v2 lilith database-architecture, evolved in v4. +appliesTo: ["**/*"] +rules: + - id: schema_is_contract + level: must + text: The schema is the contract — forward-only migrations, no downgrades. No schema changes outside a migration. + - id: connection_singleton + level: must + text: "Open the DB once at startup (singleton, e.g. openDb() in server.ts) and reuse via getDb(); no per-feature pools." + - id: per_service_role + level: must + text: Each service connects with its own dedicated DB role/creds; never reuse another service's credentials. + - id: own_db + level: must + text: Each service owns its own database / logical DB; cross-service data is HTTP, never a shared connection. + - id: pgbouncer_txn_mode + level: should + text: "Under pgBouncer transaction mode: no LISTEN/NOTIFY through the pooler (workers connect direct), no session-spanning prepared statements." + - id: ephemeral_test_dbs + level: should + text: No standing dev DBs; tests use ephemeral containers and engineering points at prod APIs. diff --git a/programming_general/error_handling_logging.yaml b/programming_general/error_handling_logging.yaml new file mode 100644 index 0000000..836c0df --- /dev/null +++ b/programming_general/error_handling_logging.yaml @@ -0,0 +1,28 @@ +apiVersion: conventions/v1 +version: 0.1.0 +updated: "2026-06-29" +name: error_handling_logging +title: Error handling & structured logging (cross-language) +scope: general +status: active +summary: Typed errors with cause chaining, no silent swallows, structured logging (never stdout in libraries), specific exception types. The shared spirit across TS/Py/Rust/GD. +appliesTo: ["**/*"] +rules: + - id: typed_errors + level: must + text: "Domain-specific typed errors (TS Error subclasses, Py exception classes, Rust thiserror enums, GD explicit failure paths). Never a bare string thrown." + - id: cause_chaining + level: must + text: "Errors carry context up the stack: TS `{ cause }`, Py `raise ... from exc`, Rust `#[from]`/source." + - id: no_silent_swallow + level: must + text: "No empty catch / `except: pass` / discarded Result. Handle, rethrow, or log+rethrow — never swallow." + - id: structured_logging + level: must + text: "Structured logger, not stdout, in libraries (no console.log / print() / println!). MCP/stdio processes log to stderr only." + - id: lazy_log_format + level: should + text: "Python: lazy %-formatting in log calls (logger.info('x=%s', x)), not f-strings." + - id: observable_failures + level: should + text: "Failures are observable (logged with context / push_error in GD), never silent returns." diff --git a/programming_general/mcp_server_patterns.yaml b/programming_general/mcp_server_patterns.yaml new file mode 100644 index 0000000..982e13f --- /dev/null +++ b/programming_general/mcp_server_patterns.yaml @@ -0,0 +1,28 @@ +apiVersion: conventions/v1 +version: 0.1.0 +updated: "2026-06-29" +name: mcp_server_patterns +title: MCP server patterns +scope: general +status: active +summary: MCP servers are thin HTTP shims over a backend API — one tool per capability, types matching the API contract, dual stdio/HTTP transport, stderr-only logging. v2→v4. +appliesTo: ["**/mcp/**", "**/*-mcp/**"] +rules: + - id: thin_shim + level: must + text: No business logic in the MCP server; every tool is one call to the backend API. The backend owns the logic. + - id: one_tool_per_capability + level: must + text: "Separate tools per capability (list_x / get_x / create_x), never one `manage` tool with a mode param." + - id: shared_types + level: should + text: Tool types mirror the backend API contract (shared via the feature's shared/ or a published api-client package), not re-invented. + - id: dual_transport + level: should + text: "stdio for dev/testing; HTTP for prod (bind port + Bearer token auth)." + - id: layout + level: should + text: "Reference layout: src/index.ts (tools) + src/client.ts (HTTP wrapper + env config) + logger to stderr." + - id: stderr_only + level: must + text: Never log to stdout (reserved for the MCP protocol) — logger writes to stderr. diff --git a/programming_general/multi_agent_workflow.yaml b/programming_general/multi_agent_workflow.yaml new file mode 100644 index 0000000..eea91db --- /dev/null +++ b/programming_general/multi_agent_workflow.yaml @@ -0,0 +1,28 @@ +apiVersion: conventions/v1 +version: 0.1.0 +updated: "2026-06-29" +name: multi_agent_workflow +title: Trunk-only multi-agent workflow +scope: general +status: active +summary: Concurrent agents work on main directly, commit only their own narrow diff with explicit pathspecs, and never clobber another session's WIP. From v2 lilith concurrent-agent protocol. +appliesTo: ["~/Code/**"] +rules: + - id: trunk_only + level: must + text: Work on `main` directly; no feature branches unless the project requires them. + - id: fresh_state + level: should + text: "Before committing, sync fresh: `git fetch && git merge --ff-only origin/main`." + - id: scoped_pathspec + level: must + text: "Concurrent agents share one working tree — stage with explicit pathspecs (`git add ` / `git commit -- `), never blind `git add -A`." + - id: own_commit + level: must + text: Each agent commits + pushes the work it produced; never defer to a parent or daemon. + - id: leave_wip_alone + level: must + text: Other agents' staged/uncommitted files are not a blocker and not yours — never `git checkout`/`git stash`/revert another session's WIP; commit only your narrow diff. + - id: atomic_conventional + level: must + text: One logical change per commit; conventional message + Co-Authored-By trailer. (See convention:git_commit.) diff --git a/programming_general/naming_conventions.yaml b/programming_general/naming_conventions.yaml new file mode 100644 index 0000000..5bbfce5 --- /dev/null +++ b/programming_general/naming_conventions.yaml @@ -0,0 +1,25 @@ +apiVersion: conventions/v1 +version: 0.1.0 +updated: "2026-06-29" +name: naming_conventions +title: Naming — provider-generic code, instance-specific domains +scope: general +status: active +summary: Code/packages are provider-generic; only deployed domains/instances are provider-specific (quinn.*). Snake_case slugs/IDs/DB fields. V4 canonical (supersedes v2 quinn-* package names). +appliesTo: ["@applications/*", "@projects/*"] +rules: + - id: provider_generic_code + level: must + text: "Package/module names are provider-generic (provider-portal, messenger, prospector) — no `quinn-*` in new code. Quinn is an instance, not the codebase." + - id: instance_domains + level: must + text: "Instance-specific names appear only in deployed domains: quinn.api / quinn.my / quinn.ai; other providers get {provider}.*." + - id: brand_shared + level: should + text: "Shared/platform infra uses the brand domain (sso.cocotte.io, platform.admin, beacon.cocotte.io)." + - id: snake_identifiers + level: must + text: "snake_case for slugs, IDs, and DB fields (org_id, user_id, slug: transquinnftw)." + - id: lang_naming + level: should + text: "Per-language casing per that language's convention (TS PascalCase types / camelCase vals / kebab files; Py snake; etc.). See programming_." diff --git a/programming_general/service_architecture.yaml b/programming_general/service_architecture.yaml new file mode 100644 index 0000000..3aced8c --- /dev/null +++ b/programming_general/service_architecture.yaml @@ -0,0 +1,28 @@ +apiVersion: conventions/v1 +version: 0.1.0 +updated: "2026-06-29" +name: service_architecture +title: Service architecture (single API plane, peer services over HTTP) +scope: general +status: active +summary: One canonical API plane per platform; peer services (AI/ML/sync/screening) are consumed over HTTP/MCP, never vendored; authoring location ≠ runtime host. Consistent v0→v4. +appliesTo: ["@applications/*", "@projects/*"] +rules: + - id: single_api_plane + level: must + text: One canonical backend API per platform; all surfaces (web/iOS/MCP/CLI) are clients of it. No second backend, no per-feature DB pools. + - id: peers_over_http + level: must + text: "Peer services are consumed over HTTP/MCP, never vendored into another repo (e.g. @ai, @ml, mac-sync, mr-number, model-boss, prospector, people)." + - id: ml_in_peers + level: must + text: ML/AI weights & inference live in peer apps; the platform holds orchestration only, never models/weights. + - id: authoring_not_host + level: must + text: Code is authored in its repo (local/dev); named hosts are deploy targets only. Verify where something runs against INFRA.md before claiming it — never infer host roles from names. + - id: own_db_per_service + level: must + text: Each service owns its own database/logical-DB + dedicated role; cross-service data access is HTTP, never a shared DB connection. + - id: no_dev_planes + level: should + text: No standing dev DBs / dev APIs; engineering points at prod APIs, test DBs are ephemeral containers. diff --git a/programming_general/tenancy_patterns.yaml b/programming_general/tenancy_patterns.yaml new file mode 100644 index 0000000..4713485 --- /dev/null +++ b/programming_general/tenancy_patterns.yaml @@ -0,0 +1,25 @@ +apiVersion: conventions/v1 +version: 0.1.0 +updated: "2026-06-29" +name: tenancy_patterns +title: Person-first, Org-optional tenancy +scope: general +status: draft +summary: Onboarding is Person-first; Org is an optional overlay. Every user-owned table carries a nullable org_id (NULL = person-owned). V4 canonical (cocotte DESIGN §2-3). +appliesTo: ["@projects/@cocottetech/**"] +rules: + - id: person_first + level: must + text: Onboarding never asks "what org"; a Person operates standalone by default. Org is a later upgrade. + - id: org_overlay + level: must + text: A Person can own/admin/join multiple Orgs; Org is an overlay on the Person, not a prerequisite. + - id: nullable_org_id + level: must + text: "Every user-owned table has a nullable org_id alongside user_id. org_id IS NULL => row belongs to the Person; set => belongs to the Org." + - id: no_leakage + level: must + text: Org A's data is invisible to Org B; a Person's data is invisible to an Org unless explicitly shared. + - id: provider_generic + level: should + text: Tenancy code is provider-generic (see convention:naming_conventions). diff --git a/programming_py/code_standards.yaml b/programming_py/code_standards.yaml new file mode 100644 index 0000000..f7eb915 --- /dev/null +++ b/programming_py/code_standards.yaml @@ -0,0 +1,34 @@ +apiVersion: conventions/v1 +version: 0.1.0 +updated: "2026-06-29" +name: code_standards +title: Python code standards +scope: py +status: active +summary: uv + hatchling, src layout, mypy strict, ruff, async-all-the-way, Pydantic v2 at boundaries, structured logging. Proven across v2 lilith Python packages. +appliesTo: ["**/*.py"] +rules: + - id: toolchain + level: must + text: "uv (deps/venv) + hatchling (build); ruff (lint+format); mypy. Never substitute (no poetry/pip/black/flake8)." + - id: src_layout + level: must + text: "src// layout (e.g. src/lilith_foo/), never a flat top-level module." + - id: mypy_strict + level: must + text: "mypy strict:true; full type annotations; no `Any` (use precise types / protocols / TypedDict)." + - id: async_all_the_way + level: should + text: Don't mix sync and async; async from the entrypoint down. No blocking calls in async paths. + - id: pydantic_boundaries + level: should + text: Pydantic v2 models validate data at system boundaries (API/IO); plain dataclasses/types internally. + - id: logging + level: must + text: "No print() in library code. logging.getLogger(__name__); lazy %-formatting (logger.info('x=%s', x)), not f-strings in log calls." + - id: specific_exceptions + level: must + text: "Catch the specific exception expected; never bare `except:` or `except Exception: pass`. Chain with `raise ... from exc`." + - id: no_dead_code + level: must + text: "Delete unused code; no commented-out blocks, no `# type: ignore` without a code+reason." diff --git a/programming_rust/code_standards.yaml b/programming_rust/code_standards.yaml new file mode 100644 index 0000000..f251b99 --- /dev/null +++ b/programming_rust/code_standards.yaml @@ -0,0 +1,34 @@ +apiVersion: conventions/v1 +version: 0.1.0 +updated: "2026-06-29" +name: code_standards +title: Rust code standards +scope: rust +status: active +summary: Result-based errors (no unwrap), thiserror domain enums, pure domain crates + thin FFI/WASM shims, SAFETY comments, snake_case serde. From v2 simulator/magic-civilization. +appliesTo: ["**/*.rs"] +rules: + - id: no_unwrap + level: must + text: "Propagate via Result<_, Error>. `.unwrap()` forbidden; `.expect(\"reason\")` only when panic is provably impossible." + - id: thiserror + level: must + text: Domain error enums via `thiserror`; errors carry context (`#[from]`, source chaining). + - id: pure_domain_crates + level: must + text: "Domain crates (crates/-*) are pure Rust — no FFI/WASM/GDExt deps. API crates are thin shims (WASM/GDExt surfaces) with no business logic." + - id: unsafe_documented + level: must + text: "Every `unsafe` block has a `// SAFETY:` comment justifying the invariants." + - id: serde_snake + level: should + text: 'Serde with #[serde(rename_all = "snake_case")] on wire types.' + - id: no_dead_code + level: must + text: "`#[allow(dead_code)]` forbidden — delete unused code. `todo!()`/`unimplemented!()` forbidden in shipped code." + - id: tracing + level: should + text: Structured logging via `tracing` (never `log`, never `println!` in libraries). + - id: workspace + level: should + text: "Cargo workspace resolver=\"2\"; pure domain crates + API shim crates clearly separated."