polymath-society 0.2.5 → 0.2.7
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 +2420 -1573
- 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,8 @@ var require_secure_json_parse = __commonJS({
|
|
|
134
134
|
});
|
|
135
135
|
|
|
136
136
|
// ../../scripts/coding-gap.mts
|
|
137
|
-
import { promises as
|
|
138
|
-
import
|
|
139
|
-
import path12 from "path";
|
|
137
|
+
import { promises as fs11 } from "fs";
|
|
138
|
+
import path13 from "path";
|
|
140
139
|
|
|
141
140
|
// ../../lib/agents/shared/agent.ts
|
|
142
141
|
import { readFileSync } from "fs";
|
|
@@ -2151,8 +2150,8 @@ function getErrorMap() {
|
|
|
2151
2150
|
|
|
2152
2151
|
// ../../node_modules/zod/v3/helpers/parseUtil.js
|
|
2153
2152
|
var makeIssue = (params) => {
|
|
2154
|
-
const { data, path:
|
|
2155
|
-
const fullPath = [...
|
|
2153
|
+
const { data, path: path14, errorMaps, issueData } = params;
|
|
2154
|
+
const fullPath = [...path14, ...issueData.path || []];
|
|
2156
2155
|
const fullIssue = {
|
|
2157
2156
|
...issueData,
|
|
2158
2157
|
path: fullPath
|
|
@@ -2268,11 +2267,11 @@ var errorUtil;
|
|
|
2268
2267
|
|
|
2269
2268
|
// ../../node_modules/zod/v3/types.js
|
|
2270
2269
|
var ParseInputLazyPath = class {
|
|
2271
|
-
constructor(parent, value,
|
|
2270
|
+
constructor(parent, value, path14, key) {
|
|
2272
2271
|
this._cachedPath = [];
|
|
2273
2272
|
this.parent = parent;
|
|
2274
2273
|
this.data = value;
|
|
2275
|
-
this._path =
|
|
2274
|
+
this._path = path14;
|
|
2276
2275
|
this._key = key;
|
|
2277
2276
|
}
|
|
2278
2277
|
get path() {
|
|
@@ -15059,39 +15058,39 @@ function createOpenAI(options = {}) {
|
|
|
15059
15058
|
});
|
|
15060
15059
|
const createChatModel = (modelId, settings = {}) => new OpenAIChatLanguageModel(modelId, settings, {
|
|
15061
15060
|
provider: `${providerName}.chat`,
|
|
15062
|
-
url: ({ path:
|
|
15061
|
+
url: ({ path: path14 }) => `${baseURL}${path14}`,
|
|
15063
15062
|
headers: getHeaders,
|
|
15064
15063
|
compatibility,
|
|
15065
15064
|
fetch: options.fetch
|
|
15066
15065
|
});
|
|
15067
15066
|
const createCompletionModel = (modelId, settings = {}) => new OpenAICompletionLanguageModel(modelId, settings, {
|
|
15068
15067
|
provider: `${providerName}.completion`,
|
|
15069
|
-
url: ({ path:
|
|
15068
|
+
url: ({ path: path14 }) => `${baseURL}${path14}`,
|
|
15070
15069
|
headers: getHeaders,
|
|
15071
15070
|
compatibility,
|
|
15072
15071
|
fetch: options.fetch
|
|
15073
15072
|
});
|
|
15074
15073
|
const createEmbeddingModel = (modelId, settings = {}) => new OpenAIEmbeddingModel(modelId, settings, {
|
|
15075
15074
|
provider: `${providerName}.embedding`,
|
|
15076
|
-
url: ({ path:
|
|
15075
|
+
url: ({ path: path14 }) => `${baseURL}${path14}`,
|
|
15077
15076
|
headers: getHeaders,
|
|
15078
15077
|
fetch: options.fetch
|
|
15079
15078
|
});
|
|
15080
15079
|
const createImageModel = (modelId, settings = {}) => new OpenAIImageModel(modelId, settings, {
|
|
15081
15080
|
provider: `${providerName}.image`,
|
|
15082
|
-
url: ({ path:
|
|
15081
|
+
url: ({ path: path14 }) => `${baseURL}${path14}`,
|
|
15083
15082
|
headers: getHeaders,
|
|
15084
15083
|
fetch: options.fetch
|
|
15085
15084
|
});
|
|
15086
15085
|
const createTranscriptionModel = (modelId) => new OpenAITranscriptionModel(modelId, {
|
|
15087
15086
|
provider: `${providerName}.transcription`,
|
|
15088
|
-
url: ({ path:
|
|
15087
|
+
url: ({ path: path14 }) => `${baseURL}${path14}`,
|
|
15089
15088
|
headers: getHeaders,
|
|
15090
15089
|
fetch: options.fetch
|
|
15091
15090
|
});
|
|
15092
15091
|
const createSpeechModel = (modelId) => new OpenAISpeechModel(modelId, {
|
|
15093
15092
|
provider: `${providerName}.speech`,
|
|
15094
|
-
url: ({ path:
|
|
15093
|
+
url: ({ path: path14 }) => `${baseURL}${path14}`,
|
|
15095
15094
|
headers: getHeaders,
|
|
15096
15095
|
fetch: options.fetch
|
|
15097
15096
|
});
|
|
@@ -15112,7 +15111,7 @@ function createOpenAI(options = {}) {
|
|
|
15112
15111
|
const createResponsesModel = (modelId) => {
|
|
15113
15112
|
return new OpenAIResponsesLanguageModel(modelId, {
|
|
15114
15113
|
provider: `${providerName}.responses`,
|
|
15115
|
-
url: ({ path:
|
|
15114
|
+
url: ({ path: path14 }) => `${baseURL}${path14}`,
|
|
15116
15115
|
headers: getHeaders,
|
|
15117
15116
|
fetch: options.fetch
|
|
15118
15117
|
});
|
|
@@ -16271,7 +16270,7 @@ function computeWorkstyle(inp) {
|
|
|
16271
16270
|
|
|
16272
16271
|
// ../../lib/calibration/index.ts
|
|
16273
16272
|
var DEFAULT_CALIBRATION = {
|
|
16274
|
-
version: "2026-07-
|
|
16273
|
+
version: "2026-07-14.2",
|
|
16275
16274
|
// = RUBRIC_FINGERPRINT of the shipped npm rubric (packages/coding-analyzer/
|
|
16276
16275
|
// src/grade/criteria.ts). A unit test fails loud when the rubric changes
|
|
16277
16276
|
// without this being updated (and re-pushed to the server).
|
|
@@ -16360,7 +16359,7 @@ var DEFAULT_CALIBRATION = {
|
|
|
16360
16359
|
}
|
|
16361
16360
|
],
|
|
16362
16361
|
codingTiers: {
|
|
16363
|
-
push: { median: 300, sigma:
|
|
16362
|
+
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
16363
|
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
16364
|
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
16365
|
},
|
|
@@ -16393,12 +16392,18 @@ var DEFAULT_CALIBRATION = {
|
|
|
16393
16392
|
line: "the Claude Code lead runs 10\u201315 sessions at once; his #1 tip is 3\u20135 git worktrees in parallel"
|
|
16394
16393
|
},
|
|
16395
16394
|
throughput: {
|
|
16396
|
-
//
|
|
16397
|
-
//
|
|
16398
|
-
//
|
|
16399
|
-
//
|
|
16400
|
-
|
|
16401
|
-
|
|
16395
|
+
// Two DIFFERENT kinds of line (2026-07-14.2): topAvg is a PERCENTILE
|
|
16396
|
+
// claim — what a 1-in-1,000 user AVERAGES over substantial days (5k/day:
|
|
16397
|
+
// near-daily heavy dictation; a measured top dictating power user
|
|
16398
|
+
// averages ~3.9k). topPeak is NOT a percentile — it is the CEILING
|
|
16399
|
+
// reference, the wildest single days on record (~10k: a 14-16h
|
|
16400
|
+
// launch-day marathon), rendered as "wildest single days", never
|
|
16401
|
+
// "top X% peak". An avg-percentile and a peak-percentile can't both be
|
|
16402
|
+
// shown at a same-ish value (avg≈peak reads broken — user call), and a
|
|
16403
|
+
// peak PERCENTILE line is unknowable anyway; the record framing is
|
|
16404
|
+
// honest and keeps the visual gap.
|
|
16405
|
+
topAvgWordsPerDay: 5e3,
|
|
16406
|
+
topPeakWordsPerDay: 1e4,
|
|
16402
16407
|
benchLabel: "top 0.1%",
|
|
16403
16408
|
// No published "words typed/day" for heavy users — the real story is OUTPUT.
|
|
16404
16409
|
loopsHeadline: ">1,000,000 lines of Rust at 99.8% tests passing",
|
|
@@ -16733,7 +16738,7 @@ async function compileCodingProfile() {
|
|
|
16733
16738
|
sRow(
|
|
16734
16739
|
"How hard you push",
|
|
16735
16740
|
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
|
|
16741
|
+
`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
16742
|
),
|
|
16738
16743
|
sRow(
|
|
16739
16744
|
"How well you use AI",
|
|
@@ -16809,6 +16814,10 @@ async function readCodingAsset(name17) {
|
|
|
16809
16814
|
);
|
|
16810
16815
|
}
|
|
16811
16816
|
|
|
16817
|
+
// ../../lib/agents/coding/docsDir.ts
|
|
16818
|
+
import { promises as fs9 } from "fs";
|
|
16819
|
+
import path12 from "path";
|
|
16820
|
+
|
|
16812
16821
|
// ../../lib/agents/coding/materialize.ts
|
|
16813
16822
|
import { promises as fs8 } from "fs";
|
|
16814
16823
|
var SYSTEM_REMINDER_RE2 = /<system-reminder>[\s\S]*?<\/system-reminder>/g;
|
|
@@ -16945,6 +16954,93 @@ async function materializeSession(file2) {
|
|
|
16945
16954
|
return { text: lines.join("\n"), humanTurns, humanChars };
|
|
16946
16955
|
}
|
|
16947
16956
|
|
|
16957
|
+
// ../../lib/agents/coding/docsDir.ts
|
|
16958
|
+
async function writeScoreboard(codingDir, docs) {
|
|
16959
|
+
const gradesDir = path12.join(codingDir, "grades");
|
|
16960
|
+
let files = [];
|
|
16961
|
+
try {
|
|
16962
|
+
files = (await fs9.readdir(gradesDir)).filter((f) => f.endsWith(".json")).sort();
|
|
16963
|
+
} catch {
|
|
16964
|
+
return;
|
|
16965
|
+
}
|
|
16966
|
+
const byCriterion = /* @__PURE__ */ new Map();
|
|
16967
|
+
for (const f of files) {
|
|
16968
|
+
let g;
|
|
16969
|
+
try {
|
|
16970
|
+
g = JSON.parse(await fs9.readFile(path12.join(gradesDir, f), "utf8"));
|
|
16971
|
+
} catch {
|
|
16972
|
+
continue;
|
|
16973
|
+
}
|
|
16974
|
+
for (const c of g.criteria ?? []) {
|
|
16975
|
+
const s = c.score ?? c.bestEstimate;
|
|
16976
|
+
if (s == null) continue;
|
|
16977
|
+
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)}`;
|
|
16978
|
+
(byCriterion.get(c.key) ?? byCriterion.set(c.key, []).get(c.key)).push({ s, line });
|
|
16979
|
+
}
|
|
16980
|
+
}
|
|
16981
|
+
if (!byCriterion.size) return;
|
|
16982
|
+
const blocks = [...byCriterion.entries()].sort(([a], [b]) => a < b ? -1 : 1).map(
|
|
16983
|
+
([key, rows]) => `## ${key}
|
|
16984
|
+
${rows.sort((a, b) => b.s - a.s).map((r) => r.line).join("\n")}`
|
|
16985
|
+
);
|
|
16986
|
+
await fs9.writeFile(
|
|
16987
|
+
path12.join(docs, "_scoreboard.md"),
|
|
16988
|
+
`# Scoreboard \u2014 every graded session per criterion, best first.
|
|
16989
|
+
# Lx~ = estimate. Format: level \xB7 date \xB7 title \xB7 sessionId \u2014 graded instance.
|
|
16990
|
+
|
|
16991
|
+
${blocks.join("\n\n")}
|
|
16992
|
+
`
|
|
16993
|
+
);
|
|
16994
|
+
}
|
|
16995
|
+
async function ensureCodingDocs(codingDir, sessions) {
|
|
16996
|
+
const docs = path12.join(codingDir, "docs");
|
|
16997
|
+
await fs9.mkdir(docs, { recursive: true });
|
|
16998
|
+
const user = sessions.filter((s) => s.sessionId && !s.duplicateOf && (!("klass" in s) || s.klass === "interactive"));
|
|
16999
|
+
let written = 0;
|
|
17000
|
+
for (const s of user) {
|
|
17001
|
+
const out = path12.join(docs, `${s.sessionId}.txt`);
|
|
17002
|
+
try {
|
|
17003
|
+
await fs9.access(out);
|
|
17004
|
+
continue;
|
|
17005
|
+
} catch {
|
|
17006
|
+
}
|
|
17007
|
+
const mat = await materializeSession(s.file).catch(() => null);
|
|
17008
|
+
if (!mat?.text) continue;
|
|
17009
|
+
await fs9.writeFile(out, mat.text);
|
|
17010
|
+
written++;
|
|
17011
|
+
}
|
|
17012
|
+
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}`);
|
|
17013
|
+
await fs9.writeFile(path12.join(docs, "_map.md"), rows.join("\n") + "\n");
|
|
17014
|
+
await writeScoreboard(codingDir, docs);
|
|
17015
|
+
if (written) console.log(`[docs] materialized ${written} new transcript(s) \u2192 ${docs}`);
|
|
17016
|
+
return docs;
|
|
17017
|
+
}
|
|
17018
|
+
function sourceLookupNote() {
|
|
17019
|
+
return `
|
|
17020
|
+
|
|
17021
|
+
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.`;
|
|
17022
|
+
}
|
|
17023
|
+
|
|
17024
|
+
// ../../lib/agents/coding/promptCache.ts
|
|
17025
|
+
import { createHash as createHash2 } from "crypto";
|
|
17026
|
+
import { promises as fs10 } from "fs";
|
|
17027
|
+
function promptSha(parts) {
|
|
17028
|
+
const h = createHash2("sha256");
|
|
17029
|
+
for (const p of parts) {
|
|
17030
|
+
h.update(p ?? "");
|
|
17031
|
+
h.update("\0");
|
|
17032
|
+
}
|
|
17033
|
+
return h.digest("hex").slice(0, 16);
|
|
17034
|
+
}
|
|
17035
|
+
async function reusableOutput(outPath, sha, valid, key = "promptSha") {
|
|
17036
|
+
try {
|
|
17037
|
+
const o = JSON.parse(await fs10.readFile(outPath, "utf8"));
|
|
17038
|
+
if (o[key] === sha && valid(o)) return o;
|
|
17039
|
+
} catch {
|
|
17040
|
+
}
|
|
17041
|
+
return null;
|
|
17042
|
+
}
|
|
17043
|
+
|
|
16948
17044
|
// ../../scripts/coding-gap.mts
|
|
16949
17045
|
var CODING = CODING_DIR;
|
|
16950
17046
|
var CONFIG = {
|
|
@@ -16958,7 +17054,7 @@ var CLAUDE_AUTO_CAP = /* @__PURE__ */ new Set(["queue-ahead", "deferred-tools",
|
|
|
16958
17054
|
var CLAUDE_AUTO_MCP = /^(visualize|Claude[_ ]?Preview|ccd[_ ]?session|ccd[_ ]?session[_ ]?mgmt|mcp[_ ]?registry)$/i;
|
|
16959
17055
|
async function entrypointOf(file2) {
|
|
16960
17056
|
try {
|
|
16961
|
-
const head = (await
|
|
17057
|
+
const head = (await fs11.readFile(file2, "utf8")).slice(0, 2e4);
|
|
16962
17058
|
if (/[\/."]\.?conductor/i.test(head)) return "conductor";
|
|
16963
17059
|
const m = /"entrypoint":"([^"]+)"/.exec(head);
|
|
16964
17060
|
return m ? m[1] : "unknown";
|
|
@@ -16980,14 +17076,14 @@ var MOBILE_WEB = /^claude-(web|mobile|ios|android)$/;
|
|
|
16980
17076
|
function sumTool(recs, name17) {
|
|
16981
17077
|
return recs.reduce((a, s) => a + (s.toolCounts?.[name17] ?? 0), 0);
|
|
16982
17078
|
}
|
|
16983
|
-
var LOCK =
|
|
17079
|
+
var LOCK = path13.join(CODING, ".gap.lock");
|
|
16984
17080
|
var lockHeld = false;
|
|
16985
17081
|
async function acquireLock() {
|
|
16986
17082
|
try {
|
|
16987
|
-
await
|
|
17083
|
+
await fs11.writeFile(LOCK, String(process.pid), { flag: "wx" });
|
|
16988
17084
|
lockHeld = true;
|
|
16989
17085
|
} catch {
|
|
16990
|
-
const pid = await
|
|
17086
|
+
const pid = await fs11.readFile(LOCK, "utf8").catch(() => "?");
|
|
16991
17087
|
throw new Error(`another coding-gap run appears active (pid ${pid}, ${LOCK}). Wait for it or delete the lock if it's stale \u2014 concurrent runs overwrite each other's gap.json.`);
|
|
16992
17088
|
}
|
|
16993
17089
|
}
|
|
@@ -16996,9 +17092,9 @@ async function main() {
|
|
|
16996
17092
|
const p = await compileCodingProfile();
|
|
16997
17093
|
const techniquesAsset = await readCodingAsset("TECHNIQUES.md");
|
|
16998
17094
|
const techniques = techniquesAsset.text;
|
|
16999
|
-
console.log(` rubric: ${techniquesAsset.path} (${(await
|
|
17095
|
+
console.log(` rubric: ${techniquesAsset.path} (${(await fs11.stat(techniquesAsset.path)).mtime.toISOString()})`);
|
|
17000
17096
|
const writing = (await readCodingAsset("WRITING.md")).text;
|
|
17001
|
-
const all = JSON.parse(await
|
|
17097
|
+
const all = JSON.parse(await fs11.readFile(path13.join(CODING, "sessions.json"), "utf8"));
|
|
17002
17098
|
const interactive = all.filter((s) => s.klass === "interactive" && s.start);
|
|
17003
17099
|
const latestMs = Math.max(...interactive.map((s) => Date.parse(s.start)));
|
|
17004
17100
|
const cutoffMs = latestMs - 14 * 864e5;
|
|
@@ -17055,7 +17151,7 @@ async function main() {
|
|
|
17055
17151
|
return m ? `--- "${s.title}" \xB7 ${(s.start || "").slice(0, 10)} ---
|
|
17056
17152
|
${m.text.slice(0, 3e3)}` : "";
|
|
17057
17153
|
}))).filter(Boolean);
|
|
17058
|
-
const SYS = "You are a Claude Code power-user coach. You judge ONE person against the COMPLETE catalog of best ways to use Claude Code (the rubric below, sourced from Boris Cherny + first-party Claude Code features) and write a comprehensive, honest gap analysis, ORDERED most-difference-making \u2192 least. Rules: (1) Go through the whole catalog and surface the techniques they are NOT doing (or under-using) that would genuinely help \u2014 respecting each tip's [EMPHASIZE]/[DE-EMPHASIZE]/[GATE] curation. (2) ORDER by differenceRank (1 = biggest unlock for THIS person). Follow the rubric's PRIME DIRECTIVE: if usage.parallelism.alreadyParallel is FALSE \u2192 'Do more in parallel' is rank 1; else \u2192 'Invest in your CLAUDE.md / tune your context' is rank 1. Then Plan mode, then 'Give Claude test cases so it can auto-verify and run longer' (Boris's 'most important thing' \u2014 rank it high, right after plan mode), then subagents, and the rest per the rubric order, skipping any that don't apply. (3) GATE the conditional tips on the STRUCTURAL usage facts, NOT on keywords \u2014 and a tip whose gate FAILS is OMITTED from recommendations entirely, never included as a softened/conditional card (recommending something their data says doesn't apply, or that they already do, reads as not having looked): loops require real PR/branch volume in usage.collaboration, else OMIT; the Chrome tip requires ~zero browser-driving in usage.chrome, else OMIT and credit in alreadyStrong; forking uses the RECENT count in usage.forking \u2014 if they fork in the recent window they already do it, OMIT and credit; remote/mobile/EC2 fires only when usage.surface.workstationBound is TRUE; plan mode by usage.planMode; subagents by usage.subagents. If they already do a thing, it goes in alreadyStrong, NOT in recommendations. (4) \u26D4 CRITICAL \u2014 this person BUILDS Claude Code tooling, so their transcripts are full of the words 'worktree', 'pull request', 'fork', 'plan mode', 'by the way', 'teleport'. A keyword in the transcript is NOT evidence they use the feature. Rely on the STRUCTURAL facts only. (5) Ground every recommendation in a RECEIPT \u2014 a structural fact from their usage or a concrete session pain point \u2014 and CONVINCE with a specific case for how it helps THIS person, not a generic benefit. (6) Tailor every action to the Claude Desktop Mac app; NEVER give terminal-only `claude -p` advice. (7) Honor config.deliberateChoices (they stay on `main` on purpose \u2014 do NOT tell them to hand-juggle worktrees; parallel SESSIONS instead) and config.claudeAutoTools (never tell them to 'use' a tool Claude drives itself; for 'explain with visuals' the user just ASKS for a visual \u2014 do not name the tool). (8) Also name what they ALREADY do well. (9) SELF-CONTAINED but not verbose \u2014 lead with the PROBLEM, then the SOLUTION, then HOW to use it in their context. Plain language, no jargon, no enumerating multiple dates. An essay-like rec is a failed rec; so is a cryptic one. Follow this writing rubric strictly:\n\n" + writing;
|
|
17154
|
+
const SYS = "You are a Claude Code power-user coach. You judge ONE person against the COMPLETE catalog of best ways to use Claude Code (the rubric below, sourced from Boris Cherny + first-party Claude Code features) and write a comprehensive, honest gap analysis, ORDERED most-difference-making \u2192 least. Rules: (1) Go through the whole catalog and surface the techniques they are NOT doing (or under-using) that would genuinely help \u2014 respecting each tip's [EMPHASIZE]/[DE-EMPHASIZE]/[GATE] curation. (2) ORDER by differenceRank (1 = biggest unlock for THIS person). Follow the rubric's PRIME DIRECTIVE: if usage.parallelism.alreadyParallel is FALSE \u2192 'Do more in parallel' is rank 1; else \u2192 'Invest in your CLAUDE.md / tune your context' is rank 1. Then Plan mode, then 'Give Claude test cases so it can auto-verify and run longer' (Boris's 'most important thing' \u2014 rank it high, right after plan mode), then subagents, and the rest per the rubric order, skipping any that don't apply. (3) GATE the conditional tips on the STRUCTURAL usage facts, NOT on keywords \u2014 and a tip whose gate FAILS is OMITTED from recommendations entirely, never included as a softened/conditional card (recommending something their data says doesn't apply, or that they already do, reads as not having looked): loops require real PR/branch volume in usage.collaboration, else OMIT; the Chrome tip requires ~zero browser-driving in usage.chrome, else OMIT and credit in alreadyStrong; forking uses the RECENT count in usage.forking \u2014 if they fork in the recent window they already do it, OMIT and credit; remote/mobile/EC2 fires only when usage.surface.workstationBound is TRUE; plan mode by usage.planMode; subagents by usage.subagents. If they already do a thing, it goes in alreadyStrong, NOT in recommendations. (4) \u26D4 CRITICAL \u2014 this person BUILDS Claude Code tooling, so their transcripts are full of the words 'worktree', 'pull request', 'fork', 'plan mode', 'by the way', 'teleport'. A keyword in the transcript is NOT evidence they use the feature. Rely on the STRUCTURAL facts only. (5) Ground every recommendation in a RECEIPT \u2014 a structural fact from their usage or a concrete session pain point \u2014 and CONVINCE with a specific case for how it helps THIS person, not a generic benefit. (6) Tailor every action to the Claude Desktop Mac app; NEVER give terminal-only `claude -p` advice. (7) Honor config.deliberateChoices (they stay on `main` on purpose \u2014 do NOT tell them to hand-juggle worktrees; parallel SESSIONS instead) and config.claudeAutoTools (never tell them to 'use' a tool Claude drives itself; for 'explain with visuals' the user just ASKS for a visual \u2014 do not name the tool). (8) Also name what they ALREADY do well. (9) SELF-CONTAINED but not verbose \u2014 lead with the PROBLEM, then the SOLUTION, then HOW to use it in their context. Plain language, no jargon, no enumerating multiple dates. An essay-like rec is a failed rec; so is a cryptic one. Follow this writing rubric strictly:\n\n" + writing + sourceLookupNote();
|
|
17059
17155
|
const prompt = `THE RUBRIC \u2014 the complete catalog of best ways to use Claude Code. Judge the person against ALL of it, and ORDER by differenceRank per its PRIME DIRECTIVE:
|
|
17060
17156
|
|
|
17061
17157
|
${techniques}
|
|
@@ -17076,18 +17172,23 @@ Produce the gap analysis. Be thorough: cover every relevant catalog item they're
|
|
|
17076
17172
|
}
|
|
17077
17173
|
\`\`\`
|
|
17078
17174
|
\`differenceRank\` is a strict 1..N ordering (1 = highest). Assign it per the PRIME DIRECTIVE and the rubric's general order; the report renders recommendations sorted by it. \`payoff\` (1-5) is a secondary strength cue. Recommend ONLY from the catalog.`;
|
|
17079
|
-
|
|
17175
|
+
const sha = promptSha([SYS, prompt, "sonnet"]);
|
|
17176
|
+
if (!process.argv.includes("--refresh")) {
|
|
17177
|
+
const prev = await reusableOutput(path13.join(CODING, "gap.json"), sha, (o) => Array.isArray(o.recommendations) && o.recommendations.length > 0);
|
|
17178
|
+
if (prev) {
|
|
17179
|
+
console.log(`[gap] inputs unchanged \u2014 reusing output from ${prev.generatedAt} (--refresh to regenerate)`);
|
|
17180
|
+
return;
|
|
17181
|
+
}
|
|
17182
|
+
}
|
|
17183
|
+
await ensureCodingDocs(CODING, all);
|
|
17184
|
+
console.log("gap \u2014 1 Sonnet pass over the full TECHNIQUES.md catalog + structural usage (+source lookups)");
|
|
17080
17185
|
console.log(` signals: alreadyParallel=${alreadyParallel} planModeCalls=${planModeUses} forks=${forkCopies}/${all.length} featureBranches=${featureBranches.length} workstationBound=${workstationBound} chrome=${chromeToolUse}`);
|
|
17081
|
-
const sandbox = await fs9.mkdtemp(path12.join(os2.tmpdir(), "gap-"));
|
|
17082
17186
|
let out = { recommendations: [], alreadyStrong: [] };
|
|
17083
17187
|
try {
|
|
17084
|
-
const run2 = await invokeAgent({ prompt, systemPrompt: SYS, addDir:
|
|
17188
|
+
const run2 = await invokeAgent({ prompt, systemPrompt: SYS, addDir: CODING, allowedTools: ["Read", "Grep", "Glob"], maxTurns: 10, timeoutMs: 6e5, model: "sonnet" });
|
|
17085
17189
|
out = run2.json || out;
|
|
17086
17190
|
} catch (e) {
|
|
17087
17191
|
console.log("ERR", e.message.slice(0, 160));
|
|
17088
|
-
} finally {
|
|
17089
|
-
await fs9.rm(sandbox, { recursive: true, force: true }).catch(() => {
|
|
17090
|
-
});
|
|
17091
17192
|
}
|
|
17092
17193
|
if (Array.isArray(out.recommendations)) {
|
|
17093
17194
|
out.recommendations = out.recommendations.map((r, i) => ({ r, i })).sort((a, b) => (a.r.differenceRank ?? 99) - (b.r.differenceRank ?? 99) || (b.r.payoff ?? 0) - (a.r.payoff ?? 0) || a.i - b.i).map((x) => x.r);
|
|
@@ -17095,14 +17196,14 @@ Produce the gap analysis. Be thorough: cover every relevant catalog item they're
|
|
|
17095
17196
|
if (!Array.isArray(out.recommendations) || out.recommendations.length === 0) {
|
|
17096
17197
|
throw new Error("gap run produced 0 recommendations \u2014 refusing to overwrite the existing gap.json. Re-run the builder.");
|
|
17097
17198
|
}
|
|
17098
|
-
const result = { generatedAt: (/* @__PURE__ */ new Date()).toISOString(), ...out };
|
|
17099
|
-
await
|
|
17199
|
+
const result = { generatedAt: (/* @__PURE__ */ new Date()).toISOString(), promptSha: sha, ...out };
|
|
17200
|
+
await fs11.writeFile(path13.join(CODING, "gap.json"), JSON.stringify(result, null, 2));
|
|
17100
17201
|
console.log(`WROTE ${CODING}/gap.json \u2014 recommendations:${(out.recommendations || []).length} \xB7 alreadyStrong:${(out.alreadyStrong || []).length}`);
|
|
17101
17202
|
}
|
|
17102
17203
|
main().catch((e) => {
|
|
17103
17204
|
console.error(e);
|
|
17104
17205
|
process.exitCode = 1;
|
|
17105
17206
|
}).finally(() => {
|
|
17106
|
-
if (lockHeld)
|
|
17207
|
+
if (lockHeld) fs11.rm(LOCK, { force: true }).catch(() => {
|
|
17107
17208
|
});
|
|
17108
17209
|
});
|
|
@@ -15637,6 +15637,9 @@ function invokeAgent(inv, opts = {}) {
|
|
|
15637
15637
|
return withLimitRetry(once, { label });
|
|
15638
15638
|
}
|
|
15639
15639
|
|
|
15640
|
+
// ../../lib/agents/coding/grade-calibration.ts
|
|
15641
|
+
var GRADE_CALIBRATION = "\n\nSCORE CALIBRATION \u2014 graders systematically COMPRESS to the middle: real peaks get hedged down to 6-7, and routine sessions get polite 5-6s instead of null. Both are failures; fight them explicitly. Work each criterion in EXACTLY this order:\nSTEP 1 \xB7 EVIDENCE GATE \u2014 find the 1-3 verbatim '>> ' quotes that bear on the criterion. INCLUDE a criterion whenever genuine evidence is present (do not MISS quiet evidence \u2014 check every thread of the session, not just the dominant one). But with NO quotable moment the score is null, full stop: a session can be long, competent, and productive while being null on most criteria. Routine hand-holding earns null, never a 5 \u2014 and null is never a deduction.\nSTEP 2 \xB7 LADDER MATCH \u2014 with quotes in hand, read the criterion's rungs and pick the ONE rung whose marker best describes the quoted moment; name that rung in 'why'. AWARD THE RUNG THE EVIDENCE MATCHES: if your own 'why' describes rung N's criteria, give rung N \u2014 never deny it for lacking the NEXT rung's criteria.\nSTEP 3 \xB7 THE SINGLE BEST MOMENT IS THE SCORE \u2014 set the score by the strongest quoted moment, as if it were the whole session. NEVER average a peak down because the surrounding session is routine (the high-water rule), and never raise a score for volume, effort, or topic prestige without a matching moment.\nSTEP 4 \xB7 ANTI-HEDGE \u2014 if the moment genuinely matches an L8-10 anchor (an override the AI conceded, a shipped-and-verified capability, an 'oh shit, they're right' call, a first-principles redefinition that held), the score IS 8-10. Hedging a real L9 to a 7 is exactly as wrong as inventing a 6 for nothing. The middle is NOT a safe default: commit high on anchor-matching evidence, or go null.\nSTEP 5 \xB7 'CONSERVATIVE' \u2260 SUBTRACT \u2014 when a criterion's ladder says to grade conservatively, that means DO NOT EXCEED the rung whose marker the evidence matches; it NEVER means subtracting rungs from matched evidence. Evidence that matches a rung's marker gets that rung under a conservative reading too.";
|
|
15642
|
+
|
|
15640
15643
|
// ../../lib/agents/shared/chunk.ts
|
|
15641
15644
|
function chunkText(text2, max) {
|
|
15642
15645
|
if (text2.length <= max) return [text2];
|
|
@@ -15985,14 +15988,28 @@ function rubric() {
|
|
|
15985
15988
|
${(c.rungs ?? []).map((r) => ` ${r.level} \u2014 ${r.marker}`).join("\n")}`
|
|
15986
15989
|
).join("\n\n");
|
|
15987
15990
|
}
|
|
15991
|
+
function rubricCompact() {
|
|
15992
|
+
return GRADED_CRITERIA.map((c) => {
|
|
15993
|
+
const anchors = /ANCHORS?:/.exec(c.read) ? c.read.slice(c.read.search(/ANCHORS?:/)) : "";
|
|
15994
|
+
return `CRITERION "${c.key}" \u2014 ${c.label} [score 1\u201311, or null if not shown]
|
|
15995
|
+
${c.definition}
|
|
15996
|
+
${anchors ? ` ${anchors}
|
|
15997
|
+
` : ""} LADDER:
|
|
15998
|
+
${(c.rungs ?? []).map((r) => ` ${r.level} \u2014 ${r.marker}`).join("\n")}`;
|
|
15999
|
+
}).join("\n\n");
|
|
16000
|
+
}
|
|
16001
|
+
var HAIKU_SCORE_MAP_ID = "haiku+1@2026-07-14";
|
|
16002
|
+
var mapSmallScore = (v) => v != null && v >= 4 ? Math.min(10, v + 1) : v;
|
|
16003
|
+
var HAIKU_CALIBRATION = "\n\nWork each criterion in TWO STEPS, in order:\nSTEP A \u2014 QUOTE the 1-3 strongest verbatim '>> ' lines bearing on the criterion, checking every thread of the session, not just the dominant one. No quotable moment = null (routine hand-holding is null, never a 5; null is never a deduction).\nSTEP B \u2014 score by the SINGLE BEST quoted moment as if it were the whole session: pick the rung whose marker it matches and AWARD THAT RUNG \u2014 never deny rung N for lacking rung N+1, never average a peak down because the rest is routine, never raise for volume or topic prestige. Evidence matching an L8-10 anchor scores 8-10; the middle is not a safe default. Include every criterion genuinely present (don't MISS quiet evidence) \u2014 but rate strength strictly: weak-but-present is low, not mid.";
|
|
15988
16004
|
var SYSTEM = "You grade how a person WORKS from one of their coding-agent sessions (Claude Code). You read mostly THEIR words; the model's code and output are compressed to context and you ignore the mechanical scaffolding. You never flatter: most sessions are routine hand-holding and should score low or null on most criteria. A score is a placement on the ladder backed by VERBATIM quotes of the user's own lines \u2014 never a vibe.\n\nSTANDING RULES (apply to every criterion):\n1. ABSENCE IS NEVER A DEDUCTION. If a criterion had no chance to show, its score is null \u2014 NOT a low. Don't invent a number for routine work.\n2. HIGH-WATER MARK. Taste and abstraction are PEAK measures \u2014 one genuinely brilliant move in a session counts, even surrounded by routine work. Never grade the person at their worst; a lone weak moment among strong ones is a slip, not the score.\n3. LOW-EFFORT-UNTIL-NEEDED IS THE IDEAL. A terse or vague prompt on routine work is correct economy \u2014 never penalize a vague ask, never reward word-count.\n4. DISCOUNT THE LITERAL HARSHNESS OF SELF-TALK. 'you idiot', 'you stupid cunt never again', 'this is retarded' \u2014 aimed at self or AI \u2014 are DRIVE and high standards, not defects. Grade the demonstrated behavior.\n5. PER-CONVERSATION CEILING IS 10. Never output 11 \u2014 that is the aggregator's job (it needs cross-conversation consistency / a stacked day this single session can't show). Scores run 2\u201310.\n6. LOG THE SPIKES IN HIGH DETAIL. When a moment is genuinely good (a flare \u2014 a sharp taste call, an out-reasons-the-tool insight, a real systems override), name it CONCRETELY and quote it. The 'instance' + 'why' are the high-detail record of exactly what was cool and why it placed where it did.";
|
|
15989
|
-
function gradeSystemPrompt() {
|
|
15990
|
-
|
|
16005
|
+
function gradeSystemPrompt(model) {
|
|
16006
|
+
const small = /haiku/i.test(model ?? "");
|
|
16007
|
+
return `${SYSTEM}${small ? HAIKU_CALIBRATION : GRADE_CALIBRATION}
|
|
15991
16008
|
|
|
15992
16009
|
Grade ONE coding session (provided in the user message) along the criteria below. ">> " lines are the USER's own words (the signal). ALL bracketed lines are machine context, never the user: "[AI: \u2026]" is the model working, "[bg task: \u2026]" / "[cmd output: \u2026]" are harness notifications, "[mode \u2192 \u2026]" marks a mode switch (context only \u2014 do not grade or quote them). ">> (queued \u2026)" is the user queuing work while the AI runs.
|
|
15993
16010
|
|
|
15994
16011
|
CRITERIA:
|
|
15995
|
-
${rubric()}
|
|
16012
|
+
${small ? rubricCompact() : rubric()}
|
|
15996
16013
|
|
|
15997
16014
|
RULES:
|
|
15998
16015
|
- Score ONLY what the user's moves genuinely show. Null is the right answer for most criteria in most sessions \u2014 do not force a number. Absence is never a deduction.
|
|
@@ -16058,7 +16075,7 @@ async function gradeSession(rec, opts = { outDir: "" }) {
|
|
|
16058
16075
|
const seg = chunks.length > 1 ? ` This is SEGMENT ${ci + 1} of ${chunks.length} of one longer session \u2014 grade only what THIS segment shows; null for criteria not shown here (segments are merged afterward).` : "";
|
|
16059
16076
|
const run2 = await invokeAgent({
|
|
16060
16077
|
prompt: buildPrompt(rec, chunks[ci], seg),
|
|
16061
|
-
systemPrompt: gradeSystemPrompt(),
|
|
16078
|
+
systemPrompt: gradeSystemPrompt(opts.model),
|
|
16062
16079
|
addDir: sandbox,
|
|
16063
16080
|
allowedTools: ["Read"],
|
|
16064
16081
|
maxTurns: 6,
|
|
@@ -16074,6 +16091,13 @@ async function gradeSession(rec, opts = { outDir: "" }) {
|
|
|
16074
16091
|
if (perChunk.length === 0) return null;
|
|
16075
16092
|
const criteria = perChunk.length > 1 ? peakMergeByKey(perChunk, "key", "quotes") : perChunk[0];
|
|
16076
16093
|
if (criteria.length === 0) return null;
|
|
16094
|
+
const small = /haiku/i.test(opts.model ?? "");
|
|
16095
|
+
if (small) for (const c of criteria) {
|
|
16096
|
+
c.score = mapSmallScore(c.score);
|
|
16097
|
+
c.low = mapSmallScore(c.low);
|
|
16098
|
+
c.high = mapSmallScore(c.high);
|
|
16099
|
+
c.bestEstimate = mapSmallScore(c.bestEstimate);
|
|
16100
|
+
}
|
|
16077
16101
|
const grade = {
|
|
16078
16102
|
sessionId: rec.sessionId,
|
|
16079
16103
|
title: rec.title,
|
|
@@ -16082,7 +16106,7 @@ async function gradeSession(rec, opts = { outDir: "" }) {
|
|
|
16082
16106
|
gradedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
16083
16107
|
rubricVersion: RUBRIC_FINGERPRINT,
|
|
16084
16108
|
criteria,
|
|
16085
|
-
meta: { costUsd, durationMs, calls: chunks.length }
|
|
16109
|
+
meta: { costUsd, durationMs, calls: chunks.length, ...small ? { scoreMap: HAIKU_SCORE_MAP_ID } : {} }
|
|
16086
16110
|
};
|
|
16087
16111
|
await fs5.mkdir(opts.outDir, { recursive: true });
|
|
16088
16112
|
await fs5.writeFile(path9.join(opts.outDir, `${rec.sessionId}.json`), JSON.stringify(grade, null, 2));
|
|
@@ -16128,7 +16152,7 @@ var TRANSCRIPT_LINE_RE = new RegExp(`^\\s*(${NOTE})((,| and) ${NOTE})*\\s*$|^\\s
|
|
|
16128
16152
|
|
|
16129
16153
|
// ../../lib/calibration/index.ts
|
|
16130
16154
|
var DEFAULT_CALIBRATION = {
|
|
16131
|
-
version: "2026-07-
|
|
16155
|
+
version: "2026-07-14.2",
|
|
16132
16156
|
// = RUBRIC_FINGERPRINT of the shipped npm rubric (packages/coding-analyzer/
|
|
16133
16157
|
// src/grade/criteria.ts). A unit test fails loud when the rubric changes
|
|
16134
16158
|
// without this being updated (and re-pushed to the server).
|
|
@@ -16217,7 +16241,7 @@ var DEFAULT_CALIBRATION = {
|
|
|
16217
16241
|
}
|
|
16218
16242
|
],
|
|
16219
16243
|
codingTiers: {
|
|
16220
|
-
push: { median: 300, sigma:
|
|
16244
|
+
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." },
|
|
16221
16245
|
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." },
|
|
16222
16246
|
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" }
|
|
16223
16247
|
},
|
|
@@ -16250,12 +16274,18 @@ var DEFAULT_CALIBRATION = {
|
|
|
16250
16274
|
line: "the Claude Code lead runs 10\u201315 sessions at once; his #1 tip is 3\u20135 git worktrees in parallel"
|
|
16251
16275
|
},
|
|
16252
16276
|
throughput: {
|
|
16253
|
-
//
|
|
16254
|
-
//
|
|
16255
|
-
//
|
|
16256
|
-
//
|
|
16257
|
-
|
|
16258
|
-
|
|
16277
|
+
// Two DIFFERENT kinds of line (2026-07-14.2): topAvg is a PERCENTILE
|
|
16278
|
+
// claim — what a 1-in-1,000 user AVERAGES over substantial days (5k/day:
|
|
16279
|
+
// near-daily heavy dictation; a measured top dictating power user
|
|
16280
|
+
// averages ~3.9k). topPeak is NOT a percentile — it is the CEILING
|
|
16281
|
+
// reference, the wildest single days on record (~10k: a 14-16h
|
|
16282
|
+
// launch-day marathon), rendered as "wildest single days", never
|
|
16283
|
+
// "top X% peak". An avg-percentile and a peak-percentile can't both be
|
|
16284
|
+
// shown at a same-ish value (avg≈peak reads broken — user call), and a
|
|
16285
|
+
// peak PERCENTILE line is unknowable anyway; the record framing is
|
|
16286
|
+
// honest and keeps the visual gap.
|
|
16287
|
+
topAvgWordsPerDay: 5e3,
|
|
16288
|
+
topPeakWordsPerDay: 1e4,
|
|
16259
16289
|
benchLabel: "top 0.1%",
|
|
16260
16290
|
// No published "words typed/day" for heavy users — the real story is OUTPUT.
|
|
16261
16291
|
loopsHeadline: ">1,000,000 lines of Rust at 99.8% tests passing",
|
|
@@ -16305,7 +16335,7 @@ var GRADES2 = path11.join(CODING, "grades");
|
|
|
16305
16335
|
var LOGS = path11.join(GRADES2, "logs");
|
|
16306
16336
|
async function main() {
|
|
16307
16337
|
const sessions = JSON.parse(await fs6.readFile(path11.join(CODING, "sessions.json"), "utf8"));
|
|
16308
|
-
const { gradable, thin, trivial } = partition(sessions.filter((s) => !s.duplicateOf));
|
|
16338
|
+
const { gradable, thin, trivial } = partition(sessions.filter((s) => s.klass === "interactive" && !s.duplicateOf));
|
|
16309
16339
|
const ranked = gradable.slice().sort((a, b) => b.humanChars * Math.log1p(b.humanTurns) - a.humanChars * Math.log1p(a.humanTurns));
|
|
16310
16340
|
console.log(`[coding-grade] ${sessions.length} sessions \u2192 ${gradable.length} gradable \xB7 ${thin.length} thin \xB7 ${trivial.length} trivial (skipped)`);
|
|
16311
16341
|
await fs6.mkdir(LOGS, { recursive: true });
|
|
@@ -15608,6 +15608,17 @@ function invokeAgent(inv, opts = {}) {
|
|
|
15608
15608
|
return withLimitRetry(once, { label });
|
|
15609
15609
|
}
|
|
15610
15610
|
|
|
15611
|
+
// ../../lib/agents/coding/promptCache.ts
|
|
15612
|
+
import { createHash } from "crypto";
|
|
15613
|
+
function promptSha(parts) {
|
|
15614
|
+
const h = createHash("sha256");
|
|
15615
|
+
for (const p of parts) {
|
|
15616
|
+
h.update(p ?? "");
|
|
15617
|
+
h.update("\0");
|
|
15618
|
+
}
|
|
15619
|
+
return h.digest("hex").slice(0, 16);
|
|
15620
|
+
}
|
|
15621
|
+
|
|
15611
15622
|
// ../../lib/agents/engine/self-image-ref.ts
|
|
15612
15623
|
import { promises as fs4 } from "fs";
|
|
15613
15624
|
|
|
@@ -15659,9 +15670,9 @@ ${parts.join("\n\n")}`;
|
|
|
15659
15670
|
import path11 from "path";
|
|
15660
15671
|
|
|
15661
15672
|
// ../../lib/calibration/fingerprint.ts
|
|
15662
|
-
import { createHash } from "node:crypto";
|
|
15673
|
+
import { createHash as createHash2 } from "node:crypto";
|
|
15663
15674
|
function rubricFingerprint(criteria) {
|
|
15664
|
-
return
|
|
15675
|
+
return createHash2("sha256").update(JSON.stringify(criteria)).digest("hex").slice(0, 10);
|
|
15665
15676
|
}
|
|
15666
15677
|
|
|
15667
15678
|
// ../../lib/agents/coding/criteria.ts
|
|
@@ -15810,7 +15821,7 @@ var TRANSCRIPT_LINE_RE = new RegExp(`^\\s*(${NOTE})((,| and) ${NOTE})*\\s*$|^\\s
|
|
|
15810
15821
|
|
|
15811
15822
|
// ../../lib/calibration/index.ts
|
|
15812
15823
|
var DEFAULT_CALIBRATION = {
|
|
15813
|
-
version: "2026-07-
|
|
15824
|
+
version: "2026-07-14.2",
|
|
15814
15825
|
// = RUBRIC_FINGERPRINT of the shipped npm rubric (packages/coding-analyzer/
|
|
15815
15826
|
// src/grade/criteria.ts). A unit test fails loud when the rubric changes
|
|
15816
15827
|
// without this being updated (and re-pushed to the server).
|
|
@@ -15899,7 +15910,7 @@ var DEFAULT_CALIBRATION = {
|
|
|
15899
15910
|
}
|
|
15900
15911
|
],
|
|
15901
15912
|
codingTiers: {
|
|
15902
|
-
push: { median: 300, sigma:
|
|
15913
|
+
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." },
|
|
15903
15914
|
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." },
|
|
15904
15915
|
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" }
|
|
15905
15916
|
},
|
|
@@ -15932,12 +15943,18 @@ var DEFAULT_CALIBRATION = {
|
|
|
15932
15943
|
line: "the Claude Code lead runs 10\u201315 sessions at once; his #1 tip is 3\u20135 git worktrees in parallel"
|
|
15933
15944
|
},
|
|
15934
15945
|
throughput: {
|
|
15935
|
-
//
|
|
15936
|
-
//
|
|
15937
|
-
//
|
|
15938
|
-
//
|
|
15939
|
-
|
|
15940
|
-
|
|
15946
|
+
// Two DIFFERENT kinds of line (2026-07-14.2): topAvg is a PERCENTILE
|
|
15947
|
+
// claim — what a 1-in-1,000 user AVERAGES over substantial days (5k/day:
|
|
15948
|
+
// near-daily heavy dictation; a measured top dictating power user
|
|
15949
|
+
// averages ~3.9k). topPeak is NOT a percentile — it is the CEILING
|
|
15950
|
+
// reference, the wildest single days on record (~10k: a 14-16h
|
|
15951
|
+
// launch-day marathon), rendered as "wildest single days", never
|
|
15952
|
+
// "top X% peak". An avg-percentile and a peak-percentile can't both be
|
|
15953
|
+
// shown at a same-ish value (avg≈peak reads broken — user call), and a
|
|
15954
|
+
// peak PERCENTILE line is unknowable anyway; the record framing is
|
|
15955
|
+
// honest and keeps the visual gap.
|
|
15956
|
+
topAvgWordsPerDay: 5e3,
|
|
15957
|
+
topPeakWordsPerDay: 1e4,
|
|
15941
15958
|
benchLabel: "top 0.1%",
|
|
15942
15959
|
// No published "words typed/day" for heavy users — the real story is OUTPUT.
|
|
15943
15960
|
loopsHeadline: ">1,000,000 lines of Rust at 99.8% tests passing",
|
|
@@ -15996,10 +16013,20 @@ async function main() {
|
|
|
15996
16013
|
`Self-sufficiency: across ${del.sessions || "?"} sessions, ${del.pctCorrect}% of delegation moments ideal, ${del.doomLoops || 0} doom-loops (got stuck and needed rescue ${del.doomLoops || 0} times)`
|
|
15997
16014
|
].join("\n");
|
|
15998
16015
|
const siRef = selfImageReference(await loadSelfImage());
|
|
16016
|
+
const promptStr = prompt(days, metrics, siRef);
|
|
16017
|
+
const sha = promptSha([SYS, promptStr, "sonnet"]);
|
|
16018
|
+
if (!process.argv.includes("--refresh")) {
|
|
16019
|
+
const cur = await readJson("aggregate.json", null);
|
|
16020
|
+
if (cur?.bigPicture && cur.bigPictureSha === sha) {
|
|
16021
|
+
console.log(`[nutshell] inputs unchanged \u2014 reusing bigPicture (--refresh to regenerate)`);
|
|
16022
|
+
console.log("\nbigPicture:\n" + cur.bigPicture);
|
|
16023
|
+
return;
|
|
16024
|
+
}
|
|
16025
|
+
}
|
|
15999
16026
|
const sandbox = await fs5.mkdtemp(path12.join(os2.tmpdir(), "nut-"));
|
|
16000
16027
|
let bigPicture = "";
|
|
16001
16028
|
try {
|
|
16002
|
-
const run2 = await invokeAgent({ prompt:
|
|
16029
|
+
const run2 = await invokeAgent({ prompt: promptStr, systemPrompt: SYS, addDir: sandbox, allowedTools: ["Read"], maxTurns: 3, timeoutMs: 24e4, model: "sonnet" });
|
|
16003
16030
|
bigPicture = String(run2.json?.bigPicture || "").trim();
|
|
16004
16031
|
} catch (e) {
|
|
16005
16032
|
console.log("ERR", e.message.slice(0, 120));
|
|
@@ -16017,6 +16044,7 @@ async function main() {
|
|
|
16017
16044
|
process.exit(1);
|
|
16018
16045
|
}
|
|
16019
16046
|
fresh.bigPicture = bigPicture;
|
|
16047
|
+
fresh.bigPictureSha = sha;
|
|
16020
16048
|
await fs5.writeFile(path12.join(CODING, "aggregate.json"), JSON.stringify(fresh, null, 2));
|
|
16021
16049
|
console.log(`WROTE ${CODING}/aggregate.json bigPicture (${bigPicture.length} chars)`);
|
|
16022
16050
|
console.log("\nbigPicture:\n" + bigPicture);
|