polymath-society 0.2.20 → 0.2.22

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.
Files changed (38) hide show
  1. package/dist/cli.js +23943 -21630
  2. package/dist/engine/chat-loops.js +8 -1
  3. package/dist/engine/exp-allfacets.js +8 -1
  4. package/dist/engine/exp-person.js +8 -1
  5. package/dist/engine/exp-pipeline.js +8 -1
  6. package/dist/engine/ingest-export.js +7 -6
  7. package/dist/engine/peak-demos.js +8 -1
  8. package/dist/engine/person-dimension-summary.js +8 -1
  9. package/dist/engine/person-facet-lines.js +8 -1
  10. package/dist/engine/person-headline.js +8 -1
  11. package/dist/engine/person-report.js +8 -1
  12. package/dist/engine/person-self-image.js +8 -1
  13. package/dist/engine/public-report.js +15 -7
  14. package/dist/engine/run-analysis.js +8 -1
  15. package/dist/engine/run-tagger.js +8 -1
  16. package/dist/index.js +19647 -17969
  17. package/dist/pipeline/coding-agglomerate.js +826 -82
  18. package/dist/pipeline/coding-aggregate.js +307 -23
  19. package/dist/pipeline/coding-build.js +453 -95
  20. package/dist/pipeline/coding-coaching.js +479 -88
  21. package/dist/pipeline/coding-day-digest.js +308 -36
  22. package/dist/pipeline/coding-delegation.js +376 -52
  23. package/dist/pipeline/coding-expertise.js +356 -62
  24. package/dist/pipeline/coding-flow.js +288 -15
  25. package/dist/pipeline/coding-focus.js +371 -51
  26. package/dist/pipeline/coding-frontier-detail.js +344 -50
  27. package/dist/pipeline/coding-frontier.js +7 -6
  28. package/dist/pipeline/coding-gap-dist.js +288 -15
  29. package/dist/pipeline/coding-gap.js +507 -115
  30. package/dist/pipeline/coding-grade.js +342 -45
  31. package/dist/pipeline/coding-growth.js +17041 -0
  32. package/dist/pipeline/coding-nutshell.js +15 -7
  33. package/dist/pipeline/coding-projects.js +7 -6
  34. package/dist/pipeline/coding-walkthrough.js +317 -37
  35. package/dist/pipeline/coding-workbrief.js +16387 -0
  36. package/dist/web/app.js +2095 -1395
  37. package/dist/web/styles.css +1 -1
  38. package/package.json +1 -1
@@ -134,8 +134,55 @@ var require_secure_json_parse = __commonJS({
134
134
  });
135
135
 
136
136
  // ../../scripts/coding-gap.mts
137
- import { promises as fs11 } from "fs";
138
- import path13 from "path";
137
+ import { promises as fs13 } from "fs";
138
+ import path14 from "path";
139
+
140
+ // ../../lib/agents/coding/stageLock.ts
141
+ import { promises as fs } from "fs";
142
+ var STALE_UNKNOWN_MS = 12 * 60 * 60 * 1e3;
143
+ function pidAlive(pid) {
144
+ try {
145
+ process.kill(pid, 0);
146
+ return true;
147
+ } catch (e) {
148
+ return e.code === "EPERM";
149
+ }
150
+ }
151
+ async function acquireStageLock(lockPath, stage) {
152
+ const mine = String(process.pid);
153
+ for (let attempt = 0; attempt < 2; attempt++) {
154
+ try {
155
+ await fs.writeFile(lockPath, mine, { flag: "wx" });
156
+ return async () => {
157
+ const held = await fs.readFile(lockPath, "utf8").catch(() => null);
158
+ if (held === mine) await fs.unlink(lockPath).catch(() => {
159
+ });
160
+ };
161
+ } catch {
162
+ const raw = (await fs.readFile(lockPath, "utf8").catch(() => "")).trim();
163
+ const pid = /^\d{1,9}$/.test(raw) ? Number(raw) : null;
164
+ if (pid != null && pidAlive(pid)) {
165
+ throw new Error(
166
+ `another ${stage} run is ACTIVE (pid ${pid} is alive, ${lockPath}) \u2014 concurrent runs overwrite each other's output. Wait for it to finish.`
167
+ );
168
+ }
169
+ if (pid == null) {
170
+ const age = Date.now() - (await fs.stat(lockPath).catch(() => null))?.mtimeMs;
171
+ if (!(age > STALE_UNKNOWN_MS)) {
172
+ throw new Error(
173
+ `a ${stage} lock exists with an unreadable holder (${lockPath}, ${Math.round(age / 6e4)}m old) \u2014 not old enough to declare stale. Wait, or delete it if you know the run is gone.`
174
+ );
175
+ }
176
+ }
177
+ console.warn(
178
+ `[${stage}] stale lock from ${pid != null ? `dead pid ${pid}` : "an unreadable holder"} \u2014 removing it and proceeding (a crashed run must never strand the next one)`
179
+ );
180
+ await fs.unlink(lockPath).catch(() => {
181
+ });
182
+ }
183
+ }
184
+ throw new Error(`could not acquire the ${stage} lock (${lockPath}) \u2014 another run raced the stale takeover`);
185
+ }
139
186
 
140
187
  // ../../lib/agents/shared/agent.ts
141
188
  import { readFileSync } from "fs";
@@ -143,7 +190,7 @@ import path8 from "path";
143
190
 
144
191
  // ../../lib/agents/shared/cliAdapter.ts
145
192
  import { spawn } from "child_process";
146
- import { promises as fs2 } from "fs";
193
+ import { promises as fs3 } from "fs";
147
194
  import path2 from "path";
148
195
 
149
196
  // ../coding-core/dist/env.js
@@ -187,7 +234,7 @@ function extractJson(text2) {
187
234
  }
188
235
 
189
236
  // ../../lib/agents/shared/toolLog.ts
190
- import { promises as fs } from "fs";
237
+ import { promises as fs2 } from "fs";
191
238
  import path from "path";
