feat: add workbench triad sentinel check

This commit is contained in:
Codex
2026-07-01 07:21:56 +00:00
parent b735b74b84
commit 098534e999
5 changed files with 276 additions and 5 deletions
@@ -4580,12 +4580,20 @@ async function sampleOnePage(targetPage, { reason, groupSeq, pageRole, targetPag
seen.add(key);
const rect = element.getBoundingClientRect();
const fallbackTitle = looksLikeSessionTitleFallback(titleText, sessionId);
const dataStatus = element.getAttribute("data-status") || element.getAttribute("data-state") || null;
const dataRunning = element.getAttribute("data-running") || element.getAttribute("data-busy") || null;
const ariaBusy = element.getAttribute("aria-busy") || null;
items.push({
index: items.length,
tag: element.tagName.toLowerCase(),
testId: element.getAttribute("data-testid"),
role: element.getAttribute("role"),
active: element.getAttribute("data-active") === "true" || element.getAttribute("aria-selected") === "true",
status: dataStatus || ariaBusy || null,
dataStatus,
running: dataRunning === "true" || ariaBusy === "true" || element.classList.contains("is-running") || element.classList.contains("running"),
dataRunning,
ariaBusy,
sessionId,
sessionIdPrefix: sessionId ? String(sessionId).slice(0, 12) : null,
titleText,
@@ -4601,6 +4609,7 @@ async function sampleOnePage(targetPage, { reason, groupSeq, pageRole, targetPag
visibleCount,
fallbackTitleCount,
fallbackTitleRatio: visibleCount > 0 ? Number((fallbackTitleCount / visibleCount).toFixed(4)) : 0,
activeItem: visibleItems.find((item) => item.active) || null,
items: visibleItems.slice(0, 60),
fallbackItems: fallbackItems.slice(0, 12),
};
@@ -4637,7 +4646,7 @@ async function sampleOnePage(targetPage, { reason, groupSeq, pageRole, targetPag
const title = element.getAttribute("title") || "";
return tag === "button" || role === "button" || //u.test(aria) || //u.test(title);
};
const stableMessageText = (element) => {
const messageBodyTextDetail = (element) => {
const bodySelectors = [
".message-markdown.message-text",
".message-text",
@@ -4651,10 +4660,21 @@ async function sampleOnePage(targetPage, { reason, groupSeq, pageRole, targetPag
for (const candidate of Array.from(element.querySelectorAll(selector))) {
if (!visible(candidate)) continue;
const text = trim(candidate.textContent || "", 1200);
if (text && !parts.includes(text)) parts.push(text);
if (text && !parts.some((part) => part.text === text)) parts.push({ text, selector });
}
}
if (parts.length > 0) return parts.join(" ");
if (parts.length > 0) {
return {
text: parts.map((part) => part.text).join(" "),
source: parts[0]?.selector || "body-selector",
candidateCount: parts.length
};
}
return { text: "", source: null, candidateCount: 0 };
};
const stableMessageText = (element) => {
const body = messageBodyTextDetail(element);
if (body.text) return body.text;
const clone = element.cloneNode(true);
for (const selector of [
".message-duration-meta",
@@ -4715,6 +4735,7 @@ async function sampleOnePage(targetPage, { reason, groupSeq, pageRole, targetPag
const summarize = (selector, limit) => summarizeElements(Array.from(document.querySelectorAll(selector)), limit);
const summarizeMessages = (selector, limit) => Array.from(document.querySelectorAll(selector)).filter(visible).slice(-limit).map((element, index) => {
const rect = element.getBoundingClientRect();
const body = messageBodyTextDetail(element);
return {
index,
tag: element.tagName.toLowerCase(),
@@ -4728,6 +4749,9 @@ async function sampleOnePage(targetPage, { reason, groupSeq, pageRole, targetPag
turnId: element.getAttribute("data-turn-id") || null,
durationText: trim(element.querySelector(".message-duration-meta")?.textContent || "", 120),
activityText: trim(element.querySelector(".message-activity-meta")?.textContent || "", 120),
bodyText: body.text,
bodyTextSource: body.source,
bodyTextCandidateCount: body.candidateCount,
text: stableMessageText(element),
rect: { x: Math.round(rect.x), y: Math.round(rect.y), width: Math.round(rect.width), height: Math.round(rect.height) },
};
@@ -4914,6 +4938,7 @@ async function sampleOnePage(targetPage, { reason, groupSeq, pageRole, targetPag
const turns = Array.from(document.querySelectorAll('article.message-card[data-role="agent"], .message-card[data-role="agent"], article[data-role="agent"]')).filter(visible).map((element, index) => {
const rect = element.getBoundingClientRect();
const text = textHashInput(element);
const finalResponse = messageBodyTextDetail(element);
const traceElement = element.matches("[data-trace-id]") ? element : element.querySelector("[data-trace-id]");
const traceMatch = text.match(/\btrc_[A-Za-z0-9_-]+\b/u);
const durationText = trim(element.querySelector(".message-duration-meta")?.textContent || "", 120);
@@ -4929,6 +4954,10 @@ async function sampleOnePage(targetPage, { reason, groupSeq, pageRole, targetPag
turnId: element.getAttribute("data-turn-id") || directTraceId,
durationText,
activityText,
finalResponseText: finalResponse.text,
finalResponseTextSource: finalResponse.source,
finalResponseCandidateCount: finalResponse.candidateCount,
finalResponsePresent: Boolean(finalResponse.text && finalResponse.text.trim()),
text,
rect: { x: Math.round(rect.x), y: Math.round(rect.y), width: Math.round(rect.width), height: Math.round(rect.height) },
};
@@ -5014,12 +5043,12 @@ async function sampleOnePage(targetPage, { reason, groupSeq, pageRole, targetPag
function digestDom(dom, pageRole = "control") {
if (dom && dom.error) return dom;
const messages = Array.isArray(dom.messages) ? dom.messages.map((item) => ({ ...item, textHash: sha256Text(item.text || ""), textPreview: truncate(item.text || "", 160), textBytes: Buffer.byteLength(item.text || "") })) : [];
const messages = Array.isArray(dom.messages) ? dom.messages.map((item) => ({ ...item, textHash: sha256Text(item.text || ""), textPreview: truncate(item.text || "", 160), textBytes: Buffer.byteLength(item.text || ""), bodyTextHash: sha256Text(item.bodyText || ""), bodyTextPreview: truncate(item.bodyText || "", 160), bodyTextBytes: Buffer.byteLength(item.bodyText || ""), bodyTextPresent: Boolean(String(item.bodyText || "").trim()) })) : [];
const traceRows = Array.isArray(dom.traceRows) ? dom.traceRows.map((item) => ({ ...item, textHash: sha256Text(item.text || ""), textPreview: truncate(item.text || "", 160), textBytes: Buffer.byteLength(item.text || "") })) : [];
const loadings = Array.isArray(dom.loadings) ? dom.loadings.map((item) => ({ ...item, textHash: sha256Text(item.text || ""), textPreview: truncate(item.text || "", 160), textBytes: Buffer.byteLength(item.text || ""), ownerTextHash: sha256Text(item.ownerText || ""), ownerTextPreview: truncate(item.ownerText || "", 160) })) : [];
const sessionRail = digestSessionRail(dom.sessionRail);
const diagnostics = Array.isArray(dom.diagnostics) ? dom.diagnostics.map((item) => ({ ...item, textHash: sha256Text(item.text || ""), textPreview: truncate(item.text || "", 260), textBytes: Buffer.byteLength(item.text || "") })) : [];
const turns = Array.isArray(dom.turns) ? dom.turns.map((item) => ({ ...item, textHash: sha256Text(item.text || ""), textPreview: truncate(item.text || "", 200), textBytes: Buffer.byteLength(item.text || "") })) : [];
const turns = Array.isArray(dom.turns) ? dom.turns.map((item) => ({ ...item, textHash: sha256Text(item.text || ""), textPreview: truncate(item.text || "", 200), textBytes: Buffer.byteLength(item.text || ""), finalResponseTextHash: sha256Text(item.finalResponseText || ""), finalResponseTextPreview: truncate(item.finalResponseText || "", 200), finalResponseTextBytes: Buffer.byteLength(item.finalResponseText || ""), finalResponsePresent: Boolean(String(item.finalResponseText || "").trim()) })) : [];
const projectManagementSample = digestProjectManagement(dom.projectManagement);
const pageProvenance = normalizePageProvenance(dom.pageProvenance, { reason: "sample", pageLoadSeq: currentPageProvenance?.pageLoadSeq ?? pageLoadSeq });
if (pageRole === "control") currentPageProvenance = pageProvenance;
@@ -5112,6 +5141,11 @@ function digestSessionRail(value) {
testId: item?.testId ?? null,
role: item?.role ?? null,
active: item?.active === true,
status: item?.status ?? null,
dataStatus: item?.dataStatus ?? null,
running: item?.running === true,
dataRunning: item?.dataRunning ?? null,
ariaBusy: item?.ariaBusy ?? null,
sessionId: item?.sessionId ?? null,
sessionIdPrefix: item?.sessionIdPrefix ?? (item?.sessionId ? String(item.sessionId).slice(0, 12) : null),
fallbackTitle: item?.fallbackTitle === true,
@@ -5128,6 +5162,7 @@ function digestSessionRail(value) {
visibleCount: Number.isFinite(visibleCount) ? visibleCount : items.length,
fallbackTitleCount: Number.isFinite(fallbackTitleCount) ? fallbackTitleCount : fallbackItems.length,
fallbackTitleRatio: Number.isFinite(Number(value.fallbackTitleRatio)) ? Number(value.fallbackTitleRatio) : (items.length > 0 ? Number((fallbackItems.length / items.length).toFixed(4)) : 0),
activeItem: items.find((item) => item.active) || null,
items,
fallbackItems,
valuesRedacted: true,