- qa-autofix.php queues Web Designer tasks for safe findings (alt, internal links) with 6h dedup; runQaFlow runs it after each pass and kicks the queue (QA_AUTOFIX env, on by default) - adminqa fix() accepts optional human instructions; /admin/qa adds an instructions input per finding for the judgment calls
71 lines
2.6 KiB
PHP
71 lines
2.6 KiB
PHP
<?php
|
|
/**
|
|
* Auto-queue Web Designer fix tasks for the SAFE QA findings of a run — the ones
|
|
* with a clear, low-risk fix (missing/empty alt text, broken internal links).
|
|
* Judgment calls (external links, images, SEO opinions) are left for the human
|
|
* via the admin's per-finding instructions box.
|
|
*
|
|
* php api/cli/qa-autofix.php --run=ID -> {"queued": N}
|
|
*
|
|
* Dedup: skips a finding if a matching fix task is already queued/running, or was
|
|
* created in the last 6 hours — so hourly heartbeats never spam or loop on the
|
|
* same issue.
|
|
*/
|
|
|
|
require __DIR__ . '/../vendor/autoload.php';
|
|
require __DIR__ . '/../config.php';
|
|
|
|
const SAFE = ['a11y', 'link'];
|
|
|
|
$opts = getopt('', ['run:']);
|
|
$runId = (int) ($opts['run'] ?? 0);
|
|
if ($runId <= 0) { echo json_encode(['queued' => 0]); exit; }
|
|
|
|
$pdo = new PDO(
|
|
sprintf('mysql:host=%s;dbname=%s;charset=utf8mb4', DB_HOST, DB_NAME),
|
|
DB_USER,
|
|
DB_PASS,
|
|
[PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION, PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC]
|
|
);
|
|
|
|
$in = implode(',', array_fill(0, count(SAFE), '?'));
|
|
$sel = $pdo->prepare(
|
|
"SELECT finding_id, check_type, url, detail, fix_hint
|
|
FROM cja_qa_findings
|
|
WHERE run_id = ? AND status = 'open' AND check_type IN ($in)"
|
|
);
|
|
$sel->execute([$runId, ...SAFE]);
|
|
|
|
$dupe = $pdo->prepare(
|
|
"SELECT COUNT(*) FROM cja_tasks
|
|
WHERE title = ? AND (status IN ('queued','running') OR created_at > (NOW() - INTERVAL 6 HOUR))"
|
|
);
|
|
$order = (int) $pdo->query('SELECT COALESCE(MAX(sort_order), 0) FROM cja_tasks')->fetchColumn();
|
|
$ins = $pdo->prepare(
|
|
'INSERT INTO cja_tasks (title, target_page, prompt, draft, assets, status, sort_order)
|
|
VALUES (?, ?, ?, "", ?, "queued", ?)'
|
|
);
|
|
$mark = $pdo->prepare("UPDATE cja_qa_findings SET status = 'fix_queued' WHERE finding_id = ?");
|
|
|
|
$queued = 0;
|
|
foreach ($sel as $f) {
|
|
$url = (string) $f['url'];
|
|
$title = 'QA fix: ' . $f['check_type'] . ' — ' . mb_substr($url, 0, 60);
|
|
|
|
$dupe->execute([$title]);
|
|
if ((int) $dupe->fetchColumn() > 0) continue;
|
|
|
|
$target = (str_starts_with($url, '/') && !str_contains($url, ',') && !str_contains($url, '://'))
|
|
? explode('#', explode('?', $url)[0])[0]
|
|
: '/';
|
|
$prompt = ($f['fix_hint'] !== null && $f['fix_hint'] !== '')
|
|
? (string) $f['fix_hint']
|
|
: "QA found a {$f['check_type']} issue on {$url}: {$f['detail']}. Fix it.";
|
|
|
|
$order += 10;
|
|
$ins->execute([mb_substr($title, 0, 200), mb_substr($target, 0, 200), $prompt, json_encode(['images' => [], 'videos' => []]), $order]);
|
|
$mark->execute([$f['finding_id']]);
|
|
$queued++;
|
|
}
|
|
|
|
echo json_encode(['queued' => $queued]);
|