| 1130 | } |
| 1131 | |
| 1132 | function buildReport(metadata, rawRows) { |
| 1133 | const groups = new Map(); |
| 1134 | for (const row of rawRows) { |
| 1135 | const key = [ |
| 1136 | row.tool, |
| 1137 | row.phase, |
| 1138 | row.action, |
| 1139 | row.status, |
| 1140 | row.note || "", |
| 1141 | ].join("\u0000"); |
| 1142 | const group = groups.get(key) || { |
| 1143 | tool: row.tool, |
| 1144 | phase: row.phase, |
| 1145 | action: row.action, |
| 1146 | status: row.status, |
| 1147 | note: row.note || "", |
| 1148 | samples: [], |
| 1149 | }; |
| 1150 | if (typeof row.durationMs === "number") { |
| 1151 | group.samples.push(row.durationMs); |
| 1152 | } |
| 1153 | if (row.status !== "ok") { |
| 1154 | group.status = row.status; |
| 1155 | } |
| 1156 | groups.set(key, group); |
| 1157 | } |
| 1158 | |
| 1159 | const lines = [ |
| 1160 | "# Agent Control Benchmark", |
| 1161 | "", |
| 1162 | `- Generated: ${metadata.generatedAt}`, |
| 1163 | `- Simulator: ${metadata.udid}`, |
| 1164 | `- Repetitions: ${metadata.reps}`, |
| 1165 | `- Versions: SimDeck ${metadata.versions.simdeck}, agent-device ${metadata.versions["agent-device"]}, Argent ${metadata.versions.argent}`, |
| 1166 | "", |
| 1167 | "| Tool | Phase | Action | Samples | Median | Min | Max | Status | Notes |", |
| 1168 | "| --- | --- | --- | ---: | ---: | ---: | ---: | --- | --- |", |
| 1169 | ]; |
| 1170 | |
| 1171 | for (const group of [...groups.values()].sort(compareGroups)) { |
| 1172 | const stats = summarize(group.samples); |
| 1173 | lines.push( |
| 1174 | [ |
| 1175 | group.tool, |
| 1176 | group.phase, |
| 1177 | group.action, |
| 1178 | String(group.samples.length || 0), |
| 1179 | stats ? formatMs(stats.median) : "n/a", |
| 1180 | stats ? formatMs(stats.min) : "n/a", |
| 1181 | stats ? formatMs(stats.max) : "n/a", |
| 1182 | group.status, |
| 1183 | truncate(group.note, markdownWidth), |
| 1184 | ] |
| 1185 | .map(escapeMarkdownCell) |
| 1186 | .join(" | ") |
| 1187 | .replace(/^/, "| ") |
| 1188 | .replace(/$/, " |"), |
| 1189 | ); |