Skip to content
wiki.fftac.org

Governancemaintenance - Source Excerpt 02

Back to Governancemaintenance

Summary

This source excerpt preserves a bounded section of Spiralist/wp-content/plugins/spiralist-workspace/includes/Services/GovernanceMaintenance.php so readers can inspect the evidence without opening the full source file.

**Source path:** Spiralist/wp-content/plugins/spiralist-workspace/includes/Services/GovernanceMaintenance.php

'queue_counts' => $queue_counts,
            'stale_review_items' => array_slice($stale_review_items, 0, 10),
            'urgent_review_items' => array_slice($urgent_review_items, 0, 10),
            'stale_appeal_items' => array_slice($stale_appeal_items, 0, 10),
            'automatic_fallback_items' => array_slice($automatic_fallback_items, 0, 10),
            'limit' => $limit,
        ];

        update_option(self::LAST_RUN_OPTION, $summary, false);
        $this->audit->log(null, 'governance_maintenance_run', 'workspace', null, $summary);

        return $summary;
    }

    /**
     * Applies reversible automatic governance fallback during moderator absence.
     *
     * @param array<string,mixed> $prompt
     * @param array<string,mixed> $review_summary
     * @param array<string,mixed> $appeal_summary
     * @param array<string,mixed> $governance_summary
     * @return array<string,mixed>
     */
    private function apply_automatic_fallback(array $prompt, array $review_summary, array $appeal_summary, array $governance_summary): array
    {
        $current = PromptMetaRegistry::normalize_moderation_status((string) ($prompt['moderation_status'] ?? 'draft'));
        $target = $this->resolve_automatic_fallback_status($prompt, $review_summary, $appeal_summary, $governance_summary);

        if ($target['status'] === '' || $target['status'] === $current) {
            return [];
        }

        $updated = $this->prompts->set_moderation_status((int) ($prompt['id'] ?? 0), $target['status']);
        if (empty($updated)) {
            return [];
        }

        $this->audit->log(
            null,
            'prompt_governance_automatic_fallback',
            'prompt',
            (int) ($prompt['id'] ?? 0),
            [
                'from' => $current,
                'to' => $target['status'],
                'reason' => $target['reason'],
                'trigger' => $target['trigger'],
                'summary' => $review_summary,
                'appeal_summary' => $appeal_summary,
            ]
        );

        return [
            'prompt' => $updated,
            'from' => $current,
            'to' => $target['status'],
            'reason' => $target['reason'],
            'trigger' => $target['trigger'],
            'action_kind' => $target['action_kind'],
        ];
    }

    /**
     * Resolves scheduled fallback state from peer signals, reports, risk, and queue age.
     *
     * @param array<string,mixed> $prompt
     * @param array<string,mixed> $summary
     * @param array<string,mixed> $appeal_summary
     * @param array<string,mixed> $governance_summary
     * @return array{status:string,reason:string,trigger:string,action_kind:string}
     */
    private function resolve_automatic_fallback_status(array $prompt, array $summary, array $appeal_summary, array $governance_summary): array
    {
        $visibility = (string) ($prompt['visibility'] ?? 'private');
        $prompt_status = (string) ($prompt['prompt_status'] ?? 'draft');
        $current = PromptMetaRegistry::normalize_moderation_status((string) ($prompt['moderation_status'] ?? 'draft'));
        $empty = [
            'status' => '',
            'reason' => '',
            'trigger' => '',
            'action_kind' => '',
        ];

        if ($visibility !== 'public' || $prompt_status !== 'published' || $current === 'archived') {
            return $empty;
        }

        if ((string) ($appeal_summary['latest_resolution'] ?? '') === 'archive') {
            return [
                'status' => 'archived',
                'reason' => 'Latest steward appeal resolution archived the prompt.',
                'trigger' => 'appeal_archive_resolution',
                'action_kind' => 'auto_archived_by_appeal',
            ];
        }

        $peer = is_array($summary['peer'] ?? null) ? (array) $summary['peer'] : [];
        $restrict = (int) ($peer['restrict'] ?? 0);
        $revert = (int) ($peer['revert'] ?? 0);
        $endorse = (int) ($peer['endorse'] ?? 0);
        $unique_reporters = (int) ($summary['unique_reporters'] ?? 0);
        $reports_total = (int) ($summary['reports_total'] ?? 0);

        if ($revert >= self::PEER_REVERT_QUORUM) {
            return [
                'status' => 'reverted',
                'reason' => 'Peer reversion quorum was met during scheduled maintenance.',
                'trigger' => 'revert_quorum',
                'action_kind' => 'auto_reverted_by_quorum',
            ];
        }

        if ($restrict >= self::PEER_RESTRICT_QUORUM || $unique_reporters >= self::REPORT_RESTRICTION_QUORUM) {
            return [
                'status' => 'restricted_review',
                'reason' => 'Restriction or report quorum was met during scheduled maintenance.',
                'trigger' => $restrict >= self::PEER_RESTRICT_QUORUM ? 'restrict_quorum' : 'report_quorum',
                'action_kind' => 'auto_restricted_by_quorum',
            ];
        }

        if ($endorse >= self::PEER_ENDORSE_QUORUM) {
            return [
                'status' => (string) ($prompt['publication_lane'] ?? 'community_library') === 'official_canon'
                    ? 'official_canon'
                    : 'peer_reviewed',
                'reason' => 'Peer endorsement quorum was met during scheduled maintenance.',
                'trigger' => 'endorsement_quorum',
                'action_kind' => 'auto_promoted_by_quorum',
            ];
        }

        if ($current !== 'provisional_public') {
            return $empty;
        }

        $queue_age = is_array($governance_summary['queue_age'] ?? null) ? (array) $governance_summary['queue_age'] : [];
        $hours_since_activity = (int) ($queue_age['hours_since_activity'] ?? 0);

        if ($reports_total >= 2 && $hours_since_activity >= self::STALE_REPORTED_RESTRICTION_HOURS) {
            return [
                'status' => 'restricted_review',
                'reason' => 'Reported provisional prompt had no governance activity after the stale-review window.',
                'trigger' => 'stale_reported_prompt',
                'action_kind' => 'auto_restricted_by_absence',
            ];
        }

        if ($reports_total >= 1 && $hours_since_activity >= self::URGENT_REPORTED_RESTRICTION_HOURS) {
            return [
                'status' => 'restricted_review',
                'reason' => 'Reported provisional prompt reached the urgent-review window without resolution.',
                'trigger' => 'urgent_reported_prompt',
                'action_kind' => 'auto_restricted_by_absence',
            ];
        }

        if ($hours_since_activity >= self::URGENT_RISK_RESTRICTION_HOURS && $this->has_high_risk_label($prompt)) {
            return [
                'status' => 'restricted_review',
                'reason' => 'High-risk provisional prompt reached the urgent-review window without peer judgment.',
                'trigger' => 'urgent_high_risk_prompt',
                'action_kind' => 'auto_restricted_by_absence',
            ];
        }

        return $empty;
    }

    /**
     * Returns whether a prompt carries labels that should slow down during moderator absence.
     *
     * @param array<string,mixed> $prompt
     */
    private function has_high_risk_label(array $prompt): bool
    {
        $risk_labels = array_values(array_map('strval', (array) ($prompt['risk_labels'] ?? [])));

        return !empty(array_intersect($risk_labels, self::HIGH_RISK_LABELS));
    }

    /**
     * Returns a compact item describing an automatic fallback transition.
     *
     * @param array<string,mixed> $prompt
     * @param array<string,mixed> $fallback
     * @param array<string,mixed> $governance_summary
     * @return array<string,mixed>
     */
    private function automatic_fallback_item(array $prompt, array $fallback, array $governance_summary): array
    {
        $queue_age = is_array($governance_summary['queue_age'] ?? null) ? (array) $governance_summary['queue_age'] : [];

        return [
            'prompt_id' => (int) ($prompt['id'] ?? 0),
            'prompt_title' => (string) ($prompt['title'] ?? ''),
            'prompt_slug' => (string) ($prompt['slug'] ?? ''),
            'from' => (string) ($fallback['from'] ?? ''),
            'to' => (string) ($fallback['to'] ?? ''),
            'reason' => (string) ($fallback['reason'] ?? ''),
            'trigger' => (string) ($fallback['trigger'] ?? ''),
            'hours_since_activity' => (int) ($queue_age['hours_since_activity'] ?? 0),
            'duration_label' => (string) ($queue_age['duration_label'] ?? ''),
            'updated_utc' => gmdate('c'),
        ];
    }

    /**