@tricoteuses/tisseuse 0.20.0 → 0.21.1

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 (54) hide show
  1. package/README.md +113 -0
  2. package/dist/{html-C07GdZ0O.js → html-tp0cMUmA.js} +4170 -3730
  3. package/dist/index.js +136 -135
  4. package/dist/{resolver-4v_fWVor.js → resolver-CzmDH4S3.js} +138 -130
  5. package/dist/server-f-legi.js +73 -92
  6. package/dist/server.js +831 -793
  7. package/dist/src/lib/extractors/action_directives_cpu.test.d.ts +1 -0
  8. package/dist/src/lib/extractors/links.citation_scope.test.d.ts +1 -0
  9. package/dist/src/lib/extractors/links.d.ts +3 -1
  10. package/dist/src/lib/extractors/portion_references_cpu.test.d.ts +1 -0
  11. package/dist/src/lib/extractors/references.d.ts +12 -8
  12. package/dist/src/lib/f_legi/resolver.d.ts +0 -2
  13. package/dist/src/lib/index.d.ts +2 -1
  14. package/dist/src/lib/legi/canutes_article_preload.test.d.ts +1 -0
  15. package/dist/src/lib/legi/canutes_candidates.test.d.ts +1 -0
  16. package/dist/src/lib/legi/canutes_resolver.d.ts +5 -4
  17. package/dist/src/lib/legi/canutes_resolver_cache.test.d.ts +1 -0
  18. package/dist/src/lib/legi/canutes_root_cid_index.integration.test.d.ts +1 -0
  19. package/dist/src/lib/legi/canutes_section_roots.test.d.ts +1 -0
  20. package/dist/src/lib/legi/canutes_sql.d.ts +4 -0
  21. package/dist/src/lib/legi/canutes_text_titles_cache.d.ts +24 -0
  22. package/dist/src/lib/legi/canutes_text_titles_cache.integration.test.d.ts +1 -0
  23. package/dist/src/lib/legi/canutes_titles_metrics.d.ts +13 -0
  24. package/dist/src/lib/legi/text_titles_infos.d.ts +1 -0
  25. package/dist/src/lib/linkers/html.d.ts +6 -4
  26. package/dist/src/lib/linkers/markdown.d.ts +5 -3
  27. package/dist/src/lib/linkers/reference-mode.test.d.ts +1 -0
  28. package/dist/src/lib/server/akn_rendering.test.d.ts +1 -0
  29. package/dist/src/lib/server/bill_action_resolver_invariance.test.d.ts +1 -0
  30. package/dist/src/lib/server/bill_action_target_fixtures.d.ts +7 -0
  31. package/dist/src/lib/server/bill_citation_anaphora.test.d.ts +1 -0
  32. package/dist/src/lib/server/bill_comparison.d.ts +42 -0
  33. package/dist/src/lib/server/bill_comparison.test.d.ts +1 -0
  34. package/dist/src/lib/server/bill_target_scope.test.d.ts +1 -0
  35. package/dist/src/lib/server/canutes_legacy_candidates.d.ts +19 -0
  36. package/dist/src/lib/server/canutes_only_compatibility.test.d.ts +1 -0
  37. package/dist/src/lib/server/databases/canutes_root_cid_index.d.ts +11 -0
  38. package/dist/src/lib/server/databases/canutes_text_titles_cache.d.ts +8 -0
  39. package/dist/src/lib/server/flegi_profiling.d.ts +14 -0
  40. package/dist/src/lib/server/flegi_profiling.test.d.ts +1 -0
  41. package/dist/src/lib/server/masquage-typesense.test.d.ts +1 -0
  42. package/dist/src/lib/server/masquage_typesense.d.ts +36 -0
  43. package/dist/src/lib/server/sql_profiling.d.ts +30 -0
  44. package/dist/src/lib/server/sql_profiling.test.d.ts +1 -0
  45. package/dist/src/lib/text_parsers/action_words.d.ts +2 -0
  46. package/dist/src/lib/text_parsers/action_words.test.d.ts +1 -0
  47. package/dist/src/lib/text_parsers/texts.d.ts +1 -0
  48. package/dist/src/scripts/compare_legi_bills.d.ts +1 -0
  49. package/dist/src/scripts/configure_postgres_legi_resolver.d.ts +1 -0
  50. package/dist/src/scripts/configure_postgres_root_cid_index.d.ts +1 -0
  51. package/dist/src/scripts/profile_canutes_bill.d.ts +1 -0
  52. package/dist/src/scripts/test_canutes_titles_cache.d.ts +1 -0
  53. package/dist/src/scripts/warm_canutes_text_titles_cache.d.ts +1 -0
  54. package/package.json +9 -1
