Skip to content

fix(pipeline): #613 harvest resilient to per-set failures (no more abort-all on one timeout) - #614

Merged
jsboige merged 1 commit into
masterfrom
fix/613-harvest-resilience
Jun 29, 2026
Merged

fix(pipeline): #613 harvest resilient to per-set failures (no more abort-all on one timeout)#614
jsboige merged 1 commit into
masterfrom
fix/613-harvest-resilience

Conversation

@jsboige

@jsboige jsboige commented Jun 29, 2026

Copy link
Copy Markdown
Contributor

Quoi

Corrige #613 : lors de la régén Release 8-lang (2026-06-29), un seul card set qui timeout (grand set — Virtues 113 / Scenarii 174 / Fallacies 1408 — sous le MaxDegreeOfParallelism que l'optimizer monte à 6) abortait TOUT le pipeline (throw propagé hors du Parallel.ForEachAsync imbriqué), perdant tous les sets pas encore traités.

Comment

HarvestImages :

  1. tente chaque set atteignable et persiste sur disque tous les harvests réussis (File.Create post-success → re-run skip via cache) ;
  2. collecte les échecs par set ;
  3. s'il y a des échecs : log [HARVEST-PARTIAL] (MessageType.Problem) listant tous les sets ratés + lève une seule ApplicationException agrégée à la fin (pas au premier échec) → une régén partielle n'est jamais silencieuse, et un re-run ne récolte que les manquants.

Garde-fou No-Pendulum : ni abort-tout-au-premier (trop fragile), ni swallow-silencieux (trop permissif) → continue + échec terminal bruyant.

Gated par le nouveau flag WebBasedGeneratorConfig.ContinueOnHarvestSetFailure (défaut true) ; false = comportement legacy (abort au premier échec).

Scope

  • HarvestManager.cs (+27/-1) : guard when (Config.ContinueOnHarvestSetFailure) au call-site + summary/throw final.
  • WebBasedGeneratorConfig.cs (+10) : flag + doc.
  • 0 write Cards/, 0 JSON (config JSON = régénérée depuis C#).

Validation

  • Build Debug : 0 erreur.
  • Tests unitaires : 549 réussis / 0 échec / 5 ignorés (≥ baseline 540).
  • Validation régén complète : en cours via la passe serial de po-2023 (workaround Option C). Le fix rend la passe parallèle résiliente pour les prochaines régén.

Ref #458 (TRACK 1 — matériel 8 langues). Diagnostic root cause : po-2023.

🤖 Coordinator ai-01 (lane pipeline-fix)

A single card set whose harvest timed out (e.g. a large set — Virtues 113,
Scenarii 174, Fallacies 1408 — under the parallelism the optimizer ramps to 6)
threw out of the nested Parallel.ForEachAsync and aborted the ENTIRE 8-language
release régén, losing every not-yet-processed set (observed 2026-06-29).

Now HarvestImages attempts every reachable set, persists all successful harvests
to disk, and collects failures. If any set failed it logs a loud [HARVEST-PARTIAL]
summary and raises a single aggregate ApplicationException at the END (listing all
failed sets) instead of on the first failure — so partial runs are never silent and
a re-run skips the good harvests (cache) and only re-collects the missing ones.

Gated by new WebBasedGeneratorConfig.ContinueOnHarvestSetFailure (default true);
set false to restore the legacy abort-on-first-failure behavior.

Build + 549/0/5 unit tests pass. Full régén validation runs via po-2023 serial pass.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@jsboige
jsboige merged commit a841aee into master Jun 29, 2026
2 checks passed
@jsboige
jsboige deleted the fix/613-harvest-resilience branch June 29, 2026 11:21
jsboige added a commit that referenced this pull request Jul 1, 2026
…ct visuel PASS ai-01

The validation dossier was last refreshed 2026-06-25 and flagged the PDF counts as
"RAPPORTÉS" and the visual verdict as "remaining (ai-01, règle HARD)". Both are now
resolved as of the 2026-07-01 cycle:

- Régén Release 8-lang executed 2026-07-01 on 18b4d02 + #614 (serial,
  EnableParallelism=false, isolated worktree) — 0 échec, 64/64 PDFs, 1229 img/lang ×8,
  "Generation finished.", bundle on GDrive review-v0.9.0-2026-06-28/ with sha256 manifest.
