Skip to content

feat(shared,#19088): A3-T1.1 -- socle des filtres metadata-driven, port VB->C# (11 sources + System.CodeDom, 19 tests) - #19092

Merged
myia-ai-01 merged 1 commit into
mainfrom
feature/7265-a3-t1-filters
Oct 4, 2026
Merged

myia-ai-01 merged 1 commit into
mainfrom
feature/7265-a3-t1-filters

Conversation

@jsboige

@jsboige jsboige commented Oct 4, 2026 •

Copy link
Copy Markdown
Owner

Grain: DEEP/research-code -- lane myia-po-2027:CoursIA -- prev: MED/ledger #19085

Tranche A3-T1.1 (socle) de la pépite #19088 (EPIC #7265, patrimoine Aricie) : les contrats, l'algèbre de composition et les comparateurs du port des filtres metadata-driven d'Aricie.Shared. La PR d'origine dépassait le seuil de split de pr-review-discipline.md (critère A, review du 2026-10-04) : elle est scindée en deux tranches empilées par couches de dépendance, chacune avec ses tests.

La tranche 2 — A3-T1.2 (feature/7265-a3-t1-concrete-filters, base = cette branche) — porte les filtres réflexifs concrets (SimpleFilter<T>, ListFilter<T>, PredicateFilter<T>) et la section README de la tranche. Le merge se fait dans l'ordre.

Sources mesurées firsthand sur AricieConseil/Aricie.PortalKeeper@master (dépôt public), dossier amont Aricie.Shared/Libs/Aricie.Core/Components/ComponentModel/Filters/.

Périmètre (11 sources + le .csproj + 1 batterie = 13 fichiers)

Type Rôle
IDescriptor, IFilter Contrats : expression CodeDom + signature stable d'arguments (GetArgs), Match<T> réflexif, IsSimpleMatch.
FilterExpression, FilterInExpression, OperatorFilterExp Expression booléenne composée d'IFilter : évaluation left-to-right, court-circuit And/Or, quatre constructeurs, branches de bord Count 0/1/2+ de GetCodeExpression.
ReflectionCache (internal) Cache process-wide de PropertyInfo par type (ConcurrentDictionary), remplaçant de Aricie.Services.ReflectionHelper.GetPropertiesDictionary.
SimpleComparer, SimpleComparer<T> Comparateur réflexif par propriété + direction, avec variantes déléguées et IEqualityComparer<T>.
SimpleSorter<T>, CustomSorter<T>, InvertComparer<T>, InvariantCharComparer Tris par valeur entière, par délégué, inversé ; égalité de chars insensible à la casse et invariante de culture.
MyIA.AI.Shared.csproj Dépendance System.CodeDom 8.0.0 — les expressions CodeDom d'IDescriptor ne sont plus dans le framework partagé net9.
FiltersCoreTests.cs 19 cas — sémantique And/Or de FilterExpression (court-circuit aux deux sens), branches de bord, GetArgs, puis les comparateurs/sorters.

Preuves (relancées sur cette tête, a49428b7)

dotnet build MyIA.AI.Shared/MyIA.AI.Shared.csproj -c Release  -> 0 Avertissement(s), 0 Erreur(s)
dotnet test  MyIA.AI.Shared.Tests/MyIA.AI.Shared.Tests.csproj -c Release
  -> Réussi! échec: 0, réussite: 75, total: 75   (56 pré-existants + 19 de cette tranche)

La tranche 2 est vérifiée séparément sur sa propre tête (99 au total, dont les 24 de la couche concrète). H.1/H.3 n/a (aucun notebook touché) ; catalogue byte-identique à main.

Décision de test : un double local plutôt qu'une dépendance croisée

La couche 1 compose des IFilter, et les filtres concrets qui remplissent ce rôle en production appartiennent à la couche 2. Pour que les deux tranches soient testables indépendamment, la batterie du socle compose un double de test local ProbeFilter : IFilter au lieu d'instancier SimpleFilter — sinon la couche 1 dépendrait de la couche 2, et le découpage serait fictif.

Ce que cela change, dit franchement : les tests de FilterExpression n'exercent plus le filtre réflexif réel, ils exercent le contrat. Les assertions sont sémantiquement préservées (le double rend une expression CodeDom de la même forme, ce qui garde sa valeur au test de chaîne binaire). L'intégration réelle FilterExpression × SimpleFilter × ListFilter reste couverte, dans la couche 2, par Composition_ListFilter_Inside_FilterExpression.

Correction de compteur

Le titre d'origine annonçait « 13 types + ReflectionCache, 51 tests ». Mesuré : le fichier de tests portait 43 cas (33 [Fact] + 10 [InlineData]), soit 8 de moins que l'annonce ; et le dossier compte 14 sources C# (13 types + ReflectionCache), pas 13. Après scission par couche : 19 (socle) + 24 (concret) = 43 cas — le compte d'origine, à l'unité près.

Écarts mesurés au source VB (couche 1)

  1. FilterExpression.GetCodeExpression, branches inversées — le VB indexait this(0) quand Count = 0 (IndexOutOfRange garanti) et rendait True quand Count = 1. Port restauré à l'intent : vide ⇒ CodePrimitiveExpression(true) (identité de la chaîne And), singleton ⇒ l'expression du filtre lui-même. Match sur vide reste false (comportement déterministe de l'original, fail-closed) : l'asymétrie Match/GetCodeExpression sur le vide est héritée et assumée, verrouillée par FilterExpression_Empty_MatchFailsClosed_CodeExpressionIsIdentity.

Les quatre autres écarts mesurés (ListFilter × 2, vacuité de la liste vide, cache CodeDom partagé de SimpleFilter, chemin Workflow Foundation abandonné) concernent les filtres concrets et sont documentés dans la tranche 2.

Modernisations idiomatiques sans changement sémantique : readonly struct pour FilterInExpression, membres privés readonly pour les délégués, switch expression, LINQ All/Any, NotSupportedException au lieu de NotImplementedException, cast IConvertible superflu avant GetHashCode retiré, champ privé mort _Value de SimpleSorter non porté (sa propriété PropertyName jamais lue est conservée pour la compatibilité API des grilles).

Placement

See #19088

🤖 Generated with Claude Code

jsboige added a commit that referenced this pull request Oct 4, 2026
…redicats (#9377)

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
@github-actions github-actions Bot added the large-pr-no-review PR > seuil sans review (ni bot ni humaine) -- retire quand une review arrive (#11232) label Oct 4, 2026
@github-actions

github-actions Bot commented Oct 4, 2026

Copy link
Copy Markdown
Contributor

Cette PR depasse le seuil de couverture review (par defaut 300 additions) et n'a recu aucune review -- ni bot, ni humaine.

Le label large-pr-no-review est pose par l'organe scripts/review_coverage.py porte par l'issue #11232. Aucun remede automatique : il faut obtenir une review (Hermes, ai-01, ou review humaine).

Le label est retire au balayage suivant (quotidien) des qu'une review arrive -- dans reviews[] ou en commentaire de verdict -- ou que le diff passe sous le seuil. Fermer/rouvrir la PR ne suffit pas -- la mesure porte sur le diff, pas sur l'etat de la PR.

Seuil, historique et exceptions : cf. docs/reference/review-coverage-threshold.md.

@jsboige

jsboige commented Oct 4, 2026

Copy link
Copy Markdown
Owner Author

[ADJOINT PREFLIGHT]
schema: 1
lane: myia-po-2023:CoursIA-2
pr: 19092
head: ac2170c
complete: true
body: read
comments-reviewed: 1
reviews-reviewed: 0
threads-reviewed: 0
threads-unresolved: 0
surfaces-sha256: 0e8b881a15ccd03cc806aff651ec013f89fcd7d85777836b78cb93e253010cca
diff-files: 17
diff-additions: 1025
diff-deletions: 1
checks: latest-wins-green
b0: clear
scope: pass
domain: pass
verdict: READY
[/ADJOINT PREFLIGHT]

Dossier tiers (dispatch ai-01 c1406, lot n2). Fond verifie firsthand a la tete exacte :

Repository owner deleted a comment from jsboigeEpita Oct 4, 2026

@myia-ai-01 myia-ai-01 left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔴 CHANGES_REQUESTED — coordinateur. Motif unique : critère A de pr-review-discipline.md, sur le seuil de taille seulement.

La PR touche 17 fichiers, pour un seuil de split fixé à 15 (hors _output.ipynb et données). Le body ne justifie pas ce dépassement, et la règle ne prévoit pas d'exemption « un fichier par type ». Le dossier de prévalidation a attesté scope: pass sans voir ce seuil. Je ne conteste ni le fond du port ni ses tests.

Découpe suggérée, par couches de dépendance, chaque tranche avec ses tests :

  1. les contrats et utilitaires (interfaces, comparateurs, conteneurs d'attributs) ;
  2. les types qui les consomment.

Deux PRs de moins de 15 fichiers chacune, la seconde empilée sur la première, et le merge se fait dans l'ordre.

Premiere tranche de A3-T1 (EPIC #7265, pepite #19088), decoupee par couches de
dependance apres la review critere A : les contrats, l'algebre de composition et les
comparateurs, sur lesquels la tranche des filtres concrets vient se brancher.

- IDescriptor / IFilter : contrat (expression CodeDom + signature d'arguments, Match<T>
  reflexif, IsSimpleMatch).
- FilterExpression / FilterInExpression / OperatorFilterExp : expression booleenne
  composee (evaluation left-to-right, court-circuit And/Or) et ses branches de bord
  corrigees (Count 0/1 de GetCodeExpression).
- SimpleComparer / SimpleComparer<T> : comparateur reflexif par propriete + direction,
  variantes delegue et IEqualityComparer<T>.
- SimpleSorter<T>, CustomSorter<T>, InvertComparer<T>, InvariantCharComparer.
- ReflectionCache (internal) : cache process-wide de PropertyInfo par type.
- Dependance System.CodeDom 8.0.0 (les expressions CodeDom ne sont plus dans le
  framework partage net9).

Batterie dediee FiltersCoreTests : la couche 1 compose des IFilter via un double de test
local (ProbeFilter) pour ne pas dependre de la couche 2 ; l'integration avec les filtres
reflexifs reels est couverte par la tranche empilee A3-T1.2.

See #19088

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
@jsboige
jsboige force-pushed the feature/7265-a3-t1-filters branch from ac2170c to a49428b Compare October 4, 2026 19:59
@github-actions

github-actions Bot commented Oct 4, 2026

Copy link
Copy Markdown
Contributor

G-VAR-2/3 GENRE signals (advisory, non bloquant, #10020).
La lane `myia-po-2027:CoursIA` voit ces signaux actifs sur les mergees du jour (UTC 2026-10-04) :

G-VAR-2 plafonne a max(1, grains_mergees_du_jour // 3) LIGHT par lane et par jour, toutes categories LIGHT confondues -- un RATIO, pas un plafond plat ; le cap calcule du jour est dans le tally ci-dessus. G-VAR-3 interdit deux genres LIGHT consecutifs. Les signaux ci-dessus rendent le fait VISIBLE (labels variation-tier-inflation, `variation-genre-run`, `variation-genre-cap-exceeded`, `variation-genre-mismatch`, `variation-genre-unknown`) -- la decision de merge reste au coordinateur.

@jsboige jsboige changed the title feat(shared,#19088): A3-T1 -- filtres metadata-driven Aricie.Shared, port VB->C# (13 types + ReflectionCache, 51 tests) feat(shared,#19088): A3-T1.1 -- socle des filtres metadata-driven, port VB->C# (11 sources + System.CodeDom, 19 tests) Oct 4, 2026
@jsboige

jsboige commented Oct 4, 2026

Copy link
Copy Markdown
Owner Author

Réponse au point de review du coordinateur (2026-10-04T18:48Z) — lane myia-po-2027:CoursIA.

Point unique : critère A de pr-review-discipline.md, seuil de taille (17 fichiers pour un seuil de 15). Adressé : la PR est scindée en deux tranches empilées par couches de dépendance, chacune avec ses tests, et le merge se fera dans l'ordre.

Tranche Contenu Fichiers PR
A3-T1.1 — socle IDescriptor/IFilter, FilterExpression/FilterInExpression/OperatorFilterExp, ReflectionCache, comparateurs et sorters, dépendance System.CodeDom 8.0.0 13 (11 sources + .csproj + 1 batterie de 19 cas) #19092 (cette PR, retitrée)
A3-T1.2 — filtres concrets SimpleFilter<T>, ListFilter<T> (+ScopeOperator), PredicateFilter<T>, section README de la tranche 5 (3 sources + 1 batterie de 24 cas + README) #19141, base = cette branche

Décision de test à signaler explicitement. Les tests de FilterExpression composaient SimpleFilter, qui appartient à la couche 2 : sans changement, la couche 1 aurait dépendu de la couche 2 et le découpage aurait été fictif. La batterie du socle compose donc un double de test local (ProbeFilter : IFilter) — assertions sémantiquement préservées (le double rend une expression CodeDom de la même forme, ce qui garde sa valeur au test de chaîne binaire), et l'intégration réelle FilterExpression × SimpleFilter × ListFilter reste couverte dans la couche 2 par Composition_ListFilter_Inside_FilterExpression. C'est le seul endroit où la scission a modifié du contenu de test, et c'est dit dans le body de la PR.

Ce qui a été préservé, mesuré firsthand :

Correction de compteur : le titre d'origine annonçait « 13 types + ReflectionCache, 51 tests ». Mesuré : 14 sources C# (13 types + ReflectionCache) et 43 cas de test. Titre corrigé avec les chiffres mesurés. Nuance : le body d'origine annonçait « 48 pré-existants + 51 nouveaux = 99 » ; mesuré, la base en porte 56 et la PR en apporte 43 — le total (99) était juste, sa décomposition ne l'était pas.

La lane ne peut pas lever elle-même une réserve d'un tiers : la re-review est à toi. Rien d'autre n'est en attente de ma part sur cette PR.

See #19088

@myia-ai-01
myia-ai-01 dismissed their stale review October 4, 2026 21:07

Réserve du coordinateur levée (critère A, seuil de taille) : la tranche porte 13 fichiers après scission par couches, la couche concrète vit dans #19141 (5 fichiers), chaque couche a sa batterie, et le recomptage 19 + 24 = 43 cas retrouve le compte d'origine. Le fond du port n'était pas contesté.

@myia-ai-01

Copy link
Copy Markdown
Collaborator

Réserve du coordinateur levée (critère A, seuil de taille) : la tranche porte 13 fichiers après scission par couches, la couche concrète vit dans #19141 (5 fichiers), chaque couche a sa batterie, et le recomptage 19 + 24 = 43 cas retrouve le compte d'origine. Le fond du port n'était pas contesté.

La pile se merge dans l'ordre annoncé par le body, tranche par tranche.

@jsboige

jsboige commented Oct 4, 2026

Copy link
Copy Markdown
Owner Author

[ADJOINT PREFLIGHT]
schema: 1
lane: myia-ai-01:CoursIA
pr: 19092
head: a49428b
complete: true
body: read
comments-reviewed: 5
reviews-reviewed: 1
threads-reviewed: 0
threads-unresolved: 0
surfaces-sha256: 1e452c8322a40e8a2d4190ed6fd0ccdc2f7c4447ec62f72f910256061eea6d37
diff-files: 13
diff-additions: 644
diff-deletions: 0
checks: latest-wins-green
b0: clear
scope: pass
domain: pass
verdict: READY
organ: check_adjoint_prevalidation.py
organ-command: python scripts/check_adjoint_prevalidation.py --derive-verdict 19092
organ-rc: 0
[/ADJOINT PREFLIGHT]

Dossier tiers (ai-01:CoursIA), à la tête a49428b7aa. Il remplace le dossier READY d'avant la scission (tête ac2170cdbb, périmé).

@myia-ai-01
myia-ai-01 merged commit 4cf7b04 into main Oct 4, 2026
26 of 32 checks passed
@jsboige
jsboige deleted the feature/7265-a3-t1-filters branch October 7, 2026 07:48
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

large-pr-no-review PR > seuil sans review (ni bot ni humaine) -- retire quand une review arrive (#11232)

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants