fix: surface pi rust diagnostics in ui

This commit is contained in:
Agent Board
2026-07-12 07:03:26 +08:00
parent 031a08288b
commit 62959b0c4d
5 changed files with 236 additions and 5 deletions
@@ -0,0 +1,25 @@
# 7-65 Page AI Pi Rust diagnostics UI checklist
## 背景
- P2 取舍里确认:`--extension-policy` / `--repair-policy` / session durability / request timeout / max tool iterations / hide cwd 等高级 runtime 策略可以先不做普通用户设置项,但必须在诊断里暴露 effective policy。
- Pi Rust 官方 `doctor` / `context-preview` / `list` / `search` / `info` / `update-index` 不属于对话主链 bug,但适合进入 Pi Lab 折叠诊断和 AI 管理页。
- MNote 只做宿主、授权、文件地址和受控诊断入口,不用 MNote 工具替代 Pi Rust 官方能力。
## Checklist
- [x] Pi Lab 折叠诊断区接入 `/api/page-ai/pi/diagnostics`,提供 `doctor` / `context-preview` / `list` / `search` / `info` / `update-index` 受控入口。
- [x] Pi Lab 诊断状态显示 effective `advancedRuntime` 摘要,覆盖 extension policy、repair policy、session durability、request timeout、max tool iterations、hide cwd。
- [x] AI 管理页 Pi Rust 服务卡展示 effective `advancedRuntime` 摘要与 JSON 明细。
- [x] AI 管理页 Pi Rust 服务卡提供同一组官方诊断按钮,复用后端受控 diagnostics wrapper,不透传 raw args。
- [x] 静态 smoke 覆盖 Pi Lab runtime 的 diagnostics API、按钮、输出区域和 advanced runtime summary。
- [x] 静态 smoke 覆盖 AI 管理页 diagnostics 卡片、按钮、路由和 effective advanced runtime 展示。
## 验收命令
```bash
node scripts/task-pi-lab-static-smoke.js
node scripts/task-ai-management-control-plane-static-smoke.js
cargo test --manifest-path rust/Cargo.toml -p mnote-web page_ai_pi -- --nocapture
cargo test --manifest-path rust/Cargo.toml -p mnote-web ai_admin -- --nocapture
```
@@ -39,6 +39,7 @@
COMPACT: '/api/page-ai/pi/compact',
CONFIGURE: '/api/page-ai/pi/configure',
QUEUE_CONFIG: '/api/page-ai/pi/queue-config',
DIAGNOSTICS: '/api/page-ai/pi/diagnostics',
EFFECTIVE: '/api/ai-settings/effective',
};
@@ -81,6 +82,7 @@
runtimeInstallHint: '',
runtimeError: '',
runtimePid: null,
advancedRuntime: {},
warmupRunning: false,
warmupSessionId: null,
managedBuiltinTools: [],
@@ -584,6 +586,7 @@
'.wolai-page-ai-pi-lab-diagnostics{display:none;border-top:1px solid #e6e2da;background:#fff;flex:0 0 auto}' +
'.wolai-page-ai-pi-lab-drawer[data-config-open="true"] .wolai-page-ai-pi-lab-diagnostics{display:block}' +
'.wolai-page-ai-pi-lab-diagnostics>summary{cursor:pointer;padding:8px 12px;font-size:11px;color:#6f6a60}' +
'.wolai-page-ai-pi-lab-diagnostic-actions{display:flex;flex-wrap:wrap;gap:6px;align-items:center;padding:0 12px 8px}.wolai-page-ai-pi-lab-diagnostic-actions button{height:26px;border:1px solid #ddd8cf;border-radius:7px;background:#fff;color:#42403a;padding:0 8px;font-size:11px;cursor:pointer}.wolai-page-ai-pi-lab-diagnostic-actions button:hover{background:#f8f7f3}.wolai-page-ai-pi-lab-diagnostic-actions input{height:26px;min-width:120px;border:1px solid #ddd8cf;border-radius:7px;background:#fff;color:#42403a;padding:0 8px;font-size:11px;outline:none}.wolai-page-ai-pi-lab-diagnostic-output[hidden]{display:none!important}.wolai-page-ai-pi-lab-diagnostic-output{border-top:1px solid #eee9e0;background:#faf9f6}' +
'.wolai-page-ai-pi-lab-diagnostics pre{margin:0;padding:0 12px 10px;white-space:pre-wrap;word-break:break-word;font:11px/1.45 ui-monospace,SFMono-Regular,Menlo,monospace;color:#5d594f}' +
'@media (max-width: 760px){.wolai-page-ai-pi-lab-drawer{left:10px;right:10px;top:58px;bottom:10px;width:auto}.wolai-page-ai-pi-lab-history-panel{width:min(320px,calc(100vw - 34px))}.wolai-page-ai-pi-lab-rail{left:14px;right:14px;top:auto;bottom:132px;width:auto;max-height:min(360px,calc(100% - 164px))}.wolai-page-ai-pi-lab-config{grid-template-columns:1fr}}' +
'@media (max-width: 520px){.wolai-page-ai-pi-lab-topbar{height:54px;padding:0 14px}.wolai-page-ai-pi-lab-title strong{font-size:21px}.wolai-page-ai-pi-lab-commandbar{height:50px;margin:0 14px 12px;gap:6px;overflow:hidden}.wolai-page-ai-pi-lab-history-panel{top:116px;left:12px;right:12px;max-height:min(300px,calc(100% - 300px))}.wolai-page-ai-pi-lab-history-row{grid-template-columns:1fr}.wolai-page-ai-pi-lab-history-actions{justify-content:flex-start}.wolai-page-ai-pi-lab-input{min-height:88px;padding:16px 58px 10px 18px;font-size:16px}.wolai-page-ai-pi-lab-modebar{min-height:48px;flex-wrap:nowrap;gap:6px;padding:6px 10px}.wolai-page-ai-pi-lab-model-control-wrap{flex:1 1 130px;min-width:92px;max-width:none}.wolai-page-ai-pi-lab-toast-stack{left:14px;right:14px;bottom:154px}.wolai-page-ai-pi-lab-toast{width:100%}}';
@@ -2018,7 +2021,17 @@
'</div>' +
'<details class="wolai-page-ai-pi-lab-diagnostics" data-page-ai-pi-lab-diagnostics>' +
'<summary>诊断</summary>' +
'<div class="wolai-page-ai-pi-lab-diagnostic-actions">' +
'<button type="button" data-page-ai-pi-lab-diagnostic-command="doctor">doctor</button>' +
'<button type="button" data-page-ai-pi-lab-diagnostic-command="context-preview">context-preview</button>' +
'<button type="button" data-page-ai-pi-lab-diagnostic-command="list">list</button>' +
'<button type="button" data-page-ai-pi-lab-diagnostic-command="update-index">update-index</button>' +
'<input type="search" data-page-ai-pi-lab-diagnostic-query placeholder="search/info keyword">' +
'<button type="button" data-page-ai-pi-lab-diagnostic-command="search">search</button>' +
'<button type="button" data-page-ai-pi-lab-diagnostic-command="info">info</button>' +
'</div>' +
'<pre data-page-ai-pi-lab-diag-text></pre>' +
'<pre class="wolai-page-ai-pi-lab-diagnostic-output" data-page-ai-pi-lab-diagnostic-output hidden></pre>' +
'</details>' +
'</div>';
}
@@ -2714,6 +2727,7 @@
lines.push('providerSession=' + (piLabState.providerSessionId || 'none'));
lines.push('model=' + currentModelLabel());
lines.push('runtime=' + currentRuntimeLabel());
lines.push('advancedRuntime=' + advancedRuntimeSummary(piLabState.advancedRuntime));
lines.push('managedBuiltinTools=' + ((Array.isArray(piLabState.managedBuiltinTools) && piLabState.managedBuiltinTools.length) ? piLabState.managedBuiltinTools.join('/') : 'pending'));
if (Array.isArray(piLabState.piExtensionSources) && piLabState.piExtensionSources.length) {
lines.push('piExtensions=' + piLabState.piExtensionSources.join(','));
@@ -2723,6 +2737,29 @@
pre.textContent = lines.join('\n');
}
function advancedRuntimeSummary(config) {
config = config || {};
var pairs = [
['extensionPolicy', config.extensionPolicy],
['repairPolicy', config.repairPolicy],
['sessionDurability', config.sessionDurability],
['requestTimeoutSecs', config.requestTimeoutSecs],
['maxToolIterations', config.maxToolIterations],
['hideCwdInPrompt', config.hideCwdInPrompt === true ? 'true' : 'false'],
].filter(function (item) { return item[1] !== undefined && item[1] !== null && item[1] !== ''; });
return pairs.length ? pairs.map(function (item) { return item[0] + '=' + item[1]; }).join(',') : 'default';
}
function setDiagnosticOutput(payload) {
if (!piLabPanelEl) return;
var output = piLabPanelEl.querySelector('[data-page-ai-pi-lab-diagnostic-output]');
var details = piLabPanelEl.querySelector('[data-page-ai-pi-lab-diagnostics]');
if (!output) return;
if (details) details.open = true;
output.hidden = false;
output.textContent = typeof payload === 'string' ? payload : JSON.stringify(payload || {}, null, 2);
}
function updatePiFloatingLayerPosition(layer) {
if (!layer || !piLabPanelEl) return;
var composer = piLabPanelEl.querySelector('.wolai-page-ai-pi-lab-composer');
@@ -3479,6 +3516,55 @@
});
}
function runPiDiagnostic(command) {
var input = piLabPanelEl && piLabPanelEl.querySelector('[data-page-ai-pi-lab-diagnostic-query]');
var keyword = input ? String(input.value || '').trim() : '';
var params = {};
if (command === 'doctor') params.format = 'json';
if (command === 'context-preview') {
params.format = 'json';
params.query = [keyword || 'MNote Pi Rust diagnostics'];
}
if (command === 'search') {
if (!keyword) {
showPiToast('请输入 search keyword', 'warning');
return Promise.resolve();
}
params.query = keyword;
params.limit = 10;
}
if (command === 'info') {
if (!keyword) {
showPiToast('请输入 info name/id', 'warning');
return Promise.resolve();
}
params.name = keyword;
}
updateDiagnostics('Pi diagnostics: ' + command);
setDiagnosticOutput('Running ' + command + '...');
return fetch(API.DIAGNOSTICS, {
method: 'POST',
credentials: 'same-origin',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
command: command,
params: params,
rootUri: piLabState.session && piLabState.session.rootUri || undefined,
workspaceId: piLabState.session && piLabState.session.workspaceId || undefined,
}),
}).then(function (response) {
return responseJsonOrError(response, 'Diagnostics failed');
}).then(function (payload) {
setDiagnosticOutput(payload);
updateDiagnostics('Pi diagnostics done: ' + command);
return payload;
}).catch(function (error) {
setDiagnosticOutput({ ok: false, command: command, error: error.message || String(error), payload: error.payload || null });
updateDiagnostics('Pi diagnostics failed: ' + (error.message || String(error)));
showPiToast('诊断失败', 'error');
});
}
function checkStatus() {
return Promise.all([
fetch(API.STATUS, { credentials: 'same-origin', cache: 'no-store' }).then(function (r) { return r.json(); }),
@@ -3511,6 +3597,7 @@
piLabState.runtimeInstallHint = data.runtimeInstallHint || data.runtime_install_hint || '';
piLabState.runtimeError = data.runtimeError || (data.session && data.session.runtimeError) || '';
piLabState.runtimePid = data.pid || (data.session && data.session.runtimePid) || piLabState.runtimePid || null;
piLabState.advancedRuntime = data.advancedRuntime || (data.session && data.session.advancedRuntime) || (data.session && data.session.runtimePolicySnapshot && data.session.runtimePolicySnapshot.piRuntime) || piLabState.advancedRuntime || {};
piLabState.warmupRunning = data.warmupRunning === true;
piLabState.warmupSessionId = data.warmupSessionId || null;
piLabState.managedBuiltinTools = data.managedPiBuiltinTools || data.managedBuiltinTools || piLabState.managedBuiltinTools || [];
@@ -3589,6 +3676,7 @@
piLabState.runtimeInstallHint = data.runtimeInstallHint || data.runtime_install_hint || '';
piLabState.runtimeError = session.runtimeError || data.runtimeError || '';
piLabState.runtimePid = session.runtimePid || data.pid || piLabState.runtimePid || null;
piLabState.advancedRuntime = data.advancedRuntime || session.advancedRuntime || (session.runtimePolicySnapshot && session.runtimePolicySnapshot.piRuntime) || piLabState.advancedRuntime || {};
piLabState.managedBuiltinTools = data.managedPiBuiltinTools || data.managedBuiltinTools || piLabState.managedBuiltinTools || [];
piLabState.piExtensionSources = data.piExtensionSources || piLabState.piExtensionSources || [];
piLabState.piExtensionToolNames = data.piExtensionToolNames || piLabState.piExtensionToolNames || [];
@@ -3733,6 +3821,7 @@
piLabState.runtimePid = payload.pid || piLabState.runtimePid;
piLabState.runtimeMode = payload.runtimeMode || piLabState.runtimeMode;
piLabState.managedBuiltinTools = payload.managedBuiltinTools || payload.managedPiBuiltinTools || piLabState.managedBuiltinTools;
piLabState.advancedRuntime = payload.advancedRuntime || piLabState.advancedRuntime || {};
piLabState.piExtensionSources = payload.piExtensionSources || piLabState.piExtensionSources || [];
piLabState.piExtensionToolNames = payload.piExtensionToolNames || piLabState.piExtensionToolNames || [];
setState(STATE_STARTED);
@@ -4723,11 +4812,16 @@
});
return;
}
var openSessionJsonl = event.target && event.target.closest ? event.target.closest('[data-page-ai-pi-lab-open-session-jsonl]') : null;
if (openSessionJsonl) {
openCurrentSessionJsonl();
return;
}
var openSessionJsonl = event.target && event.target.closest ? event.target.closest('[data-page-ai-pi-lab-open-session-jsonl]') : null;
if (openSessionJsonl) {
openCurrentSessionJsonl();
return;
}
var diagnosticCommand = event.target && event.target.closest ? event.target.closest('[data-page-ai-pi-lab-diagnostic-command]') : null;
if (diagnosticCommand) {
runPiDiagnostic(diagnosticCommand.getAttribute('data-page-ai-pi-lab-diagnostic-command') || 'doctor');
return;
}
var openArtifact = event.target && event.target.closest ? event.target.closest('[data-page-ai-pi-lab-artifact-open]') : null;
if (openArtifact) {
var artUrl = openArtifact.getAttribute('data-page-ai-pi-lab-artifact-open') || openArtifact.getAttribute('href') || '';
@@ -1040,6 +1040,12 @@ const AI_ADMIN_SCRIPT: &str = r#"
root.addEventListener('click', function (event) {
var closeTarget = event.target && event.target.closest ? event.target.closest('[data-action="close-user-drawer"], [data-ai-admin-drawer-backdrop]') : null;
if (closeTarget && drawer) drawer.classList.remove('is-open');
var piDiagnosticTarget = event.target && event.target.closest ? event.target.closest('[data-ai-admin-pi-diagnostic-command]') : null;
if (piDiagnosticTarget) {
event.preventDefault();
runPiDiagnostic(piDiagnosticTarget.getAttribute('data-ai-admin-pi-diagnostic-command') || 'doctor');
return;
}
});
function setText(node, value) {
@@ -1081,6 +1087,66 @@ const AI_ADMIN_SCRIPT: &str = r#"
return '<div class="mnote-ai-admin-kv"><span>' + escapeHtml(label) + '</span><strong>' + escapeHtml(value == null || value === '' ? '-' : value) + '</strong></div>';
}
function advancedRuntimeSummary(config) {
config = config || {};
var pairs = [
['extensionPolicy', config.extensionPolicy || config.extension_policy],
['repairPolicy', config.repairPolicy || config.repair_policy],
['sessionDurability', config.sessionDurability || config.session_durability],
['requestTimeoutSecs', config.requestTimeoutSecs || config.request_timeout_secs],
['maxToolIterations', config.maxToolIterations || config.max_tool_iterations],
['hideCwdInPrompt', (config.hideCwdInPrompt === true || config.hide_cwd_in_prompt === true) ? 'true' : 'false'],
].filter(function (item) { return item[1] !== undefined && item[1] !== null && item[1] !== ''; });
return pairs.length ? pairs.map(function (item) { return item[0] + '=' + item[1]; }).join(', ') : 'default';
}
function piDiagnosticParams(command) {
var input = root.querySelector('[data-ai-admin-pi-diagnostic-query]');
var keyword = input ? String(input.value || '').trim() : '';
var params = {};
if (command === 'doctor') params.format = 'json';
if (command === 'context-preview') {
params.format = 'json';
params.query = [keyword || 'MNote Pi Rust diagnostics'];
}
if (command === 'search') {
if (!keyword) throw new Error('请输入 search keyword');
params.query = keyword;
params.limit = 10;
}
if (command === 'info') {
if (!keyword) throw new Error('请输入 info name/id');
params.name = keyword;
}
return params;
}
function setPiDiagnosticOutput(payload) {
var details = root.querySelector('[data-ai-admin-pi-diagnostics-card]');
var output = root.querySelector('[data-ai-admin-pi-diagnostics-output]');
if (details) details.open = true;
if (!output) return;
output.hidden = false;
output.textContent = typeof payload === 'string' ? payload : JSON.stringify(payload || {}, null, 2);
}
async function runPiDiagnostic(command) {
try {
var params = piDiagnosticParams(command);
setPiDiagnosticOutput('Running ' + command + '...');
var payload = await requestJson('/api/page-ai/pi/diagnostics', {
method: 'POST',
body: JSON.stringify({
command: command,
params: params,
}),
});
setPiDiagnosticOutput(payload);
} catch (err) {
setPiDiagnosticOutput({ ok: false, command: command, error: err.message || '诊断失败' });
}
}
function normalizeDirectoryGrants(payload) {
var grants = payload && (payload.grants || (payload.policy && payload.policy.grants) || payload.allowedRoots || payload.allowed_roots || []);
return Array.isArray(grants) ? grants.filter(Boolean) : [];
@@ -1216,6 +1282,7 @@ const AI_ADMIN_SCRIPT: &str = r#"
var piRuntimeBinary = piStatus ? (piStatus.runtimeBinary || piStatus.runtime_binary || '-') : '-';
var piRuntimeAvailable = !piStatus || piStatus.runtimeAvailable !== false;
var piRuntimeError = piStatus && (piStatus.runtimeError || piStatus.runtime_error || piStatus.runtimeInstallHint || piStatus.runtime_install_hint || '');
var advancedRuntime = piStatus && (piStatus.advancedRuntime || piStatus.advanced_runtime) || {};
var piRunning = piStatus && piStatus.running === true;
var piExtensions = piStatus && Array.isArray(piStatus.piExtensionSources)
? piStatus.piExtensionSources
@@ -1242,9 +1309,24 @@ const AI_ADMIN_SCRIPT: &str = r#"
renderKv('Runtime PID', piStatus && piStatus.pid ? String(piStatus.pid) : 'none') +
renderKv('受控 Pi 原生工具', (piStatus && piStatus.managedPiBuiltinTools || ['read','write','edit','bash','grep','find','ls','hashline_edit']).join(', ')) +
renderKv('Pi 扩展包', piExtensions.length ? piExtensions.join(', ') : '待 runtime 启动') +
renderKv('Advanced runtime', advancedRuntimeSummary(advancedRuntime)) +
renderKv('Receipt storage', piStatus && piStatus.receiptStorage ? piStatus.receiptStorage : 'control-plane / provider-neutral adapter') +
renderKv('Session dir policy', piStatus && piStatus.managedPiSessionDirPolicy ? piStatus.managedPiSessionDirPolicy : '<workspace>/.mnote/ai/pi-sessions/<actor>/<session>') +
'</div>' +
'<details data-ai-admin-pi-diagnostics-card style="margin-top:12px;">' +
'<summary style="font-size:12px;color:#8B8782;cursor:pointer;">Pi 官方诊断 / effective runtime</summary>' +
'<div class="mnote-ai-admin-actions-bar" style="margin:10px 0;gap:6px;flex-wrap:wrap;">' +
'<button type="button" class="mnote-ai-admin-btn" data-ai-admin-pi-diagnostic-command="doctor">doctor</button>' +
'<button type="button" class="mnote-ai-admin-btn" data-ai-admin-pi-diagnostic-command="context-preview">context-preview</button>' +
'<button type="button" class="mnote-ai-admin-btn" data-ai-admin-pi-diagnostic-command="list">list</button>' +
'<button type="button" class="mnote-ai-admin-btn" data-ai-admin-pi-diagnostic-command="update-index">update-index</button>' +
'<input type="search" data-ai-admin-pi-diagnostic-query placeholder="search/info keyword" style="height:30px;min-width:160px;border:1px solid #ddd8cf;border-radius:8px;padding:0 10px;">' +
'<button type="button" class="mnote-ai-admin-btn" data-ai-admin-pi-diagnostic-command="search">search</button>' +
'<button type="button" class="mnote-ai-admin-btn" data-ai-admin-pi-diagnostic-command="info">info</button>' +
'</div>' +
'<pre class="mnote-ai-admin-json" data-ai-admin-pi-diagnostics-output hidden></pre>' +
'<pre class="mnote-ai-admin-json" data-ai-admin-pi-advanced-runtime-json>' + escapeHtml(JSON.stringify(advancedRuntime, null, 2)) + '</pre>' +
'</details>' +
'</div>' +
'</div>' +
'<div class="mnote-ai-admin-admin-card">' +
@@ -355,6 +355,30 @@ check(
"Pi Rust service panel exposes runtime implementation, binary, availability, and error"
);
check(
"AI management service panel exposes effective Pi advanced runtime",
aiAdminRs.includes("Advanced runtime") &&
aiAdminRs.includes("advancedRuntimeSummary") &&
aiAdminRs.includes("data-ai-admin-pi-advanced-runtime-json") &&
aiAdminRs.includes("extensionPolicy") &&
aiAdminRs.includes("maxToolIterations"),
"Shows effective extension/repair/session/request/tool-iteration policy instead of hiding host decisions"
);
check(
"AI management service panel exposes controlled Pi official diagnostics",
routesMod.includes('/api/page-ai/pi/diagnostics", post(page_ai_pi::diagnostics)') &&
aiAdminRs.includes('data-ai-admin-pi-diagnostic-command="doctor"') &&
aiAdminRs.includes('data-ai-admin-pi-diagnostic-command="context-preview"') &&
aiAdminRs.includes('data-ai-admin-pi-diagnostic-command="list"') &&
aiAdminRs.includes('data-ai-admin-pi-diagnostic-command="update-index"') &&
aiAdminRs.includes('data-ai-admin-pi-diagnostic-command="search"') &&
aiAdminRs.includes('data-ai-admin-pi-diagnostic-command="info"') &&
aiAdminRs.includes("runPiDiagnostic") &&
aiAdminRs.includes("/api/page-ai/pi/diagnostics"),
"Doctor/context-preview/list/search/info/update-index are available from Pi service diagnostics"
);
check(
"OpenHub is described as compatibility/admin boundary, not default chat",
aiAdminRs.includes("迁移期兼容 / admin 边界") &&
+6
View File
@@ -131,6 +131,11 @@ const checks = [
['runtime applies model controls through Pi RPC configure endpoint', runtime.includes("CONFIGURE: '/api/page-ai/pi/configure'") && runtime.includes('applyModelConfigToRuntime') && runtime.includes('pendingModelConfigApply')],
['runtime collapses secondary right rail sections', runtime.includes('<details class="wolai-page-ai-pi-lab-rail-section"') && runtime.includes('data-page-ai-pi-lab-receipts-section')],
['runtime has diagnostics collapsed by default', runtime.includes('<details class="wolai-page-ai-pi-lab-diagnostics"') && !runtime.includes('<details class="wolai-page-ai-pi-lab-diagnostics" open')],
['runtime has Pi diagnostics endpoint constant', runtime.includes("DIAGNOSTICS: '/api/page-ai/pi/diagnostics'")],
['runtime exposes official Pi diagnostics actions in collapsed panel', runtime.includes('data-page-ai-pi-lab-diagnostic-command="doctor"') && runtime.includes('data-page-ai-pi-lab-diagnostic-command="context-preview"') && runtime.includes('data-page-ai-pi-lab-diagnostic-command="list"') && runtime.includes('data-page-ai-pi-lab-diagnostic-command="update-index"') && runtime.includes('data-page-ai-pi-lab-diagnostic-command="search"') && runtime.includes('data-page-ai-pi-lab-diagnostic-command="info"')],
['runtime renders Pi diagnostics output separately from status text', runtime.includes('data-page-ai-pi-lab-diagnostic-output') && runtime.includes('setDiagnosticOutput')],
['runtime posts controlled diagnostics command payload', runtime.includes('function runPiDiagnostic') && runtime.includes('command: command') && runtime.includes('params: params') && runtime.includes('API.DIAGNOSTICS')],
['runtime surfaces effective advanced runtime summary', runtime.includes('advancedRuntimeSummary') && runtime.includes('advancedRuntime=') && runtime.includes('extensionPolicy') && runtime.includes('maxToolIterations')],
['runtime injects CSS styles', runtime.includes('injectStyles')],
// === Runtime JS: default model (omniroute/gpt-5.4-mini) ===
@@ -291,6 +296,7 @@ const checks = [
['runtime has API.STATE constant', runtime.includes("STATE: '/api/page-ai/pi/state'")],
['runtime has API.COMPACT constant', runtime.includes("COMPACT: '/api/page-ai/pi/compact'")],
['runtime has API.QUEUE_CONFIG constant', runtime.includes("QUEUE_CONFIG: '/api/page-ai/pi/queue-config'")],
['runtime has API.DIAGNOSTICS constant', runtime.includes("DIAGNOSTICS: '/api/page-ai/pi/diagnostics'")],
['runtime maps session tree preview into history messages', runtime.includes('entry.text || entry.content || entry.preview')],
['runtime fetches artifact diff with sessionId query', runtime.includes("'?sessionId=' + encodeURIComponent(sid)")],