fix: surface Workbench navigation root cause
This commit is contained in:
@@ -1400,6 +1400,115 @@ function buildSessionInvariantFindings(control, manifest = {}) {
|
|||||||
return findings;
|
return findings;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function buildControlledNavigationRootCauseFindings(control, manifest = {}) {
|
||||||
|
const commands = [];
|
||||||
|
for (const row of control || []) {
|
||||||
|
if (row?.phase !== "completed") continue;
|
||||||
|
if (row?.type !== "refreshCurrentSession" && row?.type !== "switchAwayAndBack") continue;
|
||||||
|
const detail = objectValue(row.detail);
|
||||||
|
const navigation = objectValue(detail.navigation);
|
||||||
|
const readiness = objectValue(navigation.readiness);
|
||||||
|
const snapshot = objectValue(readiness.snapshot);
|
||||||
|
const pageProvenance = objectValue(navigation.pageProvenance);
|
||||||
|
const blankShell = snapshot.workbenchShellVisible === false
|
||||||
|
&& snapshot.sessionRailPresent === false
|
||||||
|
&& snapshot.commandInputPresent === false
|
||||||
|
&& snapshot.bodyTextHash === "sha256:e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855";
|
||||||
|
const shellOrComposerMissing = snapshot.workbenchShellVisible === false
|
||||||
|
|| snapshot.sessionRailPresent === false
|
||||||
|
|| snapshot.commandInputPresent === false;
|
||||||
|
const degraded = navigation.degraded === true
|
||||||
|
|| readiness.ok === false
|
||||||
|
|| detail.routeOk === false
|
||||||
|
|| blankShell
|
||||||
|
|| (detail.activeOk === false && shellOrComposerMissing)
|
||||||
|
|| (detail.composerReady === false && snapshot.commandInputPresent === false);
|
||||||
|
if (!degraded) continue;
|
||||||
|
const rootCause = stringOrNull(navigation.degradedReason)
|
||||||
|
?? (readiness.ok === false ? stringOrNull(readiness.reason) : null)
|
||||||
|
?? (detail.routeOk === false ? "route-session-not-hydrated" : null)
|
||||||
|
?? (blankShell ? "workbench-blank-shell-after-navigation" : null)
|
||||||
|
?? (detail.activeOk === false && shellOrComposerMissing ? "active-session-not-hydrated" : null)
|
||||||
|
?? (detail.composerReady === false && snapshot.commandInputPresent === false ? "composer-not-ready" : null)
|
||||||
|
?? "controlled-navigation-degraded";
|
||||||
|
commands.push({
|
||||||
|
commandId: stringOrNull(row.commandId),
|
||||||
|
type: stringOrNull(row.type),
|
||||||
|
commandTs: stringOrNull(row.ts),
|
||||||
|
afterRound: numberOrNull(detail.afterRound ?? row.input?.afterRound),
|
||||||
|
rootCause,
|
||||||
|
blocking: true,
|
||||||
|
canarySessionId: stringOrNull(detail.canarySessionId),
|
||||||
|
routeSessionId: stringOrNull(detail.routeSessionId),
|
||||||
|
activeSessionId: stringOrNull(detail.activeSessionId),
|
||||||
|
routeOk: detail.routeOk === true,
|
||||||
|
activeOk: detail.activeOk === true,
|
||||||
|
composerReady: detail.composerReady === true,
|
||||||
|
navigation: {
|
||||||
|
httpStatus: numberOrNull(navigation.httpStatus),
|
||||||
|
degraded: navigation.degraded === true,
|
||||||
|
degradedReason: stringOrNull(navigation.degradedReason),
|
||||||
|
beforePath: urlPath(navigation.beforeUrl),
|
||||||
|
afterPath: urlPath(navigation.afterUrl),
|
||||||
|
valuesRedacted: true,
|
||||||
|
},
|
||||||
|
readiness: {
|
||||||
|
ok: readiness.ok === true,
|
||||||
|
reason: stringOrNull(readiness.reason),
|
||||||
|
durationMs: numberOrNull(readiness.durationMs),
|
||||||
|
path: stringOrNull(snapshot.path),
|
||||||
|
readyState: stringOrNull(snapshot.readyState),
|
||||||
|
workbenchShellVisible: snapshot.workbenchShellVisible === true,
|
||||||
|
sessionCreatePresent: snapshot.sessionCreatePresent === true,
|
||||||
|
sessionRailPresent: snapshot.sessionRailPresent === true,
|
||||||
|
commandInputPresent: snapshot.commandInputPresent === true,
|
||||||
|
activeTabPresent: snapshot.activeTabPresent === true,
|
||||||
|
loginVisible: snapshot.loginVisible === true,
|
||||||
|
blankShell,
|
||||||
|
bodyTextHash: stringOrNull(snapshot.bodyTextHash),
|
||||||
|
valuesRedacted: true,
|
||||||
|
},
|
||||||
|
pageProvenance: {
|
||||||
|
pageLoadSeq: numberOrNull(pageProvenance.pageLoadSeq),
|
||||||
|
reason: stringOrNull(pageProvenance.reason),
|
||||||
|
observedAt: stringOrNull(pageProvenance.observedAt),
|
||||||
|
urlPath: stringOrNull(pageProvenance.urlPath),
|
||||||
|
documentReadyState: stringOrNull(pageProvenance.documentReadyState),
|
||||||
|
timeOrigin: numberOrNull(pageProvenance.timeOrigin),
|
||||||
|
httpStatus: numberOrNull(pageProvenance.httpStatus),
|
||||||
|
assetFingerprint: stringOrNull(pageProvenance.assetFingerprint),
|
||||||
|
scriptCount: numberOrNull(pageProvenance.scriptCount),
|
||||||
|
stylesheetCount: numberOrNull(pageProvenance.stylesheetCount),
|
||||||
|
scripts: arrayStrings(pageProvenance.scripts).slice(0, 8),
|
||||||
|
stylesheets: arrayStrings(pageProvenance.stylesheets).slice(0, 8),
|
||||||
|
valuesRedacted: true,
|
||||||
|
},
|
||||||
|
observer: {
|
||||||
|
ok: detail.observer?.ok === true,
|
||||||
|
pageRole: stringOrNull(detail.observer?.pageRole),
|
||||||
|
pageId: stringOrNull(detail.observer?.pageId),
|
||||||
|
changed: detail.observer?.changed === true,
|
||||||
|
valuesRedacted: true,
|
||||||
|
},
|
||||||
|
observerId: stringOrNull(manifest.jobId),
|
||||||
|
stateDir: stringOrNull(manifest.stateDir),
|
||||||
|
valuesRedacted: true,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
if (commands.length === 0) return [];
|
||||||
|
return [{
|
||||||
|
id: "workbench-controlled-navigation-degraded-root-cause",
|
||||||
|
severity: "red",
|
||||||
|
summary: "controlled Workbench refresh/switch completed degraded; route may be correct but app shell, active session, or composer was not ready, so later Code Agent turns cannot continue",
|
||||||
|
count: commands.length,
|
||||||
|
blocking: true,
|
||||||
|
rootCauses: Array.from(new Set(commands.map((item) => item.rootCause))).slice(0, 12),
|
||||||
|
commands: commands.slice(0, 20),
|
||||||
|
next: "Investigate the first degraded command, then correlate browser requestfailed/static asset failures and Workbench hydration state before changing Code Agent/provider logic.",
|
||||||
|
valuesRedacted: true,
|
||||||
|
}];
|
||||||
|
}
|
||||||
|
|
||||||
function sessionInvariantNavigationWindows(control) {
|
function sessionInvariantNavigationWindows(control) {
|
||||||
const started = new Map();
|
const started = new Map();
|
||||||
const windows = [];
|
const windows = [];
|
||||||
@@ -1941,6 +2050,7 @@ function buildFindings(samples, control, network, errors, sampleMetrics, promptN
|
|||||||
const findings = [];
|
const findings = [];
|
||||||
const effectiveApiDomLag = apiDomLag || buildApiDomLagReport(samples, network);
|
const effectiveApiDomLag = apiDomLag || buildApiDomLagReport(samples, network);
|
||||||
if (commandFailures.length > 0) findings.push({ id: "observer-command-failed", severity: "red", summary: "observer control commands failed; analyze must surface command failure instead of hiding it in command artifacts", count: commandFailures.length, commands: commandFailures.slice(0, 20) });
|
if (commandFailures.length > 0) findings.push({ id: "observer-command-failed", severity: "red", summary: "observer control commands failed; analyze must surface command failure instead of hiding it in command artifacts", count: commandFailures.length, commands: commandFailures.slice(0, 20) });
|
||||||
|
findings.push(...buildControlledNavigationRootCauseFindings(control, manifest));
|
||||||
findings.push(...buildSessionInvariantFindings(control, manifest));
|
findings.push(...buildSessionInvariantFindings(control, manifest));
|
||||||
const commandTimes = control
|
const commandTimes = control
|
||||||
.filter((item) => item.phase === "completed" || item.phase === "started" || item.type === "observer-periodic-refresh")
|
.filter((item) => item.phase === "completed" || item.phase === "started" || item.type === "observer-periodic-refresh")
|
||||||
|
|||||||
Reference in New Issue
Block a user