mobius-charles 0.3.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (175) hide show
  1. mobius_charles-0.3.0/PKG-INFO +178 -0
  2. mobius_charles-0.3.0/README.md +153 -0
  3. mobius_charles-0.3.0/pyproject.toml +88 -0
  4. mobius_charles-0.3.0/src/mobius/__init__.py +3 -0
  5. mobius_charles-0.3.0/src/mobius/agents/__init__.py +6 -0
  6. mobius_charles-0.3.0/src/mobius/agents/loader.py +175 -0
  7. mobius_charles-0.3.0/src/mobius/agents/personas/__init__.py +1 -0
  8. mobius_charles-0.3.0/src/mobius/agents/personas/architect.md +60 -0
  9. mobius_charles-0.3.0/src/mobius/agents/personas/contrarian.md +64 -0
  10. mobius_charles-0.3.0/src/mobius/agents/personas/hacker.md +60 -0
  11. mobius_charles-0.3.0/src/mobius/agents/personas/researcher.md +62 -0
  12. mobius_charles-0.3.0/src/mobius/agents/personas/simplifier.md +58 -0
  13. mobius_charles-0.3.0/src/mobius/agents/templates/__init__.py +1 -0
  14. mobius_charles-0.3.0/src/mobius/agents/templates/claude.j2.md +18 -0
  15. mobius_charles-0.3.0/src/mobius/agents/templates/codex.j2.md +18 -0
  16. mobius_charles-0.3.0/src/mobius/agents/templates/hermes.j2.md +18 -0
  17. mobius_charles-0.3.0/src/mobius/cli/__init__.py +416 -0
  18. mobius_charles-0.3.0/src/mobius/cli/command_registry.py +1181 -0
  19. mobius_charles-0.3.0/src/mobius/cli/commands/__init__.py +5 -0
  20. mobius_charles-0.3.0/src/mobius/cli/commands/agent.py +170 -0
  21. mobius_charles-0.3.0/src/mobius/cli/commands/build.py +230 -0
  22. mobius_charles-0.3.0/src/mobius/cli/commands/cancel.py +22 -0
  23. mobius_charles-0.3.0/src/mobius/cli/commands/config.py +106 -0
  24. mobius_charles-0.3.0/src/mobius/cli/commands/evolve.py +55 -0
  25. mobius_charles-0.3.0/src/mobius/cli/commands/go.py +420 -0
  26. mobius_charles-0.3.0/src/mobius/cli/commands/init.py +93 -0
  27. mobius_charles-0.3.0/src/mobius/cli/commands/interview.py +781 -0
  28. mobius_charles-0.3.0/src/mobius/cli/commands/lineage.py +124 -0
  29. mobius_charles-0.3.0/src/mobius/cli/commands/qa.py +114 -0
  30. mobius_charles-0.3.0/src/mobius/cli/commands/ralph.py +143 -0
  31. mobius_charles-0.3.0/src/mobius/cli/commands/run.py +104 -0
  32. mobius_charles-0.3.0/src/mobius/cli/commands/seed.py +250 -0
  33. mobius_charles-0.3.0/src/mobius/cli/commands/setup.py +381 -0
  34. mobius_charles-0.3.0/src/mobius/cli/commands/status.py +398 -0
  35. mobius_charles-0.3.0/src/mobius/cli/commands/todo.py +162 -0
  36. mobius_charles-0.3.0/src/mobius/cli/commands/ultraqa.py +82 -0
  37. mobius_charles-0.3.0/src/mobius/cli/formatter.py +225 -0
  38. mobius_charles-0.3.0/src/mobius/cli/main.py +131 -0
  39. mobius_charles-0.3.0/src/mobius/cli/output.py +25 -0
  40. mobius_charles-0.3.0/src/mobius/cli/session_inspector.py +415 -0
  41. mobius_charles-0.3.0/src/mobius/config.py +149 -0
  42. mobius_charles-0.3.0/src/mobius/core/__init__.py +2 -0
  43. mobius_charles-0.3.0/src/mobius/core/criterion_match.py +75 -0
  44. mobius_charles-0.3.0/src/mobius/core/types.py +16 -0
  45. mobius_charles-0.3.0/src/mobius/event_schema.py +75 -0
  46. mobius_charles-0.3.0/src/mobius/integration/__init__.py +32 -0
  47. mobius_charles-0.3.0/src/mobius/integration/assets/__init__.py +1 -0
  48. mobius_charles-0.3.0/src/mobius/integration/assets/claude_commands/agent.md +14 -0
  49. mobius_charles-0.3.0/src/mobius/integration/assets/claude_commands/blind-spot.md +16 -0
  50. mobius_charles-0.3.0/src/mobius/integration/assets/claude_commands/build.md +14 -0
  51. mobius_charles-0.3.0/src/mobius/integration/assets/claude_commands/cancel.md +14 -0
  52. mobius_charles-0.3.0/src/mobius/integration/assets/claude_commands/evolve.md +15 -0
  53. mobius_charles-0.3.0/src/mobius/integration/assets/claude_commands/go.md +14 -0
  54. mobius_charles-0.3.0/src/mobius/integration/assets/claude_commands/help.md +17 -0
  55. mobius_charles-0.3.0/src/mobius/integration/assets/claude_commands/interview.md +62 -0
  56. mobius_charles-0.3.0/src/mobius/integration/assets/claude_commands/lineage.md +13 -0
  57. mobius_charles-0.3.0/src/mobius/integration/assets/claude_commands/maturity.md +14 -0
  58. mobius_charles-0.3.0/src/mobius/integration/assets/claude_commands/qa.md +13 -0
  59. mobius_charles-0.3.0/src/mobius/integration/assets/claude_commands/ralph.md +15 -0
  60. mobius_charles-0.3.0/src/mobius/integration/assets/claude_commands/run.md +15 -0
  61. mobius_charles-0.3.0/src/mobius/integration/assets/claude_commands/seed.md +14 -0
  62. mobius_charles-0.3.0/src/mobius/integration/assets/claude_commands/setup.md +19 -0
  63. mobius_charles-0.3.0/src/mobius/integration/assets/claude_commands/status.md +14 -0
  64. mobius_charles-0.3.0/src/mobius/integration/assets/claude_commands/todo.md +14 -0
  65. mobius_charles-0.3.0/src/mobius/integration/assets/claude_commands/ultraqa.md +14 -0
  66. mobius_charles-0.3.0/src/mobius/integration/assets/claude_commands/unstuck.md +17 -0
  67. mobius_charles-0.3.0/src/mobius/integration/assets/skills/agent/SKILL.md +18 -0
  68. mobius_charles-0.3.0/src/mobius/integration/assets/skills/blind-spot/SKILL.md +27 -0
  69. mobius_charles-0.3.0/src/mobius/integration/assets/skills/blind-spot.md +16 -0
  70. mobius_charles-0.3.0/src/mobius/integration/assets/skills/build/SKILL.md +18 -0
  71. mobius_charles-0.3.0/src/mobius/integration/assets/skills/cancel/SKILL.md +24 -0
  72. mobius_charles-0.3.0/src/mobius/integration/assets/skills/evolve/SKILL.md +24 -0
  73. mobius_charles-0.3.0/src/mobius/integration/assets/skills/evolve.md +16 -0
  74. mobius_charles-0.3.0/src/mobius/integration/assets/skills/go/SKILL.md +18 -0
  75. mobius_charles-0.3.0/src/mobius/integration/assets/skills/go.md +15 -0
  76. mobius_charles-0.3.0/src/mobius/integration/assets/skills/help/SKILL.md +48 -0
  77. mobius_charles-0.3.0/src/mobius/integration/assets/skills/interview/SKILL.md +245 -0
  78. mobius_charles-0.3.0/src/mobius/integration/assets/skills/lineage/SKILL.md +23 -0
  79. mobius_charles-0.3.0/src/mobius/integration/assets/skills/maturity/SKILL.md +18 -0
  80. mobius_charles-0.3.0/src/mobius/integration/assets/skills/qa/SKILL.md +24 -0
  81. mobius_charles-0.3.0/src/mobius/integration/assets/skills/qa.md +15 -0
  82. mobius_charles-0.3.0/src/mobius/integration/assets/skills/ralph/SKILL.md +26 -0
  83. mobius_charles-0.3.0/src/mobius/integration/assets/skills/ralph.md +16 -0
  84. mobius_charles-0.3.0/src/mobius/integration/assets/skills/run/SKILL.md +27 -0
  85. mobius_charles-0.3.0/src/mobius/integration/assets/skills/seed/SKILL.md +26 -0
  86. mobius_charles-0.3.0/src/mobius/integration/assets/skills/setup/SKILL.md +36 -0
  87. mobius_charles-0.3.0/src/mobius/integration/assets/skills/status/SKILL.md +24 -0
  88. mobius_charles-0.3.0/src/mobius/integration/assets/skills/status.md +16 -0
  89. mobius_charles-0.3.0/src/mobius/integration/assets/skills/todo/SKILL.md +18 -0
  90. mobius_charles-0.3.0/src/mobius/integration/assets/skills/ultraqa/SKILL.md +18 -0
  91. mobius_charles-0.3.0/src/mobius/integration/assets/skills/unstuck/SKILL.md +59 -0
  92. mobius_charles-0.3.0/src/mobius/logging.py +61 -0
  93. mobius_charles-0.3.0/src/mobius/persistence/__init__.py +5 -0
  94. mobius_charles-0.3.0/src/mobius/persistence/event_store.py +435 -0
  95. mobius_charles-0.3.0/src/mobius/persistence/projections.py +529 -0
  96. mobius_charles-0.3.0/src/mobius/v3a/__init__.py +22 -0
  97. mobius_charles-0.3.0/src/mobius/v3a/cli/__init__.py +1 -0
  98. mobius_charles-0.3.0/src/mobius/v3a/cli/commands.py +513 -0
  99. mobius_charles-0.3.0/src/mobius/v3a/cli/main.py +190 -0
  100. mobius_charles-0.3.0/src/mobius/v3a/matrix/__init__.py +5 -0
  101. mobius_charles-0.3.0/src/mobius/v3a/matrix/diff.py +88 -0
  102. mobius_charles-0.3.0/src/mobius/v3a/matrix/pipeline.py +122 -0
  103. mobius_charles-0.3.0/src/mobius/v3a/maturity/__init__.py +21 -0
  104. mobius_charles-0.3.0/src/mobius/v3a/maturity/scorer.py +387 -0
  105. mobius_charles-0.3.0/src/mobius/v3a/phase_router/__init__.py +1 -0
  106. mobius_charles-0.3.0/src/mobius/v3a/phase_router/handoff.py +177 -0
  107. mobius_charles-0.3.0/src/mobius/v3a/phase_router/resume.py +65 -0
  108. mobius_charles-0.3.0/src/mobius/v3a/phase_router/router.py +257 -0
  109. mobius_charles-0.3.0/src/mobius/v3a/phase_router/tour.py +141 -0
  110. mobius_charles-0.3.0/src/mobius/v3a/phase_router/transitions.py +144 -0
  111. mobius_charles-0.3.0/src/mobius/v3a/projections.py +163 -0
  112. mobius_charles-0.3.0/src/mobius/v3a/scoring/__init__.py +1 -0
  113. mobius_charles-0.3.0/src/mobius/v3a/scoring/engine.py +138 -0
  114. mobius_charles-0.3.0/src/mobius/v3a/scoring/llm_judge.py +121 -0
  115. mobius_charles-0.3.0/src/mobius/v3a/scoring/mechanical.py +138 -0
  116. mobius_charles-0.3.0/src/mobius/v3a/scoring/rationale.py +46 -0
  117. mobius_charles-0.3.0/src/mobius/v3a/scoring/recommend.py +77 -0
  118. mobius_charles-0.3.0/src/mobius/workflow/__init__.py +1 -0
  119. mobius_charles-0.3.0/src/mobius/workflow/_yaml.py +74 -0
  120. mobius_charles-0.3.0/src/mobius/workflow/ac_tree.py +329 -0
  121. mobius_charles-0.3.0/src/mobius/workflow/adaptive_questions.py +333 -0
  122. mobius_charles-0.3.0/src/mobius/workflow/blind_spot.py +1606 -0
  123. mobius_charles-0.3.0/src/mobius/workflow/cancel.py +206 -0
  124. mobius_charles-0.3.0/src/mobius/workflow/context_detector.py +605 -0
  125. mobius_charles-0.3.0/src/mobius/workflow/criterion_match.py +17 -0
  126. mobius_charles-0.3.0/src/mobius/workflow/decision.py +339 -0
  127. mobius_charles-0.3.0/src/mobius/workflow/doctor.py +261 -0
  128. mobius_charles-0.3.0/src/mobius/workflow/drift.py +96 -0
  129. mobius_charles-0.3.0/src/mobius/workflow/evolve.py +1034 -0
  130. mobius_charles-0.3.0/src/mobius/workflow/grade.py +199 -0
  131. mobius_charles-0.3.0/src/mobius/workflow/handoff.py +187 -0
  132. mobius_charles-0.3.0/src/mobius/workflow/hud.py +311 -0
  133. mobius_charles-0.3.0/src/mobius/workflow/ids.py +35 -0
  134. mobius_charles-0.3.0/src/mobius/workflow/interview.py +192 -0
  135. mobius_charles-0.3.0/src/mobius/workflow/interview_contract.py +435 -0
  136. mobius_charles-0.3.0/src/mobius/workflow/interview_deep.py +488 -0
  137. mobius_charles-0.3.0/src/mobius/workflow/interview_interactive.py +170 -0
  138. mobius_charles-0.3.0/src/mobius/workflow/interview_memory.py +148 -0
  139. mobius_charles-0.3.0/src/mobius/workflow/interview_milestones.py +47 -0
  140. mobius_charles-0.3.0/src/mobius/workflow/interview_parsing.py +260 -0
  141. mobius_charles-0.3.0/src/mobius/workflow/interview_prompts.py +451 -0
  142. mobius_charles-0.3.0/src/mobius/workflow/interview_render.py +196 -0
  143. mobius_charles-0.3.0/src/mobius/workflow/interview_scoring.py +93 -0
  144. mobius_charles-0.3.0/src/mobius/workflow/interview_session_helpers.py +110 -0
  145. mobius_charles-0.3.0/src/mobius/workflow/interview_types.py +280 -0
  146. mobius_charles-0.3.0/src/mobius/workflow/interview_v3a/__init__.py +1 -0
  147. mobius_charles-0.3.0/src/mobius/workflow/interview_v3a/ambiguity_trend.py +46 -0
  148. mobius_charles-0.3.0/src/mobius/workflow/interview_v3a/architecte.py +32 -0
  149. mobius_charles-0.3.0/src/mobius/workflow/interview_v3a/avocat.py +47 -0
  150. mobius_charles-0.3.0/src/mobius/workflow/interview_v3a/budget_tracker.py +28 -0
  151. mobius_charles-0.3.0/src/mobius/workflow/interview_v3a/lemma_check.py +125 -0
  152. mobius_charles-0.3.0/src/mobius/workflow/interview_v3a/oracle.py +311 -0
  153. mobius_charles-0.3.0/src/mobius/workflow/interview_v3a/runner.py +579 -0
  154. mobius_charles-0.3.0/src/mobius/workflow/interview_v3a/scribe.py +126 -0
  155. mobius_charles-0.3.0/src/mobius/workflow/interview_v3a/socrate.py +152 -0
  156. mobius_charles-0.3.0/src/mobius/workflow/interview_v3a/templates/architecte-system.tmpl +1 -0
  157. mobius_charles-0.3.0/src/mobius/workflow/interview_v3a/templates/avocat-system.tmpl +1 -0
  158. mobius_charles-0.3.0/src/mobius/workflow/interview_v3a/templates/socrate-system.tmpl +1 -0
  159. mobius_charles-0.3.0/src/mobius/workflow/interview_v3a/transcript.py +75 -0
  160. mobius_charles-0.3.0/src/mobius/workflow/lateral.py +176 -0
  161. mobius_charles-0.3.0/src/mobius/workflow/launcher.py +210 -0
  162. mobius_charles-0.3.0/src/mobius/workflow/lifecycle.py +171 -0
  163. mobius_charles-0.3.0/src/mobius/workflow/lineage.py +201 -0
  164. mobius_charles-0.3.0/src/mobius/workflow/pal_router.py +284 -0
  165. mobius_charles-0.3.0/src/mobius/workflow/qa.py +619 -0
  166. mobius_charles-0.3.0/src/mobius/workflow/question_router.py +245 -0
  167. mobius_charles-0.3.0/src/mobius/workflow/ralph.py +580 -0
  168. mobius_charles-0.3.0/src/mobius/workflow/run.py +935 -0
  169. mobius_charles-0.3.0/src/mobius/workflow/scan.py +441 -0
  170. mobius_charles-0.3.0/src/mobius/workflow/seed.py +1189 -0
  171. mobius_charles-0.3.0/src/mobius/workflow/seed_closer.py +66 -0
  172. mobius_charles-0.3.0/src/mobius/workflow/session_facts.py +109 -0
  173. mobius_charles-0.3.0/src/mobius/workflow/templates.py +281 -0
  174. mobius_charles-0.3.0/src/mobius/workflow/ultraqa.py +298 -0
  175. mobius_charles-0.3.0/src/mobius/workflow/verify.py +244 -0
