feat(M3): dossier edit+rerun UI, F2/F3, run-list badges — v0.20.0
- Dossier_Actions (4 AJAX endpoints, manage_options+nonce): save fork / queue replay / queue rebuild / stage-status poll. Run identity always derived server-side from post meta; the AJAX layer validates + queues ONLY — all mutations happen in the cron handlers (chained-cron, CPO hard constraint). Fork saves lock message structure (count/roles) so every version stays replayable. - Edit panel per editable stage: per-message textareas prefilled from the latest fork or the recorded request_json; explicit fork + downstream-stale + queued-execution copy; spend strip with ceiling warning (filterable fraction, default 0.8). Disabled stages always show WHY (policy reasons; missing-input retention copy). - Stale / human-edited / attempt chips per stage + header badges (M2 slot filled); dossier polls stage status while a re-run is active (board poll interval setting) and re-renders when the run settles. - F2: sidebar Models & Prompts card (per-stage model/pv/role) + Run Spend card. F3: log-only stages (image_a/b, llm_research, ...) render from generation_log + the _prautoblogger_image_role attachment grid. - M2 correctness: dossier is now item-scoped (idea-hash meta) and excludes gen_log rows linked to other posts of a multi-article run. - Run-list visibility (product AC): board cards get a Human-modified chip; Review Queue rows get a stale-stages chip linking to the dossier. Both via single batched queries (no N+1). - v0.20.0 + CHANGELOG + ARCHITECTURE #24 (+ file tree, schema tables, db-version note) in this commit per versioning discipline. Agent-Session: engineer-prab-m3-20260612
This commit is contained in:
@@ -127,7 +127,7 @@ class PRAutoBlogger_Board_Data_Provider {
|
||||
);
|
||||
}
|
||||
|
||||
return $cards;
|
||||
return $this->flag_human_modified( $cards );
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -183,6 +183,48 @@ class PRAutoBlogger_Board_Data_Provider {
|
||||
);
|
||||
}
|
||||
|
||||
return $this->flag_human_modified( $cards );
|
||||
}
|
||||
|
||||
/**
|
||||
* Set 'human_modified' on each card in ONE batched query (v0.20.0 —
|
||||
* CPO product AC: human-modified runs are visually distinct at the
|
||||
* run-list level). No per-card queries; self-healing on a missing
|
||||
* table/column (flag simply stays false).
|
||||
*
|
||||
* @param array<int, array<string, mixed>> $cards Column cards.
|
||||
* @return array<int, array<string, mixed>> Cards with the flag set.
|
||||
*/
|
||||
private function flag_human_modified( array $cards ): array {
|
||||
$run_ids = array();
|
||||
foreach ( $cards as $i => $card ) {
|
||||
$cards[ $i ]['human_modified'] = false;
|
||||
if ( ! empty( $card['run_id'] ) ) {
|
||||
$run_ids[] = (string) $card['run_id'];
|
||||
}
|
||||
}
|
||||
if ( empty( $run_ids ) || ! PRAutoBlogger_Run_Stage_State::is_available() ) {
|
||||
return $cards;
|
||||
}
|
||||
global $wpdb;
|
||||
$table = PRAutoBlogger_Run_Stage_State::table_name();
|
||||
$placeholders = implode( ',', array_fill( 0, count( $run_ids ), '%s' ) );
|
||||
// phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery,WordPress.DB.DirectDatabaseQuery.NoCaching,WordPress.DB.PreparedSQL.NotPrepared -- $placeholders is a fixed %s list.
|
||||
$flagged = $wpdb->get_col(
|
||||
$wpdb->prepare(
|
||||
"SELECT DISTINCT run_id FROM {$table} WHERE human_modified = 1 AND run_id IN ({$placeholders})",
|
||||
$run_ids
|
||||
)
|
||||
);
|
||||
if ( ! is_array( $flagged ) || empty( $flagged ) ) {
|
||||
return $cards;
|
||||
}
|
||||
$flagged = array_flip( array_map( 'strval', $flagged ) );
|
||||
foreach ( $cards as $i => $card ) {
|
||||
if ( isset( $flagged[ (string) ( $card['run_id'] ?? '' ) ] ) ) {
|
||||
$cards[ $i ]['human_modified'] = true;
|
||||
}
|
||||
}
|
||||
return $cards;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user