feat: Pipeline Settings M4 — generation history list + per-step I/O drill-down (v0.26.0)
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
This commit is contained in:
60
CHANGELOG.md
60
CHANGELOG.md
@@ -5,6 +5,66 @@ All notable changes to PRAutoBlogger will be documented in this file.
|
||||
Format follows [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
||||
and this project uses [Semantic Versioning](https://semver.org/).
|
||||
|
||||
## [0.26.0] - 2026-06-23
|
||||
|
||||
### Added
|
||||
- **Pipeline Settings M4 — Generation History: run list + per-step I/O drill-down (CEO ask #5 complete):**
|
||||
|
||||
- **Generations list (`prautoblogger-gen-history`):** A browsable, paginated admin page (20 runs
|
||||
per page, newest first). Each row shows the linked article title (when the run produced a post),
|
||||
start date/time, final run status chip, distinct model(s) used, settled cost, and duration.
|
||||
Linked runs surface a "Dossier" button deep-linking to the existing Article Dossier; all runs
|
||||
(including failed/orphan ones) have a "Stage I/O" toggle for the inline drill-down. Queries
|
||||
are bounded (LIMIT/OFFSET) — no unbounded SELECT *.
|
||||
|
||||
- **Per-step input AND output drill-down:** "Stage I/O" opens an inline panel (loaded via AJAX
|
||||
on first click, then toggled). For each generation_log row the panel shows:
|
||||
- **Input — System Prompt:** the `system`-role message content extracted from
|
||||
`generation_log.request_json` (the prompt template the LLM received after rendering).
|
||||
- **Input — Assembled Instruction:** the `user`-role message content (the fully token-filled
|
||||
instruction the LLM received).
|
||||
- **Output — Model Response:** extracted from `run_stages.meta_json.output` (the LLM's raw
|
||||
text response). When pruned by the retention policy or absent for log-only stages (image_a/
|
||||
image_b, llm_research, etc.), the panel says so explicitly rather than leaving a blank.
|
||||
- Per-stage model, token counts, estimated cost, and response status.
|
||||
|
||||
- **Stage-list-driven:** Stage labels come from `Stage_Display_Map::label()` so Phase 2b
|
||||
`curate`/`seo` stages appear automatically without rework.
|
||||
|
||||
- **Dossier as primary per-step I/O surface:** For runs that produced a post the "Dossier"
|
||||
button is the recommended entry point — the dossier already renders every stage's input and
|
||||
output (request payload + stage snapshot) with the full editorial context. The inline Stage I/O
|
||||
panel is complementary; it works for orphan/failed runs and shows the same data in a lighter UI.
|
||||
|
||||
- **gen-log INPUT/OUTPUT coverage confirmed:**
|
||||
- INPUT: `generation_log.request_json` stores the full JSON chat body (messages[], model,
|
||||
temperature, …) assembled by `build_body()` before the `Authorization` header is added.
|
||||
The `Request_Recorder` captures only the body — auth headers are never stored. System and
|
||||
user message content are extracted and surfaced.
|
||||
- OUTPUT: `run_stages.meta_json` holds `{output: "..."}` — the LLM's raw response text
|
||||
written by `Run_Stage_State::done()`. Image/log-only stages (image_a, image_b,
|
||||
llm_research, image_prompt_rewrite) have no `run_stages` row; their output is null (not
|
||||
pruned). When `meta_json` is present but lacks the `output` key (pruned by the
|
||||
`prautoblogger_request_json_retention_days` setting), `output_pruned = true` is returned
|
||||
and the UI explains the gap honestly.
|
||||
|
||||
- **New files:** `includes/admin/class-gen-history-query.php`,
|
||||
`includes/admin/class-gen-history-page.php`,
|
||||
`includes/ajax/class-gen-run-io-handler.php`,
|
||||
`templates/admin/gen-history-page.php`,
|
||||
`assets/css/gen-history.css`,
|
||||
`assets/js/gen-history.js`.
|
||||
|
||||
### Fixed (M3 P2 sweep)
|
||||
- **Removed dead `data-preview-nonce` and `data-diff-nonce` HTML attributes** from
|
||||
`templates/admin/pipeline-settings-prompt-panel.php`. The JS has always read nonces from
|
||||
`prabPipeline.previewNonce` / `prabPipeline.diffNonce` (via `wp_localize_script` in
|
||||
`Pipeline_Settings_Page::on_enqueue_assets`), not from `data-*` attrs — confirmed by grep.
|
||||
Removing them eliminates redundant server-side `wp_create_nonce()` calls in the renderer.
|
||||
- **Removed 3 redundant `wp_create_nonce()` calls** from
|
||||
`includes/admin/class-pipeline-settings-renderer.php` (`preview_nonce`, `history_nonce`,
|
||||
`diff_nonce` keys) — they were only feeding the now-removed dead `data-*` attrs.
|
||||
|
||||
## [0.25.0] - 2026-06-23
|
||||
|
||||
### Added
|
||||
|
||||
Reference in New Issue
Block a user