CEO ask #5 complete: browsable paginated run list + full input/output inspection
per pipeline stage.
## What was built
### Generations list (prautoblogger-gen-history)
Hidden admin page (options.php-parent, priority 14) showing all pipeline runs newest
first, 20 per page. Each row: article title (linked to dossier when a post exists),
start date, status chip, distinct model(s), settled cost, duration. Queries bounded
(LIMIT/OFFSET) — no unbounded SELECT *.
New files:
- includes/admin/class-gen-history-query.php — paginated run list + per-run I/O queries
- includes/admin/class-gen-history-page.php — hidden admin page + asset enqueue
- assets/css/gen-history.css, assets/js/gen-history.js — table + drill-down UI
- templates/admin/gen-history-page.php — HTML template
### Per-step input + output drill-down (Stage I/O)
'Stage I/O' toggle opens an AJAX-loaded inline panel. For each generation_log stage:
- input_system: system-role message content from generation_log.request_json
- input_user: last user-role message from request_json (rendered instruction)
- output: model response from run_stages.meta_json.output
- output_pruned: true when meta_json present but output key absent (retention prune)
New AJAX endpoint: prautoblogger_gen_run_io (manage_options + nonce)
New file: includes/ajax/class-gen-run-io-handler.php
### gen-log INPUT/OUTPUT coverage verified
- INPUT: generation_log.request_json stores the chat body WITHOUT the Authorization
header (Request_Recorder captures body after build_body(), before headers are added).
System + user message content extracted and surfaced.
- OUTPUT: run_stages.meta_json.output is the LLM response text (Run_Stage_State::done()).
Image/log-only stages (image_a, image_b, llm_research, image_prompt_rewrite) have no
run_stages row; output is null, NOT pruned. Pruned outputs are flagged honestly.
### Dossier as entry point
Runs with a linked post show a 'Dossier' button deep-linking into the existing dossier
(which renders full per-stage I/O with editorial context). Stage I/O is complementary —
works for failed/orphan runs and provides the same data in a lighter inline UI.
### Stage-list-driven
Stage labels via Stage_Display_Map::label() — Phase 2b curate/seo appear automatically.
### Dead prautoblogger_pipeline_history endpoint
Not dead — it IS used by pipeline-settings.js for prompt version history (M3 feature).
Left in place. No dangling endpoint.
## M3 P2 sweep
- Removed dead data-preview-nonce and data-diff-nonce HTML attrs from
pipeline-settings-prompt-panel.php (JS uses prabPipeline.*Nonce from
wp_localize_script, not data-* attrs — confirmed by grep).
- Removed 3 redundant wp_create_nonce() calls from class-pipeline-settings-renderer.php
(preview_nonce, history_nonce, diff_nonce keys that fed the now-removed dead attrs).
- Updated CONTEXT.md: added M3 + M4 terminology tables.
- Updated ARCHITECTURE.md: added ajax/ section to file tree; M3/M4 design notes.
- Updated INFORMATION-ARCHITECTURE.md: prautoblogger-gen-history entry.
## Security
- manage_options cap + prautoblogger_gen_run_io nonce on the AJAX endpoint.
- All output esc_html()/esc_url() server-side before JSON-encoding.
- JS renders prompt/response text via textContent — never innerHTML.
- No writes from history UI; request_json never contains auth headers.
## Version: v0.25.0 → v0.26.0
Agent-Session: pipeline-settings-m4
Root cause: .ab-mp-price and .ab-mp-ctx were siblings in .ab-mp-row-meta
with price first. Description text is variable-length, so the meta div
grew/shrank per row, shifting the price left/right.
Fix:
- Move price to last child in .ab-mp-row-meta so its right edge is
always pinned to the row's fixed right edge
- Add flex-shrink: 0 to .ab-mp-price so it never compresses
- Cap .ab-mp-ctx at max-width 200px with text-overflow: ellipsis
- Swap column header order (Context, then Price) to match new DOM order
.ab-mp-col-price was missing min-width and right-alignment even though
.ab-mp-price had both. The header sat left while values sat right,
so they didn't track the same column edge. Added min-width: 90px and
justify-content: flex-end to match.
- Add .ab-mp-col-headers bar between search and list with three
clickable column headers: Model (sorts by name), Price in/out
(sorts by input_price_per_m), Context (sorts by context_length)
- Track sortState at module level so preference persists across
open/close; clicking same column toggles asc/desc
- Deprecated models always sink to bottom regardless of sort column
- Add CSS for .ab-mp-col-headers, .ab-mp-col-header, .ab-mp-sort-arrow,
.ab-mp-col-active; widths mirror existing row flex layout so columns
visually align with data
Bumps version 0.13.1 → 0.13.2
Add min-width: 90px and text-align: right to .ab-mp-price so prices
like $0.0006/image and $0.0800/image stack on a consistent right edge
instead of floating at uneven offsets.
Replace plain text inputs for analysis/writing/editor model fields
with a rich model picker that fetches the OpenRouter model registry
and displays a searchable popup with model name, provider, input/output
pricing per 1M tokens, and context window. Also extracts source status
and model field renderers into dedicated field classes to keep
class-admin-page.php under the 300-line cap.
New files:
- assets/js/model-picker.js — popup UI with search, filtering, caching
- assets/css/model-picker.css — popup styles matching admin design system
- includes/admin/fields/class-open-router-model-field.php — server render
- includes/admin/fields/class-source-status-field.php — extracted field
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Save Settings shows "Saving…" on button + green success banner after
redirect (auto-dismisses after 6s)
- Test Connections shows spinning icon + progress banner while in-flight
- Generate Now shows spinning icon + timed pipeline stage messages so
the user knows the pipeline is working, not hung
- Shared ab-btn-loading CSS class with smooth dashicon spin animation
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Remove Reddit OAuth fields (Client ID/Secret) from admin settings
- Add source status indicator showing PullPush.io + .json fallback health
- Add configurable cache TTL, time window, and posts-per-subreddit settings
- Update Test Connections to report which Reddit source is active
- Bump version 0.1.0 → 0.2.0 across plugin header, constant, and readme
- Switch deploy pipeline from zip/REST API to SSH rsync with --delete
- Add LiteSpeed cache purge step to prevent stale OPcache after deploy
- Update CHANGELOG.md and readme.txt for 0.2.0 release
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
WordPress plugin that auto-researches topics from Reddit, generates
SEO-optimized articles via OpenRouter LLMs, runs them through a chief
editor agent, and publishes on a daily schedule.
Includes:
- Full generation pipeline (collect → analyze → score → generate → review → publish)
- Cost tracking and budget enforcement
- Admin UI: settings, review queue, metrics, activity log
- CI/CD pipeline (GitHub Actions → WordPress REST deploy)
- Unit test suite (PHPUnit + Brain Monkey)
- Structured logging with configurable verbosity
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>