192
239
  async function writeToolLog(logPath, d) {
193
240
  const counts = {};
@@ -204,8 +251,8 @@ async function writeToolLog(logPath, d) {
204
251
  L.push(``);
205
252
  L.push(`## Full call sequence (${d.toolCalls.length})`);
206
253
  d.toolCalls.forEach((c, i) => L.push(` ${String(i + 1).padStart(3, "0")} ${c.tool.padEnd(5)} ${c.target}`));
207
- await fs.mkdir(path.dirname(logPath), { recursive: true });
208
- await fs.writeFile(logPath, L.join("\n"), "utf-8");
254
+ await fs2.mkdir(path.dirname(logPath), { recursive: true });
255
+ await fs2.writeFile(logPath, L.join("\n"), "utf-8");
209
256
  const json = {
210
257
  roots: d.roots,
211
258
  toolCounts: counts,
@@ -215,7 +262,7 @@ async function writeToolLog(logPath, d) {
215
262
  filesRead: d.filesRead,
216
263
  callSequence: d.toolCalls
217
264
  };
218
- await fs.writeFile(logPath.replace(/\.log$/, ".json"), JSON.stringify(json, null, 2), "utf-8");
265
+ await fs2.writeFile(logPath.replace(/\.log$/, ".json"), JSON.stringify(json, null, 2), "utf-8");
219
266
  }
220
267
 
221
268
  // ../../lib/agents/shared/cliAdapter.ts
@@ -224,8 +271,8 @@ var USAGE_LEDGER = () => path2.join(process.env.POLYMATH_DATA_DIR ? path2.resolv
224
271
  async function appendUsageLedger(line) {
225
272
  try {
226
273
  const f = USAGE_LEDGER();
227
- await fs2.mkdir(path2.dirname(f), { recursive: true });
228
- await fs2.appendFile(f, JSON.stringify(line) + "\n", "utf8");
274
+ await fs3.mkdir(path2.dirname(f), { recursive: true });
275
+ await fs3.appendFile(f, JSON.stringify(line) + "\n", "utf8");
229
276
  } catch {
230
277
  }
231
278
  }
@@ -503,6 +550,13 @@ ${report}`);
503
550
  }
504
551
 
505
552
  // ../../lib/agents/shared/codexAdapter.ts
553
+ var CODEX_DEFAULT_MODEL = "gpt-5.5";
554
+ var CODEX_MINI_MODEL = "gpt-5.4-mini";
555
+ function mapCodexTier(model, env = process.env) {
556
+ if (model && !/^(claude|haiku|sonnet|opus)/i.test(model)) return model;
557
+ if (model && /^haiku/i.test(model)) return env.POLYMATH_CODEX_MODEL_MINI || CODEX_MINI_MODEL;
558
+ return env.POLYMATH_CODEX_MODEL || CODEX_DEFAULT_MODEL;
559
+ }
506
560
  function composePrompt(inv, roots) {
507
561
  return [
508
562
  inv.systemPrompt ? `<system>
@@ -543,7 +597,7 @@ var codexAdapter = {
543
597
  "read-only",
544
598
  "--json"
545
599
  ];
546
- if (inv.model && !/^claude/i.test(inv.model)) args.push("--model", inv.model);
600
+ args.push("--model", mapCodexTier(inv.model));
547
601
  args.push(composePrompt(inv, roots));
548
602
  const started = Date.now();
549
603
  const toolCalls = [];
@@ -2171,8 +2225,8 @@ function getErrorMap() {
2171
2225
 
2172
2226
  // ../../node_modules/zod/v3/helpers/parseUtil.js
2173
2227
  var makeIssue = (params) => {
2174
- const { data, path: path14, errorMaps, issueData } = params;
2175
- const fullPath = [...path14, ...issueData.path || []];
2228
+ const { data, path: path15, errorMaps, issueData } = params;
2229
+ const fullPath = [...path15, ...issueData.path || []];
2176
2230
  const fullIssue = {
2177
2231
  ...issueData,
2178
2232
  path: fullPath
@@ -2288,11 +2342,11 @@ var errorUtil;
2288
2342
 
2289
2343
  // ../../node_modules/zod/v3/types.js
2290
2344
  var ParseInputLazyPath = class {
2291
- constructor(parent, value, path14, key) {
2345
+ constructor(parent, value, path15, key) {
2292
2346
  this._cachedPath = [];
2293
2347
  this.parent = parent;
2294
2348
  this.data = value;
2295
- this._path = path14;
2349
+ this._path = path15;
2296
2350
  this._key = key;
2297
2351
  }
2298
2352
  get path() {
@@ -15079,39 +15133,39 @@ function createOpenAI(options = {}) {
15079
15133
  });
15080
15134
  const createChatModel = (modelId, settings = {}) => new OpenAIChatLanguageModel(modelId, settings, {
15081
15135
  provider: `${providerName}.chat`,
15082
- url: ({ path: path14 }) => `${baseURL}${path14}`,
15136
+ url: ({ path: path15 }) => `${baseURL}${path15}`,
15083
15137
  headers: getHeaders,
15084
15138
  compatibility,
15085
15139
  fetch: options.fetch
15086
15140
  });
15087
15141
  const createCompletionModel = (modelId, settings = {}) => new OpenAICompletionLanguageModel(modelId, settings, {
15088
15142
  provider: `${providerName}.completion`,
15089
- url: ({ path: path14 }) => `${baseURL}${path14}`,
15143
+ url: ({ path: path15 }) => `${baseURL}${path15}`,
15090
15144
  headers: getHeaders,
15091
15145
  compatibility,
15092
15146
  fetch: options.fetch
15093
15147
  });
15094
15148
  const createEmbeddingModel = (modelId, settings = {}) => new OpenAIEmbeddingModel(modelId, settings, {
15095
15149
  provider: `${providerName}.embedding`,
15096
- url: ({ path: path14 }) => `${baseURL}${path14}`,
15150
+ url: ({ path: path15 }) => `${baseURL}${path15}`,
15097
15151
  headers: getHeaders,
15098
15152
  fetch: options.fetch
15099
15153
  });
15100
15154
  const createImageModel = (modelId, settings = {}) => new OpenAIImageModel(modelId, settings, {
15101
15155
  provider: `${providerName}.image`,
15102
- url: ({ path: path14 }) => `${baseURL}${path14}`,
15156
+ url: ({ path: path15 }) => `${baseURL}${path15}`,
15103
15157
  headers: getHeaders,
15104
15158
  fetch: options.fetch
15105
15159
  });
15106
15160
  const createTranscriptionModel = (modelId) => new OpenAITranscriptionModel(modelId, {
15107
15161
  provider: `${providerName}.transcription`,
15108
- url: ({ path: path14 }) => `${baseURL}${path14}`,
15162
+ url: ({ path: path15 }) => `${baseURL}${path15}`,
15109
15163
  headers: getHeaders,
15110
15164
  fetch: options.fetch
15111
15165
  });
15112
15166
  const createSpeechModel = (modelId) => new OpenAISpeechModel(modelId, {
15113
15167
  provider: `${providerName}.speech`,
15114
- url: ({ path: path14 }) => `${baseURL}${path14}`,
15168
+ url: ({ path: path15 }) => `${baseURL}${path15}`,
15115
15169
  headers: getHeaders,
15116
15170
  fetch: options.fetch
15117
15171
  });
@@ -15132,7 +15186,7 @@ function createOpenAI(options = {}) {
15132
15186
  const createResponsesModel = (modelId) => {
15133
15187
  return new OpenAIResponsesLanguageModel(modelId, {
15134
15188
  provider: `${providerName}.responses`,
15135
- url: ({ path: path14 }) => `${baseURL}${path14}`,
15189
+ url: ({ path: path15 }) => `${baseURL}${path15}`,
15136
15190
  headers: getHeaders,
15137
15191
  fetch: options.fetch
15138
15192
  });
@@ -15162,7 +15216,7 @@ var openai = createOpenAI({
15162
15216
  });
15163
15217
 
15164
15218
  // ../../lib/agents/shared/tools.ts
15165
- import { promises as fs3 } from "fs";
15219
+ import { promises as fs4 } from "fs";
15166
15220
  import { execFile } from "child_process";
15167
15221
  import { promisify } from "util";
15168
15222
  import path5 from "path";
@@ -15182,7 +15236,7 @@ function fileTools(root) {
15182
15236
  parameters: external_exports.object({ path: external_exports.string().describe("dir path relative to source root") }),
15183
15237
  execute: async ({ path: p }) => {
15184
15238
  const dir = safeResolve(root, p);
15185
- const entries = await fs3.readdir(dir, { withFileTypes: true });
15239
+ const entries = await fs4.readdir(dir, { withFileTypes: true });
15186
15240
  return entries.filter((e) => !e.name.startsWith(".git") && e.name !== ".obsidian").map((e) => e.isDirectory() ? `${e.name}/` : e.name).slice(0, 500).join("\n");
15187
15241
  }
15188
15242
  }),
@@ -15195,7 +15249,7 @@ function fileTools(root) {
15195
15249
  }),
15196
15250
  execute: async ({ path: p, offset = 0, limit = 600 }) => {
15197
15251
  const file2 = safeResolve(root, p);
15198
- const text2 = await fs3.readFile(file2, "utf-8");
15252
+ const text2 = await fs4.readFile(file2, "utf-8");
15199
15253
  const lines = text2.split("\n");
15200
15254
  return lines.slice(offset, offset + limit).join("\n").slice(0, 6e4);
15201
15255
  }
@@ -15629,8 +15683,8 @@ function invokeAgent(inv, opts = {}) {
15629
15683
  }
15630
15684
 
15631
15685
  // ../../lib/agents/coding/profile.ts
15632
- import { promises as fs6 } from "fs";
15633
- import path10 from "path";
15686
+ import { promises as fs8 } from "fs";
15687
+ import path11 from "path";
15634
15688
 
15635
15689
  // ../../lib/calibration/fingerprint.ts
15636
15690
  import { createHash } from "node:crypto";
@@ -15776,7 +15830,7 @@ var GRADED_CRITERIA = CODING_CRITERIA.filter((c) => c.graded);
15776
15830
  var RUBRIC_FINGERPRINT = rubricFingerprint(GRADED_CRITERIA);
15777
15831
 
15778
15832
  // ../coding-core/dist/messages.js
15779
- import { promises as fs4 } from "fs";
15833
+ import { promises as fs6 } from "fs";
15780
15834
 
15781
15835
  // ../coding-core/dist/injected.js
15782
15836
  var SYSTEM_REMINDER_RE = /<system-reminder>[\s\S]*?<\/system-reminder>/g;
@@ -15902,6 +15956,286 @@ function extractCodexEvents(raw) {
15902
15956
  return out;
15903
15957
  }
15904
15958
 
15959
+ // ../coding-core/dist/cursor.js
15960
+ import { promises as fs5 } from "fs";
15961
+ var NODE_SQLITE = "node:sqlite";
15962
+ async function openCursorSqlite(dbPath) {
15963
+ try {
15964
+ await fs5.access(dbPath);
15965
+ } catch {
15966
+ return null;
15967
+ }
15968
+ let mod;
15969
+ try {
15970
+ mod = await import(NODE_SQLITE);
15971
+ } catch {
15972
+ return null;
15973
+ }
15974
+ const DatabaseSync = mod?.DatabaseSync;
15975
+ if (!DatabaseSync)
15976
+ return null;
15977
+ let db;
15978
+ try {
15979
+ db = new DatabaseSync(dbPath, { readOnly: true });
15980
+ } catch {
15981
+ try {
15982
+ db = new DatabaseSync(dbPath);
15983
+ } catch {
15984
+ return null;
15985
+ }
15986
+ }
15987
+ const asText = (v) => v == null ? null : typeof v === "string" ? v : Buffer.from(v).toString("utf-8");
15988
+ return {
15989
+ prefix(prefix) {
15990
+ try {
15991
+ const rows = db.prepare("SELECT key, value FROM cursorDiskKV WHERE key LIKE ? ESCAPE '\\'").all(likePrefix(prefix));
15992
+ return rows.map((r) => ({ key: r.key, value: asText(r.value) ?? "" }));
15993
+ } catch {
15994
+ return [];
15995
+ }
15996
+ },
15997
+ get(key) {
15998
+ try {
15999
+ const row = db.prepare("SELECT value FROM cursorDiskKV WHERE key = ?").get(key);
16000
+ return row ? asText(row.value) : null;
16001
+ } catch {
16002
+ return null;
16003
+ }
16004
+ },
16005
+ close() {
16006
+ try {
16007
+ db.close();
16008
+ } catch {
16009
+ }
16010
+ }
16011
+ };
16012
+ }
16013
+ function likePrefix(prefix) {
16014
+ return prefix.replace(/[\\%_]/g, (c) => "\\" + c) + "%";
16015
+ }
16016
+ var CURSOR_USER_QUERY_RE = /<user_query>\s*([\s\S]*?)\s*<\/user_query>/;
16017
+ function cleanUserText(raw) {
16018
+ let t = raw.replace(SYSTEM_REMINDER_RE, "");
16019
+ const m = t.match(CURSOR_USER_QUERY_RE);
16020
+ if (m)
16021
+ t = m[1];
16022
+ return t.trim();
16023
+ }
16024
+ var msFrom = (v) => {
16025
+ if (typeof v === "number" && Number.isFinite(v))
16026
+ return v;
16027
+ if (typeof v === "string") {
16028
+ const n = Date.parse(v);
16029
+ return Number.isFinite(n) ? n : null;
16030
+ }
16031
+ return null;
16032
+ };
16033
+ function readCursorComposer(db, composerId) {
16034
+ const cdRaw = db.get(`composerData:${composerId}`);
16035
+ if (!cdRaw)
16036
+ return null;
16037
+ let cd;
16038
+ try {
16039
+ cd = JSON.parse(cdRaw);
16040
+ } catch {
16041
+ return null;
16042
+ }
16043
+ const headers = Array.isArray(cd.fullConversationHeadersOnly) ? cd.fullConversationHeadersOnly : [];
16044
+ if (headers.length === 0)
16045
+ return null;
16046
+ const bubbles = /* @__PURE__ */ new Map();
16047
+ for (const row of db.prefix(`bubbleId:${composerId}:`)) {
16048
+ const bid = row.key.slice(`bubbleId:${composerId}:`.length);
16049
+ try {
16050
+ bubbles.set(bid, JSON.parse(row.value));
16051
+ } catch {
16052
+ }
16053
+ }
16054
+ const turns = [];
16055
+ let clock = msFrom(cd.createdAt) ?? 0;
16056
+ for (const h of headers) {
16057
+ const b = bubbles.get(h.bubbleId);
16058
+ if (!b)
16059
+ continue;
16060
+ const type = h.type === 1 ? 1 : 2;
16061
+ const tool2 = type === 2 && b.toolFormerData && typeof b.toolFormerData.name === "string" ? b.toolFormerData.name : null;
16062
+ const rawText = typeof b.text === "string" ? b.text : "";
16063
+ const text2 = type === 1 ? cleanUserText(rawText) : rawText.replace(SYSTEM_REMINDER_RE, "").trim();
16064
+ if (!text2 && !tool2)
16065
+ continue;
16066
+ const t = msFrom(b.createdAt);
16067
+ clock = Math.max(clock, t ?? clock + 1);
16068
+ const model = b.modelInfo && typeof b.modelInfo.modelName === "string" ? b.modelInfo.modelName : null;
16069
+ turns.push({ t: clock, type, text: text2, tool: tool2, model });
16070
+ }
16071
+ if (turns.length === 0)
16072
+ return null;
16073
+ const gitRepo = Array.isArray(cd.trackedGitRepos) && cd.trackedGitRepos[0] && typeof cd.trackedGitRepos[0].repoPath === "string" ? cd.trackedGitRepos[0].repoPath : null;
16074
+ return {
16075
+ composerId,
16076
+ createdAt: msFrom(cd.createdAt),
16077
+ updatedAt: msFrom(cd.lastUpdatedAt),
16078
+ name: typeof cd.name === "string" && cd.name.trim() ? cd.name.trim() : null,
16079
+ gitRepo,
16080
+ turns
16081
+ };
16082
+ }
16083
+ function sniffCursorRaw(raw) {
16084
+ for (const lineRaw of raw.split("\n")) {
16085
+ const line = lineRaw.trim();
16086
+ if (!line)
16087
+ continue;
16088
+ try {
16089
+ const e = JSON.parse(line);
16090
+ return (e.role === "user" || e.role === "assistant") && typeof e.message === "object" && e.message !== null && "content" in e.message && !("type" in e);
16091
+ } catch {
16092
+ return false;
16093
+ }
16094
+ }
16095
+ return false;
16096
+ }
16097
+ function jsonlText(content) {
16098
+ const parts = [];
16099
+ const tools = [];
16100
+ if (Array.isArray(content)) {
16101
+ for (const item of content) {
16102
+ if (!item || typeof item !== "object")
16103
+ continue;
16104
+ const it = item;
16105
+ if (it.type === "text" && it.text)
16106
+ parts.push(it.text);
16107
+ else if (it.type === "tool_use" && it.name)
16108
+ tools.push(it.name);
16109
+ }
16110
+ } else if (typeof content === "string")
16111
+ parts.push(content);
16112
+ return { text: parts.join("\n"), tools };
16113
+ }
16114
+ function parseCursorJsonl(raw, base) {
16115
+ const turns = [];
16116
+ let clock = base;
16117
+ for (const lineRaw of raw.split("\n")) {
16118
+ const line = lineRaw.trim();
16119
+ if (!line)
16120
+ continue;
16121
+ let e;
16122
+ try {
16123
+ e = JSON.parse(line);
16124
+ } catch {
16125
+ continue;
16126
+ }
16127
+ if (e.role !== "user" && e.role !== "assistant")
16128
+ continue;
16129
+ const { text: rawText, tools } = jsonlText(e.message?.content);
16130
+ const type = e.role === "user" ? 1 : 2;
16131
+ const text2 = type === 1 ? cleanUserText(rawText) : rawText.replace(SYSTEM_REMINDER_RE, "").trim();
16132
+ if (type === 2 && tools.length) {
16133
+ for (const tool2 of tools) {
16134
+ clock += 1;
16135
+ turns.push({ t: clock, type: 2, text: "", tool: tool2, model: null });
16136
+ }
16137
+ }
16138
+ if (!text2)
16139
+ continue;
16140
+ clock += 1;
16141
+ turns.push({ t: clock, type, text: text2, tool: null, model: null });
16142
+ }
16143
+ if (turns.length === 0)
16144
+ return null;
16145
+ return { composerId: "", createdAt: base, updatedAt: clock, name: null, gitRepo: null, turns };
16146
+ }
16147
+ var AI_GIST = 500;
16148
+ function renderCursorTranscript(c) {
16149
+ const lines = [];
16150
+ let humanTurns = 0, humanChars = 0;
16151
+ let aiProse = "";
16152
+ const aiTools = /* @__PURE__ */ new Map();
16153
+ const flushAI = () => {
16154
+ if (!aiProse && aiTools.size === 0)
16155
+ return;
16156
+ const tools = [...aiTools.entries()].map(([n, k]) => k > 1 ? `${n}\xD7${k}` : n).join(", ");
16157
+ const gist = aiProse ? aiProse.length > AI_GIST ? aiProse.slice(0, AI_GIST) + "\u2026" : aiProse : "";
16158
+ const bits = [];
16159
+ if (gist)
16160
+ bits.push(gist);
16161
+ if (tools)
16162
+ bits.push(`ran ${tools}`);
16163
+ lines.push(`[AI: ${bits.join(" \xB7 ")}]`);
16164
+ aiProse = "";
16165
+ aiTools.clear();
16166
+ };
16167
+ for (const turn of c.turns) {
16168
+ if (turn.type === 1) {
16169
+ flushAI();
16170
+ humanTurns++;
16171
+ humanChars += turn.text.length;
16172
+ lines.push(`>> ${turn.text}`);
16173
+ } else {
16174
+ if (turn.tool)
16175
+ aiTools.set(turn.tool, (aiTools.get(turn.tool) ?? 0) + 1);
16176
+ if (turn.text)
16177
+ aiProse = turn.text.replace(/\s+/g, " ").trim();
16178
+ }
16179
+ }
16180
+ flushAI();
16181
+ return { text: lines.join("\n"), humanTurns, humanChars };
16182
+ }
16183
+ function composerIdFromFile(file2) {
16184
+ const m = file2.match(/agent-transcripts\/([^/]+)\/[^/]+\.jsonl$/);
16185
+ return m ? m[1] : null;
16186
+ }
16187
+ async function loadCursorComposer(file2, raw, dbPath) {
16188
+ const cid = composerIdFromFile(file2);
16189
+ if (cid && dbPath) {
16190
+ const db = await openCursorSqlite(dbPath);
16191
+ if (db) {
16192
+ try {
16193
+ const c = readCursorComposer(db, cid);
16194
+ if (c)
16195
+ return c;
16196
+ } finally {
16197
+ db.close();
16198
+ }
16199
+ }
16200
+ }
16201
+ return parseCursorJsonl(raw, 0);
16202
+ }
16203
+
16204
+ // ../coding-core/dist/raw.js
16205
+ import path9 from "path";
16206
+ import os2 from "os";
16207
+ var SOURCE_ROOT_ENV_VARS = [
16208
+ "CLAUDE_PROJECTS_DIR",
16209
+ "CODEX_SESSIONS_DIR",
16210
+ "CURSOR_WORKSPACE_DIR",
16211
+ "CURSOR_PROJECTS_DIR",
16212
+ // Cursor's globalStorage dir (holds state.vscdb — the composer bubbles that
16213
+ // carry a Cursor session's real per-turn timestamps + content). Same
16214
+ // isolation contract: overriding any root disables every unset source.
16215
+ "CURSOR_GLOBAL_DIR"
16216
+ ];
16217
+ var anyRootOverridden = () => SOURCE_ROOT_ENV_VARS.some((v) => !!process.env[v]);
16218
+ function resolveSourceRoot(envVar, ...defaultSegments) {
16219
+ const explicit = process.env[envVar];
16220
+ if (explicit)
16221
+ return explicit;
16222
+ if (anyRootOverridden())
16223
+ return null;
16224
+ return path9.join(os2.homedir(), ...defaultSegments);
16225
+ }
16226
+ var cursorGlobalRoot = () => resolveSourceRoot("CURSOR_GLOBAL_DIR", "Library", "Application Support", "Cursor", "User", "globalStorage");
16227
+ function cursorGlobalDbPath() {
16228
+ const root = cursorGlobalRoot();
16229
+ return root === null ? null : path9.join(root, "state.vscdb");
16230
+ }
16231
+ var MACHINE_CURSOR_FILE_RE = /^(.*[/\\]machines[/\\][^/\\]+[/\\]\.cursor)[/\\]projects[/\\]/;
16232
+ function cursorDbPathForFile(file2) {
16233
+ const m = file2.match(MACHINE_CURSOR_FILE_RE);
16234
+ if (m)
16235
+ return path9.join(m[1], "globalStorage", "state.vscdb");
16236
+ return cursorGlobalDbPath();
16237
+ }
16238
+
15905
16239
  // ../coding-core/dist/messages.js
15906
16240
  function extractText(content) {
15907
16241
  if (typeof content === "string")
@@ -15929,15 +16263,35 @@ function extractUserMessagesCodex(raw) {
15929
16263
  }
15930
16264
  return out.sort((a, b) => a.t - b.t);
15931
16265
  }
16266
+ function extractUserMessagesCursor(c) {
16267
+ const out = [];
16268
+ let lastTs = null;
16269
+ for (const turn of c.turns) {
16270
+ const t = turn.t;
16271
+ const gapMs = Number.isFinite(t) && lastTs != null ? t - lastTs : NaN;
16272
+ if (Number.isFinite(t))
16273
+ lastTs = t;
16274
+ if (turn.type !== 1)
16275
+ continue;
16276
+ const text2 = humanTypedText(turn.text);
16277
+ if (text2 && Number.isFinite(t))
16278
+ out.push({ t, text: text2, gapMs });
16279
+ }
16280
+ return out.sort((a, b) => a.t - b.t);
16281
+ }
15932
16282
  async function extractUserMessages(file2) {
15933
16283
  let raw;
15934
16284
  try {
15935
- raw = await fs4.readFile(file2, "utf-8");
16285
+ raw = await fs6.readFile(file2, "utf-8");
15936
16286
  } catch {
15937
16287
  return [];
15938
16288
  }
15939
16289
  if (sniffCodexRaw(raw))
15940
16290
  return extractUserMessagesCodex(raw);
16291
+ if (sniffCursorRaw(raw)) {
16292
+ const c = await loadCursorComposer(file2, raw, cursorDbPathForFile(file2));
16293
+ return c ? extractUserMessagesCursor(c) : [];
16294
+ }
15941
16295
  const out = [];
15942
16296
  const userTexts = /* @__PURE__ */ new Set();
15943
16297
  const seenUuids = /* @__PURE__ */ new Set();
@@ -15984,11 +16338,11 @@ async function extractUserMessages(file2) {
15984
16338
  }
15985
16339
 
15986
16340
  // ../../lib/agents/coding/walkthrough.ts
15987
- import { promises as fs5 } from "fs";
15988
- import path9 from "path";
16341
+ import { promises as fs7 } from "fs";
16342
+ import path10 from "path";
15989
16343
  var IDLE_CAP_MS = 12 * 6e4;
15990
16344
  async function readWalkthrough(outDir, sessionId) {
15991
- return fs5.readFile(path9.join(outDir, `${sessionId}.json`), "utf8").then(JSON.parse).catch(() => null);
16345
+ return fs7.readFile(path10.join(outDir, `${sessionId}.json`), "utf8").then(JSON.parse).catch(() => null);
15992
16346
  }
15993
16347
 
15994
16348
  // ../coding-core/dist/words.js
@@ -16400,7 +16754,7 @@ function computeWorkstyle(inp) {
16400
16754
 
16401
16755
  // ../../lib/calibration/index.ts
16402
16756
  var DEFAULT_CALIBRATION = {
16403
- version: "2026-07-16.2",
16757
+ version: "2026-07-21.1",
16404
16758
  // = RUBRIC_FINGERPRINT of the shipped npm rubric (packages/coding-analyzer/
16405
16759
  // src/grade/criteria.ts). A unit test fails loud when the rubric changes
16406
16760
  // without this being updated (and re-pushed to the server).
@@ -16496,13 +16850,14 @@ var DEFAULT_CALIBRATION = {
16496
16850
  },
16497
16851
  codingBenchmarks: {
16498
16852
  flow: {
16499
- // typical knowledge worker ≈ 35% of an 8h day focused; ~4h/day is the
16500
- // recognized deep-work ceiling (Newport) 50% most sit far below it.
16853
+ // typical knowledge worker ≈ 35% of an 8h day focused; the ~4h/day
16854
+ // deep-work ceiling (Newport) sits nearer ~40% of a real (9-10h) top
16855
+ // performer's day — 50% overstated it (owner call 2026-07-21).
16501
16856
  typicalPctOfDay: 0.35,
16502
- topPctOfDay: 0.5,
16857
+ topPctOfDay: 0.4,
16503
16858
  tag: "measured",
16504
- source: "RescueTime 2019 (~2h48m focused/day) \xB7 Cal Newport, Deep Work (~4h/day deep-work ceiling)",
16505
- line: "the best spend ~half the workday in true deep flow; ~4h/day is the human ceiling"
16859
+ source: "RescueTime 2019 (~2h48m focused/day) \xB7 Cal Newport, Deep Work (~4h/day deep-work ceiling against a 9-10h day)",
16860
+ line: "the best spend ~40% of the workday in true deep flow; ~4h/day is the human ceiling"
16506
16861
  },
16507
16862
  longestRun: {
16508
16863
  typicalHours: 0.67,
@@ -16551,13 +16906,20 @@ function bandLabel(score, doc = DEFAULT_CALIBRATION) {
16551
16906
  for (const b of doc.scoreBands) if (b.score <= s && (!best || b.score > best.score)) best = b;
16552
16907
  return (best ?? doc.scoreBands[0]).label;
16553
16908
  }
16909
+ function scoreForTopPct(topPct, doc = DEFAULT_CALIBRATION) {
16910
+ for (const b of doc.scoreBands) {
16911
+ const x = parseFloat(b.label.replace(/^Top\s+/i, ""));
16912
+ if (Number.isFinite(x) && topPct <= x) return b.score;
16913
+ }
16914
+ return 1;
16915
+ }
16554
16916
 
16555
16917
  // ../../lib/agents/coding/benchmarks.ts
16556
16918
  var BEST = DEFAULT_CALIBRATION.codingBenchmarks;
16557
16919
 
16558
16920
  // ../../lib/agents/coding/profile.ts
16559
16921
  var ROOT = process.cwd();
16560
- var CODING_DIR = process.env.POLYMATH_DATA_DIR ? path10.join(process.env.POLYMATH_DATA_DIR, "coding") : path10.join(ROOT, ".data", "coding");
16922
+ var CODING_DIR = process.env.POLYMATH_DATA_DIR ? path11.join(process.env.POLYMATH_DATA_DIR, "coding") : path11.join(ROOT, ".data", "coding");
16561
16923
  var UMETA = /* @__PURE__ */ new Map();
16562
16924
  async function userMeta(sessionId, file2) {
16563
16925
  const hit = UMETA.get(sessionId);
@@ -16567,9 +16929,9 @@ async function userMeta(sessionId, file2) {
16567
16929
  UMETA.set(sessionId, meta);
16568
16930
  return meta;
16569
16931
  }
16570
- var GRADES = path10.join(CODING_DIR, "grades");
16932
+ var GRADES = path11.join(CODING_DIR, "grades");
16571
16933
  async function readJson(p, fallback) {
16572
- return fs6.readFile(p, "utf8").then((s) => JSON.parse(s)).catch(() => fallback);
16934
+ return fs8.readFile(p, "utf8").then((s) => JSON.parse(s)).catch(() => fallback);
16573
16935
  }
16574
16936
  function cadenceScore(fraction, multiRatio) {
16575
16937
  let s;
@@ -16609,21 +16971,27 @@ var NO_GRADES_GAP = "no sessions graded for this yet \u2014 this fills in once g
16609
16971
  function estimateRowParts(score, nTakes, evidenceGap) {
16610
16972
  return nTakes === 0 && score == null ? { score: null, gap: NO_GRADES_GAP } : { score, gap: evidenceGap };
16611
16973
  }
16974
+ function verdictRowParts(v, fallback) {
16975
+ if (!v) return fallback;
16976
+ const ranged = v.confidence === "provisional" || (v.qualifying ?? 0) < 2;
16977
+ if (ranged) return { score: null, gap: `best ${v.best} inside an honest ${v.low}-${v.high} range so far. ${v.verdictLine} (${v.statsLine})`.trim() };
16978
+ return { score: v.best, gap: `${v.verdictLine} (${v.statsLine})`.trim() };
16979
+ }
16612
16980
  async function compileCodingProfile() {
16613
- const allRecords = await readJson(path10.join(CODING_DIR, "sessions.json"), []);
16981
+ const allRecords = await readJson(path11.join(CODING_DIR, "sessions.json"), []);
16614
16982
  const dupIds = new Set(allRecords.filter((s) => s.duplicateOf).map((s) => s.sessionId));
16615
16983
  const sessions = allRecords.filter((s) => !s.duplicateOf);
16616
- const conc = await readJson(path10.join(CODING_DIR, "concurrency.json"), null);
16617
- const renames = await readJson(path10.join(CODING_DIR, "renames.json"), []);
16984
+ const conc = await readJson(path11.join(CODING_DIR, "concurrency.json"), null);
16985
+ const renames = await readJson(path11.join(CODING_DIR, "renames.json"), []);
16618
16986
  const byId = new Map(sessions.map((s) => [s.sessionId, s]));
16619
16987
  let gradeFiles = [];
16620
16988
  try {
16621
- gradeFiles = (await fs6.readdir(GRADES)).filter((f) => f.endsWith(".json"));
16989
+ gradeFiles = (await fs8.readdir(GRADES)).filter((f) => f.endsWith(".json"));
16622
16990
  } catch {
16623
16991
  }
16624
16992
  const grades = [];
16625
16993
  for (const f of gradeFiles) {
16626
- const g = await readJson(path10.join(GRADES, f), null);
16994
+ const g = await readJson(path11.join(GRADES, f), null);
16627
16995
  if (g && byId.has(g.sessionId)) grades.push(g);
16628
16996
  }
16629
16997
  const takesByCriterion = /* @__PURE__ */ new Map();
@@ -16700,9 +17068,12 @@ async function compileCodingProfile() {
16700
17068
  const timeline = [...dayMap.values()].sort((a, b) => b.date.localeCompare(a.date));
16701
17069
  const levelHist = conc?.levelHistogramMin ?? {};
16702
17070
  const sumFrom = (min) => Object.entries(levelHist).filter(([k]) => Number(k) >= min).reduce((a, [, v]) => a + v, 0);
17071
+ const totalParallelMin = Object.values(levelHist).reduce((a, v) => a + v, 0);
17072
+ const avgConcurrency = totalParallelMin > 0 ? Math.round(Object.entries(levelHist).reduce((a, [k, v]) => a + Number(k) * v, 0) / totalParallelMin * 10) / 10 : 0;
16703
17073
  const topWindows = (conc?.segments ?? []).slice().sort((a, b) => b.level - a.level || b.minutes - a.minutes).slice(0, 12).map((s) => ({ start: s.start, end: s.end, minutes: s.minutes, level: s.level, titles: [...new Set(s.sessions.map((x) => x.title))] }));
16704
17074
  const parallelism = {
16705
17075
  maxConcurrency: conc?.maxConcurrency ?? 0,
17076
+ avgConcurrency,
16706
17077
  levelHistogramMin: levelHist,
16707
17078
  minutesAt2plus: Math.round(sumFrom(2)),
16708
17079
  minutesAt6plus: Math.round(sumFrom(6)),
@@ -16732,13 +17103,13 @@ async function compileCodingProfile() {
16732
17103
  models: Object.fromEntries([...models.entries()].sort((a, b) => b[1] - a[1])),
16733
17104
  lateNightSessions: lateNight
16734
17105
  };
16735
- const agglomeration = await readJson(path10.join(CODING_DIR, "agglomerate.json"), null);
16736
- const dayDigest = await readJson(path10.join(CODING_DIR, "day-digest.json"), null);
17106
+ const agglomeration = await readJson(path11.join(CODING_DIR, "agglomerate.json"), null);
17107
+ const dayDigest = await readJson(path11.join(CODING_DIR, "day-digest.json"), null);
16737
17108
  if (dayDigest?.days) dayDigest.days = dayDigest.days.map((day) => {
16738
17109
  const convs = day.conversations.filter((c) => byId.has(c.sessionId));
16739
17110
  return { ...day, conversations: convs, conversationsTouched: convs.length, totalMessages: convs.reduce((a, c) => a + c.messageCount, 0) };
16740
17111
  }).filter((day) => day.conversations.length > 0);
16741
- const dayChart = await readJson(path10.join(CODING_DIR, "day-chart.json"), []);
17112
+ const dayChart = await readJson(path11.join(CODING_DIR, "day-chart.json"), []);
16742
17113
  const intervalsBy = /* @__PURE__ */ new Map();
16743
17114
  const titleBy = /* @__PURE__ */ new Map();
16744
17115
  const fileById = new Map(sessions.map((s) => [s.sessionId, s.file]));
@@ -16757,8 +17128,8 @@ async function compileCodingProfile() {
16757
17128
  return ms;
16758
17129
  };
16759
17130
  const walkthroughs = {};
16760
- const wdir = path10.join(CODING_DIR, "walkthroughs");
16761
- for (const f of await fs6.readdir(wdir).catch(() => [])) {
17131
+ const wdir = path11.join(CODING_DIR, "walkthroughs");
17132
+ for (const f of await fs8.readdir(wdir).catch(() => [])) {
16762
17133
  if (!f.endsWith(".json")) continue;
16763
17134
  const w = await readWalkthrough(wdir, f.replace(".json", ""));
16764
17135
  if (!w || !byId.has(w.sessionId)) continue;
@@ -16805,17 +17176,19 @@ async function compileCodingProfile() {
16805
17176
  const tCeiling = throughputCeiling(Object.values(wordsByDay));
16806
17177
  const criteriaMean = {};
16807
17178
  for (const c of criteria) criteriaMean[c.key] = { mean: c.dist.mean, n: c.dist.n };
16808
- const flow = await readJson(path10.join(CODING_DIR, "flow.json"), null);
16809
- const focus = await readJson(path10.join(CODING_DIR, "focus.json"), null);
16810
- const expertiseMap = await readJson(path10.join(CODING_DIR, "expertise.json"), null);
16811
- const frontierArsenal = await readJson(path10.join(CODING_DIR, "frontier.json"), null);
16812
- const frontierDetail = await readJson(path10.join(CODING_DIR, "frontier-detail.json"), null);
16813
- const coaching = await readJson(path10.join(CODING_DIR, "coaching.json"), null);
16814
- const gap = await readJson(path10.join(CODING_DIR, "gap.json"), null);
16815
- const aggregate = await readJson(path10.join(CODING_DIR, "aggregate.json"), null);
16816
- const delegationRollup = await readJson(path10.join(CODING_DIR, "delegation-rollup.json"), null);
16817
- const gapDist = await readJson(path10.join(CODING_DIR, "gap-dist.json"), null);
16818
- const projects = await readJson(path10.join(CODING_DIR, "projects.json"), null);
17179
+ const flow = await readJson(path11.join(CODING_DIR, "flow.json"), null);
17180
+ const focus = await readJson(path11.join(CODING_DIR, "focus.json"), null);
17181
+ const expertiseMap = await readJson(path11.join(CODING_DIR, "expertise.json"), null);
17182
+ const frontierArsenal = await readJson(path11.join(CODING_DIR, "frontier.json"), null);
17183
+ const frontierDetail = await readJson(path11.join(CODING_DIR, "frontier-detail.json"), null);
17184
+ const coaching = await readJson(path11.join(CODING_DIR, "coaching.json"), null);
17185
+ const gap = await readJson(path11.join(CODING_DIR, "gap.json"), null);
17186
+ const aggregate = await readJson(path11.join(CODING_DIR, "aggregate.json"), null);
17187
+ const delegationRollup = await readJson(path11.join(CODING_DIR, "delegation-rollup.json"), null);
17188
+ const gapDist = await readJson(path11.join(CODING_DIR, "gap-dist.json"), null);
17189
+ const projects = await readJson(path11.join(CODING_DIR, "projects.json"), null);
17190
+ const growth = await readJson(path11.join(CODING_DIR, "growth.json"), null);
17191
+ const workbrief = await readJson(path11.join(CODING_DIR, "workbrief.json"), null);
16819
17192
  const workstyle = computeWorkstyle({
16820
17193
  dayChart,
16821
17194
  tz,
@@ -16875,15 +17248,25 @@ async function compileCodingProfile() {
16875
17248
  const hoursPctl = lognPct(workDayHrs, tiers?.hours);
16876
17249
  const hoursAt = (min) => Object.entries(pHist).reduce((a, [k, v]) => Number(k) >= min ? a + v : a, 0) / 60;
16877
17250
  const orchPctl = hoursAt(5) >= 5 || hoursAt(3) >= 10 && parallelism.queueOps >= 1e3 ? 99.5 : hoursAt(3) >= 10 ? 99 : hoursAt(2) >= 0.1 * (soloMin + parMin) / 60 ? 97 : hoursAt(2) >= 2 ? 90 : 70;
17251
+ const estScore = (pctl) => pctl == null ? null : scoreForTopPct(100 - pctl);
16878
17252
  const stackUp = [
17253
+ // The subtext leads with the AVERAGE — that is the number this row is
17254
+ // scored and pool-ranked on (wordsPerDay); a peak-led line once shipped
17255
+ // next to an average-based rank and read as a mismatch (owner call
17256
+ // 2026-07-21). The peak rides along as color.
16879
17257
  sRow(
16880
17258
  "How hard you push",
16881
- aggregate?.throughput?.score ?? tCeiling,
16882
- `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()}`
17259
+ estScore(pushPctl) ?? aggregate?.throughput?.score ?? tCeiling,
17260
+ avgWords != null ? `you average ~${Math.round(avgWords).toLocaleString()} words of pure direction a day (peak day ~${peakWords.toLocaleString()}) \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()}` : `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`
16883
17261
  ),
17262
+ // Graded like its siblings from the SAME fitted hours curve that ranks it
17263
+ // (tiers.hours → hoursPctl → estScore) and feeds the shared pool, so the
17264
+ // 1-11 badge can never contradict the pooled rank. Was `null` until
17265
+ // 2026-07-21, which left this the only measured row with no grade shown —
17266
+ // it read as broken next to push/parallelism/focus (owner call).
16884
17267
  sRow(
16885
17268
  "Hours you put in",
16886
- null,
17269
+ estScore(hoursPctl),
16887
17270
  workDayHrs != null ? `~${workDayHrs}h of active building on a typical work day \u2014 engaged builders average ~3h, and sustaining 7h+ day after day, week after week, is top-1% territory` : "not enough dated activity yet to measure a typical work day"
16888
17271
  ),
16889
17272
  // The copy FOLLOWS the person's actual orchestration band (orchPctl above) —
@@ -16894,7 +17277,7 @@ async function compileCodingProfile() {
16894
17277
  // orchestration.
16895
17278
  sRow(
16896
17279
  "Your AI parallelism",
16897
- ceilOf("delegation"),
17280
+ estScore(orchPctl),
16898
17281
  soloPct != null ? orchPctl >= 97 ? `you already run parallel at the frontier \u2014 ${Math.round(parMin / 60)}h of your hours with 2+ agents live vs ${Math.round(soloMin / 60)}h solo; the Claude Code lead keeps 10\u201315 going at once, and you work the same way` : `~${soloPct}% of your hours you drive a single agent (${Math.round(soloMin / 60)}h solo vs ${Math.round(parMin / 60)}h with 2+ live) \u2014 the Claude Code lead keeps 10\u201315 going at once, so this is the single biggest speed-up still on the table` : "you brief the AI sharply, but mostly drive one agent at a time \u2014 the top run 10\u201315 in parallel, a several-fold speed-up"
16899
17282
  ),
16900
17283
  // The evidence line cites the RANKING metric (flow as a share of the work
@@ -16905,7 +17288,7 @@ async function compileCodingProfile() {
16905
17288
  // the volume of hours is its own chip above.
16906
17289
  sRow(
16907
17290
  "Focus quality when you work",
16908
- focusScore,
17291
+ estScore(focusPctl) ?? focusScore,
16909
17292
  flowPctDay != null ? `~${Math.round(flowPctDay * 100)}% of your work day is true deep flow${flowHrsDay != null ? ` (~${flowHrsDay}h)` : ""} \u2014 the very best hold ~${Math.round(BEST.flow.topPctOfDay * 100)}% of theirs in one unbroken block; yours fragments across parallel sessions, so the gain is directing your attention at one thread for longer` : "your attention scatters across parallel sessions \u2014 directing it at one thread for longer is the unlock"
16910
17293
  ),
16911
17294
  // The four estimates LEAD with a concrete moment from their own sessions, then an
@@ -16954,24 +17337,39 @@ async function compileCodingProfile() {
16954
17337
  }
16955
17338
  if (r.label === "Your AI parallelism") r.percentile = orchPctl;
16956
17339
  }
16957
- return { generatedAt: (/* @__PURE__ */ new Date()).toISOString(), gradedSessions: grades.length, agglomeration, outcomeCadence, dayDigest, dayChart, timeline, walkthroughs, rubric, wordsByDay, dayThroughput, throughputCeiling: tCeiling, stackUp, criteria, parallelism, throughput, workstyle, flow, focus, expertiseMap, frontierArsenal, frontierDetail, coaching, gap, aggregate, delegationRollup, gapDist, projects };
17340
+ if (agglomeration?.verdicts) {
17341
+ const byLabel = {
17342
+ Judgement: agglomeration.verdicts.judgement,
17343
+ Agency: agglomeration.verdicts.agency,
17344
+ Taste: agglomeration.verdicts.taste
17345
+ };
17346
+ for (const r of stackUp) {
17347
+ const v = byLabel[r.label];
17348
+ if (!v) continue;
17349
+ const p = verdictRowParts(v, { score: r.score, gap: r.gap });
17350
+ r.score = p.score;
17351
+ r.gap = p.gap;
17352
+ r.percentile = pctOf(p.score);
17353
+ }
17354
+ }
17355
+ return { generatedAt: (/* @__PURE__ */ new Date()).toISOString(), gradedSessions: grades.length, agglomeration, outcomeCadence, dayDigest, dayChart, timeline, walkthroughs, rubric, wordsByDay, dayThroughput, throughputCeiling: tCeiling, stackUp, criteria, parallelism, throughput, workstyle, flow, focus, expertiseMap, frontierArsenal, frontierDetail, coaching, gap, aggregate, delegationRollup, gapDist, projects, growth, workbrief };
16958
17356
  }
16959
17357
 
16960
17358
  // ../../lib/agents/coding/assets.ts
16961
- import { promises as fs7 } from "fs";
16962
- import path11 from "path";
17359
+ import { promises as fs9 } from "fs";
17360
+ import path12 from "path";
16963
17361
  import { fileURLToPath } from "url";
16964
- var MODULE_DIR = path11.dirname(fileURLToPath(import.meta.url));
17362
+ var MODULE_DIR = path12.dirname(fileURLToPath(import.meta.url));
16965
17363
  async function readCodingAsset(name17) {
16966
17364
  const candidates = [
16967
- path11.join(MODULE_DIR, name17),
17365
+ path12.join(MODULE_DIR, name17),
16968
17366
  // dev: beside this file · bundled: beside the bundle
16969
- path11.resolve("lib", "agents", "coding", name17)
17367
+ path12.resolve("lib", "agents", "coding", name17)
16970
17368
  // legacy cwd-relative (repo-root cwd)
16971
17369
  ];
16972
17370
  for (const p of candidates) {
16973
17371
  try {
16974
- return { text: await fs7.readFile(p, "utf8"), path: p };
17372
+ return { text: await fs9.readFile(p, "utf8"), path: p };
16975
17373
  } catch {
16976
17374
  }
16977
17375
  }
@@ -16981,11 +17379,11 @@ async function readCodingAsset(name17) {
16981
17379
  }
16982
17380
 
16983
17381
  // ../../lib/agents/coding/docsDir.ts
16984
- import { promises as fs9 } from "fs";
16985
- import path12 from "path";
17382
+ import { promises as fs11 } from "fs";
17383
+ import path13 from "path";
16986
17384
 
16987
17385
  // ../../lib/agents/coding/materialize.ts
16988
- import { promises as fs8 } from "fs";
17386
+ import { promises as fs10 } from "fs";
16989
17387
  var SYSTEM_REMINDER_RE3 = /<system-reminder>[\s\S]*?<\/system-reminder>/g;
16990
17388
  var INJECT_GIST = 120;
16991
17389
  var INJECTED = [
@@ -17022,7 +17420,7 @@ function extractText2(content) {
17022
17420
  function isToolResultOnly2(content) {
17023
17421
  return Array.isArray(content) && content.length > 0 && content.every((c) => c && typeof c === "object" && c.type === "tool_result");
17024
17422
  }
17025
- var AI_GIST = 160;
17423
+ var AI_GIST2 = 160;
17026
17424
  function materializeCodex(raw) {
17027
17425
  const lines = [];
17028
17426
  let humanTurns = 0, humanChars = 0;
@@ -17031,7 +17429,7 @@ function materializeCodex(raw) {
17031
17429
  const flushAI = () => {
17032
17430
  if (!aiLastProse && aiTools.size === 0) return;
17033
17431
  const tools = [...aiTools.entries()].map(([n, c]) => c > 1 ? `${n}\xD7${c}` : n).join(", ");
17034
- const gist = aiLastProse ? aiLastProse.length > AI_GIST ? aiLastProse.slice(0, AI_GIST) + "\u2026" : aiLastProse : "";
17432
+ const gist = aiLastProse ? aiLastProse.length > AI_GIST2 ? aiLastProse.slice(0, AI_GIST2) + "\u2026" : aiLastProse : "";
17035
17433
  const bits = [];
17036
17434
  if (gist) bits.push(gist);
17037
17435
  if (tools) bits.push(`ran ${tools}`);
@@ -17055,14 +17453,19 @@ function materializeCodex(raw) {
17055
17453
  flushAI();
17056
17454
  return { text: lines.join("\n"), humanTurns, humanChars };
17057
17455
  }
17456
+ async function materializeCursor(file2, raw) {
17457
+ const composer = await loadCursorComposer(file2, raw, cursorDbPathForFile(file2));
17458
+ return composer ? renderCursorTranscript(composer) : { text: "", humanTurns: 0, humanChars: 0 };
17459
+ }
17058
17460
  async function materializeSession(file2) {
17059
17461
  let raw;
17060
17462
  try {
17061
- raw = await fs8.readFile(file2, "utf-8");
17463
+ raw = await fs10.readFile(file2, "utf-8");
17062
17464
  } catch {
17063
17465
  return null;
17064
17466
  }
17065
17467
  if (sniffCodexRaw(raw)) return materializeCodex(raw);
17468
+ if (sniffCursorRaw(raw)) return materializeCursor(file2, raw);
17066
17469
  const lines = [];
17067
17470
  let humanTurns = 0, humanChars = 0;
17068
17471
  const pendingQueued = [];
@@ -17075,7 +17478,7 @@ async function materializeSession(file2) {
17075
17478
  const flushAI = () => {
17076
17479
  if (!aiLastProse && aiTools.size === 0) return;
17077
17480
  const tools = [...aiTools.entries()].map(([n, c]) => c > 1 ? `${n}\xD7${c}` : n).join(", ");
17078
- const gist = aiLastProse ? aiLastProse.length > AI_GIST ? aiLastProse.slice(0, AI_GIST) + "\u2026" : aiLastProse : "";
17481
+ const gist = aiLastProse ? aiLastProse.length > AI_GIST2 ? aiLastProse.slice(0, AI_GIST2) + "\u2026" : aiLastProse : "";
17079
17482
  const bits = [];
17080
17483
  if (gist) bits.push(gist);
17081
17484
  if (tools) bits.push(`ran ${tools}`);
@@ -17155,10 +17558,10 @@ async function materializeSession(file2) {
17155
17558
 
17156
17559
  // ../../lib/agents/coding/docsDir.ts
17157
17560
  async function writeScoreboard(codingDir, docs) {
17158
- const gradesDir = path12.join(codingDir, "grades");
17561
+ const gradesDir = path13.join(codingDir, "grades");
17159
17562
  let files = [];
17160
17563
  try {
17161
- files = (await fs9.readdir(gradesDir)).filter((f) => f.endsWith(".json")).sort();
17564
+ files = (await fs11.readdir(gradesDir)).filter((f) => f.endsWith(".json")).sort();
17162
17565
  } catch {
17163
17566
  return;
17164
17567
  }
@@ -17166,7 +17569,7 @@ async function writeScoreboard(codingDir, docs) {
17166
17569
  for (const f of files) {
17167
17570
  let g;
17168
17571
  try {
17169
- g = JSON.parse(await fs9.readFile(path12.join(gradesDir, f), "utf8"));
17572
+ g = JSON.parse(await fs11.readFile(path13.join(gradesDir, f), "utf8"));
17170
17573
  } catch {
17171
17574
  continue;
17172
17575
  }
@@ -17182,8 +17585,8 @@ async function writeScoreboard(codingDir, docs) {
17182
17585
  ([key, rows]) => `## ${key}
17183
17586
  ${rows.sort((a, b) => b.s - a.s).map((r) => r.line).join("\n")}`
17184
17587
  );
17185
- await fs9.writeFile(
17186
- path12.join(docs, "_scoreboard.md"),
17588
+ await fs11.writeFile(
17589
+ path13.join(docs, "_scoreboard.md"),
17187
17590
  `# Scoreboard \u2014 every graded session per criterion, best first.
17188
17591
  # Lx~ = estimate. Format: level \xB7 date \xB7 title \xB7 sessionId \u2014 graded instance.
17189
17592
 
@@ -17192,24 +17595,24 @@ ${blocks.join("\n\n")}
17192
17595
  );
17193
17596
  }
17194
17597
  async function ensureCodingDocs(codingDir, sessions) {
17195
- const docs = path12.join(codingDir, "docs");
17196
- await fs9.mkdir(docs, { recursive: true });
17598
+ const docs = path13.join(codingDir, "docs");
17599
+ await fs11.mkdir(docs, { recursive: true });
17197
17600
  const user = sessions.filter((s) => s.sessionId && !s.duplicateOf && (!("klass" in s) || s.klass === "interactive"));
17198
17601
  let written = 0;
17199
17602
  for (const s of user) {
17200
- const out = path12.join(docs, `${s.sessionId}.txt`);
17603
+ const out = path13.join(docs, `${s.sessionId}.txt`);
17201
17604
  try {
17202
- await fs9.access(out);
17605
+ await fs11.access(out);
17203
17606
  continue;
17204
17607
  } catch {
17205
17608
  }
17206
17609
  const mat = await materializeSession(s.file).catch(() => null);
17207
17610
  if (!mat?.text) continue;
17208
- await fs9.writeFile(out, mat.text);
17611
+ await fs11.writeFile(out, mat.text);
17209
17612
  written++;
17210
17613
  }
17211
17614
  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}`);
17212
- await fs9.writeFile(path12.join(docs, "_map.md"), rows.join("\n") + "\n");
17615
+ await fs11.writeFile(path13.join(docs, "_map.md"), rows.join("\n") + "\n");
17213
17616
  await writeScoreboard(codingDir, docs);
17214
17617
  if (written) console.log(`[docs] materialized ${written} new transcript(s) \u2192 ${docs}`);
17215
17618
  return docs;
@@ -17222,7 +17625,7 @@ SOURCE LOOKUP \u2014 you have Read/Grep/Glob over the working directory, which h
17222
17625
 
17223
17626
  // ../../lib/agents/coding/promptCache.ts
17224
17627
  import { createHash as createHash2 } from "crypto";
17225
- import { promises as fs10 } from "fs";
17628
+ import { promises as fs12 } from "fs";
17226
17629
  function promptSha(parts) {
17227
17630
  const h = createHash2("sha256");
17228
17631
  for (const p of parts) {
@@ -17233,7 +17636,7 @@ function promptSha(parts) {
17233
17636
  }
17234
17637
  async function reusableOutput(outPath, sha, valid, key = "promptSha") {
17235
17638
  try {
17236
- const o = JSON.parse(await fs10.readFile(outPath, "utf8"));
17639
+ const o = JSON.parse(await fs12.readFile(outPath, "utf8"));
17237
17640
  if (o[key] === sha && valid(o)) return o;
17238
17641
  } catch {
17239
17642
  }
@@ -17253,7 +17656,7 @@ var CLAUDE_AUTO_CAP = /* @__PURE__ */ new Set(["queue-ahead", "deferred-tools",
17253
17656
  var CLAUDE_AUTO_MCP = /^(visualize|Claude[_ ]?Preview|ccd[_ ]?session|ccd[_ ]?session[_ ]?mgmt|mcp[_ ]?registry)$/i;
17254
17657
  async function entrypointOf(file2) {
17255
17658
  try {
17256
- const head = (await fs11.readFile(file2, "utf8")).slice(0, 2e4);
17659
+ const head = (await fs13.readFile(file2, "utf8")).slice(0, 2e4);
17257
17660
  if (/[\/."]\.?conductor/i.test(head)) return "conductor";
17258
17661
  const m = /"entrypoint":"([^"]+)"/.exec(head);
17259
17662
  return m ? m[1] : "unknown";
@@ -17275,25 +17678,15 @@ var MOBILE_WEB = /^claude-(web|mobile|ios|android)$/;
17275
17678
  function sumTool(recs, name17) {
17276
17679
  return recs.reduce((a, s) => a + (s.toolCounts?.[name17] ?? 0), 0);
17277
17680
  }
17278
- var LOCK = path13.join(CODING, ".gap.lock");
17279
- var lockHeld = false;
17280
- async function acquireLock() {
17281
- try {
17282
- await fs11.writeFile(LOCK, String(process.pid), { flag: "wx" });
17283
- lockHeld = true;
17284
- } catch {
17285
- const pid = await fs11.readFile(LOCK, "utf8").catch(() => "?");
17286
- 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.`);
17287
- }
17288
- }
17681
+ var LOCK = path14.join(CODING, ".gap.lock");
17289
17682
  async function main() {
17290
- await acquireLock();
17683
+ releaseLock = await acquireStageLock(LOCK, "coding-gap");
17291
17684
  const p = await compileCodingProfile();
17292
17685
  const techniquesAsset = await readCodingAsset("TECHNIQUES.md");
17293
17686
  const techniques = techniquesAsset.text;
17294
- console.log(` rubric: ${techniquesAsset.path} (${(await fs11.stat(techniquesAsset.path)).mtime.toISOString()})`);
17687
+ console.log(` rubric: ${techniquesAsset.path} (${(await fs13.stat(techniquesAsset.path)).mtime.toISOString()})`);
17295
17688
  const writing = (await readCodingAsset("WRITING.md")).text;
17296
- const all = JSON.parse(await fs11.readFile(path13.join(CODING, "sessions.json"), "utf8"));
17689
+ const all = JSON.parse(await fs13.readFile(path14.join(CODING, "sessions.json"), "utf8"));
17297
17690
  const interactive = all.filter((s) => s.klass === "interactive" && s.start);
17298
17691
  const latestMs = Math.max(...interactive.map((s) => Date.parse(s.start)));
17299
17692
  const cutoffMs = latestMs - 14 * 864e5;
@@ -17350,7 +17743,7 @@ async function main() {
17350
17743
  return m ? `--- "${s.title}" \xB7 ${(s.start || "").slice(0, 10)} ---
17351
17744
  ${m.text.slice(0, 3e3)}` : "";
17352
17745
  }))).filter(Boolean);
17353
- const digestDays = (await fs11.readFile(path13.join(CODING, "day-digest.json"), "utf-8").then(JSON.parse).catch(() => ({ days: [] }))).days ?? [];
17746
+ const digestDays = (await fs13.readFile(path14.join(CODING, "day-digest.json"), "utf-8").then(JSON.parse).catch(() => ({ days: [] }))).days ?? [];
17354
17747
  const digestLines = digestDays.slice().sort((a, b) => a.date < b.date ? -1 : 1).slice(-21).map((d) => `${d.date}: ${d.overall ?? ""}
17355
17748
  ${(d.conversations ?? []).slice(0, 4).map((c) => ` - ${c.title ?? ""}: ${c.summary ?? ""}`).join("\n")}`).join("\n").slice(0, 12e3);
17356
17749
  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();
@@ -17380,7 +17773,7 @@ Produce the gap analysis. Be thorough: cover every relevant catalog item they're
17380
17773
  \`applyItHere\` HARD RULES: 3 entries per recommendation when the material supports 3, minimum 2 \u2014 and every moment must be VISIBLY present in THEIR RECENT DAYS or the excerpts (a real dated task, named the way they name it). NEVER invent, generalize, or reuse the same moment across recommendations. If the material truly supports only one real moment, give that one \u2014 a fabricated example is worse than a short list.`;
17381
17774
  const sha = promptSha([SYS, prompt, "sonnet"]);
17382
17775
  if (!process.argv.includes("--refresh")) {
17383
- const prev = await reusableOutput(path13.join(CODING, "gap.json"), sha, (o) => Array.isArray(o.recommendations) && o.recommendations.length > 0);
17776
+ const prev = await reusableOutput(path14.join(CODING, "gap.json"), sha, (o) => Array.isArray(o.recommendations) && o.recommendations.length > 0);
17384
17777
  if (prev) {
17385
17778
  console.log(`[gap] inputs unchanged \u2014 reusing output from ${prev.generatedAt} (--refresh to regenerate)`);
17386
17779
  return;
@@ -17403,13 +17796,12 @@ Produce the gap analysis. Be thorough: cover every relevant catalog item they're
17403
17796
  throw new Error("gap run produced 0 recommendations \u2014 refusing to overwrite the existing gap.json. Re-run the builder.");
17404
17797
  }
17405
17798
  const result = { generatedAt: (/* @__PURE__ */ new Date()).toISOString(), promptSha: sha, ...out };
17406
- await fs11.writeFile(path13.join(CODING, "gap.json"), JSON.stringify(result, null, 2));
17799
+ await fs13.writeFile(path14.join(CODING, "gap.json"), JSON.stringify(result, null, 2));
17407
17800
  console.log(`WROTE ${CODING}/gap.json \u2014 recommendations:${(out.recommendations || []).length} \xB7 alreadyStrong:${(out.alreadyStrong || []).length}`);
17408
17801
  }
17802
+ var releaseLock = null;
17409
17803
  main().catch((e) => {
17410
17804
  console.error(e);
17411
17805
  process.exitCode = 1;
17412
- }).finally(() => {
17413
- if (lockHeld) fs11.rm(LOCK, { force: true }).catch(() => {
17414
- });
17415
- });
17806
+ }).finally(() => releaseLock?.().catch(() => {
17807
+ }));