- Verdict visuel ai-01 = PASS représentatif (2026-07-01 08:50): spot-check
  Fallacies_Web_Thumbnails p1 across zh/ar/fa/ru/es covering CJK + RTL + cyrillic + latin;
  bug #216 (FR contamination) held, structure complete 8 types × 8 languages.
- DNN migration full-IIS now CLOSED (dnn.argumentum.myia.io LIVE) — coupling no longer an
  assets blocker.

Refreshed sections: header (date/status/master-ref), §1 (méthode), §3.3 (PDFs counts +
verdict PASS), §4 (tests 549/0/5), §5 (decisions: verdict FAIT/PASS, régén 07-01, DNN LIVE,
new §5.7 params Debug-vs-Release), §7 (risks lifted), §8 (recommendations).

content-only, 0 write Cards/, 0 runtime change. CHANGELOG + RELEASE-NOTES untouched.

Co-Authored-By: Claude-Code <noreply@anthropic.com>
jsboige added a commit that referenced this pull request Jul 1, 2026
…ANGELOG SVGs 8-lang (#591)

* docs(release): v0.9.0 validation dossier + fix CHANGELOG SVGs 8-lang

Add the v0.9.0 release validation dossier (go-live GATE for #134):
- scope (8 languages, jsboige decisions), verified asset inventory
  (CSV 8-lang, MindMap SVGs 8-lang via #565, OWL 5.4MB, PDFs reported
  from 12-Jun regen 64/64), toolchain state (zero-warning CS+NU,
  533/0/5), residual risks, and the decision points that need jsboige
  before the tag (pixel RTL/CJK eyeball, fresh regen, DNN coupling,
  tag v0.9.0).

Fix CHANGELOG line 16: it stated "ES/AR/FA/ZH SVG regeneration
pending" but #565 (merged 2fff84c) shipped those 12 SVGs. Wording
now reflects the delivered 8-language set including RTL + CJK.

Dossier built on committed assets + the reported 12-Jun release
regen (64/64 PDFs, 9834 images, exit 0); no fresh regen run this
session (bin/ empty post-crash, no RDP GO).

Co-Authored-By: Claude <noreply@anthropic.com>

* docs(release): #591 address NanoClaw review notes on v0.9.0 dossier

- Byte-verify asset sizes: OWL 5.4MB→5.13MB (5,378,765 bytes),
  zh SVG 18MB→17.2MB (18,075,919 bytes).
- Add §3.1 source pointer for the 1408/223/167 taxonomy counts
  (issues #335/#499 spec / Scenarii commits, not re-derived this day).
- Clarify §5 point 5: CHANGELOG already fixed in this PR;
  docs/RELEASE-NOTES-v0.9.0.md does NOT exist on master
  (verified 22eb5f3) — only CHANGELOG.md documents the release.

Non-blocking review notes from ai-01/NanoClaw; no content change
to the 6 gate decisions.

Co-Authored-By: Claude <noreply@anthropic.com>

* docs(release): #591 update coupling reco + draft v0.9.0 release notes

Per ai-01 jalon dispatch (review-ready WE):
- Update dossier §5 point #3 with po-2023 recommendation: DE-COUPLE
  (tag assets-only; DNN upgrade as post-release ops milestone), with
  effort estimate pointer to UPGRADE-ASSESSMENT §10 (#593).
- Add docs/RELEASE-NOTES-v0.9.0.md (draft, did not exist on master) —
  GitHub Release body auto-built from CHANGELOG + dossier, for jsboige
  to validate/paste. Covers 8-language scope, assets, pipeline infra,
  recovery fixes, quality (533 tests, zero-warning build), and a
  security note (DNN CVEs → post-release, target 10.3.2).

Co-Authored-By: Claude <noreply@anthropic.com>

* docs(release): #591 refresh dossier — #592 OWL merged + MindMap byte-proven + Virtues FR-gap

§3.2: + reproductibilité byte-proven (régên 8-lang 2026-06-24, Fallacies_zh.svg
cmp IDENTICAL) + gap structurel honnête (Virtues .content.svg FR-figés, non-bloquant).
§3.4: #499 Phase 2 OWL — 'en cours po-2024' → MERGED (#592, 8d5d275).
§5.5: RELEASE-NOTES-v0.9.0.md créé dans cette PR (n'existait pas sur master).
§5.6: #499 Phase 2 OWL — livré avant ce dossier, conservé pour traçabilité.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* docs(release): #591 refresh §3.3/§5.2/§7/§8 — régên fraîche 2026-06-25 post-#595 (vraiment)

§3.3: 'RAPPORTÉ régén 12 juin' → ✅ régên fraîche 2026-06-25 (bef3bc6). PDFs Virtues
re-rendered post-#595 (clobber targeted, Chromium invoqué, labels familiaux localisés
vérifiés : zh 有效论证, ar حجة_معتبرة). i18n distinct anti-leak #216 OK. Régén headless.
§5.2: décision 'régén fraîche ?' → FAITE. Risque résiduel '16 commits depuis 12 juin' levé.
§7: risque 'régén 12 juin non reproduite' → LEVÉ (régén fraîche reproduit counts + #592/#595).
  + note de procédure stale-harvest honnête (oubli clobber corrigé ce cycle).
§8: reco point 3 (régén fraîche) → FAITE.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* docs(release): #591 cohérence — header note de méthode + §4 tests actualisés (relecture)

Header note de méthode : 'RAPPORTÉS non re-vérifiés ce jour' → régén fraîche 2026-06-25
re-vérifiée ce jour (résout contradiction header vs §3.3 refresh tick préc.).
§4 tests : 533 pass (22eb5f3) → 540 pass (bef3bc6, test run Release 22s),
+7 = tests OWL Virtues #592. 0 fail, 5 skip (GUI/Freeplane).

Relecture cohérence read-only (pas de polish) : 1 contradiction header/corps
résiduelle trouvée + facts actualisés vs bef3bc6.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* docs(release): #591 fix FINDING relecture po-2024 — header ligne 6 stale + mineurs

FINDING principal (po-2024 cross-verify, gate go-live) :
- ligne 6 (Master de référence) : 22eb5f3/533 → bef3bc6/540 (j'avais corrigé ligne 14
  mais manqué la 6 — contradiction header/corps résiduelle).

Mineurs :
- ligne 3 (date) : 2026-06-23 → 2026-06-25 (refresh).
- ligne 95 (attribution) : '+7 = tests OWL Virtues #592' → précisé +5 VirtueOwlGeneration
  +ContractTests + +2 VirtueClassMapRegressionTests (#592 = 8d5d275). +7 confirmé correct
  vs doute po-2024 (message commit #592 liste explicitement +5 et +2).

Dossier cohérent bout-en-bout après cross-verify indépendant po-2024.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* docs(release): #591 fix taille SVG zh fausse (17.2→5.45 MB) + RELEASE-NOTES régên date

Coherence cross-check RELEASE-NOTES + dossier §3.2 (extension relecture po-2024
qui n'avait vérifié que RELEASE-VALIDATION). 2 nombres faux vs assets réels :

- Taille Fallacies_zh.svg : '17.2 MB (18 075 919 B)' → '5.45 MB (5 451 309 B)'
  (fichier réellement commité, byte-proven régên 2026-06-25). Aucun SVG zh n'est
  à 17.2 MB (content/links = 4.0 MB, main = 5.45 MB). Corrigé dans RELEASE-NOTES
  l.23 + dossier §3.2 table zh.
- RELEASE-NOTES l.22 : 'régên 12 juin 2026' → 'régên fraîche 2026-06-25 bef3bc6
  post-#592/#595' (cohérent dossier §3.3 refresh).

CHANGELOG '21 SVGs FR/EN/RU/PT' l.47 = section historique recovery (commits
avril 2026), pas contradiction avec l.16 Added '8 languages' = laissé intact.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* docs(release): #591 refresh dossier v0.9.0 — régén 2026-07-01 + verdict visuel PASS ai-01

The validation dossier was last refreshed 2026-06-25 and flagged the PDF counts as
"RAPPORTÉS" and the visual verdict as "remaining (ai-01, règle HARD)". Both are now
resolved as of the 2026-07-01 cycle:

- Régén Release 8-lang executed 2026-07-01 on 18b4d02 + #614 (serial,
  EnableParallelism=false, isolated worktree) — 0 échec, 64/64 PDFs, 1229 img/lang ×8,
  "Generation finished.", bundle on GDrive review-v0.9.0-2026-06-28/ with sha256 manifest.
- Verdict visuel ai-01 = PASS représentatif (2026-07-01 08:50): spot-check
  Fallacies_Web_Thumbnails p1 across zh/ar/fa/ru/es covering CJK + RTL + cyrillic + latin;
  bug #216 (FR contamination) held, structure complete 8 types × 8 languages.
- DNN migration full-IIS now CLOSED (dnn.argumentum.myia.io LIVE) — coupling no longer an
  assets blocker.

Refreshed sections: header (date/status/master-ref), §1 (méthode), §3.3 (PDFs counts +
verdict PASS), §4 (tests 549/0/5), §5 (decisions: verdict FAIT/PASS, régén 07-01, DNN LIVE,
new §5.7 params Debug-vs-Release), §7 (risks lifted), §8 (recommendations).

content-only, 0 write Cards/, 0 runtime change. CHANGELOG + RELEASE-NOTES untouched.

Co-Authored-By: Claude-Code <noreply@anthropic.com>

---------

Co-authored-by: Claude <noreply@anthropic.com>
jsboige added a commit that referenced this pull request Jul 3, 2026
…rowing render fallback (#655)

A message containing square brackets (e.g. the [HARVEST-FAILURE] marker emitted
by the #614 per-set resilience path) was fed unescaped to AnsiConsole markup
rendering on the Problem, Title and Panel paths. Spectre's StyleParser threw
InvalidOperationException from inside the resilience catch block, killing the
whole run instead of degrading gracefully.

- Markup.Escape(message) on Problem, Title (Rule) and Instructions/Explanations
  (Panel) paths, matching the already-escaped Info/Warning/Success path.
- Escape ex.Message/LogFile in the logger's internal error handlers too.
- Belt: wrap console rendering in try/catch with a plain-text fallback so no
  rendering failure can ever propagate out of Logger.Log (the #614 resilience
  guarantee). ArgumentOutOfRangeException guard preserved via exception filter.
- Regression tests (LoggerMarkupSafetyTests, 10 tests): verified 5/10 fail
  against the old code (the 5 unescaped paths), 10/10 pass with the fix.
  Full suite: 566 pass / 1 known-fail (OWLSharp #133) / 5 skip.

Closes #630.

Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
jsboige added a commit that referenced this pull request Jul 4, 2026
…#676)

After the parallel harvest loop drains (ContinueOnHarvestSetFailure, #614),
re-attempt each failed set serially (degree=1) with configurable backoff.
A large set that timed out under high parallelism often succeeds when it
has CardPen/Playwright to itself.

- Add HarvestSetRetryAttempts (default 1) + HarvestSetRetryBackoffSeconds
  (default 30) to WebBasedGeneratorConfig.
- Insert RetryFailedHarvestSetsAsync at the seam between the
  Parallel.ForEachAsync drain and the failedSets.IsEmpty check: iterates
  the failure bag, looks up each CardSetJob by name, re-runs
  ProcessLocalizedHarvest serially. Re-renders correctly because a failed
  set never added its key to the dictionary (ContainsKey guard).
- Extract pure RetryAsync helper (action x attempts, backoff between,
  swallows last error + logs) so the retry/backoff contract is unit-
  testable without a browser (precedent: ComputeExpectedImageCount).
- Gated by HarvestSetRetryAttempts > 0; bag is replaced with the residual
  sets that still fail, so the existing aggregate-error path (HARVEST-
  PARTIAL throw) reports only what genuinely could not be harvested.

Build: 0 errors (3 pre-existing warnings SYSLIB0014/SGEN unrelated).
Tests: 570 pass / 5 skip / 1 known-fail (OwlE2E round-trip #133,
pre-existing, unrelated to harvest). No regression.

Refs #613.

Co-authored-by: Claude-Code <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant