feat(conventions): seed central workspace+coding conventions repo
convention.yaml.schema (meta-schema) + per-language dirs (general/ts/swift/py/ rust/gd). Seed conventions: recursive_code_workspace (the ~/Code @org tree, always-active), infra_manifest (per-project .infra.yaml + its schema), and ts/code_standards + general/git_commit (shifted from the prose agentic configs). Referenced by global config as convention:<name>(<args>). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
commit
48d4853685
10 changed files with 253 additions and 0 deletions
36
README.md
Normal file
36
README.md
Normal file
|
|
@ -0,0 +1,36 @@
|
|||
# @conventions
|
||||
|
||||
Single source of truth for workspace + coding conventions, shared by every project
|
||||
under `~/Code` (and known to global agentic config, so any agent in any repo can
|
||||
resolve them).
|
||||
|
||||
## Layout
|
||||
```
|
||||
@conventions/
|
||||
├── convention.yaml.schema # meta-schema every convention validates against
|
||||
├── programming_general/<name>.yaml # language-agnostic conventions
|
||||
├── programming_ts/<name>.yaml # TypeScript
|
||||
├── programming_swift/<name>.yaml # Swift
|
||||
├── programming_py/<name>.yaml # Python
|
||||
├── programming_rust/<name>.yaml # Rust
|
||||
└── programming_gd/<name>.yaml # GDScript
|
||||
```
|
||||
|
||||
## A convention
|
||||
A `<name>.yaml` is metadata + `rules`, and may:
|
||||
- **accept `params`** — referenced as `convention:<name>(<args>)`, e.g. `convention:recursive_code_workspace(~/Code)`;
|
||||
- **define a manifest** via `providesFile` — a file (e.g. `.infra.yaml`) every conforming project must contain, with a nested JSON Schema for its contents.
|
||||
|
||||
Validate a convention file against `convention.yaml.schema`; validate a project's
|
||||
manifest against the convention's `providesFile.schema`.
|
||||
|
||||
## How agents use it
|
||||
Global config points agents here. An agent resolves `convention:<name>` by reading
|
||||
`programming_<scope>/<name>.yaml`, applies its `rules`, and (for `providesFile`
|
||||
conventions) reads/writes the project's manifest to that schema. Conventions are
|
||||
data, not prose — tooling (a future `infra-apply`, linters, scaffolders) can consume
|
||||
them directly.
|
||||
|
||||
## Seed conventions
|
||||
- `programming_general/recursive_code_workspace.yaml` — the `~/Code` @org layout.
|
||||
- `programming_general/infra-manifest.yaml` — per-project `.infra.yaml`.
|
||||
69
convention.yaml.schema
Normal file
69
convention.yaml.schema
Normal file
|
|
@ -0,0 +1,69 @@
|
|||
# JSON Schema (draft 2020-12, written in YAML) for a single workspace convention.
|
||||
# Every file at @conventions/programming_<scope>/<name>.yaml validates against this.
|
||||
# Agents reference a convention as convention:<name> or convention:<name>(<args>).
|
||||
$schema: "https://json-schema.org/draft/2020-12/schema"
|
||||
$id: "conventions/convention.yaml.schema"
|
||||
title: Convention
|
||||
description: One workspace convention — metadata + rules, optionally defining a project manifest file and/or accepting parameters.
|
||||
type: object
|
||||
additionalProperties: false
|
||||
required: [name, title, scope, status, summary]
|
||||
properties:
|
||||
name:
|
||||
type: string
|
||||
pattern: "^[a-z0-9][a-z0-9_]*$"
|
||||
description: snake_case id; MUST match the filename (without .yaml).
|
||||
title:
|
||||
type: string
|
||||
scope:
|
||||
type: string
|
||||
enum: [general, ts, swift, py, rust, gd]
|
||||
description: Matches the programming_<scope>/ directory the file lives in.
|
||||
status:
|
||||
type: string
|
||||
enum: [draft, active, deprecated]
|
||||
summary:
|
||||
type: string
|
||||
description: One line; shown when an agent lists available conventions.
|
||||
params:
|
||||
type: array
|
||||
description: Named arguments the convention accepts, e.g. recursive_code_workspace(root).
|
||||
items:
|
||||
type: object
|
||||
additionalProperties: false
|
||||
required: [name]
|
||||
properties:
|
||||
name: { type: string }
|
||||
description: { type: string }
|
||||
default: {}
|
||||
appliesTo:
|
||||
type: array
|
||||
description: Globs or project kinds this convention governs.
|
||||
items: { type: string }
|
||||
supersedes:
|
||||
type: array
|
||||
items: { type: string }
|
||||
rules:
|
||||
type: array
|
||||
items:
|
||||
type: object
|
||||
additionalProperties: false
|
||||
required: [id, level, text]
|
||||
properties:
|
||||
id: { type: string }
|
||||
level: { type: string, enum: [must, should, may] }
|
||||
text: { type: string }
|
||||
rationale: { type: string }
|
||||
# When set, the convention defines a manifest file every conforming project must
|
||||
# provide (e.g. .infra.yaml), with a nested JSON Schema for that file's contents.
|
||||
providesFile:
|
||||
type: object
|
||||
additionalProperties: false
|
||||
required: [path, schema]
|
||||
properties:
|
||||
path:
|
||||
type: string
|
||||
description: Repo-relative path each conforming project must contain (e.g. ".infra.yaml").
|
||||
schema:
|
||||
type: object
|
||||
description: JSON Schema (draft 2020-12) the manifest file validates against.
|
||||
0
programming_gd/.gitkeep
Normal file
0
programming_gd/.gitkeep
Normal file
25
programming_general/git_commit.yaml
Normal file
25
programming_general/git_commit.yaml
Normal file
|
|
@ -0,0 +1,25 @@
|
|||
name: git_commit
|
||||
title: Atomic commit + push protocol
|
||||
scope: general
|
||||
status: active
|
||||
summary: Each verified logical change is its own scoped, conventional commit, pushed immediately; every agent commits the work it produced.
|
||||
appliesTo: ["~/Code/**"]
|
||||
rules:
|
||||
- id: atomic
|
||||
level: must
|
||||
text: One logical, verified change per commit. Stage with scoped `git add <paths>` — never blind `git add -A`.
|
||||
- id: verify_first
|
||||
level: must
|
||||
text: Tests / build / typecheck pass before the commit. Never commit unverified code.
|
||||
- id: conventional
|
||||
level: must
|
||||
text: Conventional-commit message; end with the Co-Authored-By trailer.
|
||||
- id: push_after
|
||||
level: must
|
||||
text: git push (fast-forward only) after each commit so work isn't stranded on one host. Never force-push.
|
||||
- id: agent_owns_commit
|
||||
level: must
|
||||
text: Each agent (orchestrator or sub) commits + pushes its own work; never defer to a parent or a daemon. (The apricot ACS auto-commit-service is stale/offline.)
|
||||
- id: branch
|
||||
level: should
|
||||
text: These repos work on main directly; don't auto-create branches unless the project requires it.
|
||||
54
programming_general/infra-manifest.yaml
Normal file
54
programming_general/infra-manifest.yaml
Normal file
|
|
@ -0,0 +1,54 @@
|
|||
name: infra_manifest
|
||||
title: Per-project infra manifest (.infra.yaml)
|
||||
scope: general
|
||||
status: draft
|
||||
summary: Every deployable project declares its infrastructure in a root .infra.yaml; a future infra-apply tool renders it to the provider (DO / Terraform).
|
||||
appliesTo: ["@applications/*", "@projects/@cocottetech", "@projects/@magic-civilization"]
|
||||
rules:
|
||||
- id: own_db
|
||||
level: must
|
||||
text: A project needing a database declares its own logical DB + dedicated user on the shared managed cluster (data-sourced), never reusing another service's creds.
|
||||
rationale: own-DB-per-service + credential separation.
|
||||
- id: http_coupling
|
||||
level: must
|
||||
text: Cross-service dependencies are HTTP only (declared in depends_on), never shared databases.
|
||||
- id: gpu_ondemand
|
||||
level: should
|
||||
text: GPU workloads are on-demand — provision, keep warm while the queue is deep, release on idle. Never a standing GPU.
|
||||
providesFile:
|
||||
path: .infra.yaml
|
||||
schema:
|
||||
$schema: "https://json-schema.org/draft/2020-12/schema"
|
||||
title: ProjectInfraManifest
|
||||
type: object
|
||||
additionalProperties: false
|
||||
required: [project, provider]
|
||||
properties:
|
||||
project: { type: string }
|
||||
provider: { type: string, enum: [digitalocean] }
|
||||
database:
|
||||
type: object
|
||||
additionalProperties: false
|
||||
required: [cluster, name, user]
|
||||
properties:
|
||||
cluster: { type: string, description: Shared managed cluster — data-sourced, not owned here. }
|
||||
name: { type: string }
|
||||
user: { type: string }
|
||||
service:
|
||||
type: object
|
||||
additionalProperties: false
|
||||
properties:
|
||||
host: { type: string }
|
||||
runtime: { type: string }
|
||||
port: { type: integer }
|
||||
systemd_unit: { type: string }
|
||||
gpu:
|
||||
type: object
|
||||
additionalProperties: false
|
||||
properties:
|
||||
mode: { type: string, enum: [on-demand] }
|
||||
droplet: { type: string }
|
||||
depends_on:
|
||||
type: array
|
||||
items: { type: string }
|
||||
description: Other services consumed over HTTP.
|
||||
29
programming_general/recursive_code_workspace.yaml
Normal file
29
programming_general/recursive_code_workspace.yaml
Normal file
|
|
@ -0,0 +1,29 @@
|
|||
name: recursive_code_workspace
|
||||
title: Recursive code workspace (~/Code @org tree)
|
||||
scope: general
|
||||
status: active
|
||||
summary: ~/Code is a recursive tree of @org dirs, each holding many independent git repos; tools and agents resolve projects by walking it.
|
||||
params:
|
||||
- name: root
|
||||
description: Workspace root to walk.
|
||||
default: "~/Code"
|
||||
appliesTo: ["~/Code/**"]
|
||||
rules:
|
||||
- id: orgs
|
||||
level: must
|
||||
text: >
|
||||
Top-level @org dirs partition the workspace: @applications (apps/services you
|
||||
operate), @projects (platforms incl. @cocottetech, @magic-civilization, @lilith),
|
||||
@packages (shared libraries), @conventions (this repo), plus support buckets
|
||||
@scripts / @docs / @forks / @external / @archives / @work.
|
||||
- id: independent_repos
|
||||
level: must
|
||||
text: Each project under an @org is its own independent git repo. Never assume a single monorepo at the root.
|
||||
rationale: Repos are cloned/forge-managed per-project; cross-repo coupling is HTTP/registry, not filesystem.
|
||||
- id: per_project_infra
|
||||
level: should
|
||||
text: A deployable project owns its infra via a root .infra.yaml (see convention:infra-manifest). Shared infra (e.g. the managed PG cluster) is data-sourced, not owned per-project.
|
||||
rationale: Catch-all shared infra repos (uvlava-style) are superseded by per-project ownership.
|
||||
- id: support_buckets
|
||||
level: may
|
||||
text: Cross-cutting or transient items live in the support buckets, not inside project repos.
|
||||
0
programming_py/.gitkeep
Normal file
0
programming_py/.gitkeep
Normal file
0
programming_rust/.gitkeep
Normal file
0
programming_rust/.gitkeep
Normal file
0
programming_swift/.gitkeep
Normal file
0
programming_swift/.gitkeep
Normal file
40
programming_ts/code_standards.yaml
Normal file
40
programming_ts/code_standards.yaml
Normal file
|
|
@ -0,0 +1,40 @@
|
|||
name: code_standards
|
||||
title: TypeScript code standards
|
||||
scope: ts
|
||||
status: active
|
||||
summary: Portable TS conventions — strict typing, ESM, typed errors, named exports, Vitest. Project-specific architecture (kernels, golden-vectors, file-size caps) lives with the project, not here.
|
||||
appliesTo: ["**/*.ts", "**/*.tsx"]
|
||||
rules:
|
||||
- id: strict
|
||||
level: must
|
||||
text: "tsconfig strict:true; prefer noUncheckedIndexedAccess + exactOptionalPropertyTypes. No escape hatches."
|
||||
- id: no_any
|
||||
level: must
|
||||
text: No `any`; use `unknown` at boundaries and narrow with type guards. Never `as unknown as T`.
|
||||
- id: no_ts_ignore
|
||||
level: must
|
||||
text: No `@ts-ignore`; fix the type, or `@ts-expect-error` with a reason.
|
||||
- id: explicit_return_types
|
||||
level: should
|
||||
text: Explicit return types on exported functions and React components.
|
||||
- id: discriminated_unions
|
||||
level: should
|
||||
text: Discriminated unions over boolean flags; add variants via switch, don't branch on strings.
|
||||
- id: typed_errors
|
||||
level: must
|
||||
text: Typed Error subclasses with cause chaining. Never empty catch; never catch-and-only-console.
|
||||
- id: esm_named_exports
|
||||
level: must
|
||||
text: ESM only; named exports in libraries (default exports only in app pages/components); index.ts is the public manifest.
|
||||
- id: no_link_file
|
||||
level: must
|
||||
text: Monorepo deps via workspace:* or the registry — never file:/link:.
|
||||
- id: vitest
|
||||
level: must
|
||||
text: Vitest (not Jest); *.test.ts co-located, full-sentence it(...); mocks only in test files.
|
||||
- id: structured_logging
|
||||
level: must
|
||||
text: No console.log in library code — use a structured logger.
|
||||
- id: no_dead_code
|
||||
level: must
|
||||
text: Delete unused code entirely; no _unused prefixes, no commented-out blocks.
|
||||
Loading…
Add table
Reference in a new issue