Send a bug report to one place, on purpose, after reading it

The page built its own markdown and nothing could send it; local and upstream
are different people, so neither falls back to the other.
This commit is contained in:
Gmer4Lfe
2026-08-13 16:32:36 -04:00
parent 2c1fd4c8bf
commit 2ccc93bb14
6 changed files with 261 additions and 39 deletions
+46
View File
@@ -382,6 +382,52 @@ if ($action === 'bug_close') {
exit;
}
// The report, rendered server-side. Read-only by design: what the operator reviews is byte for
// byte what gets sent, so approving one text and transmitting another is not possible. It is also
// the only renderer — the page used to build its own markdown, which is two formats to keep in
// step and one of them always losing.
if ($action === 'bug_report') {
$id = trim($_GET['id'] ?? '');
$bug = null;
foreach (vv_ai_bugs_list(false) as $b) if (($b['id'] ?? '') === $id) { $bug = $b; break; }
if (!$bug) { echo json_encode(['ok' => false, 'error' => 'no such report']); exit; }
$t = vv_ai_bug_targets();
$title = '[' . ($bug['component'] ?? '?') . '] ' . ($bug['summary'] ?? '');
echo json_encode([
'ok' => true,
'title' => $title,
'markdown' => vv_ai_bug_report($bug),
'targets' => $t,
// Built here because the repo name lives here. Length is the caller's problem to notice:
// GitHub truncates a very long query rather than refusing it, which would silently send a
// half report — so the page checks and falls back to the copy box.
'github' => 'https://github.com/' . $t['github_repo'] . '/issues/new?title='
. rawurlencode($title) . '&body=' . rawurlencode(vv_ai_bug_report($bug)),
]);
exit;
}
// Sends to the operator's own Gitea, and only there. Never falls back to GitHub on failure: the
// two destinations are different people, and a silent substitution is how a report meant for a
// private backlog ends up public.
if ($action === 'bug_send_local') {
if (!$isPost) { http_response_code(405); echo json_encode(['ok' => false, 'error' => 'POST only']); exit; }
$id = trim($_POST['id'] ?? '');
$bug = null;
foreach (vv_ai_bugs_list(false) as $b) if (($b['id'] ?? '') === $id) { $bug = $b; break; }
if (!$bug) { echo json_encode(['ok' => false, 'error' => 'no such report']); exit; }
// Re-rendered from the store rather than taken from the request. The browser showed this text
// read-only; accepting a body from the page would make that guarantee decorative.
$r = vv_ai_bug_send_local('[' . ($bug['component'] ?? '?') . '] ' . ($bug['summary'] ?? ''),
vv_ai_bug_report($bug));
vv_ai_log(sprintf('bug_send_local id=%s %s', $id,
$r['ok'] ? 'ok ' . ($r['url'] ?? '') : 'failed: ' . ($r['error'] ?? '?')));
echo json_encode($r);
exit;
}
// ── findings / finding_action ─────────────────────────────────────────────────
// What the repair sweep found, and the operator's answer to it. include/ai_repair.php is pulled
// in here rather than at the top of the file: it is the largest include in the plugin and poll