Synaplan
開源 AI 平台,供企業使用:自行託管的 AI 代理、符合 GDPR 的聊天機器人小工具、RAG 知識庫、WhatsApp 與 Outlook AI、MCP、多模型路由。Docker、Kubernetes 或託管於 Germ
AI 翻譯
尚未偵測到更新。GitHub 發布版本後會顯示在這裡。
個人 GitHub 帳號下公開儲存庫的擁有者可以登入並驗證所有權,自行管理介紹,無需管理員核准。
登入並產生驗證檔案,在 30 分鐘內將其提交至此儲存庫的預設分支。其他分支或分叉儲存庫中的檔案無效。然後在下方檢查檔案,即可無需管理員核准直接管理專案。請保留檔案以維持管理權限。
如需登入,將前往登入頁面。登入後請回到此處,再次點擊所選的驗證按鈕。
在專案資料夾中執行 /nomorevibe verify,即可驗證所有權並自行管理介紹。
一分鐘完成驗證製作者的介紹僅有上面的一句話。 更多詳情請閱讀儲存庫 README。 儲存庫 README ↗
正在載入完整 README。
檢視完整 README ↗Une application pour piloter une très petite entreprise : sa journée, ses clients, son argent. Pas de compte à créer, pas de configuration, pas de serveur — un seul fichier HTML qui s'ouvre dans un navigateur.
Elle s'est appelée Cadence, puis Simpli le 17 septembre 2026, puis Plenitu, avant de devenir Cura le 18 septembre 2026. Les copies de sauvegarde enregistrées sous l'un ou l'autre de ces noms se restaurent toujours.
| Onglet | Ce qu'on y fait |
|---|---|
| Agenda | La journée en ruban, les créneaux libres, le temps de route entre deux rendez-vous qui s'enchaînent, et le tableau des notes en dessous |
| Clients | Le carnet, rangé par mois de signature, et sur chaque fiche de quoi appeler, écrire ou s'y rendre. Au-dessus, une ligne dit combien de personnes attendent un appel — impayé, devis qui dort, client content, client oublié — et mène à l'écran qui les propose une à la fois |
| Comptabilité | Calculs : ce qu'il vous restera une fois cotisations et impôt payés. Factures : les totaux de l'année, la liste, le PDF. Mon argent : ce qui est vraiment à vous |
Les factures. « Mon argent » et « Calculs » en dérivent, facturer quelqu'un l'inscrit au carnet des clients. Aucun total n'est stocké : tout se recalcule. Deux listes parallèles, et les écrans finissent par se contredire — c'est l'erreur qui a coûté le plus cher sur ce projet.
Un total sans son périmètre n'est pas une mesure. Les écrans filtrent sur l'année en cours : annoncer un chiffre sans dire « 2026, hors brouillons » est une source de désaccord, pas une information.
Tout est enregistré dans le localStorage du navigateur, sur l'appareil du
visiteur uniquement. Rien n'est envoyé nulle part, il n'y a pas de serveur.
L'application s'ouvre vide : c'est la sienne, pas une démonstration. Un
contrôle refuse la publication si des fiches d'exemple réapparaissent.
Cette promesse est désormais tenue par le navigateur lui-même : une politique de sécurité déclarée dans la page n'autorise aucune connexion sortante. Même si un script tiers était un jour compromis, il ne pourrait rien envoyer.
Le dossier supabase/ contient les migrations d'un socle de données en ligne :
schéma, sécurité au niveau des lignes, back-office en lecture seule. Il n'est
branché à rien. Le jour où il le sera, la phrase ci-dessus devra être réécrite
dans le même commit — jamais avant, jamais après.
Les fichiers livrés, index.html et sw.js, sont générés : ne les modifiez
pas à la main, et ne les fusionnez jamais ligne à ligne. sw.js porte
l'empreinte de la page ; une fusion produit un fichier qui ne correspond à
aucune version, donc un cache qui ne sera jamais mis au rebut. En cas de
conflit sur l'un ou l'autre : prendre n'importe quelle version, puis
régénérer.
python3 src/build.py
src/page.html — le gabarit, avec le marqueur __SEED__ à la place des donnéessrc/verif.py — contrôle du script : chaînes fermées, blocs équilibrés,
fonctions appelées qui existent. Ce garde-fou existe parce que des guillemets
mal appariés ont blanchi la page plusieurs foissrc/controles.py — ce qu'on vérifie sur la page avant de publier : un seul
nom, l'application qui s'ouvre vide, la politique de sécurité, aucun script
tiers sans empreinte, aucun domaine non prévu. Chaque contrôle correspond à
quelque chose qui a déjà cassé — on n'en ajoute pas par principesrc/tiers.py — l'empreinte annoncée pour le script extérieur est-elle celle
du fichier réellement servisrc/sw.js — la copie locale qui permet d'ouvrir l'application sans réseauoutils/serveur-partage.py — l'adresse commune sur le port 4173, qui sert ce
dépôt en interdisant toute mise en cacheoutils/hooks/pre-push — le dernier verrou avant l'envoi⚠️ Avant de lancer build.py dans le dépôt principal, vérifier que
git status est propre. Ce dossier est celui que sert le 4173, et un agent
peut y avoir du travail en cours non commité. Régénérer à ce moment-là ne
l'écrase pas — c'est pire : on le compile dans index.html et on le publie
sous son propre nom, sans l'avoir jamais lu. Rien n'est perdu, et pourtant du
code que personne n'a relu se retrouve en ligne. C'est passé à un cheveu le
18 septembre 2026.
build.py écrit d'abord un brouillon, le contrôle, et ne remplace index.html
qu'une fois les contrôles passés. Il l'a longtemps fait dans l'autre sens : une
erreur de syntaxe était déjà publiée quand le message « Publication annulée »
s'affichait. L'ancienne page reste dans index.precedent.html, le temps d'un
retour en arrière.
Quatre verrous, du plus proche au plus lointain :
build.py ne remplace la page qu'une fois les contrôles passés.outils/hooks/pre-push refuse d'envoyer une page qui ne les passe pas.
Le commit local, lui, se fait toujours : le travail en cours n'est jamais
perdu, et la page en ligne reste la dernière qui fonctionnait..github/workflows/verification.yml régénère la page et la compare à
celle qui est publiée. Modifier le gabarit sans relancer build.py est
l'oubli le plus coûteux du projet ; il ne passe plus..github/workflows/veille.yml, chaque matin : l'adresse publique répond,
elle porte bien ses protections, et le script extérieur n'a pas changé.sw.js garde une copie de la page. Il ne la sert que si le réseau ne répond
pas. Une copie servie en priorité fige l'application à la version du jour où
elle a été installée, et plus personne ne comprend pourquoi les corrections
n'arrivent pas — c'est exactement ce qui a coûté une journée entière. Un contrôle
refuse la publication si sw.js s'écarte de cette règle.
Une session qui démarre reçoit ce fichier, pas ce que les autres se sont dit. Sans cette liste, les mêmes questions reviennent — l'une d'elles est remontée quatre fois à Sacha en deux jours, chaque fois présentée comme neuve. Avant de lui proposer quelque chose, vérifier ici.
robots.txt en Disallow retire ce qu'il restait
de l'argument. fichesExemple() reste dans le code comme jeu de
vérification, injecté en mémoire et jamais enregistré — pas comme une
fonctionnalité en attente.supabase/ n'est branché à rien, et ce n'est pas un oubli.Une note conditionnelle dans un message de commit finit par être lue comme une tâche : la condition est la première chose qui saute quand quelqu'un relaie la phrase, et l'attribution la deuxième. Ne pas en écrire ; l'écrire ici à la place.
Le fonctionnement hors-ligne ne s'observe que sur la page publique. Le
navigateur de contrôle refuse d'enregistrer un service worker sur une origine
en http://, localhost compris, avec un message qui ne dit pas sa cause :
« An unknown error occurred when fetching the script ». Deux agents ont cru
successivement à un en-tête, à la version du protocole, puis aux accents du
fichier — éprouvé avec un script de quarante-huit octets en pur ASCII sur un
serveur neutre, il échoue aussi.
Tout fonctionne en ligne, mise à jour comprise. Ne pas rediagnostiquer ceci depuis un port local : y observer une anomalie ne prouve rien.
Trois agents travaillent en parallèle, chacun sur un onglet, chacun dans sa copie isolée du dépôt. Les règles qui font que ça tient :
main : un travail non fusionné
est invisible pour tout le monde.index.html, qui est généré.
Fusionner sans relancer build.py ne change rien à l'écran.python3 outils/surfaces.py
Il compare les quatre surfaces — copie de travail, main, le 4173, la page
publique — et dit laquelle diverge. La cause la plus fréquente d'un « ce n'est
pas à jour » n'est pas le code : c'est qu'on ne regarde pas la surface qu'on
vérifie. Le 4173 a déjà servi la copie isolée d'un agent pendant qu'un autre en
tirait des conclusions sur main.
Le script existe pour une raison précise : deux agents ont comparé le même
fichier, l'un avec shasum, l'autre avec shasum -a 256, obtenu deux valeurs
différentes et failli conclure qu'ils regardaient des pages différentes. Une
règle qui dépend de l'outil que chacun choisit n'est pas une règle — d'où un
seul script, un seul algorithme, pour tout le monde.