aims/skills/dev-workers/code-implementation/SKILL.md
Implémenter du code selon les spécifications reçues du dev-orchestrator. Ce skill guide l'agent dev-worker dans la réception des tâches via Desk, la lecture de l'ontologie et des spécifications, le coding selon les patterns projet, et la validation avant submission pour review. Utiliser ce skill à chaque fois qu'une tâche task.assign arrive depuis le dev-orchestrator.
npx skillsauth add SomtechSolutionMAxime/somtech-pack code-implementationInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
Coder, c'est transformer une spécification en code qui marche, qui dure, et que d'autres peuvent lire. Ce skill définit le workflow complet : recevoir la tâche, comprendre le contexte, implémenter sans surprises, valider, et passer aux autres.
task.assign orientée dev-workerpr.review_request avec action "modify")task.bug_fix)Dès qu'une tâche arrive, consulter la table desk_tasks :
SELECT task_id, task_type, priority, payload, assigned_to, created_at
FROM desk_tasks
WHERE assigned_to = 'dev-worker-1' -- ou dev-worker-2
AND status = 'pending'
ORDER BY priority DESC, created_at ASC;
Chaque task.assign contient :
{
"task_id": "uuid",
"task_type": "task.assign",
"priority": "P1|P2|P3",
"assigned_to": "dev-worker-1",
"payload": {
"spec_id": "uuid",
"feature_name": "invoicing-export",
"description": "Export des factures en Excel avec filtres de période",
"acceptance_criteria": [
"Utilisateur sélectionne période",
"Export déclenché depuis page Facturation",
"Fichier contient : date, N° facture, montant TTC"
],
"technical_scope": {
"components": ["InvoiceExportButton", "ExportDialog"],
"tables": ["invoices"],
"policies_required": ["RLS sur invoices"],
"edge_functions": ["export-to-excel"]
},
"constraints": {
"max_rows": 10000,
"must_respect_rls": true
},
"related_tickets": ["TK-150"]
}
}
Vérifier s'il y a des dépendances :
SELECT task_id, feature_name, status
FROM desk_tasks
WHERE related_to_task_id = :task_id;
Si d'autres tâches dépendent de celle-ci, le dev-worker doit en être conscient pour bien prioriser.
Avant de coder, consulter :
| Document | Pourquoi |
|----------|----------|
| /ontologie/02_ontologie.yaml | Structure des entités et tables concernées |
| /ontologie/01_ontologie.md | Contexte métier et définitions |
| /security/ARCHITECTURE_DE_SECURITÉ.md | Règles RLS et patterns sécurité |
| /memory/constitution.md | Principes non-négociables du projet |
| CLAUDE.md du projet | Stack, conventions, anti-patterns |
Ne pas lire l'ontologie = risque de coder hors des patterns établis.
Créer un ticket interne dans Desk (pour toi-même) :
{
"task_type": "internal.analysis",
"from_agent": "dev-worker-1",
"payload": {
"task_id": "uuid",
"analysis": {
"user_story": "[Copier depuis la spec]",
"affected_entities": ["invoices", "export_logs"],
"new_tables_or_columns": ["export_logs.file_url"],
"required_policies": [
"RLS: invoices.user_id = auth.uid()",
"RLS: export_logs.user_id = auth.uid()"
],
"frontend_changes": [
"InvoiceExportButton component",
"ExportDialog with date picker"
],
"backend_changes": [
"Edge Function: export-to-excel",
"Database trigger: log_export"
],
"migration_required": "Yes — new table export_logs"
}
}
}
Log cet analyse dans silo-logging (skill transversal).
// app/invoicing/components/invoice-export-button.tsx
'use client';
import { useState } from 'react';
import { ExportDialog } from './export-dialog';
import { Button } from '@/components/ui/button';
export function InvoiceExportButton() {
const [open, setOpen] = useState(false);
return (
<>
<Button onClick={() => setOpen(true)} variant="outline">
Exporter en Excel
</Button>
<ExportDialog open={open} onOpenChange={setOpen} />
</>
);
}
interface ExportRequest {
startDate: Date;
endDate: Date;
includeDetails: boolean;
}
async function handleExport(params: ExportRequest): Promise<void> {
// ...
}
supabase/migrations/YYYYMMDDHHMMSS_add_export_logs.sql)CREATE TABLE export_logs (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
user_id UUID NOT NULL REFERENCES auth.users(id),
export_type TEXT NOT NULL CHECK (export_type IN ('invoices', 'quotes')),
filters JSONB,
file_url TEXT,
status TEXT DEFAULT 'pending' CHECK (status IN ('pending', 'completed', 'failed')),
created_at TIMESTAMPTZ DEFAULT now(),
exported_at TIMESTAMPTZ
);
-- RLS (obligatoire)
ALTER TABLE export_logs ENABLE ROW LEVEL SECURITY;
CREATE POLICY "Users can only access their own exports"
ON export_logs
FOR SELECT
USING (auth.uid() = user_id);
CREATE POLICY "Users can create their own exports"
ON export_logs
FOR INSERT
WITH CHECK (auth.uid() = user_id);
supabase/functions/export-to-excel/index.ts)import { serve } from 'https://deno.land/[email protected]/http/server.ts';
import * as XLSX from 'https://deno.land/x/[email protected]/mod.ts';
serve(async (req) => {
// Vérifier auth
const authHeader = req.headers.get('authorization');
if (!authHeader) {
return new Response('Unauthorized', { status: 401 });
}
// Parser le payload
const { startDate, endDate } = await req.json();
// Valider les paramètres
if (!startDate || !endDate) {
return new Response('Missing parameters', { status: 400 });
}
// Génère le fichier Excel
const data = [
['Date', 'N° Facture', 'Montant TTC'],
// ... données
];
const workbook = XLSX.utils.book_new();
const worksheet = XLSX.utils.aoa_to_sheet(data);
XLSX.utils.book_append_sheet(workbook, worksheet, 'Factures');
// Upload vers Storage et retourner l'URL
return new Response(JSON.stringify({ file_url: 'https://...' }));
});
CREATE INDEX idx_export_logs_user_id ON export_logs(user_id);
CREATE INDEX idx_export_logs_created_at ON export_logs(created_at DESC);
-- Chaque table avec user_id doit avoir une policy
ALTER TABLE invoices ENABLE ROW LEVEL SECURITY;
CREATE POLICY "Users see only their own invoices"
ON invoices
FOR SELECT
USING (auth.uid() = user_id);
Consulter /security/ARCHITECTURE_DE_SECURITÉ.md avant de créer une policy.
Tous les fichiers TypeScript doivent avoir :
{
"compilerOptions": {
"strict": true,
"noImplicitAny": true,
"strictNullChecks": true,
"strictFunctionTypes": true
}
}
Aucune variable any, même temporaire. Si tu es bloqué, escalade via error-escalation.
✅ CORRECT
app/invoicing/components/invoice-export-button.tsx
export function InvoiceExportButton() { }
❌ INCORRECT
app/invoicing/components/InvoiceExportButton.tsx
app/invoicing/components/invoiceExportButton.tsx
✅ CORRECT
CREATE TABLE invoice_items (
invoice_id UUID REFERENCES invoices(id),
amount_ht DECIMAL
);
❌ INCORRECT
CREATE TABLE InvoiceItems (...);
CREATE TABLE invoice_items (amountHT ...);
enum INVOICE_STATUS {
DRAFT = 'draft',
SENT = 'sent',
PAID = 'paid'
}
Frontend :
try {
const response = await fetch('/api/export', { method: 'POST' });
if (!response.ok) {
throw new Error(`Export failed: ${response.statusText}`);
}
const data = await response.json();
} catch (error) {
// Logger + afficher UI
console.error('Export error:', error);
setError('Impossible d\'exporter. Veuillez réessayer.');
}
Backend :
try {
// opération
} catch (error) {
console.error('Export error:', error);
return new Response(
JSON.stringify({ error: 'Export failed' }),
{ status: 500 }
);
}
Avant de dire "c'est fait", exécuter cette checklist :
any, tous les types explicites ?silo-logging uniquement ?feat(invoicing): add export to Excel (type(scope): description) ?feat/invoicing-export (pas de main) ?# Depuis le répertoire du projet
npm run lint
npm run type-check
npm test # Si tests existent pour cette feature
Zéro erreur avant de soumettre.
Une fois validé, créer une PR et notifier l'autre dev-worker :
{
"task_type": "pr.review_request",
"from_agent": "dev-worker-1",
"to_agent": "dev-worker-2",
"priority": "P2",
"payload": {
"pr_url": "https://github.com/...",
"branch": "feat/invoicing-export",
"spec_id": "uuid-de-la-spec",
"summary": "Implémentation export Excel factures avec RLS et Edge Function",
"checklist_done": [
"✅ Ontologie lue",
"✅ RLS configurée",
"✅ TypeScript strict validé",
"✅ Console: 0 erreur"
],
"known_limitations": [],
"test_instructions": "1. Naviguez vers /invoicing. 2. Cliquez 'Exporter en Excel'. 3. Sélectionnez 2026-01 à 2026-03. 4. Vérifiez fichier téléchargé avec 10 factures."
}
}
Après chaque implémentation, enregistrer :
{
"task_type": "internal.metrics",
"from_agent": "dev-worker-1",
"payload": {
"task_id": "uuid",
"implementation_metrics": {
"time_spent_minutes": 120,
"lines_added": 385,
"files_modified": 7,
"migrations_created": 1,
"edge_functions_created": 1,
"components_created": 2,
"rls_policies_added": 2
},
"quality_metrics": {
"console_errors_before": 0,
"console_errors_after": 0,
"test_coverage_new": "85%",
"type_errors": 0
},
"review_feedback_incorporated": false,
"blockers_encountered": []
}
}
any crée des bugs invisibles. Tu fermes juste les yeux sur les erreurs.policy.console.log ne doivent pas partir en production. Utiliser silo-logging.supabase db reset.} catch (e) {}) est une bombe. Toujours logger + escalader.tools
Documentation de référence SomCraft — DMS Markdown-native avec AI, MCP server, et Studio. À consulter pour toute question sur l'architecture, les APIs, les concepts, ou l'exploitation d'une instance SomCraft. TRIGGERS : somcraft, dms, document management, workspace somcraft, studio somcraft, mcp somcraft, api somcraft
tools
Déployer une instance SomCraft pour un client existant (migrations Supabase + Fly.io + skills). Orchestre 7 phases : pré-flight, plan, migrations, seed, déploiement, smoke tests, installation des skills. TRIGGERS : deploy-somcraft, déployer somcraft, installer somcraft, somcraft client, setup somcraft, upgrade somcraft, status somcraft
tools
Génère l'intégralité de la configuration d'un silo SomTech : docker-compose, services Fly.io, constitutions d'agents, et templates d'environnement. Valide les métadonnées d'application avant génération. À utiliser après validation initiale du client et avant déploiement.
development
Exécute le déploiement complet d'une silo après sa génération : conteneurs Docker, environnement de développement Fly.io, branche Git, et configuration Netlify. Transforme les configs générées en infrastructure active avec URLs stables et builds automatisés.