fix: bound web probe performance summary collect

This commit is contained in:
Codex
2026-07-02 08:04:28 +00:00
parent 0975703097
commit c8b2c08445
3 changed files with 267 additions and 151 deletions
@@ -0,0 +1,229 @@
// SPEC: PJ2026-01040111 长程观测 draft-2026-06-20-p0-passive-web-probe-observer.
// Responsibility: bounded raw payloads for web-probe observe collect views.
export function compactObserveCollectForRaw(collect: Record<string, unknown> | null): Record<string, unknown> | null {
if (collect === null) return null;
const rows = Array.isArray(collect.rows) ? collect.rows.map((item) => {
const row = observeRecord(item);
const finalResponse = observeRecord(row.finalResponse);
return {
round: row.round ?? null,
commandId: row.commandId ?? null,
userHash: row.userHash ?? null,
userBytes: row.userBytes ?? null,
traceId: row.traceId ?? null,
status: row.status ?? null,
elapsedSeconds: row.elapsedSeconds ?? null,
recentUpdateSeconds: row.recentUpdateSeconds ?? null,
marks: row.marks ?? null,
firstSeq: row.firstSeq ?? null,
lastSeq: row.lastSeq ?? null,
lastTs: row.lastTs ?? null,
finalResponse: {
preview: finalResponse.preview ?? null,
textHash: finalResponse.textHash ?? null,
textBytes: finalResponse.textBytes ?? null,
empty: finalResponse.empty === true,
},
valuesRedacted: true,
};
}) : undefined;
const timelineRows = Array.isArray(collect.timelineRows) ? collect.timelineRows.slice(0, 12).map((item) => {
const row = observeRecord(item);
return {
ts: row.ts ?? null,
seq: row.seq ?? null,
kind: row.kind ?? null,
phase: row.phase ?? null,
type: row.type ?? null,
commandId: row.commandId ?? null,
sessionId: row.sessionId ?? null,
traceId: row.traceId ?? null,
summary: row.summary ?? null,
valuesRedacted: true,
};
}) : undefined;
const collectView = typeof collect.view === "string" ? collect.view : null;
const slimNetworkEvidence = (value: unknown): Record<string, unknown> => {
const source = observeRecord(value);
const latestTurn = observeRecord(source.latestTurnResponse);
const latestTrace = observeRecord(source.latestTraceEventsResponse);
return {
requestCount: source.requestCount ?? null,
responseCount: source.responseCount ?? null,
failedCount: source.failedCount ?? null,
terminalResponseCount: source.terminalResponseCount ?? null,
turnResponseCount: source.turnResponseCount ?? null,
traceEventsResponseCount: source.traceEventsResponseCount ?? null,
latestTurnResponse: {
ts: latestTurn.ts ?? null,
sampleSeq: latestTurn.sampleSeq ?? null,
status: latestTurn.status ?? null,
bodySummary: observeRecord(latestTurn.bodySummary),
valuesRedacted: true,
},
latestTraceEventsResponse: {
ts: latestTrace.ts ?? null,
sampleSeq: latestTrace.sampleSeq ?? null,
status: latestTrace.status ?? null,
bodySummary: observeRecord(latestTrace.bodySummary),
valuesRedacted: true,
},
valuesRedacted: true,
};
};
const slimFreeze = (value: unknown): Record<string, unknown> => {
const source = observeRecord(value);
const blocker = observeRecord(source.latestBlocker);
return {
blockerCount: source.blockerCount ?? null,
responsivenessEventCount: source.responsivenessEventCount ?? null,
latestBlocker: {
ts: blocker.ts ?? null,
sampleSeq: blocker.sampleSeq ?? null,
rootCause: blocker.rootCause ?? null,
rootCauseStatus: blocker.rootCauseStatus ?? null,
fallbackAllowed: blocker.fallbackAllowed === true,
observed: observeRecord(blocker.observed),
page: observeRecord(blocker.page),
valuesRedacted: true,
},
valuesRedacted: true,
};
};
const slimFindings = Array.isArray(collect.findings) ? collect.findings.slice(0, 6).map((item) => {
const row = observeRecord(item);
return {
id: row.id ?? null,
severity: row.severity ?? null,
count: row.count ?? null,
rootCause: row.rootCause ?? row.rootCauseStatus ?? null,
summary: typeof row.summary === "string" ? row.summary.slice(0, 140) : row.summary ?? null,
valuesRedacted: true,
};
}) : undefined;
const slimPerfFrame = (value: unknown): Record<string, unknown> => {
const row = observeRecord(value);
return {
functionName: row.functionName ?? null,
url: row.url ?? null,
scriptId: row.scriptId ?? null,
lineNumber: row.lineNumber ?? null,
columnNumber: row.columnNumber ?? null,
valuesRedacted: true,
};
};
const slimPerfStack = (value: unknown): Record<string, unknown> => {
const row = observeRecord(value);
return {
functionName: row.functionName ?? null,
url: row.url ?? null,
scriptId: row.scriptId ?? null,
lineNumber: row.lineNumber ?? null,
columnNumber: row.columnNumber ?? null,
selfTimeMs: row.selfTimeMs ?? null,
totalTimeMs: row.totalTimeMs ?? null,
hitCount: row.hitCount ?? null,
frameCount: row.frameCount ?? null,
frames: Array.isArray(row.frames) ? row.frames.slice(0, 3).map(slimPerfFrame) : [],
framesOmitted: row.framesOmitted ?? null,
valuesRedacted: true,
};
};
const slimPerfHotspot = (value: unknown): Record<string, unknown> => {
const row = observeRecord(value);
return {
functionName: row.functionName ?? row.sourceFunctionName ?? null,
url: row.url ?? row.sourceURL ?? null,
scriptId: row.scriptId ?? null,
lineNumber: row.lineNumber ?? null,
columnNumber: row.columnNumber ?? null,
selfTimeMs: row.selfTimeMs ?? null,
totalTimeMs: row.totalTimeMs ?? null,
totalDurationMs: row.totalDurationMs ?? null,
count: row.count ?? null,
hitCount: row.hitCount ?? null,
captureCount: row.captureCount ?? null,
invoker: row.invoker ?? null,
valuesRedacted: true,
};
};
const slimPerfEvent = (value: unknown): Record<string, unknown> => {
const row = observeRecord(value);
return {
ts: row.ts ?? null,
kind: row.kind ?? null,
durationMs: row.durationMs ?? null,
pageRole: row.pageRole ?? null,
pageId: row.pageId ?? null,
sampleSeq: row.sampleSeq ?? null,
scriptCount: row.scriptCount ?? null,
url: row.url ?? null,
valuesRedacted: true,
};
};
const slimPerfCapture = (value: unknown): Record<string, unknown> => {
const row = observeRecord(value);
return {
ts: row.ts ?? null,
commandId: row.commandId ?? null,
status: row.status ?? null,
durationMs: row.durationMs ?? null,
sampleCount: row.sampleCount ?? null,
nodeCount: row.nodeCount ?? null,
file: row.file ?? null,
valuesRedacted: true,
};
};
const slimPerfFindings = Array.isArray(collect.findings) ? collect.findings.slice(0, 5).map((item) => {
const row = observeRecord(item);
return {
id: row.id ?? null,
severity: row.severity ?? null,
count: row.count ?? null,
rootCause: row.rootCause ?? row.rootCauseStatus ?? null,
summary: typeof row.summary === "string" ? row.summary.slice(0, 110) : row.summary ?? null,
valuesRedacted: true,
};
}) : undefined;
const isPerformanceSummary = collectView === "performance-summary";
return {
ok: collect.ok !== false,
command: collect.command,
view: collect.view,
stateDir: collect.stateDir,
turnCount: collect.turnCount,
artifactFileCount: collect.artifactFileCount ?? collect.fileCount,
skippedFileCount: collect.skippedFileCount,
skippedFiles: Array.isArray(collect.skippedFiles) ? collect.skippedFiles.slice(0, 8) : undefined,
anchor: observeRecord(collect.anchor),
window: observeRecord(collect.window),
counts: observeRecord(collect.counts),
summary: observeRecord(collect.summary),
...(rows === undefined ? {} : { rows }),
...(timelineRows === undefined ? {} : { timelineRows }),
renderedText: collectView === "timeline" || collectView === "workbench-triad" ? undefined : typeof collect.renderedText === "string" ? collect.renderedText : undefined,
sourceFiles: Array.isArray(collect.sourceFiles) ? collect.sourceFiles : undefined,
blocker: collect.blocker,
sampleSeq: collect.sampleSeq,
traceId: collect.traceId,
finalResponse: collect.finalResponse,
statusGap: observeRecord(collect.statusGap),
dom: observeRecord(collect.dom),
networkEvidence: collectView === "workbench-triad" ? slimNetworkEvidence(collect.networkEvidence) : observeRecord(collect.networkEvidence),
freeze: collectView === "workbench-triad" ? slimFreeze(collect.freeze) : observeRecord(collect.freeze),
profileHotspots: Array.isArray(collect.profileHotspots) ? (isPerformanceSummary ? collect.profileHotspots.slice(0, 5).map(slimPerfHotspot) : collect.profileHotspots.slice(0, 8)) : undefined,
profileStacks: Array.isArray(collect.profileStacks) ? (isPerformanceSummary ? collect.profileStacks.slice(0, 3).map(slimPerfStack) : collect.profileStacks.slice(0, 5)) : undefined,
scriptHotspots: Array.isArray(collect.scriptHotspots) ? (isPerformanceSummary ? collect.scriptHotspots.slice(0, 5).map(slimPerfHotspot) : collect.scriptHotspots.slice(0, 8)) : undefined,
longTasks: Array.isArray(collect.longTasks) ? (isPerformanceSummary ? collect.longTasks.slice(0, 3).map(slimPerfEvent) : collect.longTasks.slice(0, 8)) : undefined,
longAnimationFrames: Array.isArray(collect.longAnimationFrames) ? (isPerformanceSummary ? collect.longAnimationFrames.slice(0, 3).map(slimPerfEvent) : collect.longAnimationFrames.slice(0, 8)) : undefined,
eventLoopGaps: Array.isArray(collect.eventLoopGaps) ? (isPerformanceSummary ? collect.eventLoopGaps.slice(0, 3).map(slimPerfEvent) : collect.eventLoopGaps.slice(0, 8)) : undefined,
captures: Array.isArray(collect.captures) ? (isPerformanceSummary ? collect.captures.slice(0, 3).map(slimPerfCapture) : collect.captures.slice(0, 8)) : undefined,
findings: collectView === "workbench-triad" ? slimFindings : isPerformanceSummary ? slimPerfFindings : Array.isArray(collect.findings) ? collect.findings.slice(0, 8) : undefined,
valuesRedacted: true,
};
}
function observeRecord(value: unknown): Record<string, unknown> {
return typeof value === "object" && value !== null && !Array.isArray(value) ? value as Record<string, unknown> : {};
}
+1 -142
View File
@@ -36,6 +36,7 @@ import { transPath } from "./runtime-common";
import { assertLane, assertNodeId, compactCommandResult, compactCommandResultRedacted, compactCommandResultWithStdoutTail, nullableRecord, optionValue, parseJsonObject, positiveIntegerOption, record, requiredOption, shellQuote } from "./utils";
import { nodeWebObserveResolveStateDirShell, recoverWebObserveAnalyzeTurnDetails, renderWebObserveStartResult, renderWebProbeRunResult, upsertWebObserveIndexEntry, webObserveCommandLabel, webObserveIdFromOptions, webObserveIdFromStatus, webObserveIndexEntryFromOptions, webObserveNextCommands, withWebObserveAnalyzeRendered, withWebObserveShortcuts } from "./web-observe-render";
import { commandSummaryForOutput, isSafeWebObserveArchivePrefix, isSafeWebObserveCollectFile, isSafeWebObserveFindingId, isSafeWebObserveJobId, isSafeWebObserveStateDir, isSafeWebObserveTraceId, nodeWebObserveCollectNodeScript, nodeWebObserveForceStopNodeScript, nodeWebObserveStatusNodeScript, nodeWebObserveWaitCommandShell, runNodeWebProbeScript, safeWebObserveSegment, safeWebObserveTargetSegment } from "./web-observe-scripts";
import { compactObserveCollectForRaw } from "./web-observe-collect-compact";
import { displayRepoPath, readBootstrapAdminPasswordMaterial, sleepSync } from "./web-probe";
export function parseNodeWebProbeSentinelOptions(args: string[]): NodeWebProbeSentinelOptions {
@@ -2063,148 +2064,6 @@ export function runNodeWebProbeObserveCollect(options: NodeWebProbeObserveOption
return options.raw ? payload : withWebObserveCollectRendered(payload);
}
function compactObserveCollectForRaw(collect: Record<string, unknown> | null): Record<string, unknown> | null {
if (collect === null) return null;
const rows = Array.isArray(collect.rows) ? collect.rows.map((item) => {
const row = observeRecord(item);
const finalResponse = observeRecord(row.finalResponse);
return {
round: row.round ?? null,
commandId: row.commandId ?? null,
userHash: row.userHash ?? null,
userBytes: row.userBytes ?? null,
traceId: row.traceId ?? null,
status: row.status ?? null,
elapsedSeconds: row.elapsedSeconds ?? null,
recentUpdateSeconds: row.recentUpdateSeconds ?? null,
marks: row.marks ?? null,
firstSeq: row.firstSeq ?? null,
lastSeq: row.lastSeq ?? null,
lastTs: row.lastTs ?? null,
finalResponse: {
preview: finalResponse.preview ?? null,
textHash: finalResponse.textHash ?? null,
textBytes: finalResponse.textBytes ?? null,
empty: finalResponse.empty === true,
},
valuesRedacted: true,
};
}) : undefined;
const timelineRows = Array.isArray(collect.timelineRows) ? collect.timelineRows.slice(0, 12).map((item) => {
const row = observeRecord(item);
return {
ts: row.ts ?? null,
seq: row.seq ?? null,
kind: row.kind ?? null,
phase: row.phase ?? null,
type: row.type ?? null,
commandId: row.commandId ?? null,
sessionId: row.sessionId ?? null,
traceId: row.traceId ?? null,
summary: row.summary ?? null,
valuesRedacted: true,
};
}) : undefined;
const collectView = typeof collect.view === "string" ? collect.view : null;
const slimNetworkEvidence = (value: unknown): Record<string, unknown> => {
const source = observeRecord(value);
const latestTurn = observeRecord(source.latestTurnResponse);
const latestTrace = observeRecord(source.latestTraceEventsResponse);
return {
requestCount: source.requestCount ?? null,
responseCount: source.responseCount ?? null,
failedCount: source.failedCount ?? null,
terminalResponseCount: source.terminalResponseCount ?? null,
turnResponseCount: source.turnResponseCount ?? null,
traceEventsResponseCount: source.traceEventsResponseCount ?? null,
latestTurnResponse: {
ts: latestTurn.ts ?? null,
sampleSeq: latestTurn.sampleSeq ?? null,
status: latestTurn.status ?? null,
bodySummary: observeRecord(latestTurn.bodySummary),
valuesRedacted: true,
},
latestTraceEventsResponse: {
ts: latestTrace.ts ?? null,
sampleSeq: latestTrace.sampleSeq ?? null,
status: latestTrace.status ?? null,
bodySummary: observeRecord(latestTrace.bodySummary),
valuesRedacted: true,
},
valuesRedacted: true,
};
};
const slimFreeze = (value: unknown): Record<string, unknown> => {
const source = observeRecord(value);
const blocker = observeRecord(source.latestBlocker);
return {
blockerCount: source.blockerCount ?? null,
responsivenessEventCount: source.responsivenessEventCount ?? null,
latestBlocker: {
ts: blocker.ts ?? null,
sampleSeq: blocker.sampleSeq ?? null,
rootCause: blocker.rootCause ?? null,
rootCauseStatus: blocker.rootCauseStatus ?? null,
fallbackAllowed: blocker.fallbackAllowed === true,
observed: observeRecord(blocker.observed),
page: observeRecord(blocker.page),
valuesRedacted: true,
},
valuesRedacted: true,
};
};
const slimFindings = Array.isArray(collect.findings) ? collect.findings.slice(0, 6).map((item) => {
const row = observeRecord(item);
return {
id: row.id ?? null,
severity: row.severity ?? null,
count: row.count ?? null,
rootCause: row.rootCause ?? row.rootCauseStatus ?? null,
summary: typeof row.summary === "string" ? row.summary.slice(0, 140) : row.summary ?? null,
valuesRedacted: true,
};
}) : undefined;
return {
ok: collect.ok !== false,
command: collect.command,
view: collect.view,
stateDir: collect.stateDir,
turnCount: collect.turnCount,
artifactFileCount: collect.artifactFileCount ?? collect.fileCount,
skippedFileCount: collect.skippedFileCount,
skippedFiles: Array.isArray(collect.skippedFiles) ? collect.skippedFiles.slice(0, 8) : undefined,
anchor: observeRecord(collect.anchor),
window: observeRecord(collect.window),
counts: observeRecord(collect.counts),
summary: observeRecord(collect.summary),
...(rows === undefined ? {} : { rows }),
...(timelineRows === undefined ? {} : { timelineRows }),
renderedText: collectView === "timeline" || collectView === "workbench-triad" ? undefined : typeof collect.renderedText === "string" ? collect.renderedText : undefined,
sourceFiles: Array.isArray(collect.sourceFiles) ? collect.sourceFiles : undefined,
blocker: collect.blocker,
sampleSeq: collect.sampleSeq,
traceId: collect.traceId,
finalResponse: collect.finalResponse,
statusGap: observeRecord(collect.statusGap),
dom: observeRecord(collect.dom),
networkEvidence: collectView === "workbench-triad" ? slimNetworkEvidence(collect.networkEvidence) : observeRecord(collect.networkEvidence),
freeze: collectView === "workbench-triad" ? slimFreeze(collect.freeze) : observeRecord(collect.freeze),
profileHotspots: Array.isArray(collect.profileHotspots) ? collect.profileHotspots.slice(0, 8) : undefined,
profileStacks: Array.isArray(collect.profileStacks) ? collect.profileStacks.slice(0, 5) : undefined,
scriptHotspots: Array.isArray(collect.scriptHotspots) ? collect.scriptHotspots.slice(0, 8) : undefined,
longTasks: Array.isArray(collect.longTasks) ? collect.longTasks.slice(0, 8) : undefined,
longAnimationFrames: Array.isArray(collect.longAnimationFrames) ? collect.longAnimationFrames.slice(0, 8) : undefined,
eventLoopGaps: Array.isArray(collect.eventLoopGaps) ? collect.eventLoopGaps.slice(0, 8) : undefined,
captures: Array.isArray(collect.captures) ? collect.captures.slice(0, 8) : undefined,
findings: collectView === "workbench-triad" ? slimFindings : Array.isArray(collect.findings) ? collect.findings.slice(0, 8) : undefined,
valuesRedacted: true,
};
}
function observeRecord(value: unknown): Record<string, unknown> {
return typeof value === "object" && value !== null && !Array.isArray(value) ? value as Record<string, unknown> : {};
}
export function runNodeWebProbeObserveAnalyze(options: NodeWebProbeObserveOptions, spec: HwlabRuntimeLaneSpec): Record<string, unknown> | RenderedCliResult {
const analyzerB64 = Buffer.from(nodeWebObserveAnalyzerSource(), "utf8").toString("base64");
const alertThresholds = nodeWebProbeAlertThresholds(spec);