> */ public static function steps(): array { return array( array( 'id' => 'research', 'label' => __( 'Research', 'prautoblogger' ), 'icon' => 'dashicons-search', 'model_option' => 'prautoblogger_research_model', 'capability' => 'text→text', 'system_key' => 'research.system', 'agent_keys' => array(), 'description' => __( 'LLM deep-research call. The user-side research brief is a setting below, not a registry prompt.', 'prautoblogger' ), ), array( 'id' => 'analysis', 'label' => __( 'Analysis', 'prautoblogger' ), 'icon' => 'dashicons-chart-bar', 'model_option' => 'prautoblogger_analysis_model', 'capability' => 'text→text', 'system_key' => 'analysis.system', 'agent_keys' => array( 'analysis.user' ), 'description' => __( 'Scores and selects ideas from research findings.', 'prautoblogger' ), ), array( 'id' => 'writer', 'label' => __( 'Writer', 'prautoblogger' ), 'icon' => 'dashicons-edit', 'model_option' => 'prautoblogger_writing_model', 'capability' => 'text→text', 'system_key' => 'content.system', 'agent_keys' => array( 'content.single_pass', 'content.outline', 'content.draft', 'content.polish' ), 'description' => __( 'Generates article content. Active sub-stages depend on the Writing Pipeline mode setting.', 'prautoblogger' ), ), array( 'id' => 'editorial', 'label' => __( 'Editorial', 'prautoblogger' ), 'icon' => 'dashicons-admin-comments', 'model_option' => 'prautoblogger_editor_model', 'capability' => 'text→text', 'system_key' => 'editor.system', 'agent_keys' => array( 'editor.review' ), 'description' => __( 'Single-pass editorial review — approves, revises, or rejects the draft.', 'prautoblogger' ), ), array( 'id' => 'image', 'label' => __( 'Image', 'prautoblogger' ), 'icon' => 'dashicons-format-image', 'model_option' => 'prautoblogger_image_model', 'capability' => 'image_generation', 'system_key' => 'image.rewriter_system', 'agent_keys' => array( 'image.style_template' ), 'description' => __( 'Image prompt rewriter + diffusion generation. The rewriter LLM uses the Analysis model.', 'prautoblogger' ), ), ); } /** * Return a single step definition by its id, or null when not found. * * @param string $step_id Machine identifier of the step. * @return array|null */ public static function find( string $step_id ): ?array { foreach ( self::steps() as $step ) { if ( $step['id'] === $step_id ) { return $step; } } return null; } /** * All registry keys that the save handler is permitted to update via * the Pipeline Settings page. Any submitted key not in this list is rejected. * * @return string[] */ public static function allowed_prompt_keys(): array { $keys = array(); foreach ( self::steps() as $step ) { if ( ! empty( $step['system_key'] ) ) { $keys[] = $step['system_key']; } foreach ( ( $step['agent_keys'] ?? array() ) as $k ) { $keys[] = $k; } } return array_unique( $keys ); } /** * All model option names that the save handler may update. * * @return string[] */ public static function allowed_model_options(): array { $opts = array(); foreach ( self::steps() as $step ) { if ( ! empty( $step['model_option'] ) ) { $opts[] = $step['model_option']; } } return array_unique( $opts ); } }