refactor(#2416): remove the non-pr config-change flow (request_apply_commit / applycommit)

This commit is contained in:
damocles 2026-07-15 20:45:29 +02:00 committed by mara
commit c2bd7db998
34 changed files with 293 additions and 1635 deletions

View file

@ -130,7 +130,6 @@ export function applyApprovalAdded(ev) {
kind: ev.approval_kind,
sha_short: ev.sha_short || null,
pr_number: ev.pr_number ?? null,
diff: ev.diff || null,
description: ev.description || null,
// The ApprovalAdded event carries no requested_at; a live-added
// approval was queued just now, so client-now is accurate — and
@ -167,68 +166,6 @@ export function applyApprovalResolved(ev) {
}
renderApprovals();
}
// Classify each unified-diff line by its leading char so
// `.diff-add` / `.diff-del` / `.diff-hunk` / `.diff-file` /
// `.diff-ctx` colour the output. Built as text-only spans (no
// innerHTML) so there's no HTML-escape surface.
function buildDiffPre(text) {
const pre = el('pre', { class: 'diff' });
for (const raw of String(text).split('\n')) {
let cls = 'diff-ctx';
if (raw.startsWith('--- ') || raw.startsWith('+++ ')) cls = 'diff-file';
else if (raw.startsWith('@')) cls = 'diff-hunk';
else if (raw.startsWith('+')) cls = 'diff-add';
else if (raw.startsWith('-')) cls = 'diff-del';
const span = document.createElement('span');
span.className = cls;
span.textContent = raw + '\n';
pre.appendChild(span);
}
return pre;
}
// Open an approval's diff in the side panel with a 3-way base
// toggle: vs applied (running tree), vs last-approved, vs previous
// proposal. `applied` uses the diff already shipped on the approval
// for instant paint; the other two fetch /api/approval-diff.
function openDiffPanel(a) {
const bases = [
['applied', 'vs applied'],
['approved', 'vs last-approved'],
['previous', 'vs previous proposal'],
];
const tabs = el('div', { class: 'diff-base-tabs' });
const host = el('div', { class: 'diff-host' });
async function selectBase(base) {
for (const btn of tabs.children) {
btn.classList.toggle('active', btn.dataset.base === base);
}
if (base === 'applied' && a.diff != null) {
host.replaceChildren(buildDiffPre(a.diff));
return;
}
host.replaceChildren(el('div', { class: 'meta' }, 'loading…'));
try {
const resp = await fetch('/api/approval-diff/' + a.id + '?base=' + base);
const text = await resp.text();
host.replaceChildren(resp.ok
? buildDiffPre(text)
: el('div', { class: 'meta' }, 'error: ' + text));
} catch (e) {
host.replaceChildren(el('div', { class: 'meta' }, 'error: ' + e));
}
}
for (const [base, label] of bases) {
const btn = el('button',
{ type: 'button', class: 'diff-base-tab', 'data-base': base }, label);
btn.addEventListener('click', () => selectBase(base));
tabs.append(btn);
}
const wrap = el('div', { class: 'diff-panel' }, tabs, host);
Panel.open('diff · ' + a.agent + ' #' + a.id, wrap);
selectBase('applied');
}
export function renderApprovals() {
const root = $('approvals-section');
// #approvals-section only lives on /dashboard.html (Y3R C4LL tab);
@ -313,7 +250,6 @@ export function renderApprovals() {
const ul = el('ul', { class: 'approvals' });
for (const a of pending) {
const isApply = a.kind === 'apply_commit';
const isInit = a.kind === 'init_config';
const isMergePr = a.kind === 'merge_config_pr';
const isUpdateMeta = a.kind === 'update_meta_inputs';
@ -322,13 +258,13 @@ export function renderApprovals() {
// ── identity header ──────────────────────────────────────────
const head = el('div', { class: 'approval-head' },
el('span', { class: 'glyph' }, isApply ? '→' : isMergePr ? '⇒' : isUpdateMeta ? '↻' : isSchedule ? '⏱' : '⊕'),
el('span', { class: 'glyph' }, isMergePr ? '⇒' : isUpdateMeta ? '↻' : isSchedule ? '⏱' : '⊕'),
el('span', { class: 'id' }, '#' + a.id),
el('span', { class: 'agent' }, a.agent),
el('span', { class: 'kind' + ((isApply || isMergePr || isUpdateMeta || isSchedule) ? '' : ' kind-spawn') },
isApply ? 'apply' : isMergePr ? 'merge-pr' : isUpdateMeta ? 'meta-update' : isSchedule ? 'schedule' : isInit ? 'init' : 'spawn'),
el('span', { class: 'kind' + ((isMergePr || isUpdateMeta || isSchedule) ? '' : ' kind-spawn') },
isMergePr ? 'merge-pr' : isUpdateMeta ? 'meta-update' : isSchedule ? 'schedule' : isInit ? 'init' : 'spawn'),
);
if ((isApply || isMergePr) && a.sha_short) head.append(el('code', {}, a.sha_short));
if (isMergePr && a.sha_short) head.append(el('code', {}, a.sha_short));
// When the approval was requested — relative time, right-aligned.
// Goes amber once it's been pending an hour so a stale request is
// obvious at a glance (see docs/web-ui.md::Approval card).
@ -348,24 +284,9 @@ export function renderApprovals() {
if (a.description) {
body.append(el('div', { class: 'approval-description' }, a.description));
}
if (isApply) {
const drill = el('div', { class: 'drill-ins' });
const diffBtn = el('button', { type: 'button', class: 'panel-trigger' },
'↳ view diff');
diffBtn.addEventListener('click', () => openDiffPanel(a));
drill.append(diffBtn);
if (forgeBase && a.sha_full) {
drill.append(el('a', {
class: 'panel-trigger', target: '_blank', rel: 'noopener',
href: `${forgeBase}/agent-configs/${a.agent}/commit/${a.sha_full}`,
title: 'this proposal commit on the hive forge',
}, '↳ commit on forge ↗'));
}
body.append(drill);
} else if (isMergePr) {
// PR-based config deploy: link to the reviewed PR on the forge
// (mirrors the apply_commit "commit on forge" link). The config
// diff side-panel is apply_commit-only for now.
if (isMergePr) {
// PR-based config deploy: link to the reviewed PR on the forge.
// The config diff lives on the forge PR itself.
const drill = el('div', { class: 'drill-ins' });
if (forgeBase && a.pr_number != null) {
drill.append(el('a', {
@ -443,7 +364,7 @@ function renderApprovalHistory(root, history) {
el('span', { class: 'glyph glyph-' + a.status }, glyph), ' ',
el('span', { class: 'id' }, '#' + a.id), ' ',
el('span', { class: 'agent' }, a.agent), ' ',
el('span', { class: 'kind' }, a.kind === 'apply_commit' ? 'apply' : a.kind === 'merge_config_pr' ? 'merge-pr' : a.kind === 'update_meta_inputs' ? 'meta-update' : a.kind === 'schedule_prompt' ? 'schedule' : a.kind === 'init_config' ? 'init' : 'spawn'), ' ',
el('span', { class: 'kind' }, a.kind === 'merge_config_pr' ? 'merge-pr' : a.kind === 'update_meta_inputs' ? 'meta-update' : a.kind === 'schedule_prompt' ? 'schedule' : a.kind === 'init_config' ? 'init' : 'spawn'), ' ',
);
if (a.sha_short) row.append(el('code', {}, a.sha_short), ' ');
row.append(