(dir, label)
| 35 | } |
| 36 | |
| 37 | function parse(dir, label) { |
| 38 | const files = segments(dir, label); |
| 39 | if (!files) return null; |
| 40 | const s = parseSession(files); |
| 41 | if (!s.ok) return null; |
| 42 | const o = s.occupancy; |
| 43 | return { |
| 44 | dur: s.dur, tools: s.tools, reads: s.reads, grep: s.grep, cg: s.cg, |
| 45 | bash: s.counts.Bash || 0, cliCalls: s.cliCalls, cliContaminated: s.cliContaminated, |
| 46 | tokens: s.processed, cost: s.cost, raced: s.raced, turns: s.turns, |
| 47 | segments: files.length, |
| 48 | ctx: o.ctxFinal, |
| 49 | ctxBase: o.ctxBase, |
| 50 | occCg: o.residual.codegraph, |
| 51 | occFile: o.residualFileAccess, |
| 52 | // The arm's own retrieval residual: codegraph in the with-arm, Read/Grep/Bash |
| 53 | // in the without-arm. Comparing these is the apples-to-apples pair. |
| 54 | occSelf: o.residual.codegraph + o.residualFileAccess, |
| 55 | occShareCtx: o.ctxFinal > 0 ? ((o.residual.codegraph + o.residualFileAccess) / o.ctxFinal) * 100 : 0, |
| 56 | occShareWin: ((o.residual.codegraph + o.residualFileAccess) / o.windowTokens) * 100, |
| 57 | window: o.windowTokens, |
| 58 | // The other two feedback metrics, carried per run so the campaign can pool |
| 59 | // them. Both are with-arm-only in practice — a without-arm makes no explore |
| 60 | // calls, so it has nothing to be sufficient about and no bytes to allocate. |
| 61 | suffAnswered: s.sufficiency.answered, |
| 62 | suffCounts: s.sufficiency.counts, |
| 63 | // Byte-weighted, so a run with no explore contributes NOTHING rather than a |
| 64 | // zero; a zero would drag a repo toward "wasteful" for never spending a byte. |
| 65 | allocUsed: s.allocation.envelope ? s.allocation.used : 0, |
| 66 | allocEnvelope: s.allocation.envelope, |
| 67 | allocCalls: s.allocation.calls.length, |
| 68 | }; |
| 69 | } |
| 70 | |
| 71 | const median = (arr) => { const v = [...arr].sort((a, b) => a - b); const n = v.length; return n === 0 ? 0 : n % 2 ? v[(n - 1) / 2] : (v[n / 2 - 1] + v[n / 2]) / 2; }; |
| 72 | const fmtTime = (s) => s >= 60 ? `${Math.floor(s / 60)}m ${Math.round(s % 60)}s` : `${Math.round(s)}s`; |
no test coverage detected