Items completed:
1. GD-rung tests (QA P2, verdict 2026-06-11-6f76df1.md P2-1):
- New ImageComposerEditorTest.php: 7 tests covering wp_get_image_editor WP_Error,
resize WP_Error, upscale size-mismatch guard, save WP_Error, zero-width geometry
guard, missing-role guard, and successful OG resize happy path.
- Orchestrator gd-rung test added to ImageComposerTest.php: forces capability='gd'
via filter, asserts Imagick renderer is never called, pass-through featured is
always first.
2. Dead layout keys removed (QA P3, same verdict P3-3):
- Removed caption_margin_right (og) and caption_side_padding (square) from
Layout::defaults(). The Imagick renderer never reads them: og text is
left-anchored from logo_x+logo_w+caption_gap; square text is center-anchored
at floor(width/2). Right-edge geometry is enforced by caption_chars_per_line.
Decision: remove (not consume) — no renderer geometry to wire them to.
3. Amortized pv/role (P3 carried, phase-1 thread seq 49 + seq 50):
- Post_Assembler::amortize_research_costs() SELECT now includes prompt_version
and agent_role; INSERT carries them forward so amortized llm_research rows are
no longer stamped with NULL/empty audit fields.
4. fetch_page() error body (P3 carried, phase-1 thread seq 50):
- Runware_Catalog_Fetcher::fetch_page() non-200 exceptions now include up to
200 chars of the response body for log-based diagnosis.
5. cto-review.yml isinstance guard: ALREADY FIXED at HEAD (line 454 uses
c.get("severity", "UNKNOWN")). Noted in CHANGELOG; no code change.
Agent-Session: engineer-prab-maint-20260612
Runware retired taskType:models; all 42 daily catalog 401s come from this
deprecated endpoint. Migrated to auth+modelSearch pair per Runware's
current API. Paginator fetches up to 5 pages x 100 = 500 models, filters
client-side to io:text-to-image in capabilities[]. Uses air identifier as
model id. Cache key bumped to v2 (prautoblogger_runware_model_cache_v2)
to invalidate v1 rows that used old taskType/requiresImage shape.
Failure cooldown: sync() records prautoblogger_runware_catalog_last_failure_at
on every error path. get_models() gates re-trigger via is_in_failure_cooldown()
which reads prautoblogger_runware_catalog_failure_cooldown_seconds (default
3600s). Success clears the timestamp. Caps cascade to ~24 errors/day.
300-line rule: fetching/normalization extracted to new companion class
PRAutoBlogger_Runware_Catalog_Fetcher (class-runware-catalog-fetcher.php,
205 lines). Catalog class: 261 lines. Autoloader picks up the new file.
Tests: normalize_models against real modelSearch fixture (redacted key);
cooldown behavior (failure->active->expired); sync clears timestamp; fallback
list always served when cache empty. 328/328 PHPUnit green.
Agent-Session: prab-v0183-20260612