@@ -0,0 +1,178 @@
1
+ Metadata-Version: 2.4
2
+ Name: mobius-charles
3
+ Version: 0.3.0
4
+ Summary: Local-first AI workflow CLI with event-sourced runs and deterministic agent routing.
5
+ Keywords: ai-agents,cli,event-sourcing,local-first,workflow
6
+ Author: Mobius contributors
7
+ License-Expression: MIT
8
+ Classifier: Development Status :: 3 - Alpha
9
+ Classifier: Environment :: Console
10
+ Classifier: Intended Audience :: Developers
11
+ Classifier: License :: OSI Approved :: MIT License
12
+ Classifier: Programming Language :: Python :: 3
13
+ Classifier: Programming Language :: Python :: 3.12
14
+ Classifier: Topic :: Software Development :: Build Tools
15
+ Classifier: Topic :: Software Development :: Quality Assurance
16
+ Requires-Dist: pydantic>=2.12.0
17
+ Requires-Dist: rich>=14.0.0
18
+ Requires-Dist: typer>=0.20.0
19
+ Requires-Python: >=3.12
20
+ Project-URL: Homepage, https://github.com/charlescstpierr/mobius-charles
21
+ Project-URL: Repository, https://github.com/charlescstpierr/mobius-charles
22
+ Project-URL: Issues, https://github.com/charlescstpierr/mobius-charles/issues
23
+ Project-URL: Changelog, https://github.com/charlescstpierr/mobius-charles/blob/main/CHANGELOG.md
24
+ Description-Content-Type: text/markdown
25
+
26
+ # Mobius
27
+
28
+ [![CI](https://github.com/charlescstpierr/mobius-charles/actions/workflows/ci.yml/badge.svg)](https://github.com/charlescstpierr/mobius-charles/actions/workflows/ci.yml)
29
+ [![Coverage](https://img.shields.io/badge/coverage-%E2%89%A595%25-brightgreen.svg)](docs/benchmarks.md)
30
+ [![PyPI](https://img.shields.io/pypi/v/mobius-charles.svg)](https://pypi.org/project/mobius-charles/)
31
+ [![License](https://img.shields.io/github/license/charlescstpierr/mobius-charles)](LICENSE)
32
+ [![Python](https://img.shields.io/badge/python-3.12%2B-blue.svg)](pyproject.toml)
33
+
34
+ Mobius est une CLI Python **local-first, auditable et déterministe** pour piloter des agents IA. Event sourcing SQLite, lineage rejouable, routage d'agent offline (PAL Router) — zéro serveur, zéro dépendance réseau. Un **chemin débutant en une commande** :
35
+
36
+ ```sh
37
+ mobius go "je veux une app de recettes"
38
+ ```
39
+
40
+ Cette commande clarifie l'idée, écrit `spec.yaml`, crée le seed, lance un run, puis vous indique les prochaines commandes lisibles (`mobius status`, `mobius qa`, `mobius ralph`). Quand l'exécution est activée, `go` transmet l'approbation agent au run généré par défaut; utilisez `--ask-agent` pour reprendre une validation explicite.
41
+
42
+ > **Event sourcing** — chaque décision, chaque run, chaque évaluation est un événement immuable dans SQLite (WAL). Rejouez n'importe quel état passé avec `mobius lineage`.
43
+ >
44
+ > **PAL Router** — routage déterministe offline vers l'agent optimal (claude, codex, droid) sans appel LLM. `--agent auto --approve-agent` résout localement.
45
+ >
46
+ > **Transparence totale** — le code réel reste exécuté par votre agent choisi ou vos commandes locales; Mobius orchestre le happy path et trace les preuves. Pas de serveur, pas de LLM caché.
47
+
48
+ ## Installation
49
+
50
+ Paquet public PyPI (nom de distribution: `mobius-charles`, commande installée: `mobius`) :
51
+
52
+ ```bash
53
+ uv tool install mobius-charles
54
+ ```
55
+
56
+ ```bash
57
+ mobius --help
58
+ ```
59
+
60
+ Chemins équivalents :
61
+
62
+ ```sh
63
+ pipx install mobius-charles
64
+ # ou depuis un checkout de développement
65
+ uv tool install . --force
66
+ ./install.sh
67
+ ```
68
+
69
+ Puis démarrez le chemin débutant :
70
+
71
+ ```sh
72
+ mobius go "mon idée"
73
+ ```
74
+
75
+ ## Répertoire d'état
76
+
77
+ Mobius stocke l'état dans SQLite à `$MOBIUS_HOME/events.db`. Sans `MOBIUS_HOME`, le chemin par défaut est `~/.mobius/events.db`, partagé entre les projets (`shared across every Mobius project`). Pour isoler un workspace :
78
+
79
+ ```sh
80
+ export MOBIUS_HOME="$PWD/.mobius"
81
+ ```
82
+
83
+ `mobius init` affiche le chemin résolu et `mobius config get event_store` le retourne à tout moment.
84
+
85
+ ## Démarrage rapide
86
+
87
+ ```sh
88
+ uv tool install mobius-charles
89
+ mobius go "je veux une petite CLI qui salue l'utilisateur"
90
+ mobius status
91
+ mobius qa
92
+ mobius ralph --dry-run
93
+ ```
94
+
95
+ Chemin CI/script avancé :
96
+
97
+ ```bash
98
+ export MOBIUS_HOME="$(mktemp -d)" # optionnel: isole l'état
99
+ cat > /tmp/mobius-fixture.yaml <<'YAML'
100
+ project_type: greenfield
101
+ goal: Livrer un petit test de fumée CLI.
102
+ constraints:
103
+ - Garder tout l'état dans le MOBIUS_HOME temporaire.
104
+ - Éviter les services réseau.
105
+ success:
106
+ - Interview écrit une spec.
107
+ - Seed crée une session.
108
+ - Run se termine avec succès.
109
+ YAML
110
+ mobius interview --non-interactive --input /tmp/mobius-fixture.yaml --output /tmp/mobius-spec.yaml
111
+ mobius seed /tmp/mobius-spec.yaml --json
112
+ run_id="$(mobius run --spec /tmp/mobius-spec.yaml)"
113
+ mobius status "$run_id" --follow
114
+ ```
115
+
116
+ Pour démarrer un vrai workspace :
117
+
118
+ ```sh
119
+ mobius go "mon idée de projet"
120
+ ```
121
+
122
+ ## Commandes principales
123
+
124
+ - `mobius interview` — entretien projet interactif (modes deep, quick, conversationnel) avec juge interne à 3 lentilles (Clarté, Risques, Faisabilité), breadth keeper par questions-ponts, et persistance par tour.
125
+ - `mobius seed` — valide une spec et crée une session seed.
126
+ - `mobius run` — exécute avec un agent (`--agent codex --model gpt-5.5`, `--agent claude`, `--agent droid`). Chaque run est isolé dans un git worktree pour permettre l'exécution parallèle.
127
+ - `mobius status` — affiche la santé globale ou le statut d'un run.
128
+ - `mobius qa [RUN_ID]` — évalue un run avec un juge local déterministe.
129
+ - `mobius evolve [RUN_ID]` — lance une boucle d'évolution depuis un run existant.
130
+ - `mobius cancel RUN_ID` — annule un run détaché et nettoie son PID.
131
+ - `mobius lineage [AGGREGATE_ID]` — affiche les ancêtres, descendants ou le hash de replay.
132
+ - `mobius init` — crée un `spec.yaml` de départ et initialise l'event store.
133
+ - `mobius setup` — installe les assets d'intégration agent.
134
+ - `mobius config` — affiche, lit ou modifie la configuration Mobius.
135
+ - `mobius handoff` — génère un prompt versionné pour un agent de code.
136
+ - `mobius hud` — tableau de bord basé sur les projections.
137
+
138
+ Commandes avancées :
139
+
140
+ - `mobius build` — compose une première spec guidée depuis une idée.
141
+ - `mobius projection` — gère le cache de projections.
142
+ - `mobius cold-start` — mesure le budget de démarrage à froid.
143
+
144
+ ## Exécution parallèle
145
+
146
+ Chaque `mobius run` isole automatiquement l'agent dans un **git worktree** dédié. Cela permet de lancer plusieurs runs en parallèle sans conflit :
147
+
148
+ ```sh
149
+ mobius run --spec spec-auth.yaml --agent codex --model gpt-5.5 --approve-agent
150
+ mobius run --spec spec-ui.yaml --agent codex --model gpt-5.5 --approve-agent
151
+ mobius run --spec spec-api.yaml --agent claude --model opus-4.7 --approve-agent
152
+ # Les 3 tournent en parallèle, chacun dans son propre espace.
153
+ ```
154
+
155
+ ## Interview Deep améliorée
156
+
157
+ Le mode `--mode deep` inclut :
158
+
159
+ - **Persistance par tour** — chaque round est sauvegardé dans un fichier JSON incrémental. Un crash ne perd aucune donnée.
160
+ - **Juge interne à 3 lentilles** — Clarté (Socrate), Risques (Avocat), Faisabilité (Architecte). Le juge guide silencieusement le choix des questions et hausse le ton quand un problème est détecté.
161
+ - **Breadth keeper** — si un axe thématique est touché 2 fois de suite, une question-pont connecte naturellement vers un axe non couvert.
162
+ - **Recommandations argumentées** — chaque question inclut la recommandation de Mobius avant de demander l'avis de l'utilisateur.
163
+ - **Reprise après crash** — détection automatique d'une interview interrompue avec 3 choix (reprendre / recommencer / voir le résumé).
164
+
165
+ ## Préparation release PyPI
166
+
167
+ Avant publication, sans effet externe :
168
+
169
+ 1. Vérifier que le nom PyPI public est libre/choisi : `mobius-charles` (le nom `mobius` est déjà pris sur PyPI).
170
+ 2. Vérifier les métadonnées : `uv build --out-dir /tmp/mobius-dist`.
171
+ 3. Valider les artefacts : `uvx twine check /tmp/mobius-dist/*`.
172
+ 4. Installer le wheel dans un environnement propre et lancer `mobius --help`.
173
+ 5. Tester les assets sans écrire : `mobius setup --runtime claude|codex|hermes --dry-run`.
174
+ 6. Vérifier l'authentification de publication sans contacter PyPI : `uv run python scripts/verify_publish_auth.py`.
175
+ 7. Publier seulement après GO explicite, idéalement via GitHub Actions `Publish PyPI` + PyPI Trusted Publishing. En local seulement si token disponible : `uv publish --token "$PYPI_TOKEN" /tmp/mobius-dist/*`.
176
+ 8. Après publication, vérifier le paquet réellement publié : `uv run python scripts/verify_post_publish.py --version 0.3.0`.
177
+
178
+ Voir aussi [`docs/cli-reference.md`](docs/cli-reference.md), [`CHANGELOG.md`](CHANGELOG.md), [`CONTRIBUTING.md`](CONTRIBUTING.md) et [`SECURITY.md`](SECURITY.md).
@@ -0,0 +1,153 @@
1
+ # Mobius
2
+
3
+ [![CI](https://github.com/charlescstpierr/mobius-charles/actions/workflows/ci.yml/badge.svg)](https://github.com/charlescstpierr/mobius-charles/actions/workflows/ci.yml)
4
+ [![Coverage](https://img.shields.io/badge/coverage-%E2%89%A595%25-brightgreen.svg)](docs/benchmarks.md)
5
+ [![PyPI](https://img.shields.io/pypi/v/mobius-charles.svg)](https://pypi.org/project/mobius-charles/)
6
+ [![License](https://img.shields.io/github/license/charlescstpierr/mobius-charles)](LICENSE)
7
+ [![Python](https://img.shields.io/badge/python-3.12%2B-blue.svg)](pyproject.toml)
8
+
9
+ Mobius est une CLI Python **local-first, auditable et déterministe** pour piloter des agents IA. Event sourcing SQLite, lineage rejouable, routage d'agent offline (PAL Router) — zéro serveur, zéro dépendance réseau. Un **chemin débutant en une commande** :
10
+
11
+ ```sh
12
+ mobius go "je veux une app de recettes"
13
+ ```
14
+
15
+ Cette commande clarifie l'idée, écrit `spec.yaml`, crée le seed, lance un run, puis vous indique les prochaines commandes lisibles (`mobius status`, `mobius qa`, `mobius ralph`). Quand l'exécution est activée, `go` transmet l'approbation agent au run généré par défaut; utilisez `--ask-agent` pour reprendre une validation explicite.
16
+
17
+ > **Event sourcing** — chaque décision, chaque run, chaque évaluation est un événement immuable dans SQLite (WAL). Rejouez n'importe quel état passé avec `mobius lineage`.
18
+ >
19
+ > **PAL Router** — routage déterministe offline vers l'agent optimal (claude, codex, droid) sans appel LLM. `--agent auto --approve-agent` résout localement.
20
+ >
21
+ > **Transparence totale** — le code réel reste exécuté par votre agent choisi ou vos commandes locales; Mobius orchestre le happy path et trace les preuves. Pas de serveur, pas de LLM caché.
22
+
23
+ ## Installation
24
+
25
+ Paquet public PyPI (nom de distribution: `mobius-charles`, commande installée: `mobius`) :
26
+
27
+ ```bash
28
+ uv tool install mobius-charles
29
+ ```
30
+
31
+ ```bash
32
+ mobius --help
33
+ ```
34
+
35
+ Chemins équivalents :
36
+
37
+ ```sh
38
+ pipx install mobius-charles
39
+ # ou depuis un checkout de développement
40
+ uv tool install . --force
41
+ ./install.sh
42
+ ```
43
+
44
+ Puis démarrez le chemin débutant :
45
+
46
+ ```sh
47
+ mobius go "mon idée"
48
+ ```
49
+
50
+ ## Répertoire d'état
51
+
52
+ Mobius stocke l'état dans SQLite à `$MOBIUS_HOME/events.db`. Sans `MOBIUS_HOME`, le chemin par défaut est `~/.mobius/events.db`, partagé entre les projets (`shared across every Mobius project`). Pour isoler un workspace :
53
+
54
+ ```sh
55
+ export MOBIUS_HOME="$PWD/.mobius"
56
+ ```
57
+
58
+ `mobius init` affiche le chemin résolu et `mobius config get event_store` le retourne à tout moment.
59
+
60
+ ## Démarrage rapide
61
+
62
+ ```sh
63
+ uv tool install mobius-charles
64
+ mobius go "je veux une petite CLI qui salue l'utilisateur"
65
+ mobius status
66
+ mobius qa
67
+ mobius ralph --dry-run
68
+ ```
69
+
70
+ Chemin CI/script avancé :
71
+
72
+ ```bash
73
+ export MOBIUS_HOME="$(mktemp -d)" # optionnel: isole l'état
74
+ cat > /tmp/mobius-fixture.yaml <<'YAML'
75
+ project_type: greenfield
76
+ goal: Livrer un petit test de fumée CLI.
77
+ constraints:
78
+ - Garder tout l'état dans le MOBIUS_HOME temporaire.
79
+ - Éviter les services réseau.
80
+ success:
81
+ - Interview écrit une spec.
82
+ - Seed crée une session.
83
+ - Run se termine avec succès.
84
+ YAML
85
+ mobius interview --non-interactive --input /tmp/mobius-fixture.yaml --output /tmp/mobius-spec.yaml
86
+ mobius seed /tmp/mobius-spec.yaml --json
87
+ run_id="$(mobius run --spec /tmp/mobius-spec.yaml)"
88
+ mobius status "$run_id" --follow
89
+ ```
90
+
91
+ Pour démarrer un vrai workspace :
92
+
93
+ ```sh
94
+ mobius go "mon idée de projet"
95
+ ```
96
+
97
+ ## Commandes principales
98
+
99
+ - `mobius interview` — entretien projet interactif (modes deep, quick, conversationnel) avec juge interne à 3 lentilles (Clarté, Risques, Faisabilité), breadth keeper par questions-ponts, et persistance par tour.
100
+ - `mobius seed` — valide une spec et crée une session seed.
101
+ - `mobius run` — exécute avec un agent (`--agent codex --model gpt-5.5`, `--agent claude`, `--agent droid`). Chaque run est isolé dans un git worktree pour permettre l'exécution parallèle.
102
+ - `mobius status` — affiche la santé globale ou le statut d'un run.
103
+ - `mobius qa [RUN_ID]` — évalue un run avec un juge local déterministe.
104
+ - `mobius evolve [RUN_ID]` — lance une boucle d'évolution depuis un run existant.
105
+ - `mobius cancel RUN_ID` — annule un run détaché et nettoie son PID.
106
+ - `mobius lineage [AGGREGATE_ID]` — affiche les ancêtres, descendants ou le hash de replay.
107
+ - `mobius init` — crée un `spec.yaml` de départ et initialise l'event store.
108
+ - `mobius setup` — installe les assets d'intégration agent.
109
+ - `mobius config` — affiche, lit ou modifie la configuration Mobius.
110
+ - `mobius handoff` — génère un prompt versionné pour un agent de code.
111
+ - `mobius hud` — tableau de bord basé sur les projections.
112
+
113
+ Commandes avancées :
114
+
115
+ - `mobius build` — compose une première spec guidée depuis une idée.
116
+ - `mobius projection` — gère le cache de projections.
117
+ - `mobius cold-start` — mesure le budget de démarrage à froid.
118
+
119
+ ## Exécution parallèle
120
+
121
+ Chaque `mobius run` isole automatiquement l'agent dans un **git worktree** dédié. Cela permet de lancer plusieurs runs en parallèle sans conflit :
122
+
123
+ ```sh
124
+ mobius run --spec spec-auth.yaml --agent codex --model gpt-5.5 --approve-agent
125
+ mobius run --spec spec-ui.yaml --agent codex --model gpt-5.5 --approve-agent
126
+ mobius run --spec spec-api.yaml --agent claude --model opus-4.7 --approve-agent
127
+ # Les 3 tournent en parallèle, chacun dans son propre espace.
128
+ ```
129
+
130
+ ## Interview Deep améliorée
131
+
132
+ Le mode `--mode deep` inclut :
133
+
134
+ - **Persistance par tour** — chaque round est sauvegardé dans un fichier JSON incrémental. Un crash ne perd aucune donnée.
135
+ - **Juge interne à 3 lentilles** — Clarté (Socrate), Risques (Avocat), Faisabilité (Architecte). Le juge guide silencieusement le choix des questions et hausse le ton quand un problème est détecté.
136
+ - **Breadth keeper** — si un axe thématique est touché 2 fois de suite, une question-pont connecte naturellement vers un axe non couvert.
137
+ - **Recommandations argumentées** — chaque question inclut la recommandation de Mobius avant de demander l'avis de l'utilisateur.
138
+ - **Reprise après crash** — détection automatique d'une interview interrompue avec 3 choix (reprendre / recommencer / voir le résumé).
139
+
140
+ ## Préparation release PyPI
141
+
142
+ Avant publication, sans effet externe :
143
+
144
+ 1. Vérifier que le nom PyPI public est libre/choisi : `mobius-charles` (le nom `mobius` est déjà pris sur PyPI).
145
+ 2. Vérifier les métadonnées : `uv build --out-dir /tmp/mobius-dist`.
146
+ 3. Valider les artefacts : `uvx twine check /tmp/mobius-dist/*`.
147
+ 4. Installer le wheel dans un environnement propre et lancer `mobius --help`.
148
+ 5. Tester les assets sans écrire : `mobius setup --runtime claude|codex|hermes --dry-run`.
149
+ 6. Vérifier l'authentification de publication sans contacter PyPI : `uv run python scripts/verify_publish_auth.py`.
150
+ 7. Publier seulement après GO explicite, idéalement via GitHub Actions `Publish PyPI` + PyPI Trusted Publishing. En local seulement si token disponible : `uv publish --token "$PYPI_TOKEN" /tmp/mobius-dist/*`.
151
+ 8. Après publication, vérifier le paquet réellement publié : `uv run python scripts/verify_post_publish.py --version 0.3.0`.
152
+
153
+ Voir aussi [`docs/cli-reference.md`](docs/cli-reference.md), [`CHANGELOG.md`](CHANGELOG.md), [`CONTRIBUTING.md`](CONTRIBUTING.md) et [`SECURITY.md`](SECURITY.md).
@@ -0,0 +1,88 @@
1
+ [project]
2
+ name = "mobius-charles"
3
+ version = "0.3.0"
4
+ description = "Local-first AI workflow CLI with event-sourced runs and deterministic agent routing."
5
+ readme = "README.md"
6
+ keywords = ["ai-agents", "cli", "event-sourcing", "local-first", "workflow"]
7
+ requires-python = ">=3.12"
8
+ license = "MIT"
9
+ authors = [
10
+ { name = "Mobius contributors" },
11
+ ]
12
+ dependencies = [
13
+ "pydantic>=2.12.0",
14
+ "rich>=14.0.0",
15
+ "typer>=0.20.0",
16
+ ]
17
+ classifiers = [
18
+ "Development Status :: 3 - Alpha",
19
+ "Environment :: Console",
20
+ "Intended Audience :: Developers",
21
+ "License :: OSI Approved :: MIT License",
22
+ "Programming Language :: Python :: 3",
23
+ "Programming Language :: Python :: 3.12",
24
+ "Topic :: Software Development :: Build Tools",
25
+ "Topic :: Software Development :: Quality Assurance",
26
+ ]
27
+
28
+ [project.urls]
29
+ Homepage = "https://github.com/charlescstpierr/mobius-charles"
30
+ Repository = "https://github.com/charlescstpierr/mobius-charles"
31
+ Issues = "https://github.com/charlescstpierr/mobius-charles/issues"
32
+ Changelog = "https://github.com/charlescstpierr/mobius-charles/blob/main/CHANGELOG.md"
33
+
34
+ [project.scripts]
35
+ mobius = "mobius.cli:main"
36
+
37
+ [dependency-groups]
38
+ dev = [
39
+ "hypothesis>=6.152.4",
40
+ "mypy>=1.19.0",
41
+ "pytest>=9.0.0",
42
+ "pytest-cov>=7.1.0",
43
+ "ruff>=0.14.0",
44
+ ]
45
+
46
+ [build-system]
47
+ requires = ["uv_build>=0.10.0,<0.11.0"]
48
+ build-backend = "uv_build"
49
+
50
+ [tool.uv.build-backend]
51
+ module-root = "src"
52
+ module-name = "mobius"
53
+
54
+ [tool.ruff]
55
+ target-version = "py312"
56
+ line-length = 100
57
+ src = ["src"]
58
+
59
+ [tool.ruff.lint]
60
+ select = ["E", "F", "I", "UP", "B", "SIM"]
61
+
62
+ [tool.ruff.lint.per-file-ignores]
63
+ # The blind-spot catalog contains long French prose and diagram strings where
64
+ # wrapping would make the source harder to review without changing behavior.
65
+ "src/mobius/workflow/blind_spot.py" = ["E501"]
66
+
67
+ [tool.ruff.format]
68
+ quote-style = "double"
69
+ indent-style = "space"
70
+
71
+ [tool.mypy]
72
+ python_version = "3.12"
73
+ strict = true
74
+ files = ["src/mobius"]
75
+
76
+ [tool.pytest.ini_options]
77
+ addopts = "--import-mode=importlib"
78
+ testpaths = ["tests"]
79
+
80
+ [tool.coverage.run]
81
+ patch = ["subprocess"]
82
+ source = ["src/mobius"]
83
+ branch = true
84
+
85
+ [tool.coverage.report]
86
+ fail_under = 80
87
+ precision = 2
88
+ show_missing = true
@@ -0,0 +1,3 @@
1
+ """Mobius package."""
2
+
3
+ __version__ = "0.3.0"
@@ -0,0 +1,6 @@
1
+ """Agent handoff template registry."""
2
+
3
+ from __future__ import annotations
4
+
5
+ KNOWN_AGENTS: tuple[str, ...] = ("claude", "codex", "hermes")
6
+ TEMPLATE_VERSION = 1
@@ -0,0 +1,175 @@
1
+ """Chargeur de prompts de personas — source unique pour tous les prompts système.
2
+
3
+ Charge les fichiers .md avec une stratégie de résolution à 3 niveaux :
4
+
5
+ 1. Répertoire projet-local ``.mobius/agents/`` dans le répertoire courant
6
+ 2. Variable d'environnement ``MOBIUS_AGENTS_DIR`` — répertoire d'override utilisateur
7
+ 3. ``importlib.resources`` — prompts embarqués dans le package
8
+ """
9
+
10
+ from __future__ import annotations
11
+
12
+ import functools
13
+ import importlib.resources
14
+ import os
15
+ import re
16
+ from dataclasses import dataclass
17
+ from pathlib import Path
18
+
19
+ PERSONAS = ("contrarian", "hacker", "simplifier", "researcher", "architect")
20
+
21
+
22
+ def _is_safe_path(path: Path, parent: Path) -> bool:
23
+ """Vérifier qu'un chemin résolu reste sous le répertoire parent (anti-symlink escape)."""
24
+ try:
25
+ resolved = path.resolve(strict=True)
26
+ return str(resolved).startswith(str(parent.resolve()))
27
+ except OSError:
28
+ return False
29
+
30
+
31
+ @functools.lru_cache(maxsize=32)
32
+ def _resolve_persona_path(name: str, _cwd: str = "") -> Path | None:
33
+ """Trouver un fichier .md de persona via la stratégie d'override à 3 niveaux."""
34
+ filename = f"{name}.md"
35
+ project_dir = Path(_cwd or Path.cwd()) / ".mobius" / "agents"
36
+ if project_dir.is_dir():
37
+ path = project_dir / filename
38
+ if path.exists() and _is_safe_path(path, project_dir):
39
+ return path
40
+ agents_dir = os.environ.get("MOBIUS_AGENTS_DIR")
41
+ if agents_dir:
42
+ env_dir = Path(agents_dir)
43
+ path = env_dir / filename
44
+ if path.exists() and _is_safe_path(path, env_dir):
45
+ return path
46
+ return None
47
+
48
+
49
+ @functools.lru_cache(maxsize=32)
50
+ def load_persona(name: str) -> str:
51
+ """Charger le contenu markdown complet d'une persona.
52
+
53
+ Args:
54
+ name: Identifiant de la persona, ex. ``"contrarian"``.
55
+
56
+ Returns:
57
+ Texte markdown complet.
58
+
59
+ Raises:
60
+ FileNotFoundError: Si le fichier .md est introuvable.
61
+ """
62
+ _validate_name(name)
63
+ path = _resolve_persona_path(name, str(Path.cwd()))
64
+ if path is not None:
65
+ return path.read_text(encoding="utf-8")
66
+
67
+ package = importlib.resources.files("mobius.agents.personas")
68
+ resource = package.joinpath(f"{name}.md")
69
+ try:
70
+ return resource.read_text(encoding="utf-8")
71
+ except (FileNotFoundError, TypeError):
72
+ raise FileNotFoundError(
73
+ f"Persona introuvable : {name}.md "
74
+ f"(cherché dans MOBIUS_AGENTS_DIR et mobius.agents.personas)"
75
+ ) from None
76
+
77
+
78
+ def load_section(name: str, section: str) -> str:
79
+ """Extraire une section ``## <section>`` d'un fichier de persona."""
80
+ content = load_persona(name)
81
+ return extract_section(content, section)
82
+
83
+
84
+ def list_personas() -> tuple[str, ...]:
85
+ """Retourner les noms de toutes les personas disponibles (embarquées + projet)."""
86
+ names: set[str] = set(PERSONAS)
87
+ project_dir = Path.cwd() / ".mobius" / "agents"
88
+ if project_dir.is_dir():
89
+ for md in project_dir.glob("*.md"):
90
+ names.add(md.stem)
91
+ agents_dir = os.environ.get("MOBIUS_AGENTS_DIR")
92
+ if agents_dir:
93
+ env_path = Path(agents_dir)
94
+ if env_path.is_dir():
95
+ for md in env_path.glob("*.md"):
96
+ names.add(md.stem)
97
+ return tuple(sorted(names))
98
+
99
+
100
+ def clear_cache() -> None:
101
+ """Vider le cache des prompts. Utile pour les tests."""
102
+ load_persona.cache_clear()
103
+ _resolve_persona_path.cache_clear()
104
+
105
+
106
+ def extract_section(content: str, section: str) -> str:
107
+ """Extraire tout entre ``## <section>`` et le prochain ``##``."""
108
+ lines = content.split("\n")
109
+ pattern = re.compile(rf"^##\s+{re.escape(section)}\s*$", re.IGNORECASE)
110
+
111
+ start: int | None = None
112
+ for i, line in enumerate(lines):
113
+ if pattern.match(line.strip()):
114
+ start = i + 1
115
+ break
116
+ if start is None:
117
+ raise KeyError(f"Section '## {section}' introuvable")
118
+
119
+ end = len(lines)
120
+ for i in range(start, len(lines)):
121
+ if lines[i].strip().startswith("## "):
122
+ end = i
123
+ break
124
+
125
+ return "\n".join(lines[start:end]).strip()
126
+
127
+
128
+ def extract_questions(name: str) -> tuple[str, ...]:
129
+ """Extraire les questions (lignes ``- item``) de la section TES QUESTIONS."""
130
+ section = load_section(name, "TES QUESTIONS")
131
+ items: list[str] = []
132
+ for line in section.split("\n"):
133
+ stripped = line.strip()
134
+ if stripped.startswith("- "):
135
+ items.append(stripped[2:].strip())
136
+ return tuple(items)
137
+
138
+
139
+ @dataclass(frozen=True, slots=True)
140
+ class PersonaData:
141
+ """Données parsées d'un fichier .md de persona."""
142
+
143
+ name: str
144
+ philosophy: str
145
+ questions: tuple[str, ...]
146
+
147
+
148
+ def load_persona_data(name: str) -> PersonaData:
149
+ """Charger et parser un fichier .md de persona."""
150
+ content = load_persona(name)
151
+
152
+ lines = content.split("\n")
153
+ philosophy_lines: list[str] = []
154
+ past_title = False
155
+ for line in lines:
156
+ if line.startswith("# ") and not past_title:
157
+ past_title = True
158
+ continue
159
+ if line.startswith("## "):
160
+ break
161
+ if past_title and line.strip():
162
+ philosophy_lines.append(line.strip())
163
+
164
+ return PersonaData(
165
+ name=name,
166
+ philosophy=" ".join(philosophy_lines),
167
+ questions=extract_questions(name),
168
+ )
169
+
170
+
171
+ def _validate_name(name: str) -> None:
172
+ if name not in list_personas():
173
+ raise FileNotFoundError(
174
+ f"Persona inconnue : {name}. Personas disponibles : {', '.join(list_personas())}"
175
+ )
@@ -0,0 +1 @@
1
+ """Prompts de personas de pensée latérale embarqués dans le package."""
@@ -0,0 +1,60 @@
1
+ # Architect
2
+
3
+ Tu remets en question les fondations et restructures l'approche si nécessaire.
4
+
5
+ ## TA PHILOSOPHIE
6
+
7
+ « Un bon architecte sait quand renforcer les fondations et quand les remplacer. Corriger un défaut structurel tôt coûte 10x moins que le corriger tard. »
8
+
9
+ Tu ne patches pas — tu restructures. Si les fondations sont bancales, aucun correctif en surface ne tiendra.
10
+
11
+ ## TON APPROCHE
12
+
13
+ ### 1. Évaluer les fondations
14
+ Le problème est-il structurel ou superficiel ?
15
+ - Si chaque correctif crée un nouveau bug → problème structurel
16
+ - Si le code est difficile à modifier → le design est mauvais
17
+ - Si les tests sont fragiles → les abstractions sont mauvaises
18
+
19
+ ### 2. Identifier les couplages toxiques
20
+ Quels composants sont trop liés entre eux ?
21
+ - A change quand B change → couplage à casser
22
+ - Un changement touche 10 fichiers → abstraction manquante
23
+ - Les tests nécessitent des mocks complexes → interfaces mal définies
24
+
25
+ ### 3. Proposer une restructuration ciblée
26
+ Ne pas tout réécrire — cibler le point de levier :
27
+ - Extraire une interface là où le couplage est le pire
28
+ - Inverser une dépendance pour briser un cycle
29
+ - Séparer les préoccupations mélangées
30
+
31
+ ### 4. Valider avec les contraintes réelles
32
+ - La restructuration est-elle possible avec les délais actuels ?
33
+ - Peut-on migrer graduellement sans big bang ?
34
+ - Le bénéfice justifie-t-il le coût ?
35
+
36
+ ## TES QUESTIONS
37
+
38
+ - Le problème est-il dans le code ou dans le design ?
39
+ - Quel est le couplage le plus toxique du système ?
40
+ - Si on devait repartir de zéro, que ferait-on différemment ?
41
+ - Peut-on restructurer graduellement ou faut-il un big bang ?
42
+ - Quelle est la dette technique la plus coûteuse à ne PAS rembourser ?
43
+
44
+ ## TON RÔLE FACE AU BLOCAGE
45
+
46
+ Quand les correctifs ne tiennent pas, tu :
47
+ 1. Diagnostiques si le problème est structurel
48
+ 2. Identifies le point de levier minimal pour restructurer
49
+ 3. Proposes un plan de migration graduel
50
+ 4. Évalues le coût vs bénéfice de la restructuration
51
+
52
+ ## SORTIE
53
+
54
+ Fournis une analyse architecturale qui :
55
+ - Diagnostique si le problème est structurel ou superficiel
56
+ - Identifie les 1-2 couplages les plus toxiques
57
+ - Propose une restructuration ciblée (pas une réécriture)
58
+ - Donne un plan de migration en 3 étapes maximum
59
+
60
+ Sois pragmatique. L'architecture parfaite n'existe pas — seulement l'architecture suffisamment bonne.