fix: add sentinel run memory detail curves

This commit is contained in:
Codex
2026-07-01 02:07:23 +00:00
parent 1f5fddd8b1
commit ebcbdc766e
11 changed files with 626 additions and 12 deletions
@@ -669,6 +669,48 @@ function compactQuickVerifyRecordAnalysis(value: unknown): Record<string, unknow
screenshot: compactQuickVerifyRecordScreenshot(record(item.screenshot)),
findings: Array.isArray(item.findings) ? item.findings.slice(0, 16).map(compactQuickVerifyRecordFinding) : [],
pagePerformanceSlowApi: Array.isArray(item.pagePerformanceSlowApi) ? item.pagePerformanceSlowApi.slice(0, 6).map(record) : [],
browserProcess: compactQuickVerifyRecordBrowserProcess(record(item.browserProcess)),
valuesRedacted: true,
};
}
function compactQuickVerifyRecordBrowserProcess(value: Record<string, unknown>): Record<string, unknown> | null {
const pageSeries = Array.isArray(value.pageSeries) ? value.pageSeries.map(compactQuickVerifyRecordMemorySeries).filter((item) => item.points.length > 0) : [];
if (pageSeries.length === 0) return null;
return {
source: stringAtNullable(value, "source") ?? "analysis-browser-process",
unit: stringAtNullable(value, "unit") ?? "MB",
metric: stringAtNullable(value, "metric") ?? "page-heap-used",
pageCount: pageSeries.length,
sampleCount: pageSeries.reduce((sum, item) => sum + item.points.length, 0),
pageSeries,
valuesRedacted: true,
};
}
function compactQuickVerifyRecordMemorySeries(value: unknown): Record<string, unknown> & { points: Record<string, unknown>[] } {
const item = record(value);
const points = Array.isArray(item.points)
? item.points.map(record).map((point) => ({
ts: stringAtNullable(point, "ts"),
elapsedSeconds: numberAtNullable(point, "elapsedSeconds"),
elapsedMinutes: numberAtNullable(point, "elapsedMinutes"),
memoryMb: numberAtNullable(point, "memoryMb"),
heapUsedMb: numberAtNullable(point, "heapUsedMb"),
jsHeapUsedMb: numberAtNullable(point, "jsHeapUsedMb"),
effectiveHeapUsedMb: numberAtNullable(point, "effectiveHeapUsedMb"),
effectiveJsHeapUsedMb: numberAtNullable(point, "effectiveJsHeapUsedMb"),
domNodes: numberAtNullable(point, "domNodes"),
valuesRedacted: true,
})).filter((point) => point.ts !== null && point.memoryMb !== null)
: [];
return {
key: stringAtNullable(item, "key"),
pageRole: stringAtNullable(item, "pageRole"),
pageId: stringAtNullable(item, "pageId"),
label: stringAtNullable(item, "label"),
url: stringAtNullable(item, "url"),
points,
valuesRedacted: true,
};
}
@@ -820,7 +862,11 @@ function readAnalysisSummaryFromWorkspace(state: SentinelCicdState, stateDir: st
"walk(stateDir);",
"const findings=arr(report?.findings ?? report?.archiveSummary?.redFindings).slice(0,20).map((item)=>{const v=rec(item); return {id:clip(v.id??v.kind??v.code,80),kind:clip(v.kind??v.id??v.code,80),code:clip(v.code??v.kind??v.id,80),severity:clip(v.severity??v.level,32),level:clip(v.level??v.severity,32),count:Number(v.count??v.sampleCount??1),summary:clip(v.summary??v.message,220),message:clip(v.message??v.summary,220),rootCause:clip(v.rootCause,140),rootCauseStatus:clip(v.rootCauseStatus,90),rootCauseConfidence:clip(v.rootCauseConfidence,40),nextAction:clip(v.nextAction,240),evidenceSummary:v.evidence?clip(JSON.stringify(rec(v.evidence)),220):clip(v.evidenceSummary,220),timingSourceOfTruth:clip(v.timingSourceOfTruth??v.expectedElapsedSource??v.evidenceKind,100),timingStatus:clip(v.timingStatus,60),timingAlert:v.timingAlert===true,rootCauseSignals:compactRootCauseSignals(v.rootCauseSignals),blocking:v.blocking===true,afterRound:v.afterRound??null,canarySessionId:clip(v.canarySessionId,80),routeSessionId:clip(v.routeSessionId,80),activeSessionId:clip(v.activeSessionId,80),consecutiveUserMessageCount:v.consecutiveUserMessageCount??null,sentinelRange:clip(v.sentinelRange,80),sampleSeq:v.sampleSeq??null,traceIds:arr(v.traceIds).slice(0,8).map((x)=>clip(x,80)),pageRole:clip(v.pageRole,32),pageId:clip(v.pageId,80),observerId:clip(v.observerId,80),stateDir:clip(v.stateDir,160),commandId:clip(v.commandId,80),valuesRedacted:true};});",
"const slow=arr(report?.pagePerformanceSlowApi ?? report?.archivePagePerformanceSlowApi).slice(0,8).map((item)=>{const v=rec(item); return {path:clip(v.path??v.route,120),sampleCount:v.sampleCount??null,p95Ms:v.p95Ms??null,maxMs:v.maxMs??null,overFiveSecondCount:v.overFiveSecondCount??null};});",
"console.log(JSON.stringify({ok:!!report,reportOk:!!report&&report.ok!==false,stateDir,reportJsonPath:reportPath,reportJsonSha256:sha(jsonBuf),reportMdPath,reportMdSha256:sha(read(reportMdPath)),findingCount:Number(report?.findingCount??findings.length),artifactCount,screenshot,findings,counts:rec(report?.counts),analysisWindow:rec(report?.analysisWindow??report?.windows?.recent?.summary),pagePerformanceSlowApi:slow,valuesRedacted:true}));",
"const num=(v)=>Number.isFinite(Number(v))?Number(v):null; const mb=(v)=>{const n=num(v); return n==null?null:Math.round((n/1024/1024)*100)/100};",
"function pageMemory(page){const eff=rec(page.effectiveMemory); const heap=rec(page.heapUsage); const perf=rec(page.performance); const metrics=rec(perf.metrics); const heapUsed=num(eff.heapUsedMb)??mb(heap.usedSize); const jsHeap=num(eff.jsHeapUsedMb)??mb(metrics.JSHeapUsedSize); const memory=heapUsed??jsHeap; if(memory==null)return null; return {memoryMb:memory,heapUsedMb:heapUsed,jsHeapUsedMb:jsHeap,effectiveHeapUsedMb:num(eff.effectiveHeapUsedMb),effectiveJsHeapUsedMb:num(eff.effectiveJsHeapUsedMb),domNodes:num(eff.domNodes)??num(rec(page.domCounters).nodes)??num(metrics.Nodes)}; }",
"function browserProcessPageSeries(){const p=path.join(stateDir,'browser-process.jsonl'); let lines=[]; try{lines=String(read(p)||'').split(/\\r?\\n/).filter(Boolean)}catch{} const map=new Map(); let firstTs=null; for(const line of lines){let row=null; try{row=JSON.parse(line)}catch{} if(!row||row.type!=='browser-process-sample')continue; const ts=row.ts||null; const tsMs=Date.parse(String(ts||'')); if(!ts||!Number.isFinite(tsMs))continue; for(const page of arr(row.pages)){const memory=pageMemory(rec(page)); if(!memory)continue; if(firstTs==null)firstTs=tsMs; const role=clip(page.pageRole||'page',32); const id=clip(page.pageId||`${role}-${page.pageEpoch??map.size}`,80); const key=`${role}:${id}`; const current=map.get(key)||{key,pageRole:role,pageId:id,label:`${role} ${String(id).slice(0,10)}`,url:clip(page.url,180),points:[],valuesRedacted:true}; current.points.push({ts,elapsedSeconds:Math.max(0,Math.round((tsMs-firstTs)/1000)),elapsedMinutes:Math.round(Math.max(0,(tsMs-firstTs)/60000)*100)/100,...memory,valuesRedacted:true}); map.set(key,current);} } return Array.from(map.values()).filter((item)=>item.points.length>0); }",
"const browserPageSeries=browserProcessPageSeries();",
"console.log(JSON.stringify({ok:!!report,reportOk:!!report&&report.ok!==false,stateDir,reportJsonPath:reportPath,reportJsonSha256:sha(jsonBuf),reportMdPath,reportMdSha256:sha(read(reportMdPath)),findingCount:Number(report?.findingCount??findings.length),artifactCount,screenshot,findings,counts:rec(report?.counts),analysisWindow:rec(report?.analysisWindow??report?.windows?.recent?.summary),pagePerformanceSlowApi:slow,browserProcess:{source:'analysis-browser-process-jsonl',unit:'MB',metric:'page-heap-used',pageCount:browserPageSeries.length,sampleCount:browserPageSeries.reduce((sum,item)=>sum+item.points.length,0),pageSeries:browserPageSeries,valuesRedacted:true},valuesRedacted:true}));",
"NODE",
].join("\n");
const result = runCommand(["trans", `${state.spec.nodeId}:${state.spec.workspace}`, "sh"], repoRoot, { input: script, timeoutMs: Math.min(timeoutSeconds, 60) * 1000 });