Plataforma técnica · Convenciones
Convenciones de Código
Desarrollo Convenciones
Estas convenciones aplican a los cuatro sistemas del ecosistema (Mother, Orchestrator, Sevastopol, Nostromo) y al sitio de documentación Jean d’Arc. Cuando una regla es específica de un componente, está marcada.
Principios Generales
Section titled “Principios Generales”- Claridad sobre brevedad — Código legible gana sobre código corto.
- Consistencia con el código existente — Imitar los patrones que ya están en el repositorio antes de proponer otros nuevos.
- Explícito sobre implícito — Nombrar claramente, evitar abreviaciones, evitar magia.
- Fail fast — Validar en el borde (entrada HTTP, parsing CLI, lectura de
.env); fallar con mensaje claro. - Una capa, una responsabilidad — Route maneja HTTP, Service orquesta, Engine calcula, Repository persiste. No mezclar.
Gestores de Paquetes
Section titled “Gestores de Paquetes”| Componente | Gestor | Notas |
|---|---|---|
orchestrator/ | pnpm (workspace) | El monorepo Accounting/ pinea [email protected] en packageManager. Scripts: dev, build, test:unit, … |
sevastopol/ | pnpm (workspace) | Mismo workspace que Orchestrator; comparte pnpm-workspace.yaml. |
accounting_system/ | pip + venv | Sin dependencias compartidas con Node. |
jean_d_arc/ | pnpm (corepack) only | npm está prohibido. El package-lock.json no se mantiene y pnpm-workspace.yaml solo aplica con pnpm. |
TypeScript
Section titled “TypeScript”Aplica a Orchestrator y Sevastopol.
Naming
Section titled “Naming”| Elemento | Convención | Ejemplo |
|---|---|---|
| Archivos | PascalCase para clases; camelCase para utilidades | PayrollService.ts, dateUtils.ts |
| Clases | PascalCase | ContractRepository, PayrollEngine |
| Interfaces | PascalCase sin prefijo I | ServiceContext, PayrollInput |
| Types | PascalCase | HealthMode, GratificationMode |
| Funciones | camelCase | calculateGrossPay, getTenantPool |
| Constantes | UPPER_SNAKE_CASE | MAX_RETRIES, JWT_EXPIRES_IN |
| Variables | camelCase | totalAmount, baseSalary |
Servicios (patrón estático)
Section titled “Servicios (patrón estático)”Los servicios, engines y repositories del Orchestrator usan métodos estáticos, no clases con constructor. La instancia de pool se pasa como argumento.
export class PayrollService { static async generatePayroll( pool: Pool, input: PayrollInput, ): Promise<PayrollResult> { // 1. Cargar contexto (Repository) const ctx = await PayrollRepository.getPayrollContext(pool, input);
// 2. Cálculo puro (Engine) const result = PayrollEngine.calculate(ctx);
// 3. Persistir (Repository) await PayrollRepository.savePayroll(pool, result);
return result; }}Engines (lógica pura)
Section titled “Engines (lógica pura)”Sin acceso a base de datos ni Pool. Solo recibe input, retorna result. Permite unit tests sin mockear PG.
export class PayrollEngine { static calculate(input: PayrollInput): PayrollResult { const base = BaseSalaryCalculator.calculate(input); const grat = GratificationCalculator.calculate(input); // ... return { total_liquido, total_haberes, total_descuentos }; }}Imports
Section titled “Imports”// 1. Node.js built-insimport { readFileSync } from "node:fs";
// 2. Dependencias externasimport express from "express";import { Pool } from "pg";
// 3. Alias internos (@/lib, @/middleware, @/domain, @/routes)import { getTenantPool } from "@/lib/db";import { authenticateToken } from "@/middleware/auth";
// 4. Imports relativosimport { PayrollRepository } from "./PayrollRepository";import type { PayrollInput } from "./types";Frontera HTTP ↔ Dominio
Section titled “Frontera HTTP ↔ Dominio”Convención crítica del Orchestrator:
| Lado | Convención | Ejemplo |
|---|---|---|
| Variables internas | camelCase | totalHaberes, sueldoBase |
| Columnas PostgreSQL | snake_case | total_haberes, sueldo_base |
| Respuestas API | snake_case | { "total_haberes": 1500000 } |
Las respuestas de la API replican la forma de la base de datos para evitar una capa de transformación adicional. El frontend consume snake_case directamente.
SQL / PostgreSQL
Section titled “SQL / PostgreSQL”Naming
Section titled “Naming”| Elemento | Convención | Ejemplo |
|---|---|---|
| Bases | nostromo_<contexto> | nostromo_common, nostromo_command, nostromo_60004317 |
| Schemas | snake_case, sin prefijo | remuneraciones, operaciones_sii, parametros, command, accounting |
| Tablas | snake_case, plural | contratos, empleados, liquidaciones |
| Vistas | v_<descripción> | v_liquidaciones_departamento |
| Columnas | snake_case | fecha_inicio, monto_bruto |
| Índices | idx_<tabla>_<columna> | idx_contratos_empleado_id |
| Foreign keys | fk_<tabla>_<referencia> | fk_contratos_empleados |
Queries
Section titled “Queries”-- Aliases descriptivos, JOIN explícito, columnas listadasSELECT c.id, c.fecha_inicio, c.monto_bruto, e.nombres, e.apellido_paternoFROM remuneraciones.contratos cINNER JOIN remuneraciones.empleados e ON e.id = c.empleado_idWHERE c.activo = trueORDER BY c.fecha_inicio DESC;SELECT *solo en pruebas exploratorias.- Aplicar filtros y agregaciones en vistas (
v_*), no en TypeScript (principio Hybrid Core).
Python (Nostromo ETL)
Section titled “Python (Nostromo ETL)”Aplica a los loaders en accounting_system/.
Naming
Section titled “Naming”| Elemento | Convención | Ejemplo |
|---|---|---|
| Archivos | snake_case | bc_loader.py, previred_loader.py |
| Funciones | snake_case | load_uf_series, parse_period |
| Clases | PascalCase | BcLoader, SiiScraper |
| Constantes | UPPER_SNAKE_CASE | BASE_URL, DEFAULT_TIMEOUT |
Patrón de Loader
Section titled “Patrón de Loader”Cada loader expone una CLI con argparse, lee .env con python-dotenv, conecta a Mother con psycopg2 y soporta --dry-run.
def main() -> int: args = parse_args() load_dotenv() with get_connection() as conn: rows = fetch_from_source(args.period) if args.dry_run: print(f"DRY-RUN: {len(rows)} filas") return 0 insert_rows(conn, rows) return 0Flags estándar
Section titled “Flags estándar”| Flag | Uso |
|---|---|
--dry-run | Ejecutar el loader sin escribir en la base. |
--period | Período objetivo en formato YYYY-MM. |
-fi, -fn | Fecha inicial y final (loaders con rango de fechas). |
-m | Métrica o moneda a cargar (UF, USD, EUR). |
Frontend (Sevastopol)
Section titled “Frontend (Sevastopol)”Estructura
Section titled “Estructura”| Tipo | Ubicación | Naming |
|---|---|---|
| Layouts | src/layouts/ | BaseLayout.astro |
| Pages | src/pages/ | index.astro, [slug].astro |
| Islands | src/islands/<dominio>/ | PayrollViewIsland.tsx |
| UI Components | src/components/ui/ | Button.tsx, Modal.tsx |
| Hooks | src/hooks/ | useTenant.ts, useSession.ts |
Islands (SolidJS con createResource)
Section titled “Islands (SolidJS con createResource)”El patrón vigente para fetch + render usa createResource, no createSignal + onMount.
import { createResource, Show, For } from "solid-js";
export function EmployeesViewIsland() { const [employees] = createResource(async () => { const res = await fetch("/api/employees"); return res.json(); });
return ( <Show when={!employees.loading} fallback={<Spinner />}> <For each={employees()}> {(emp) => <EmployeeRow employee={emp} />} </For> </Show> );}createSignal se reserva para estado local del componente (formularios, tabs, modales).
Testing
Section titled “Testing”Naming y ubicación (Orchestrator)
Section titled “Naming y ubicación (Orchestrator)”| Tipo | Sufijo | Qué cubre |
|---|---|---|
| Unit | *.unit.test.ts | Funciones puras de la capa Engine. Sin acceso a DB. |
| Integration | *.integration.test.ts | Repository contra una base de datos real (o transacciones). |
| E2E | *.e2e.test.ts | Ciclo HTTP completo vía supertest. |
Cobertura esperada
Section titled “Cobertura esperada”| Capa | Cobertura mínima |
|---|---|
| Endpoints críticos | 100% (auth, generación de nómina) |
| Engine (lógica) | 90%+ |
| Repository (SQL) | 70%+ |
Frontend
Section titled “Frontend”E2E con @playwright/test. Unit/component tests con vitest cuando aplique. Sin mockear el backend en E2E: levantar Orchestrator contra una base de pruebas.
Mensajes de commit
Section titled “Mensajes de commit”<tipo>(<scope>): <descripción corta>
[cuerpo opcional]
[footer opcional]| Tipo | Uso |
|---|---|
feat | Nueva funcionalidad |
fix | Corrección de bug |
docs | Documentación |
refactor | Refactor sin cambio funcional |
style | Formato, indentación, sin cambio lógico |
test | Agregar o ajustar tests |
chore | Mantenimiento, deps, config |
feat(payroll): agregar prorrateo de gratificación al cálculo bruto
- Implementa cálculo proporcional sobre días trabajados- Cubre tope de 4.75 SMM y modalidad 25% mensual- Agrega unit tests para edge cases (mes parcial, recontratado)
Closes #123- Mensajes en español (consistente con el corpus contable).
- Imperativo: “agregar”, “corregir”, “mover” — no “agregado” ni “agregamos”.
Branches
Section titled “Branches”| Patrón | Uso |
|---|---|
main | Producción (deploy automático en CD). |
feature/<nombre> | Nueva funcionalidad. |
fix/<nombre> | Corrección de bug. |
docs/<nombre> | Documentación. |
refactor/<nombre> | Refactor. |
Las ramas se crean directamente desde main y se mergean vía PR. No hay rama develop.
Documentación (Jean d’Arc)
Section titled “Documentación (Jean d’Arc)”Frontmatter mínimo
Section titled “Frontmatter mínimo”---title: Título descriptivodescription: Una línea breve para SEO y preview.sidebar: label: Etiqueta en sidebar order: 1updated: 2026-05-23audience: dev # dev | auditor | bothdomain: orchestrator # ver lista canónica en DEV-STRUCTURE.mdlayer: orchestrator # mother | orchestrator | sevastopol | nostromo | infraestructura | seguridad | accountingkind: reference # reference | concept | service | ui | runbook | standardbadge: Orchestratortags: - orchestratortopic: - orchestratorrelated: upstream: - /dev/orchestrator/ downstream: [] references: - /accounting/remuneraciones/---Reglas del b-tree related
Section titled “Reglas del b-tree related”| Clave | Qué incluye |
|---|---|
upstream | Padre directo en el árbol de carpetas (solo uno; raíces sin upstream). |
downstream | Hijos directos. Solo el index de cada sección los lista. |
references | Cualquier cruce que no sea padre/hijo directo (dev↔accounting, servicio→island, etc.). |
standards | Solo páginas IFRS/NIC en /accounting/ifrs/. |
accounts | Códigos del manual de cuentas (solo en páginas accounting). |
patterns | Patrones de diseño implementados (solo en páginas kind: service). |
Regla de oro: si un link no es padre/hijo directo en el árbol de carpetas, va en references.
Headings
Section titled “Headings”- El
titledel frontmatter es el H1. Nunca escribir#en el cuerpo. - Las secciones del cuerpo empiezan en
##. - Jerarquía:
##→###→####.
Callouts
Section titled “Callouts”Usar la sintaxis fenced de Starlight, no <Aside>:
:::noteNota informativa.:::
:::tipSugerencia o atajo útil.:::
:::cautionAdvertencia que el lector debe leer antes de actuar.:::
:::dangerAcción irreversible o que rompe producción.:::Mermaid
Section titled “Mermaid”Bloques fenced con lenguaje mermaid. Renderizados por astro-mermaid.
<MermaidLightbox>
```mermaidgraph LR A[Orchestrator] --> B[Mother]```
</MermaidLightbox>Fórmulas matemáticas
Section titled “Fórmulas matemáticas”LaTeX vía remark-math + rehype-katex. Inline con $...$, bloque con $$...$$ en línea propia. No simular fórmulas con <sub> o <sup>.
Audience LinkCards
Section titled “Audience LinkCards”En landings que apuntan a sub-páginas dev, usar LinkCard con la clase audience-link--dev. En landings contables, audience-link--auditor.
<LinkCard class="audience-link--dev" title="Orchestrator" href="/dev/orchestrator/" description="API Node.js y dominios DDD."/>Componentes Starlight permitidos
Section titled “Componentes Starlight permitidos”<Steps>para procedimientos numerados.<Tabs>/<TabItem>para alternativas (Linux/Windows, npm/pnpm).<CardGrid>con<Card>o<LinkCard>para navegación o agrupación visual.<FileTree>para árboles de directorios.<Badge>para marcar audiencia o estado.