Skip to content

feat(ci,#15511): organe soft_deadlock_detector — détection deadlock soft (P2) - #18668

Merged
myia-ai-01 merged 1 commit into
mainfrom
feature/15511-soft-deadlock-detector
Oct 1, 2026
Merged

myia-ai-01 merged 1 commit into
mainfrom
feature/15511-soft-deadlock-detector

Conversation

@jsboige

@jsboige jsboige commented Oct 1, 2026

Copy link
Copy Markdown
Owner

Grain: LIGHT/tooling — lane myia-po-2024:CoursIA — prev: DEEP/training #18664

Requalification honnête du tag : le claim portait MED/tooling ; la passe
live a rendu 0 deadlock — le litmus MED exige un finding qui change une
décision, « 0 trouvé » ne l'est pas. Le finding de design (criterion 5,
mesure #18158 ci-dessous) ne change pas une décision de plateau.

P2 de #15511 : organe de détection de deadlock soft

scripts/ci/soft_deadlock_detector.py — mesure de plateau, jamais un
gate
: un signal [DEADLOCK] par PR détectée, le triage reste humain.
Cas fondateur : #14821 (31 commentaires / 68 101 chars / 5 jours, livrable
inchangé, clôturée sans merge).

Conjonction de détection (5 critères)

  1. state: OPEN ;
  2. mergeable: MERGEABLE — une PR en conflit est une candidate réparable
    (picker, file P0), pas un deadlock soft ;
  3. âge > 72 h (--min-age-hours) ;
  4. commentaires humains > 5 sur 24 h (--window-hours,
    --min-comments) — les bots mécaniques ne comptent pas ;
  5. aucun commit dans la fenêtre — la signature fondatrice est
    « ~6 commentaires/jour pour 0 commit de code ».

Le critère 5 vient de la mesure, pas de la spéculation

La première passe live (critères 1-4 seuls) rendait une détection :
#18158 (82 h, mergeable, 6 commentaires humains / 7 811 chars sur 24 h).
Triage firsthand : réserve Hermes levée à 17:58Z, commit poussé à
21:41Z dans la fenêtre
— boucle de review active, pas un deadlock. La
date du dernier commit n'étant pas dans le JSON de pr list, elle se
prend en seconde phase bornée aux seules candidates (gh pr view, un
appel par candidate — ici un seul). Une requête échouée conserve la
candidate (fail-open vers le signal, marquée last_commit_unknown) — le
triage humain départage.

Sémantique de sortie

  • rc=0 : mesure effectuée, avec ou sans détections (convention
    prune_merged_worktrees : une détection est une décision rendue) ;
  • rc=1 : panne opérationnelle ([PANNE] sur stderr — observé une fois sur
    un flake transitoire gh à stdout vide, refus fail-closed) ;
  • rc=2 : uniquement avec --fail-on-findings, pour un appelant cron qui
    veut un code distingué ;
  • --json : findings + compteurs (scanned,
    skipped_mergeable_unknown, skipped_active_in_window).

Première mesure live (2026-10-01)

69 PRs ouvertes scannées, 0 deadlock soft, 1 écartée (#18158, commit
dans la fenêtre), 1 mergeable: UNKNOWN reportée au tir suivant.

Tests

scripts/tests/test_soft_deadlock_detector.py — 17 tests, sans réseau
(runner injectable, pattern guard_comment_upsert) : chaque branche de la
conjonction isolée (âge frais, conflit, silencieuse, churn de bots, hors
fenêtre, UNKNOWN, bornes strictes), tri par bruit décroissant, formes de
sortie JSON/texte, rc 0/1/2, fail-open de la seconde phase.

Câblage (coordinateur)

