polymath-society 0.2.5 → 0.2.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli.js +2339 -1546
- package/dist/engine/ingest-export.js +14 -8
- package/dist/engine/public-report.js +14 -8
- package/dist/index.js +1475 -60
- package/dist/pipeline/coding-agglomerate.js +289 -35
- package/dist/pipeline/coding-aggregate.js +15 -9
- package/dist/pipeline/coding-build.js +14 -8
- package/dist/pipeline/coding-coaching.js +273 -21
- package/dist/pipeline/coding-day-digest.js +17 -10
- package/dist/pipeline/coding-delegation.js +62 -17
- package/dist/pipeline/coding-expertise.js +166 -61
- package/dist/pipeline/coding-flow.js +14 -8
- package/dist/pipeline/coding-frontier-detail.js +143 -27
- package/dist/pipeline/coding-frontier.js +14 -8
- package/dist/pipeline/coding-gap-dist.js +14 -8
- package/dist/pipeline/coding-gap.js +140 -39
- package/dist/pipeline/coding-grade.js +44 -14
- package/dist/pipeline/coding-nutshell.js +39 -11
- package/dist/pipeline/coding-projects.js +41 -10
- package/dist/pipeline/coding-walkthrough.js +15 -9
- package/dist/web/app.js +493 -117
- package/dist/web/styles.css +1 -1
- package/package.json +1 -1
|
@@ -134,9 +134,7 @@ var require_secure_json_parse = __commonJS({
|
|
|
134
134
|
});
|
|
135
135
|
|
|
136
136
|
// ../../scripts/coding-coaching.mts
|
|
137
|
-
import { promises as
|
|
138
|
-
import os2 from "os";
|
|
139
|
-
import path12 from "path";
|
|
137
|
+
import { promises as fs11 } from "fs";
|
|
140
138
|
|
|
141
139
|
// ../../lib/agents/shared/agent.ts
|
|
142
140
|
import { readFileSync } from "fs";
|
|
@@ -16271,7 +16269,7 @@ function computeWorkstyle(inp) {
|
|
|
16271
16269
|
|
|
16272
16270
|
// ../../lib/calibration/index.ts
|
|
16273
16271
|
var DEFAULT_CALIBRATION = {
|
|
16274
|
-
version: "2026-07-
|
|
16272
|
+
version: "2026-07-14.2",
|
|
16275
16273
|
// = RUBRIC_FINGERPRINT of the shipped npm rubric (packages/coding-analyzer/
|
|
16276
16274
|
// src/grade/criteria.ts). A unit test fails loud when the rubric changes
|
|
16277
16275
|
// without this being updated (and re-pushed to the server).
|
|
@@ -16360,7 +16358,7 @@ var DEFAULT_CALIBRATION = {
|
|
|
16360
16358
|
}
|
|
16361
16359
|
],
|
|
16362
16360
|
codingTiers: {
|
|
16363
|
-
push: { median: 300, sigma:
|
|
16361
|
+
push: { median: 300, sigma: 0.91, tag: "estimated \u2014 log-normal fit", source: "Anthropic 2026 Claude Code study (400k sessions): median engaged user ~8 prompts/day at ~35 words \u2014 ~300 directed words/day; tail: a 1-in-1,000 user AVERAGES ~5k directed words/day (near-daily heavy dictation, clearly below the ~10k single-day record). AVERAGE over substantial days, cumulative not spiky." },
|
|
16364
16362
|
focus: { median: 0.08, sigma: 0.559, tag: "estimated \u2014 proxy-anchored", source: "median: Anthropic 20h/week engaged-user figure implies ~1h/day of true rapid exchange against an 8h working day; ceiling anchored to the ~4h/day deep-work limit (45% share = 1-in-1,000). AVERAGE share, cumulative not spiky." },
|
|
16365
16363
|
orchestration: { tag: "estimated \u2014 behavior bands", source: "no published concurrency distribution exists; ceiling anchored to the Claude Code lead's documented 10-15 parallel sessions" }
|
|
16366
16364
|
},
|
|
@@ -16393,12 +16391,18 @@ var DEFAULT_CALIBRATION = {
|
|
|
16393
16391
|
line: "the Claude Code lead runs 10\u201315 sessions at once; his #1 tip is 3\u20135 git worktrees in parallel"
|
|
16394
16392
|
},
|
|
16395
16393
|
throughput: {
|
|
16396
|
-
//
|
|
16397
|
-
//
|
|
16398
|
-
//
|
|
16399
|
-
//
|
|
16400
|
-
|
|
16401
|
-
|
|
16394
|
+
// Two DIFFERENT kinds of line (2026-07-14.2): topAvg is a PERCENTILE
|
|
16395
|
+
// claim — what a 1-in-1,000 user AVERAGES over substantial days (5k/day:
|
|
16396
|
+
// near-daily heavy dictation; a measured top dictating power user
|
|
16397
|
+
// averages ~3.9k). topPeak is NOT a percentile — it is the CEILING
|
|
16398
|
+
// reference, the wildest single days on record (~10k: a 14-16h
|
|
16399
|
+
// launch-day marathon), rendered as "wildest single days", never
|
|
16400
|
+
// "top X% peak". An avg-percentile and a peak-percentile can't both be
|
|
16401
|
+
// shown at a same-ish value (avg≈peak reads broken — user call), and a
|
|
16402
|
+
// peak PERCENTILE line is unknowable anyway; the record framing is
|
|
16403
|
+
// honest and keeps the visual gap.
|
|
16404
|
+
topAvgWordsPerDay: 5e3,
|
|
16405
|
+
topPeakWordsPerDay: 1e4,
|
|
16402
16406
|
benchLabel: "top 0.1%",
|
|
16403
16407
|
// No published "words typed/day" for heavy users — the real story is OUTPUT.
|
|
16404
16408
|
loopsHeadline: ">1,000,000 lines of Rust at 99.8% tests passing",
|
|
@@ -16733,7 +16737,7 @@ async function compileCodingProfile() {
|
|
|
16733
16737
|
sRow(
|
|
16734
16738
|
"How hard you push",
|
|
16735
16739
|
aggregate?.throughput?.score ?? tCeiling,
|
|
16736
|
-
`you peak at ~${peakWords.toLocaleString()} words of pure direction in a single day \u2014 the very top sustain ~${BEST.throughput.topAvgWordsPerDay.toLocaleString()} every day, week after week
|
|
16740
|
+
`you peak at ~${peakWords.toLocaleString()} words of pure direction in a single day \u2014 the very top sustain ~${BEST.throughput.topAvgWordsPerDay.toLocaleString()} every day, week after week; the wildest single days on record push ~${BEST.throughput.topPeakWordsPerDay.toLocaleString()}`
|
|
16737
16741
|
),
|
|
16738
16742
|
sRow(
|
|
16739
16743
|
"How well you use AI",
|
|
@@ -16809,6 +16813,233 @@ async function readCodingAsset(name17) {
|
|
|
16809
16813
|
);
|
|
16810
16814
|
}
|
|
16811
16815
|
|
|
16816
|
+
// ../../lib/agents/coding/docsDir.ts
|
|
16817
|
+
import { promises as fs9 } from "fs";
|
|
16818
|
+
import path12 from "path";
|
|
16819
|
+
|
|
16820
|
+
// ../../lib/agents/coding/materialize.ts
|
|
16821
|
+
import { promises as fs8 } from "fs";
|
|
16822
|
+
var SYSTEM_REMINDER_RE2 = /<system-reminder>[\s\S]*?<\/system-reminder>/g;
|
|
16823
|
+
var INJECT_GIST = 120;
|
|
16824
|
+
var INJECTED = [
|
|
16825
|
+
{ re: /<task-notification>[\s\S]*?<\/task-notification>/g, label: "bg task", gistRe: /<summary>([\s\S]*?)<\/summary>/ },
|
|
16826
|
+
{ re: /<local-command-stdout>[\s\S]*?<\/local-command-stdout>/g, label: "cmd output" },
|
|
16827
|
+
{ re: /<local-command-caveat>[\s\S]*?<\/local-command-caveat>/g, label: null },
|
|
16828
|
+
{ re: /<ide_opened_file>[\s\S]*?<\/ide_opened_file>/g, label: null }
|
|
16829
|
+
];
|
|
16830
|
+
function collapseInjected(input) {
|
|
16831
|
+
const markers = [];
|
|
16832
|
+
let text2 = input;
|
|
16833
|
+
for (const { re: re2, label, gistRe } of INJECTED) {
|
|
16834
|
+
text2 = text2.replace(re2, (block) => {
|
|
16835
|
+
if (label) {
|
|
16836
|
+
const gist = (gistRe ? block.match(gistRe)?.[1] ?? "" : block.replace(/<[^>]*>/g, " ")).replace(/\s+/g, " ").trim().slice(0, INJECT_GIST);
|
|
16837
|
+
markers.push(gist ? `[${label}: ${gist}]` : `[${label}]`);
|
|
16838
|
+
}
|
|
16839
|
+
return "";
|
|
16840
|
+
});
|
|
16841
|
+
}
|
|
16842
|
+
return { text: text2.replace(SYSTEM_REMINDER_RE2, "").trim(), markers };
|
|
16843
|
+
}
|
|
16844
|
+
function extractText2(content) {
|
|
16845
|
+
if (typeof content === "string") return content;
|
|
16846
|
+
if (Array.isArray(content)) {
|
|
16847
|
+
const parts = [];
|
|
16848
|
+
for (const item of content) {
|
|
16849
|
+
if (item && typeof item === "object" && item.type === "text") parts.push(item.text || "");
|
|
16850
|
+
}
|
|
16851
|
+
return parts.join("\n");
|
|
16852
|
+
}
|
|
16853
|
+
return "";
|
|
16854
|
+
}
|
|
16855
|
+
function isToolResultOnly2(content) {
|
|
16856
|
+
return Array.isArray(content) && content.length > 0 && content.every((c) => c && typeof c === "object" && c.type === "tool_result");
|
|
16857
|
+
}
|
|
16858
|
+
var AI_GIST = 160;
|
|
16859
|
+
async function materializeSession(file2) {
|
|
16860
|
+
let raw;
|
|
16861
|
+
try {
|
|
16862
|
+
raw = await fs8.readFile(file2, "utf-8");
|
|
16863
|
+
} catch {
|
|
16864
|
+
return null;
|
|
16865
|
+
}
|
|
16866
|
+
const lines = [];
|
|
16867
|
+
let humanTurns = 0, humanChars = 0;
|
|
16868
|
+
const pendingQueued = [];
|
|
16869
|
+
let lastMode = "";
|
|
16870
|
+
const pushMarkers = (markers) => {
|
|
16871
|
+
for (const mk of markers) if (mk !== lines[lines.length - 1]) lines.push(mk);
|
|
16872
|
+
};
|
|
16873
|
+
let aiLastProse = "";
|
|
16874
|
+
const aiTools = /* @__PURE__ */ new Map();
|
|
16875
|
+
const flushAI = () => {
|
|
16876
|
+
if (!aiLastProse && aiTools.size === 0) return;
|
|
16877
|
+
const tools = [...aiTools.entries()].map(([n, c]) => c > 1 ? `${n}\xD7${c}` : n).join(", ");
|
|
16878
|
+
const gist = aiLastProse ? aiLastProse.length > AI_GIST ? aiLastProse.slice(0, AI_GIST) + "\u2026" : aiLastProse : "";
|
|
16879
|
+
const bits = [];
|
|
16880
|
+
if (gist) bits.push(gist);
|
|
16881
|
+
if (tools) bits.push(`ran ${tools}`);
|
|
16882
|
+
lines.push(`[AI: ${bits.join(" \xB7 ")}]`);
|
|
16883
|
+
aiLastProse = "";
|
|
16884
|
+
aiTools.clear();
|
|
16885
|
+
};
|
|
16886
|
+
for (const lineRaw of raw.split("\n")) {
|
|
16887
|
+
const line = lineRaw.trim();
|
|
16888
|
+
if (!line) continue;
|
|
16889
|
+
let e;
|
|
16890
|
+
try {
|
|
16891
|
+
e = JSON.parse(line);
|
|
16892
|
+
} catch {
|
|
16893
|
+
continue;
|
|
16894
|
+
}
|
|
16895
|
+
const type = e.type;
|
|
16896
|
+
if (type === "ai-title") continue;
|
|
16897
|
+
if (type === "mode") {
|
|
16898
|
+
flushAI();
|
|
16899
|
+
const m = e.mode;
|
|
16900
|
+
if (m && String(m) !== lastMode) {
|
|
16901
|
+
lastMode = String(m);
|
|
16902
|
+
lines.push(`[mode \u2192 ${m}]`);
|
|
16903
|
+
}
|
|
16904
|
+
continue;
|
|
16905
|
+
}
|
|
16906
|
+
if (type === "queue-operation") {
|
|
16907
|
+
if (e.operation === "enqueue" && typeof e.content === "string") {
|
|
16908
|
+
const { text: t, markers } = collapseInjected(e.content);
|
|
16909
|
+
if (t || markers.length) flushAI();
|
|
16910
|
+
pushMarkers(markers);
|
|
16911
|
+
if (t) {
|
|
16912
|
+
pendingQueued.push(t);
|
|
16913
|
+
lines.push(`>> (queued while AI working) ${t}`);
|
|
16914
|
+
}
|
|
16915
|
+
}
|
|
16916
|
+
continue;
|
|
16917
|
+
}
|
|
16918
|
+
if (type === "user") {
|
|
16919
|
+
if (isHarnessEntry(e)) continue;
|
|
16920
|
+
const content = e.message?.content;
|
|
16921
|
+
if (isToolResultOnly2(content)) continue;
|
|
16922
|
+
const { text: t, markers } = collapseInjected(extractText2(content));
|
|
16923
|
+
if (!t && !markers.length) continue;
|
|
16924
|
+
flushAI();
|
|
16925
|
+
pushMarkers(markers);
|
|
16926
|
+
if (!t) continue;
|
|
16927
|
+
humanTurns++;
|
|
16928
|
+
humanChars += t.length;
|
|
16929
|
+
const qi = pendingQueued.indexOf(t);
|
|
16930
|
+
if (qi >= 0) {
|
|
16931
|
+
pendingQueued.splice(qi, 1);
|
|
16932
|
+
continue;
|
|
16933
|
+
}
|
|
16934
|
+
lines.push(`>> ${t}`);
|
|
16935
|
+
continue;
|
|
16936
|
+
}
|
|
16937
|
+
if (type === "assistant") {
|
|
16938
|
+
const msg = e.message ?? {};
|
|
16939
|
+
let prose = "";
|
|
16940
|
+
if (Array.isArray(msg.content)) {
|
|
16941
|
+
for (const item of msg.content) {
|
|
16942
|
+
const it = item;
|
|
16943
|
+
if (it.type === "text" && it.text) prose += it.text;
|
|
16944
|
+
else if (it.type === "tool_use" && it.name) aiTools.set(it.name, (aiTools.get(it.name) ?? 0) + 1);
|
|
16945
|
+
}
|
|
16946
|
+
} else prose = extractText2(msg.content);
|
|
16947
|
+
prose = prose.replace(/\s+/g, " ").trim();
|
|
16948
|
+
if (prose) aiLastProse = prose;
|
|
16949
|
+
continue;
|
|
16950
|
+
}
|
|
16951
|
+
}
|
|
16952
|
+
flushAI();
|
|
16953
|
+
return { text: lines.join("\n"), humanTurns, humanChars };
|
|
16954
|
+
}
|
|
16955
|
+
|
|
16956
|
+
// ../../lib/agents/coding/docsDir.ts
|
|
16957
|
+
async function writeScoreboard(codingDir, docs) {
|
|
16958
|
+
const gradesDir = path12.join(codingDir, "grades");
|
|
16959
|
+
let files = [];
|
|
16960
|
+
try {
|
|
16961
|
+
files = (await fs9.readdir(gradesDir)).filter((f) => f.endsWith(".json")).sort();
|
|
16962
|
+
} catch {
|
|
16963
|
+
return;
|
|
16964
|
+
}
|
|
16965
|
+
const byCriterion = /* @__PURE__ */ new Map();
|
|
16966
|
+
for (const f of files) {
|
|
16967
|
+
let g;
|
|
16968
|
+
try {
|
|
16969
|
+
g = JSON.parse(await fs9.readFile(path12.join(gradesDir, f), "utf8"));
|
|
16970
|
+
} catch {
|
|
16971
|
+
continue;
|
|
16972
|
+
}
|
|
16973
|
+
for (const c of g.criteria ?? []) {
|
|
16974
|
+
const s = c.score ?? c.bestEstimate;
|
|
16975
|
+
if (s == null) continue;
|
|
16976
|
+
const line = `L${s}${c.score == null ? "~" : ""} \xB7 ${(g.date ?? "").slice(0, 10)} \xB7 ${(g.title ?? g.sessionId ?? "").replace(/\n.*/s, "").slice(0, 60)} \xB7 ${g.sessionId} \u2014 ${(c.instance ?? "").slice(0, 110)}`;
|
|
16977
|
+
(byCriterion.get(c.key) ?? byCriterion.set(c.key, []).get(c.key)).push({ s, line });
|
|
16978
|
+
}
|
|
16979
|
+
}
|
|
16980
|
+
if (!byCriterion.size) return;
|
|
16981
|
+
const blocks = [...byCriterion.entries()].sort(([a], [b]) => a < b ? -1 : 1).map(
|
|
16982
|
+
([key, rows]) => `## ${key}
|
|
16983
|
+
${rows.sort((a, b) => b.s - a.s).map((r) => r.line).join("\n")}`
|
|
16984
|
+
);
|
|
16985
|
+
await fs9.writeFile(
|
|
16986
|
+
path12.join(docs, "_scoreboard.md"),
|
|
16987
|
+
`# Scoreboard \u2014 every graded session per criterion, best first.
|
|
16988
|
+
# Lx~ = estimate. Format: level \xB7 date \xB7 title \xB7 sessionId \u2014 graded instance.
|
|
16989
|
+
|
|
16990
|
+
${blocks.join("\n\n")}
|
|
16991
|
+
`
|
|
16992
|
+
);
|
|
16993
|
+
}
|
|
16994
|
+
async function ensureCodingDocs(codingDir, sessions) {
|
|
16995
|
+
const docs = path12.join(codingDir, "docs");
|
|
16996
|
+
await fs9.mkdir(docs, { recursive: true });
|
|
16997
|
+
const user = sessions.filter((s) => s.sessionId && !s.duplicateOf && (!("klass" in s) || s.klass === "interactive"));
|
|
16998
|
+
let written = 0;
|
|
16999
|
+
for (const s of user) {
|
|
17000
|
+
const out = path12.join(docs, `${s.sessionId}.txt`);
|
|
17001
|
+
try {
|
|
17002
|
+
await fs9.access(out);
|
|
17003
|
+
continue;
|
|
17004
|
+
} catch {
|
|
17005
|
+
}
|
|
17006
|
+
const mat = await materializeSession(s.file).catch(() => null);
|
|
17007
|
+
if (!mat?.text) continue;
|
|
17008
|
+
await fs9.writeFile(out, mat.text);
|
|
17009
|
+
written++;
|
|
17010
|
+
}
|
|
17011
|
+
const rows = user.sort((a, b) => (a.start ?? "") < (b.start ?? "") ? -1 : 1).map((s) => `${(s.start ?? "").slice(0, 10)} \xB7 ${(s.title ?? "").replace(/\n.*/s, "").slice(0, 80)} \xB7 ${s.sessionId}`);
|
|
17012
|
+
await fs9.writeFile(path12.join(docs, "_map.md"), rows.join("\n") + "\n");
|
|
17013
|
+
await writeScoreboard(codingDir, docs);
|
|
17014
|
+
if (written) console.log(`[docs] materialized ${written} new transcript(s) \u2192 ${docs}`);
|
|
17015
|
+
return docs;
|
|
17016
|
+
}
|
|
17017
|
+
function sourceLookupNote() {
|
|
17018
|
+
return `
|
|
17019
|
+
|
|
17020
|
+
SOURCE LOOKUP \u2014 you have Read/Grep/Glob over the working directory, which holds EVERYTHING known about this person's coding work. MAPS FIRST, grep second (the engine rule): docs/_scoreboard.md ranks every graded session per criterion, best first \u2014 one glance shows where the spikes/flair are, so start there when hunting peaks or checking whether a high mark is consistent or a one-off; day-digest.json is the day-by-day story of what they did in order \u2014 read the relevant days to get the arc before searching; docs/_map.md lists every session (date \xB7 title \xB7 sessionId). Then drill down: walkthroughs/<sessionId>.json is that session's phase-by-phase account (cheap, already distilled), grades/<sessionId>.json its graded findings with quotes, and docs/<sessionId>.txt the FULL transcript (">> " = the person, "[AI]" = the model) \u2014 the ground truth, read it when the distilled layers can't settle it. Other artifacts (flow.json, delegation/, expertise/, aggregate.json) are there too if a claim depends on them. The digest you were given is the spine \u2014 use lookups when a CLAIM-MOVING question cannot be settled from it (a moment you are about to headline, a promotion/depth call, an ambiguous engagement, whether detail was vision or boilerplate). VERIFY every verbatim quote you cite by finding it in the transcript first; if you cannot find it, do not use it. Look up what changes the output \u2014 do not re-read the whole corpus.`;
|
|
17021
|
+
}
|
|
17022
|
+
|
|
17023
|
+
// ../../lib/agents/coding/promptCache.ts
|
|
17024
|
+
import { createHash as createHash2 } from "crypto";
|
|
17025
|
+
import { promises as fs10 } from "fs";
|
|
17026
|
+
function promptSha(parts) {
|
|
17027
|
+
const h = createHash2("sha256");
|
|
17028
|
+
for (const p of parts) {
|
|
17029
|
+
h.update(p ?? "");
|
|
17030
|
+
h.update("\0");
|
|
17031
|
+
}
|
|
17032
|
+
return h.digest("hex").slice(0, 16);
|
|
17033
|
+
}
|
|
17034
|
+
async function reusableOutput(outPath, sha, valid, key = "promptSha") {
|
|
17035
|
+
try {
|
|
17036
|
+
const o = JSON.parse(await fs10.readFile(outPath, "utf8"));
|
|
17037
|
+
if (o[key] === sha && valid(o)) return o;
|
|
17038
|
+
} catch {
|
|
17039
|
+
}
|
|
17040
|
+
return null;
|
|
17041
|
+
}
|
|
17042
|
+
|
|
16812
17043
|
// ../../scripts/coding-coaching.mts
|
|
16813
17044
|
var CODING = CODING_DIR;
|
|
16814
17045
|
async function main() {
|
|
@@ -16847,13 +17078,27 @@ async function main() {
|
|
|
16847
17078
|
whatYouAre: {
|
|
16848
17079
|
gradedSessions: p.gradedSessions,
|
|
16849
17080
|
qualities: (p.stackUp ?? []).map((r) => ({ quality: r.label, score: r.score })),
|
|
17081
|
+
// Person-level judgments (coding-person, when it has run): one traversing
|
|
17082
|
+
// agent per criterion already ranked the PERSON with source-verified
|
|
17083
|
+
// receipts — the placement runs AFTER those judgments and builds on them.
|
|
17084
|
+
personLevelJudgments: await fs11.readFile(`${CODING}/person.json`, "utf8").then((t) => {
|
|
17085
|
+
const j = JSON.parse(t);
|
|
17086
|
+
return Object.values(j.criteria ?? {}).map((g) => ({
|
|
17087
|
+
quality: g.label,
|
|
17088
|
+
score: g.score,
|
|
17089
|
+
confidence: g.confidence,
|
|
17090
|
+
headline: g.headline,
|
|
17091
|
+
receipts: (g.receipts ?? []).slice(0, 2).map((r) => ({ date: r.date, quote: r.quote, what: r.what }))
|
|
17092
|
+
}));
|
|
17093
|
+
}).catch(() => null),
|
|
17094
|
+
personNote: "When personLevelJudgments is present it is the AUTHORITATIVE per-quality read (a per-criterion judge already verified these receipts at the source) \u2014 pick the spikes for the 'line' from ITS highest scores and sharpest receipts; 'qualities' is the fallback when it is null.",
|
|
16850
17095
|
receipts: p.criteria.filter((c) => c.graded).map((c) => ({
|
|
16851
17096
|
criterion: c.label,
|
|
16852
17097
|
takes: c.takes.slice(0, 2).map((t) => ({ date: t.date, title: t.title, score: t.score ?? t.best, what: t.instance, quote: t.quotes?.[0] ?? "" }))
|
|
16853
17098
|
}))
|
|
16854
17099
|
}
|
|
16855
17100
|
};
|
|
16856
|
-
const SYS = "You write the COACHING and FEEL-SEEN copy for a coding-skills report, strictly following this writing rubric:\n\n" + writing + "\n\nYou are given structured facts (numbers + concrete instances) from one person's Claude Code sessions. Three jobs:\n1) COACHING \u2014 for each section, write ONE sentence: the single most useful thing for THIS person, grounded in their actual numbers \u2014 how to improve, where they're weak, or the best thing to do differently. If a section is genuinely strong, say what to push further. Cite the number. No hedging, no fluff, no generic best-practice. Compare to the top where it helps (top ENGAGED time ~50% of day; the best sustain focus ~4h and run many agents in parallel). Vocabulary law: 'flow' means ONLY the strict metric (strictFlow facts); the loose metric is 'engaged time' \u2014 never call it flow, and never write a line that contradicts the strict flow map shown above this card. Deliberate-choice guard: NEVER recommend git worktrees (this person runs parallel agents on main by design and has never hit clobbering); do not recommend a frontier capability unless it appears in pendingFrontier.\n2) FEEL-SEEN \u2014 for abstraction, agency, and taste, write ONE concrete sentence that makes the person feel SEEN: name a SPECIFIC thing they did (from the instances) so they think 'it actually saw that', not generic praise. Second person, present tense.\n3) WHAT-YOU-ARE \u2014 the report's concluding identity read: a PLACEMENT verdict. Judge, from the receipts and scores, where this person would actually land on a real team, and say it flatteringly AND accurately. 'evidence' = one or two sentences pointing at the 2-3 sharpest receipts (named project, session, date, or number) that prove the line, chosen so the person thinks 'it actually saw that'.\n 'line' has EXACTLY this three-beat shape, hard-hitting and pithy:\n BEAT 1 \u2014 THE SPIKES, first words: name their 1-2 standout qualities flat and confident, plain words ('You have <spike> and you <spike>') \u2014 chosen from the highest scores and sharpest receipts, so the reader's first glance already says what to expect from this person.\n BEAT 2 \u2014 THE PLACEMENT those spikes buy: 'drop you into <team> and you'd be <placement>' \u2014 a coined identity (the register of 'high-agency outcomes machine'), NEVER a job title ('founding engineer', 'senior engineer' = flat, cringe), one clause ending on a punch word, sized to the evidence: star-of-any-startup for truly exceptional receipts, 'top third of engineers at any big tech company \u2014 ships without being managed' for a notch less. A size too big is patronizing, a size too small is a snub.\n BEAT 3 \u2014 a short hard verdict: why that pair is the rare, load-bearing thing, and that it's real.\n Worked examples across the calibration range \u2014 generic people, FORM and SIZE only; never reuse their wording, never treat them as a menu (the spikes must come from THIS person's scores):\n - exceptional agency + push: 'You push harder than almost anyone and you own outcomes end-to-end \u2014 drop you into any small startup and you'd be the engine of the whole thing, relentlessly shipping what's actually good. That pair is the rarest, most load-bearing thing here, and it's real.'\n - exceptional taste + judgement: 'Your taste is the real thing and your calls under ambiguity keep being right \u2014 drop you into any product team and you'd be the bar: the one who knows which version is right before anyone can say why. Now that AI makes output infinite, that's the scarcest seat in the room.'\n - strong delegation + expertise, a notch less: 'You run AI like a staff and your depth shows exactly where the tool runs out \u2014 you'd be in the top third of engineers at any big tech company, the one who ships without being managed. That combination is rarer than it sounds, and yours is proven.'\n - real focus + follow-through, modest spikes: 'You hold deep focus for hours and you finish what you start \u2014 drop you onto any team and you'd be the steady core, the one whose thread always converges. Every team needs exactly one of those; few have one.'\n - Pithy: two sentences max. No receipts crammed into the line (evidence carries those). No qualifier stacks, no consultant words (force multiplier, leverage, north star), no hedging.\n - TESTABLE placement, not adjectives. No population percentages.\n - If the receipts support NO honest flattering placement, output empty strings for both fields \u2014 nothing is better than an inflated or hedged read.\n - Never invent; every claim in 'evidence' must trace to a given receipt.";
|
|
17101
|
+
const SYS = "You write the COACHING and FEEL-SEEN copy for a coding-skills report, strictly following this writing rubric:\n\n" + writing + "\n\nYou are given structured facts (numbers + concrete instances) from one person's Claude Code sessions. Three jobs:\n1) COACHING \u2014 for each section, write ONE sentence: the single most useful thing for THIS person, grounded in their actual numbers \u2014 how to improve, where they're weak, or the best thing to do differently. If a section is genuinely strong, say what to push further. Cite the number. No hedging, no fluff, no generic best-practice. Compare to the top where it helps (top ENGAGED time ~50% of day; the best sustain focus ~4h and run many agents in parallel). Vocabulary law: 'flow' means ONLY the strict metric (strictFlow facts); the loose metric is 'engaged time' \u2014 never call it flow, and never write a line that contradicts the strict flow map shown above this card. Deliberate-choice guard: NEVER recommend git worktrees (this person runs parallel agents on main by design and has never hit clobbering); do not recommend a frontier capability unless it appears in pendingFrontier.\n2) FEEL-SEEN \u2014 for abstraction, agency, and taste, write ONE concrete sentence that makes the person feel SEEN: name a SPECIFIC thing they did (from the instances) so they think 'it actually saw that', not generic praise. Second person, present tense.\n3) WHAT-YOU-ARE \u2014 the report's concluding identity read: a PLACEMENT verdict. Judge, from the receipts and scores, where this person would actually land on a real team, and say it flatteringly AND accurately. 'evidence' = one or two sentences pointing at the 2-3 sharpest receipts (named project, session, date, or number) that prove the line, chosen so the person thinks 'it actually saw that'.\n 'line' has EXACTLY this three-beat shape, hard-hitting and pithy:\n BEAT 1 \u2014 THE SPIKES, first words: name their 1-2 standout qualities flat and confident, plain words ('You have <spike> and you <spike>') \u2014 chosen from the highest scores and sharpest receipts, so the reader's first glance already says what to expect from this person.\n BEAT 2 \u2014 THE PLACEMENT those spikes buy: 'drop you into <team> and you'd be <placement>' \u2014 a coined identity (the register of 'high-agency outcomes machine'), NEVER a job title ('founding engineer', 'senior engineer' = flat, cringe), one clause ending on a punch word, sized to the evidence: star-of-any-startup for truly exceptional receipts, 'top third of engineers at any big tech company \u2014 ships without being managed' for a notch less. A size too big is patronizing, a size too small is a snub.\n BEAT 3 \u2014 a short hard verdict: why that pair is the rare, load-bearing thing, and that it's real.\n Worked examples across the calibration range \u2014 generic people, FORM and SIZE only; never reuse their wording, never treat them as a menu (the spikes must come from THIS person's scores):\n - exceptional agency + push: 'You push harder than almost anyone and you own outcomes end-to-end \u2014 drop you into any small startup and you'd be the engine of the whole thing, relentlessly shipping what's actually good. That pair is the rarest, most load-bearing thing here, and it's real.'\n - exceptional taste + judgement: 'Your taste is the real thing and your calls under ambiguity keep being right \u2014 drop you into any product team and you'd be the bar: the one who knows which version is right before anyone can say why. Now that AI makes output infinite, that's the scarcest seat in the room.'\n - strong delegation + expertise, a notch less: 'You run AI like a staff and your depth shows exactly where the tool runs out \u2014 you'd be in the top third of engineers at any big tech company, the one who ships without being managed. That combination is rarer than it sounds, and yours is proven.'\n - real focus + follow-through, modest spikes: 'You hold deep focus for hours and you finish what you start \u2014 drop you onto any team and you'd be the steady core, the one whose thread always converges. Every team needs exactly one of those; few have one.'\n - Pithy: two sentences max. No receipts crammed into the line (evidence carries those). No qualifier stacks, no consultant words (force multiplier, leverage, north star), no hedging.\n - TESTABLE placement, not adjectives. No population percentages.\n - If the receipts support NO honest flattering placement, output empty strings for both fields \u2014 nothing is better than an inflated or hedged read.\n - Never invent; every claim in 'evidence' must trace to a given receipt." + sourceLookupNote();
|
|
16857
17102
|
const prompt = `FACTS (numbers + concrete instances per section):
|
|
16858
17103
|
${JSON.stringify(facts, null, 1).slice(0, 6e4)}
|
|
16859
17104
|
|
|
@@ -16865,17 +17110,24 @@ Output a SINGLE fenced json block, every value a single tight sentence (whatYouA
|
|
|
16865
17110
|
"whatYouAre": { "line": "", "evidence": "" }
|
|
16866
17111
|
}
|
|
16867
17112
|
\`\`\``;
|
|
16868
|
-
|
|
16869
|
-
const
|
|
17113
|
+
const model = process.env.AGENT_MODEL || "opus";
|
|
17114
|
+
const sha = promptSha([SYS, prompt, model]);
|
|
17115
|
+
if (!process.argv.includes("--refresh")) {
|
|
17116
|
+
const prev = await reusableOutput(`${CODING}/coaching.json`, sha, (o) => Object.keys(o.coaching || {}).length >= 5 && Object.keys(o.feelSeen || {}).length >= 3);
|
|
17117
|
+
if (prev) {
|
|
17118
|
+
console.log(`[coaching] inputs unchanged \u2014 reusing output from ${prev.generatedAt} (--refresh to regenerate)`);
|
|
17119
|
+
return;
|
|
17120
|
+
}
|
|
17121
|
+
}
|
|
17122
|
+
const sessions = await fs11.readFile(`${CODING}/sessions.json`, "utf8").then(JSON.parse).catch(() => []);
|
|
17123
|
+
await ensureCodingDocs(CODING, sessions);
|
|
17124
|
+
console.log(`coaching \u2014 1 ${model} pass over compiled profile (+source lookups)`);
|
|
16870
17125
|
let out = { coaching: {}, feelSeen: {} };
|
|
16871
17126
|
try {
|
|
16872
|
-
const run2 = await invokeAgent({ prompt, systemPrompt: SYS, addDir:
|
|
17127
|
+
const run2 = await invokeAgent({ prompt, systemPrompt: SYS, addDir: CODING, allowedTools: ["Read", "Grep", "Glob"], maxTurns: 10, timeoutMs: 54e4, model });
|
|
16873
17128
|
out = run2.json || out;
|
|
16874
17129
|
} catch (e) {
|
|
16875
17130
|
console.log("ERR", e.message.slice(0, 120));
|
|
16876
|
-
} finally {
|
|
16877
|
-
await fs8.rm(sandbox, { recursive: true, force: true }).catch(() => {
|
|
16878
|
-
});
|
|
16879
17131
|
}
|
|
16880
17132
|
const wya = out.whatYouAre;
|
|
16881
17133
|
const complete = Object.keys(out.coaching || {}).length >= 5 && Object.keys(out.feelSeen || {}).length >= 3 && wya && typeof wya.line === "string" && typeof wya.evidence === "string";
|
|
@@ -16883,8 +17135,8 @@ Output a SINGLE fenced json block, every value a single tight sentence (whatYouA
|
|
|
16883
17135
|
console.error(`REFUSING to write ${CODING}/coaching.json \u2014 incomplete output (coaching:${Object.keys(out.coaching || {}).length} feelSeen:${Object.keys(out.feelSeen || {}).length} whatYouAre:${wya ? "malformed" : "missing"})`);
|
|
16884
17136
|
process.exit(1);
|
|
16885
17137
|
}
|
|
16886
|
-
const result = { generatedAt: (/* @__PURE__ */ new Date()).toISOString(), ...out };
|
|
16887
|
-
await
|
|
17138
|
+
const result = { generatedAt: (/* @__PURE__ */ new Date()).toISOString(), promptSha: sha, ...out };
|
|
17139
|
+
await fs11.writeFile(`${CODING}/coaching.json`, JSON.stringify(result, null, 2));
|
|
16888
17140
|
console.log(`WROTE ${CODING}/coaching.json \u2014 coaching:${Object.keys(out.coaching || {}).length} feelSeen:${Object.keys(out.feelSeen || {}).length} whatYouAre:${wya.line.trim() ? "ok" : "declined"}`);
|
|
16889
17141
|
}
|
|
16890
17142
|
main().catch((e) => {
|
|
@@ -15975,7 +15975,7 @@ var TRANSCRIPT_LINE_RE = new RegExp(`^\\s*(${NOTE})((,| and) ${NOTE})*\\s*$|^\\s
|
|
|
15975
15975
|
|
|
15976
15976
|
// ../../lib/calibration/index.ts
|
|
15977
15977
|
var DEFAULT_CALIBRATION = {
|
|
15978
|
-
version: "2026-07-
|
|
15978
|
+
version: "2026-07-14.2",
|
|
15979
15979
|
// = RUBRIC_FINGERPRINT of the shipped npm rubric (packages/coding-analyzer/
|
|
15980
15980
|
// src/grade/criteria.ts). A unit test fails loud when the rubric changes
|
|
15981
15981
|
// without this being updated (and re-pushed to the server).
|
|
@@ -16064,7 +16064,7 @@ var DEFAULT_CALIBRATION = {
|
|
|
16064
16064
|
}
|
|
16065
16065
|
],
|
|
16066
16066
|
codingTiers: {
|
|
16067
|
-
push: { median: 300, sigma:
|
|
16067
|
+
push: { median: 300, sigma: 0.91, tag: "estimated \u2014 log-normal fit", source: "Anthropic 2026 Claude Code study (400k sessions): median engaged user ~8 prompts/day at ~35 words \u2014 ~300 directed words/day; tail: a 1-in-1,000 user AVERAGES ~5k directed words/day (near-daily heavy dictation, clearly below the ~10k single-day record). AVERAGE over substantial days, cumulative not spiky." },
|
|
16068
16068
|
focus: { median: 0.08, sigma: 0.559, tag: "estimated \u2014 proxy-anchored", source: "median: Anthropic 20h/week engaged-user figure implies ~1h/day of true rapid exchange against an 8h working day; ceiling anchored to the ~4h/day deep-work limit (45% share = 1-in-1,000). AVERAGE share, cumulative not spiky." },
|
|
16069
16069
|
orchestration: { tag: "estimated \u2014 behavior bands", source: "no published concurrency distribution exists; ceiling anchored to the Claude Code lead's documented 10-15 parallel sessions" }
|
|
16070
16070
|
},
|
|
@@ -16097,12 +16097,18 @@ var DEFAULT_CALIBRATION = {
|
|
|
16097
16097
|
line: "the Claude Code lead runs 10\u201315 sessions at once; his #1 tip is 3\u20135 git worktrees in parallel"
|
|
16098
16098
|
},
|
|
16099
16099
|
throughput: {
|
|
16100
|
-
//
|
|
16101
|
-
//
|
|
16102
|
-
//
|
|
16103
|
-
//
|
|
16104
|
-
|
|
16105
|
-
|
|
16100
|
+
// Two DIFFERENT kinds of line (2026-07-14.2): topAvg is a PERCENTILE
|
|
16101
|
+
// claim — what a 1-in-1,000 user AVERAGES over substantial days (5k/day:
|
|
16102
|
+
// near-daily heavy dictation; a measured top dictating power user
|
|
16103
|
+
// averages ~3.9k). topPeak is NOT a percentile — it is the CEILING
|
|
16104
|
+
// reference, the wildest single days on record (~10k: a 14-16h
|
|
16105
|
+
// launch-day marathon), rendered as "wildest single days", never
|
|
16106
|
+
// "top X% peak". An avg-percentile and a peak-percentile can't both be
|
|
16107
|
+
// shown at a same-ish value (avg≈peak reads broken — user call), and a
|
|
16108
|
+
// peak PERCENTILE line is unknowable anyway; the record framing is
|
|
16109
|
+
// honest and keeps the visual gap.
|
|
16110
|
+
topAvgWordsPerDay: 5e3,
|
|
16111
|
+
topPeakWordsPerDay: 1e4,
|
|
16106
16112
|
benchLabel: "top 0.1%",
|
|
16107
16113
|
// No published "words typed/day" for heavy users — the real story is OUTPUT.
|
|
16108
16114
|
loopsHeadline: ">1,000,000 lines of Rust at 99.8% tests passing",
|
|
@@ -16131,8 +16137,9 @@ var CODING = CODING_DIR;
|
|
|
16131
16137
|
var OUT = path11.join(CODING, "day-digest.json");
|
|
16132
16138
|
var TZ = process.env.CODING_TZ || "America/Los_Angeles";
|
|
16133
16139
|
async function main() {
|
|
16134
|
-
const
|
|
16135
|
-
|
|
16140
|
+
const all = JSON.parse(await fs6.readFile(path11.join(CODING, "sessions.json"), "utf8"));
|
|
16141
|
+
const sessions = all.filter((s) => s.klass === "interactive");
|
|
16142
|
+
console.log(`[day-digest] grouping ${sessions.length}/${all.length} interactive sessions' messages by day (tz ${TZ})\u2026`);
|
|
16136
16143
|
const dayConvs = await buildDayConversations(sessions, TZ);
|
|
16137
16144
|
console.log(`[day-digest] ${dayConvs.length} active days \xB7 ${dayConvs.reduce((a, d) => a + d.totalMessages, 0)} user messages total`);
|
|
16138
16145
|
const prev = REDO ? { generatedAt: "", tz: TZ, days: [] } : await fs6.readFile(OUT, "utf8").then(JSON.parse).catch(() => ({ generatedAt: "", tz: TZ, days: [] }));
|
|
@@ -134,7 +134,7 @@ var require_secure_json_parse = __commonJS({
|
|
|
134
134
|
});
|
|
135
135
|
|
|
136
136
|
// ../../scripts/coding-delegation.mts
|
|
137
|
-
import { promises as
|
|
137
|
+
import { promises as fs9 } from "fs";
|
|
138
138
|
import path12 from "path";
|
|
139
139
|
|
|
140
140
|
// ../../lib/agents/coding/delegation/detect.ts
|
|
@@ -16221,13 +16221,33 @@ function partition(sessions) {
|
|
|
16221
16221
|
return { gradable, thin, trivial };
|
|
16222
16222
|
}
|
|
16223
16223
|
|
|
16224
|
+
// ../../lib/agents/coding/promptCache.ts
|
|
16225
|
+
import { createHash } from "crypto";
|
|
16226
|
+
import { promises as fs8 } from "fs";
|
|
16227
|
+
function promptSha(parts) {
|
|
16228
|
+
const h = createHash("sha256");
|
|
16229
|
+
for (const p of parts) {
|
|
16230
|
+
h.update(p ?? "");
|
|
16231
|
+
h.update("\0");
|
|
16232
|
+
}
|
|
16233
|
+
return h.digest("hex").slice(0, 16);
|
|
16234
|
+
}
|
|
16235
|
+
async function reusableOutput(outPath, sha, valid, key = "promptSha") {
|
|
16236
|
+
try {
|
|
16237
|
+
const o = JSON.parse(await fs8.readFile(outPath, "utf8"));
|
|
16238
|
+
if (o[key] === sha && valid(o)) return o;
|
|
16239
|
+
} catch {
|
|
16240
|
+
}
|
|
16241
|
+
return null;
|
|
16242
|
+
}
|
|
16243
|
+
|
|
16224
16244
|
// ../../lib/agents/coding/profile.ts
|
|
16225
16245
|
import path11 from "path";
|
|
16226
16246
|
|
|
16227
16247
|
// ../../lib/calibration/fingerprint.ts
|
|
16228
|
-
import { createHash } from "node:crypto";
|
|
16248
|
+
import { createHash as createHash2 } from "node:crypto";
|
|
16229
16249
|
function rubricFingerprint(criteria) {
|
|
16230
|
-
return
|
|
16250
|
+
return createHash2("sha256").update(JSON.stringify(criteria)).digest("hex").slice(0, 10);
|
|
16231
16251
|
}
|
|
16232
16252
|
|
|
16233
16253
|
// ../../lib/agents/coding/criteria.ts
|
|
@@ -16376,7 +16396,7 @@ var TRANSCRIPT_LINE_RE = new RegExp(`^\\s*(${NOTE})((,| and) ${NOTE})*\\s*$|^\\s
|
|
|
16376
16396
|
|
|
16377
16397
|
// ../../lib/calibration/index.ts
|
|
16378
16398
|
var DEFAULT_CALIBRATION = {
|
|
16379
|
-
version: "2026-07-
|
|
16399
|
+
version: "2026-07-14.2",
|
|
16380
16400
|
// = RUBRIC_FINGERPRINT of the shipped npm rubric (packages/coding-analyzer/
|
|
16381
16401
|
// src/grade/criteria.ts). A unit test fails loud when the rubric changes
|
|
16382
16402
|
// without this being updated (and re-pushed to the server).
|
|
@@ -16465,7 +16485,7 @@ var DEFAULT_CALIBRATION = {
|
|
|
16465
16485
|
}
|
|
16466
16486
|
],
|
|
16467
16487
|
codingTiers: {
|
|
16468
|
-
push: { median: 300, sigma:
|
|
16488
|
+
push: { median: 300, sigma: 0.91, tag: "estimated \u2014 log-normal fit", source: "Anthropic 2026 Claude Code study (400k sessions): median engaged user ~8 prompts/day at ~35 words \u2014 ~300 directed words/day; tail: a 1-in-1,000 user AVERAGES ~5k directed words/day (near-daily heavy dictation, clearly below the ~10k single-day record). AVERAGE over substantial days, cumulative not spiky." },
|
|
16469
16489
|
focus: { median: 0.08, sigma: 0.559, tag: "estimated \u2014 proxy-anchored", source: "median: Anthropic 20h/week engaged-user figure implies ~1h/day of true rapid exchange against an 8h working day; ceiling anchored to the ~4h/day deep-work limit (45% share = 1-in-1,000). AVERAGE share, cumulative not spiky." },
|
|
16470
16490
|
orchestration: { tag: "estimated \u2014 behavior bands", source: "no published concurrency distribution exists; ceiling anchored to the Claude Code lead's documented 10-15 parallel sessions" }
|
|
16471
16491
|
},
|
|
@@ -16498,12 +16518,18 @@ var DEFAULT_CALIBRATION = {
|
|
|
16498
16518
|
line: "the Claude Code lead runs 10\u201315 sessions at once; his #1 tip is 3\u20135 git worktrees in parallel"
|
|
16499
16519
|
},
|
|
16500
16520
|
throughput: {
|
|
16501
|
-
//
|
|
16502
|
-
//
|
|
16503
|
-
//
|
|
16504
|
-
//
|
|
16505
|
-
|
|
16506
|
-
|
|
16521
|
+
// Two DIFFERENT kinds of line (2026-07-14.2): topAvg is a PERCENTILE
|
|
16522
|
+
// claim — what a 1-in-1,000 user AVERAGES over substantial days (5k/day:
|
|
16523
|
+
// near-daily heavy dictation; a measured top dictating power user
|
|
16524
|
+
// averages ~3.9k). topPeak is NOT a percentile — it is the CEILING
|
|
16525
|
+
// reference, the wildest single days on record (~10k: a 14-16h
|
|
16526
|
+
// launch-day marathon), rendered as "wildest single days", never
|
|
16527
|
+
// "top X% peak". An avg-percentile and a peak-percentile can't both be
|
|
16528
|
+
// shown at a same-ish value (avg≈peak reads broken — user call), and a
|
|
16529
|
+
// peak PERCENTILE line is unknowable anyway; the record framing is
|
|
16530
|
+
// honest and keeps the visual gap.
|
|
16531
|
+
topAvgWordsPerDay: 5e3,
|
|
16532
|
+
topPeakWordsPerDay: 1e4,
|
|
16507
16533
|
benchLabel: "top 0.1%",
|
|
16508
16534
|
// No published "words typed/day" for heavy users — the real story is OUTPUT.
|
|
16509
16535
|
loopsHeadline: ">1,000,000 lines of Rust at 99.8% tests passing",
|
|
@@ -16533,6 +16559,7 @@ var MODEL = flag("model", "sonnet");
|
|
|
16533
16559
|
var CONC = Number(flag("conc", "4"));
|
|
16534
16560
|
var IDS = flag("ids", "").split(",").map((s) => s.trim()).filter(Boolean);
|
|
16535
16561
|
var N = argv.includes("--n") ? Number(flag("n", "0")) : 0;
|
|
16562
|
+
var REFRESH = argv.includes("--refresh");
|
|
16536
16563
|
function makeLimiter(max) {
|
|
16537
16564
|
let active = 0;
|
|
16538
16565
|
const q = [];
|
|
@@ -16551,19 +16578,29 @@ var CODING = CODING_DIR;
|
|
|
16551
16578
|
var OUT = path12.join(CODING, "delegation");
|
|
16552
16579
|
var LOGS = path12.join(OUT, "logs");
|
|
16553
16580
|
async function main() {
|
|
16554
|
-
const sessions = JSON.parse(await
|
|
16555
|
-
const live = sessions.filter((s) => !s.duplicateOf);
|
|
16581
|
+
const sessions = JSON.parse(await fs9.readFile(path12.join(CODING, "sessions.json"), "utf8"));
|
|
16582
|
+
const live = sessions.filter((s) => s.klass === "interactive" && !s.duplicateOf);
|
|
16556
16583
|
const { gradable } = partition(live);
|
|
16557
16584
|
let picked = gradable;
|
|
16558
16585
|
if (IDS.length) {
|
|
16559
16586
|
const set = new Set(IDS);
|
|
16560
16587
|
picked = live.filter((s) => set.has(s.sessionId));
|
|
16561
16588
|
} else if (N > 0) picked = gradable.slice().sort((a, b) => b.humanChars * Math.log1p(b.humanTurns) - a.humanChars * Math.log1p(a.humanTurns)).slice(0, N);
|
|
16562
|
-
await
|
|
16589
|
+
await fs9.mkdir(LOGS, { recursive: true });
|
|
16563
16590
|
console.log(`[delegation] ${live.length} live \xB7 ${gradable.length} gradable \xB7 running detect on ${picked.length} (LLM only on stuck-loop candidates)\u2026`);
|
|
16564
16591
|
const lim = makeLimiter(CONC);
|
|
16592
|
+
let reused = 0;
|
|
16565
16593
|
startRun("coding-delegation", picked.length);
|
|
16566
16594
|
const reads = (await Promise.all(picked.map((s) => lim(async () => {
|
|
16595
|
+
if (!REFRESH) {
|
|
16596
|
+
try {
|
|
16597
|
+
const prev = JSON.parse(await fs9.readFile(path12.join(OUT, `${s.sessionId}.json`), "utf8"));
|
|
16598
|
+
reused++;
|
|
16599
|
+
tick(true);
|
|
16600
|
+
return prev;
|
|
16601
|
+
} catch {
|
|
16602
|
+
}
|
|
16603
|
+
}
|
|
16567
16604
|
try {
|
|
16568
16605
|
const r = await detectDelegation(s, { model: MODEL, outDir: OUT, logDir: LOGS });
|
|
16569
16606
|
tick(!!r);
|
|
@@ -16576,9 +16613,17 @@ async function main() {
|
|
|
16576
16613
|
}
|
|
16577
16614
|
})))).filter(Boolean);
|
|
16578
16615
|
endRun();
|
|
16579
|
-
console.log(`[delegation]
|
|
16580
|
-
const
|
|
16581
|
-
|
|
16616
|
+
if (reused) console.log(`[delegation] reused ${reused} existing per-session read(s) (--refresh to re-detect)`);
|
|
16617
|
+
const stable = reads.map((r) => ({ id: r.sessionId, loops: r.stuckLoops, od: r.overDrive })).sort((a, b) => a.id < b.id ? -1 : 1);
|
|
16618
|
+
const sha = promptSha([JSON.stringify(stable), MODEL]);
|
|
16619
|
+
const rollupPath = path12.join(CODING, "delegation-rollup.json");
|
|
16620
|
+
let rollup = REFRESH ? null : await reusableOutput(rollupPath, sha, (o) => typeof o.sessions === "number");
|
|
16621
|
+
if (rollup) console.log(`[delegation] rollup inputs unchanged \u2014 reusing (--refresh to regenerate)`);
|
|
16622
|
+
else {
|
|
16623
|
+
console.log(`[delegation] corpus rollup (Case A count + Case B over-drive judgment)\u2026`);
|
|
16624
|
+
rollup = { ...await rollupDelegation(reads, live, { model: MODEL }), promptSha: sha };
|
|
16625
|
+
await fs9.writeFile(rollupPath, JSON.stringify(rollup, null, 2));
|
|
16626
|
+
}
|
|
16582
16627
|
console.log(`
|
|
16583
16628
|
\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 DELEGATION \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550`);
|
|
16584
16629
|
console.log(`CASE A \u2014 stuck loops: ${rollup.stuckLoopInstances} across ${rollup.sessions} sessions`);
|