package/README.md CHANGED
@@ -9,6 +9,22 @@ _Tricoteuses Tisseuse_ is free and open source software.
9
9
 
10
10
  _Tricoteuses Tisseuse_ started from a full rewrite of [Metslesliens](https://www.npmjs.com/package/metslesliens) by Seb35, published under the "DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE" (WTFPL) version 2.
11
11
 
12
+ ## Contexte de lecture des références
13
+
14
+ `addLinksToMarkdown` et `addLinksToHtml` acceptent l’option facultative
15
+ `parsingMode: "document" | "references"`. Le type `ReferenceParsingMode` et
16
+ la liste `referenceParsingModes` sont exportés par le point d’entrée public.
17
+
18
+ - Sans option, ou avec `"document"`, l’analyse existante est conservée :
19
+ « Article 2 » peut définir un article d’une loi ou d’un projet de loi.
20
+ - Avec `"references"`, un libellé autonome non législatif tel que
21
+ « Article 197 du code général des impôts. » peut être lié sans ajouter « l’ ».
22
+ N’utilisez pas ce mode pour analyser une loi ou un projet/proposition de loi.
23
+ - Les syntaxes doctrinales telles que « CGI, art. 197 » utilisent la grammaire
24
+ commune dans les deux modes ; il ne s’agit pas d’un sélecteur de corpus.
25
+
26
+ Voir le [contrat et les limites de validation](../../fonctionnalités/references-autonomes-tisseuse-moulineuse.md).
27
+
12
28
  ## Installation
13
29
 
14
30
  ### Create database
@@ -31,6 +47,67 @@ exit
31
47
  npm install
32
48
  ```
33
49
 
50
+ ### Cache de l’index des titres juridiques dans Canutes
51
+
52
+ **Cache persistant non activé.** La [qualification de coût #312](https://git.tricoteuses.fr/logiciels/tricoteuses-juridique/pulls/312) ne démontre pas sa rentabilité en production. Le [correctif transactionnel #310](../../docs/architecture/correction-repli-transaction-titres-canutes.md), intégré via [#313](https://git.tricoteuses.fr/logiciels/tricoteuses-juridique/pulls/313), traite aussi les préchargements d’articles des vrais consommateurs. Les deux services ont été initialement déployés sur `93daabf0`, correctif et compteurs #314 inclus ; l’[observation ciblée bornée](../../docs/architecture/observation-chargements-titres-canutes.md) est close depuis le 15 octobre 2026 vers 17 h 36 Europe/Paris, avec rollbacks conservés et compteurs désactivés. Minima : 362 reconstructions web, dont neuf sur l’artefact isolé initial et 353 sur des builds ordinaires non qualifiés par leur seul HEAD ; une reconstruction et cinq réutilisations MCP. Le delta complet observé est rejoué sur copies jetables ; Moulineuse suit de nouveau `latest` sans changer d’image exécutée. Ni ces mesures locales ni ce déploiement ne qualifient la rentabilité nette de production. Les tests historiques de l’[audit initial](../../docs/architecture/audit-optimisation-canutes-tisseuse.md) ne suffisaient pas à qualifier cette chaîne avec `TransactionSql`. ACL/réplication et exploitation restent à valider ; la [procédure](../../docs/architecture/deployer-optimisation-canutes-tisseuse.md) et les commandes ci-dessous ne sont pas une autorisation d’activation.
53
+
54
+ L’index préconstruit des titres juridiques est stocké dans `tisseuse.text_titles_infos_parser_cache`, avec la révision de `tisseuse.text_titles_infos_parser_state`. Un lecteur n’écrit jamais ce cache : il le charge si ses gardes et sa révision sont valides, sinon construit les titres en mémoire. L’absence des tables ou de grants de lecture entraîne aussi un repli mémoire.
55
+
56
+ Les linkers et `CanutesResolver` acceptent un pool `Sql` ou une transaction `TransactionSql` **`REPEATABLE READ READ ONLY` / `SERIALIZABLE READ ONLY`**. Les transactions fournies sont réutilisées sans `BEGIN` imbriqué ; `READ COMMITTED` et les transactions écrivables sont refusés, pas implicitement modifiés. BOFiP/BOSS/Ameli utilisent le premier mode. Les lectures de cache optionnelles sont protégées par savepoints ; aucune écriture du lecteur. L’index mémoire reste propre à l’objet SQL exact : une nouvelle transaction peut refaire le chargement, même dans un processus chaud. Le snapshot fourni reste ouvert pendant le parsing, avec un coût potentiel de rétention MVCC ; ce n’est pas le petit snapshot interne d’un pool.
57
+
58
+ La [qualification historique du coût net sur stock complet](../../docs/architecture/cout-net-cache-titres-canutes.md) conserve le défaut transactionnel observé avant sa correction par #313. Ses mesures restent attachées à `bb33b942` ; le bon dénominateur est le chargement évitable par objet SQL, pas seulement le redémarrage du processus. Elle n’autorise aucune activation.
59
+
60
+ `npm run configure` crée les tables et fonctions, sans changer la version globale du schéma (12). Les déclencheurs et ACL sont une étape administrative distincte sur le **primaire**, après préparation du DDL des abonnés logiques :
61
+
62
+ ```sh
63
+ npm run configure:postgres:legi-resolver -- \
64
+ --reader-roles '<role-lecteur>,<role-replication>' \
65
+ --builder-roles '<role-constructeur>'
66
+ npm run warm:postgres:legi-titles # après les imports, sur le primaire seulement
67
+ ```
68
+
69
+ Quatre déclencheurs suivent les modifications pertinentes de titres, dans la transaction source. Le warmup construit hors transaction à partir d’un snapshot et vérifie la révision avant publication ; un import concurrent provoque un retry. Un cache déjà valide est réutilisé ; `--force` impose une reconstruction. Ne pas simplement réactiver un déclencheur qui a été désactivé : réinstaller avec la commande administrative pour invalider les titres devenus douteux.
70
+
71
+ L’index composite texte/numéro existant de Canutes n’est pas dupliqué. L’option administrative `--index-num` crée ou répare un index numéro seul, uniquement si les plans mesurés justifient son ajout. Ces opérations ne font plus partie de la configuration courante.
72
+
73
+ Tests PostgreSQL dédiés : `TISSEUSE_CACHE_TEST_DATABASE_URL=… npm run test:postgres:legi-cache` (base neuve `tisseuse_cache_test_*`, jamais Canutes). Profilage complet en lecture seule : `npm run profile:canutes-bill -- <fichier> --format assemblee-html --date YYYY-MM-DD --titles source|cache --runs 3`. Les hashes des HTML liés/directives permettent de vérifier l’équivalence. Le [profilage après index CID](../../docs/architecture/performance-canutes-apres-index.md) mesure désormais le vrai cache persistant sur une copie jetable de 62 327 projections de titres, sans activation de production : premier chargement local médian 2 674 → 349 ms, réutilisation mémoire 0,7 ms dans les deux modes. Ce n’est pas une prédiction du gain réseau/imports en production. La même qualification reprend le court-circuit CPU de #289 et propose des lectures structurelles plus petites, avec sorties complètes inchangées sur huit PJL et les deux backends ; ces propositions restent indépendantes de l’adoption native #273/#275. Le [profilage du parcours actuel sur Canutes réelle](../../docs/architecture/profilage-canutes-liens-actions.md) identifie surtout un préchargement global d’articles trop volumineux et des parcours CPU coûteux.
74
+
75
+ Pour diagnostiquer la solution actuelle, `--titles source` est désormais le mode par défaut. Le CLI impose une session PostgreSQL read-only, une seule connexion et un timeout de 30 s par requête (ajustable avec `--statement-timeout-ms`, maximum 120 s). Il fournit les temps/lignes par signature SQL sans enregistrer les paramètres ; `--details` capture les phases du parseur et du résolveur, `--plans` ajoute des EXPLAIN sans ANALYZE hors chronométrage. `--article-candidates legacy|bounded` compare le transfert global initial à l’optimisation des numéros fréquents, sur le même parseur et la même base. `bounded` est le défaut ; `legacy` est réservé au profilage. La [comparaison mesurée](../../docs/architecture/optimisation-prechargement-articles-canutes.md) donne environ 25 % de gain sur le document Sénat, sans nouvelle structure ni index. `--article-lookups individual|batch` compare les recherches texte/numéro individuelles au préchargement ciblé, en conservant le mode global choisi. `batch` est le défaut ; `individual` désactive seulement le hint pour le profilage. La [comparaison sur quatre documents](../../docs/architecture/optimisation-recherches-texte-numero-canutes.md) montre un gain chaud supplémentaire de ~1,7 s côté Assemblée et ~3 s côté Sénat sur les deux références. Les lots sont limités en couples potentiels, pas en versions, et conservent toutes les périodes. Un timeout ou une erreur produit un rapport partiel et un code de sortie non nul. Les durées SQL sont celles vues du client, transfert et décodage inclus ; ne pas additionner les phases imbriquées.
76
+
77
+ L’[optimisation CPU du rendu AKN et des directives](../../docs/architecture/optimisation-cpu-rendu-directives-tisseuse.md), avec les deux optimisations SQL maintenues, réduit ensuite le traitement chaud du Sénat de **24,67 à 14,51 s** (−41,2 %), sans changer les sorties des quatre documents comparés. Les faibles variations Assemblée ne démontrent pas un gain robuste. Le marquage des tableaux cités reste conservé et les normalisations sont réutilisées dans un cache borné propre à chaque extraction, sans nouvel état global. Aucun changement de Canutes, aucune fusion ni aucun déploiement ; les coûts restants et la revue/CI du dernier commit restent à traiter.
78
+
79
+ ### Intégration autorisée des adoptions natives et de la performance
80
+
81
+ #273 et #275 sont intégrées à `main` par `f27c62d4` puis `bde427c8`, après réussite des deux jobs de tests de chaque head. Le [rapport d’intégration](../../docs/architecture/integration-native-performance-tisseuse.md) vérifie les deux flags supprimés, les sorties combinées et l’invariance complète du candidat #297 après ces fusions. La voie CPU choisie est #297, pas une seconde intégration de #289. Les qualifications historiques ci-dessous gardent leurs bases et limites : pas de cache activé, nouveau benchmark ou déploiement manuel.
82
+
83
+ ### Requalification historique des propositions sur `main` 40041bee
84
+
85
+ Le [rapport commun](../../docs/architecture/requalification-tisseuse-main-40041bee.md) consigne le retour favorable de David côté legi-ui avec ses limites de runtime/SHA et les rebases indépendants #273/#275/#297. Les fichiers source et sorties restent inchangés par rebase ; la combinaison native retrouve ses sorties qualifiées et #297 conserve exactement les documents du nouveau main. Les mesures de cache/performance précédentes restent historiques ; aucun cache activé, fusion ou déploiement.
86
+
87
+ Au checkpoint précédant les installations du 12 octobre, l’[étude locale d’indexation des racines CID](../../docs/architecture/etude-index-cid-racines-canutes.md) confirme la suppression du balayage et l’invariance des résultats sur une copie complète de `texte_version`. Un index d’expression sur le JSONB bloque cependant HOT, même hors du prédicat partiel ; une colonne CID stockée préserve HOT dans la preuve locale. **Ce n’est pas une migration prête ni un gain end-to-end mesuré** : imports, schema/réplication et rollout restent à concevoir, aucun runtime/index/cache de production n’est changé.
88
+
89
+ La recommandation historique tirée des [statistiques des changements publiés sur 30/60 jours](../../docs/architecture/frequence-changements-canutes.md) révisait la priorité : ~251 fiches texte touchées/jour, dont ~153 modifiées seulement, ne justifient pas seules la colonne dédiée. **Qualifier l’index d’expression partiel plus simple en premier**, avec mesure de la charge d’import réelle et autorisation distincte. Les articles ne sont pas concernés par cet index et les compteurs du standby ne mesurent pas les écritures du primaire. Aucun changement/installation automatique.
90
+
91
+ ### Index d’expression CID des racines
92
+
93
+ Le [lot de consolidation du 16 octobre](../../docs/architecture/consolidation-canutes-gel-2026-10-16.md) ne modifie pas les résolveurs. Après intégration, nos développements Tisseuse sont gelés quelques jours pour les remaniements de David ; le cache persistant des titres et son hook restent inactifs.
94
+
95
+ L’index partiel `LEGITEXT%` peut accélérer le lookup des racines sans changer sa requête ni ajouter de colonne. [Installation, garde-fous, tests et état réel](../../docs/architecture/installer-index-cid-racines-canutes.md). Contrôle SELECT-only par défaut :
96
+
97
+ ```sh
98
+ npm run configure:postgres:legi-root-cid-index
99
+ ```
100
+
101
+ L’installation demande `-- --apply` et un rôle administratif sur une cible explicitement autorisée ; réparation d’une construction interrompue uniquement avec `--repair-invalid`. Aucune création depuis `configure`/les lecteurs, aucun cache/triggers/ACL activé. DDL physique répliqué, DDL logique à coordonner localement ; garder dates/ambiguïtés et contrôler imports/WAL. [Coordination Casanabo réalisée sous autorisations distinctes](../../docs/architecture/casanabo-index-cid-replication-canutes.md) : réparation des structures de réplication puis index local, sans activation du cache ni backfill d’embeddings.
102
+
103
+ ### Comparer Canutes et `f_legi` en lecture seule
104
+
105
+ `npm run profile:legi-bill -- <fichier> --resolver canutes|flegi --format … --date … --titles source --runs 3 --details --document-output /tmp/document.json` utilise les variables `CANUTES_DB_*` pour la base choisie. Le mode `flegi` emploie un résolveur de profilage qui ne construit ni n’écrit le cache natif ; `--titles cache` exige un cache existant compatible et échoue sinon. Les modes Canutes `legacy`/`individual` ne s’appliquent pas à `flegi`.
106
+
107
+ `npm run compare:legi-bills -- /tmp/canutes.json /tmp/flegi.json --max-examples 10 --output /tmp/comparaison.json` compare hors ligne l’égalité exacte, les AST/positions, les ensembles de cibles et les multiensembles des liens légaux. Les fichiers sont écrits hors chronométrage, sans écrasement et avec permissions restrictives. Les paramètres SQL ne sont pas exportés ; ne pas additionner les phases imbriquées ni confondre mémoire de fin et pic.
108
+
109
+ La [comparaison réelle sur huit documents](../../docs/architecture/comparaison-canutes-flegi-tisseuse.md) montre des temps chauds du même ordre et aucun écart grammatical, mais **101 écarts de cibles** liés aux historiques et aux divisions, ainsi que des liens européens absents côté `f_legi`. Les sorties ne sont pas déclarées équivalentes ; les [huit cas de divisions sont qualifiés](../../docs/architecture/qualification-divisions-canutes-flegi.md), avec des erreurs de cibles héritées/texte parent à corriger séparément. La lecture du cache existant `f_legi` ne mesure pas le gain du cache Canutes, toujours différé.
110
+
34
111
  ## Server Configuration
35
112
 
36
113
  Create a `.env` file to set configuration variables (you can use `example.env` as a template). Then:
@@ -158,6 +235,42 @@ exported as an abstract class from both `@tricoteuses/tisseuse` and
158
235
  `@tricoteuses/tisseuse/server`, so applications can provide another
159
236
  storage-backed implementation.
160
237
 
238
+ In the **native quotation-scope candidate, not yet agreed or merged**, references
239
+ inside standalone quotations cannot change the outside amended-text context for
240
+ any resolver. The temporary `isolateStandaloneCitationContext` property, Canutes
241
+ override and diagnostic forwarding are removed together. Adapters declaring the
242
+ property should remove their override. Grammar and source positions remain
243
+ unchanged; the initial candidate deliberately changed native links/targets and
244
+ preserved Canutes outputs. David subsequently requested anaphoric carryover
245
+ between related quotations. The [corrective qualification](../../docs/architecture/correction-anaphores-citations-tisseuse.md)
246
+ restores explicit same/said-code references without changing outside action
247
+ scope, and intentionally corrects some Canutes links too. Adoption remains
248
+ blocked pending consumer validation; archived B0235 article mapping and the
249
+ reported future 1519 A version remain explicitly limited/unresolved.
250
+
251
+ This proposal requires David's native/other-adapter validation and coordinated
252
+ adoption with [the action-target proposal #273](https://git.tricoteuses.fr/logiciels/tricoteuses-juridique/pulls/273)
253
+ to remove remaining bad inherited action targets. Mixed target roles still need
254
+ review. No native SQL rewrite or adoption acceptance is presumed. See
255
+ [the scope, evidence and explicit remaining limits](../../docs/architecture/adoption-native-citations.md).
256
+
257
+ In the **native adoption candidate, not yet agreed or merged**, both bill parsers
258
+ stop explicitly numbered unlinked references from inheriting unrelated targets
259
+ and support only explicitly referred, unambiguous adjacent renumberings for all
260
+ resolvers and prelinked HTML. The temporary `scopeExplicitBillActionTargets`
261
+ property, Canutes override and all conditional plumbing are removed together;
262
+ external adapters declaring that property should remove their override.
263
+
264
+ Correct native targets change deliberately; HTML, links, grammar and positions
265
+ remain unchanged on the tested corpus. Canutes results remain unchanged. No new
266
+ snapshots or fixed expectations validate known native errors. Native and
267
+ other-adapter adoption remains proposed to David (`dsmadja`), not accepted; no SQL
268
+ reimplementation is required. See [the qualification and removal candidate](../../docs/architecture/adoption-native-cibles-actions.md).
269
+ The separate quotation-context capability remains unchanged.
270
+ The independent action increment did not include the optimization, cache,
271
+ quotation-context or root-fallback work. Those separate increments are now
272
+ combined without changing the native opt-out.
273
+
161
274
  The default Canutes resolver reads the title metadata it needs directly from
162
275
  `legifrance.texte_version` and builds the parser indexes in memory. Concurrent
163
276
  callers share the same preload operation, and the resulting indexes remain fixed