L'armement du cron 1x/jour relève de l'agent principal (jamais de la lane
qui écrit l'organe) : soft_deadlock_detector.py --fail-on-findings dans
un prompt de cycle, le signal [DEADLOCK] allant au dashboard workspace.

Résiduel

P1 (tags [ACTION]/[DIAG]/[ASK]) et P3 (règle commentaire-avec-action) ne
sont pas couverts par cette PR. P4 est déjà livré par ailleurs (marqueurs
de verdict #14682 + siège qualifiant #16768). P5 (compteur chars
dashboard) est couvert en sous-produit : chars_window par finding.

See #15511

🤖 Generated with Claude Code

…ck soft sur PRs ouvertes

Conjonction #15511 P2 : OPEN + mergeable + age > 72h + churn commentaires
humains > 5/24h + aucun commit dans la fenetre. Seconde phase bornee aux
candidates (gh pr view commits[-1]) ajoutee par la mesure live elle-meme :
#18158, seule candidate du passage initial, est une boucle de review active
(reserve levee puis commit pousse dans la fenetre) — la signature fondatrice
#14821 est le churn SANS commit.

Signal [DEADLOCK] seul, jamais un gate ; rc=0 mesure, rc=1 panne gh,
rc=2 uniquement via --fail-on-findings (pour un cron). Runner injectable
(pattern guard_comment_upsert), 17 tests sans reseau.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
@github-actions

github-actions Bot commented Oct 1, 2026

Copy link
Copy Markdown
Contributor

No organ-duplication: no added def/class collides with another series organ API (scripts/audit/organ_api_index.yaml).

Detector: python scripts/audit/detect_organ_duplication.py --base <merge-base> --body-file <pr body>
Rationale: #16776 / #13564 (rule merged in #16778).

@github-actions

github-actions Bot commented Oct 1, 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.

@myia-ai-01

Copy link
Copy Markdown
Collaborator

Décision coordinateur sur l'armement (section « L'armement du cron 1x/jour relève de l'agent principal ») : pas de second cron. La règle du coordinateur est une cadence unique, et un deuxième déclencheur ne ferait qu'ajouter de la consommation.

Une fois la PR mergée, je passe soft_deadlock_detector.py une fois par jour, au premier cycle /coordinate de la journée, avec les autres organes de plateau de la phase 2. Le signal [DEADLOCK] part sur le dashboard workspace, comme la PR le propose. L'absence de cron n'est donc pas un oubli : c'est ce choix.

Pour le merge, la PR suit le chemin ordinaire : dossier tiers exact-head, puis ma lecture B.0.

@jsboige

jsboige commented Oct 1, 2026

Copy link
Copy Markdown
Owner Author

[ADJOINT PREFLIGHT]
schema: 1
lane: myia-po-2026:CoursIA-3
pr: 18668
head: 881a584
complete: true
body: read
comments-reviewed: 3
reviews-reviewed: 0
threads-reviewed: 0
threads-unresolved: 0
surfaces-sha256: 465911ffef400f58b7806998873ba53109e72f4eaa5df53a57e6d78931818832
diff-files: 2
diff-additions: 547
diff-deletions: 0
checks: latest-wins-green
b0: clear
scope: pass
domain: pass
verdict: READY
[/ADJOINT PREFLIGHT]

@myia-ai-01
myia-ai-01 merged commit 4c55f3a into main Oct 1, 2026
19 of 20 checks passed
myia-ai-01 pushed a commit that referenced this pull request Oct 2, 2026
…_now() injectable (#18846)

Le test_main_json_and_fail_on_findings_rc2 ancre ses fixtures au NOW dur
2026-10-01 12:00Z mais main() lisait datetime.now() reel : 24 h apres la
redaction, le churn (commentaires humains a <24 h de NOW) sort de la
fenetre --window-hours, la conjonction OPEN+age+churn+commit se brise et
rc vaut 0 au lieu de 2. Mesure sur main le 2026-10-02 : meme fixture,
analyze(now fixture) = 1 finding, analyze(now reel) = 0.

Fix : helper _now() dans le detecteur (meme pattern d'injection que
_default_runner) + monkeypatch vers NOW dans le test. 17/17 verts.

Co-authored-by: Claude Sonnet 5.5 <noreply@anthropic.com>
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