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
@@ -1,8 +1,8 @@
1
1
  import{createRequire as __cr}from'module';const require=__cr(import.meta.url);
2
2
 
3
3
  // ../../scripts/coding-gap-dist.mts
4
- import { promises as fs2 } from "fs";
5
- import path2 from "path";
4
+ import { promises as fs3 } from "fs";
5
+ import path3 from "path";
6
6
 
7
7
  // ../../lib/agents/shared/cliAdapter.ts
8
8
  var CLAUDE_BIN = process.env.CLAUDE_BIN || "claude";
@@ -50,7 +50,7 @@ var LIBERAL = [
50
50
  var ALS = new AsyncLocalStorage();
51
51
 
52
52
  // ../coding-core/dist/messages.js
53
- import { promises as fs } from "fs";
53
+ import { promises as fs2 } from "fs";
54
54
 
55
55
  // ../coding-core/dist/injected.js
56
56
  var SYSTEM_REMINDER_RE = /<system-reminder>[\s\S]*?<\/system-reminder>/g;
@@ -176,6 +176,274 @@ function extractCodexEvents(raw) {
176
176
  return out;
177
177
  }
178
178
 
179
+ // ../coding-core/dist/cursor.js
180
+ import { promises as fs } from "fs";
181
+ var NODE_SQLITE = "node:sqlite";
182
+ async function openCursorSqlite(dbPath) {
183
+ try {
184
+ await fs.access(dbPath);
185
+ } catch {
186
+ return null;
187
+ }
188
+ let mod;
189
+ try {
190
+ mod = await import(NODE_SQLITE);
191
+ } catch {
192
+ return null;
193
+ }
194
+ const DatabaseSync = mod?.DatabaseSync;
195
+ if (!DatabaseSync)
196
+ return null;
197
+ let db;
198
+ try {
199
+ db = new DatabaseSync(dbPath, { readOnly: true });
200
+ } catch {
201
+ try {
202
+ db = new DatabaseSync(dbPath);
203
+ } catch {
204
+ return null;
205
+ }
206
+ }
207
+ const asText = (v) => v == null ? null : typeof v === "string" ? v : Buffer.from(v).toString("utf-8");
208
+ return {
209
+ prefix(prefix) {
210
+ try {
211
+ const rows = db.prepare("SELECT key, value FROM cursorDiskKV WHERE key LIKE ? ESCAPE '\\'").all(likePrefix(prefix));
212
+ return rows.map((r) => ({ key: r.key, value: asText(r.value) ?? "" }));
213
+ } catch {
214
+ return [];
215
+ }
216
+ },
217
+ get(key) {
218
+ try {
219
+ const row = db.prepare("SELECT value FROM cursorDiskKV WHERE key = ?").get(key);
220
+ return row ? asText(row.value) : null;
221
+ } catch {
222
+ return null;
223
+ }
224
+ },
225
+ close() {
226
+ try {
227
+ db.close();
228
+ } catch {
229
+ }
230
+ }
231
+ };
232
+ }
233
+ function likePrefix(prefix) {
234
+ return prefix.replace(/[\\%_]/g, (c) => "\\" + c) + "%";
235
+ }
236
+ var CURSOR_USER_QUERY_RE = /<user_query>\s*([\s\S]*?)\s*<\/user_query>/;
237
+ function cleanUserText(raw) {
238
+ let t = raw.replace(SYSTEM_REMINDER_RE, "");
239
+ const m = t.match(CURSOR_USER_QUERY_RE);
240
+ if (m)
241
+ t = m[1];
242
+ return t.trim();
243
+ }
244
+ var msFrom = (v) => {
245
+ if (typeof v === "number" && Number.isFinite(v))
246
+ return v;
247
+ if (typeof v === "string") {
248
+ const n = Date.parse(v);
249
+ return Number.isFinite(n) ? n : null;
250
+ }
251
+ return null;
252
+ };
253
+ function readCursorComposer(db, composerId) {
254
+ const cdRaw = db.get(`composerData:${composerId}`);
255
+ if (!cdRaw)
256
+ return null;
257
+ let cd;
258
+ try {
259
+ cd = JSON.parse(cdRaw);
260
+ } catch {
261
+ return null;
262
+ }
263
+ const headers = Array.isArray(cd.fullConversationHeadersOnly) ? cd.fullConversationHeadersOnly : [];
264
+ if (headers.length === 0)
265
+ return null;
266
+ const bubbles = /* @__PURE__ */ new Map();
267
+ for (const row of db.prefix(`bubbleId:${composerId}:`)) {
268
+ const bid = row.key.slice(`bubbleId:${composerId}:`.length);
269
+ try {
270
+ bubbles.set(bid, JSON.parse(row.value));
271
+ } catch {
272
+ }
273
+ }
274
+ const turns = [];
275
+ let clock = msFrom(cd.createdAt) ?? 0;
276
+ for (const h of headers) {
277
+ const b = bubbles.get(h.bubbleId);
278
+ if (!b)
279
+ continue;
280
+ const type = h.type === 1 ? 1 : 2;
281
+ const tool = type === 2 && b.toolFormerData && typeof b.toolFormerData.name === "string" ? b.toolFormerData.name : null;
282
+ const rawText = typeof b.text === "string" ? b.text : "";
283
+ const text = type === 1 ? cleanUserText(rawText) : rawText.replace(SYSTEM_REMINDER_RE, "").trim();
284
+ if (!text && !tool)
285
+ continue;
286
+ const t = msFrom(b.createdAt);
287
+ clock = Math.max(clock, t ?? clock + 1);
288
+ const model = b.modelInfo && typeof b.modelInfo.modelName === "string" ? b.modelInfo.modelName : null;
289
+ turns.push({ t: clock, type, text, tool, model });
290
+ }
291
+ if (turns.length === 0)
292
+ return null;
293
+ const gitRepo = Array.isArray(cd.trackedGitRepos) && cd.trackedGitRepos[0] && typeof cd.trackedGitRepos[0].repoPath === "string" ? cd.trackedGitRepos[0].repoPath : null;
294
+ return {
295
+ composerId,
296
+ createdAt: msFrom(cd.createdAt),
297
+ updatedAt: msFrom(cd.lastUpdatedAt),
298
+ name: typeof cd.name === "string" && cd.name.trim() ? cd.name.trim() : null,
299
+ gitRepo,
300
+ turns
301
+ };
302
+ }
303
+ function sniffCursorRaw(raw) {
304
+ for (const lineRaw of raw.split("\n")) {
305
+ const line = lineRaw.trim();
306
+ if (!line)
307
+ continue;
308
+ try {
309
+ const e = JSON.parse(line);
310
+ return (e.role === "user" || e.role === "assistant") && typeof e.message === "object" && e.message !== null && "content" in e.message && !("type" in e);
311
+ } catch {
312
+ return false;
313
+ }
314
+ }
315
+ return false;
316
+ }
317
+ function jsonlText(content) {
318
+ const parts = [];
319
+ const tools = [];
320
+ if (Array.isArray(content)) {
321
+ for (const item of content) {
322
+ if (!item || typeof item !== "object")
323
+ continue;
324
+ const it = item;
325
+ if (it.type === "text" && it.text)
326
+ parts.push(it.text);
327
+ else if (it.type === "tool_use" && it.name)
328
+ tools.push(it.name);
329
+ }
330
+ } else if (typeof content === "string")
331
+ parts.push(content);
332
+ return { text: parts.join("\n"), tools };
333
+ }
334
+ function parseCursorJsonl(raw, base) {
335
+ const turns = [];
336
+ let clock = base;
337
+ for (const lineRaw of raw.split("\n")) {
338
+ const line = lineRaw.trim();
339
+ if (!line)
340
+ continue;
341
+ let e;
342
+ try {
343
+ e = JSON.parse(line);
344
+ } catch {
345
+ continue;
346
+ }
347
+ if (e.role !== "user" && e.role !== "assistant")
348
+ continue;
349
+ const { text: rawText, tools } = jsonlText(e.message?.content);
350
+ const type = e.role === "user" ? 1 : 2;
351
+ const text = type === 1 ? cleanUserText(rawText) : rawText.replace(SYSTEM_REMINDER_RE, "").trim();
352
+ if (type === 2 && tools.length) {
353
+ for (const tool of tools) {
354
+ clock += 1;
355
+ turns.push({ t: clock, type: 2, text: "", tool, model: null });
356
+ }
357
+ }
358
+ if (!text)
359
+ continue;
360
+ clock += 1;
361
+ turns.push({ t: clock, type, text, tool: null, model: null });
362
+ }
363
+ if (turns.length === 0)
364
+ return null;
365
+ return { composerId: "", createdAt: base, updatedAt: clock, name: null, gitRepo: null, turns };
366
+ }
367
+ function cursorMessages(c) {
368
+ const out = [];
369
+ let aiStart = 0;
370
+ let aiParts = [];
371
+ const flushAI = () => {
372
+ if (!aiParts.length)
373
+ return;
374
+ out.push({ t: aiStart, role: "ai", text: aiParts.join("\n") });
375
+ aiParts = [];
376
+ };
377
+ for (const turn of c.turns) {
378
+ if (turn.type === 1) {
379
+ flushAI();
380
+ out.push({ t: turn.t, role: "user", text: turn.text });
381
+ } else {
382
+ if (aiParts.length === 0)
383
+ aiStart = turn.t;
384
+ if (turn.text)
385
+ aiParts.push(turn.text);
386
+ }
387
+ }
388
+ flushAI();
389
+ return out;
390
+ }
391
+ function composerIdFromFile(file) {
392
+ const m = file.match(/agent-transcripts\/([^/]+)\/[^/]+\.jsonl$/);
393
+ return m ? m[1] : null;
394
+ }
395
+ async function loadCursorComposer(file, raw, dbPath) {
396
+ const cid = composerIdFromFile(file);
397
+ if (cid && dbPath) {
398
+ const db = await openCursorSqlite(dbPath);
399
+ if (db) {
400
+ try {
401
+ const c = readCursorComposer(db, cid);
402
+ if (c)
403
+ return c;
404
+ } finally {
405
+ db.close();
406
+ }
407
+ }
408
+ }
409
+ return parseCursorJsonl(raw, 0);
410
+ }
411
+
412
+ // ../coding-core/dist/raw.js
413
+ import path from "path";
414
+ import os2 from "os";
415
+ var SOURCE_ROOT_ENV_VARS = [
416
+ "CLAUDE_PROJECTS_DIR",
417
+ "CODEX_SESSIONS_DIR",
418
+ "CURSOR_WORKSPACE_DIR",
419
+ "CURSOR_PROJECTS_DIR",
420
+ // Cursor's globalStorage dir (holds state.vscdb — the composer bubbles that
421
+ // carry a Cursor session's real per-turn timestamps + content). Same
422
+ // isolation contract: overriding any root disables every unset source.
423
+ "CURSOR_GLOBAL_DIR"
424
+ ];
425
+ var anyRootOverridden = () => SOURCE_ROOT_ENV_VARS.some((v) => !!process.env[v]);
426
+ function resolveSourceRoot(envVar, ...defaultSegments) {
427
+ const explicit = process.env[envVar];
428
+ if (explicit)
429
+ return explicit;
430
+ if (anyRootOverridden())
431
+ return null;
432
+ return path.join(os2.homedir(), ...defaultSegments);
433
+ }
434
+ var cursorGlobalRoot = () => resolveSourceRoot("CURSOR_GLOBAL_DIR", "Library", "Application Support", "Cursor", "User", "globalStorage");
435
+ function cursorGlobalDbPath() {
436
+ const root = cursorGlobalRoot();
437
+ return root === null ? null : path.join(root, "state.vscdb");
438
+ }
439
+ var MACHINE_CURSOR_FILE_RE = /^(.*[/\\]machines[/\\][^/\\]+[/\\]\.cursor)[/\\]projects[/\\]/;
440
+ function cursorDbPathForFile(file) {
441
+ const m = file.match(MACHINE_CURSOR_FILE_RE);
442
+ if (m)
443
+ return path.join(m[1], "globalStorage", "state.vscdb");
444
+ return cursorGlobalDbPath();
445
+ }
446
+
179
447
  // ../coding-core/dist/messages.js
180
448
  function extractText(content) {
181
449
  if (typeof content === "string")
@@ -233,12 +501,16 @@ function extractMessagesCodex(raw) {
233
501
  async function extractMessages(file) {
234
502
  let raw;
235
503
  try {
236
- raw = await fs.readFile(file, "utf-8");
504
+ raw = await fs2.readFile(file, "utf-8");
237
505
  } catch {
238
506
  return [];
239
507
  }
240
508
  if (sniffCodexRaw(raw))
241
509
  return extractMessagesCodex(raw);
510
+ if (sniffCursorRaw(raw)) {
511
+ const c = await loadCursorComposer(file, raw, cursorDbPathForFile(file));
512
+ return c ? cursorMessages(c) : [];
513
+ }
242
514
  const out = [];
243
515
  const userTexts = /* @__PURE__ */ new Set();
244
516
  const seenUuids = /* @__PURE__ */ new Set();
@@ -380,7 +652,7 @@ function proseWords(text) {
380
652
  }
381
653
 
382
654
  // ../../lib/agents/coding/profile.ts
383
- import path from "path";
655
+ import path2 from "path";
384
656
 
385
657
  // ../../lib/calibration/fingerprint.ts
386
658
  import { createHash } from "node:crypto";
@@ -530,7 +802,7 @@ var IDLE_CAP_MS = 12 * 6e4;
530
802
 
531
803
  // ../../lib/calibration/index.ts
532
804
  var DEFAULT_CALIBRATION = {
533
- version: "2026-07-16.2",
805
+ version: "2026-07-21.1",
534
806
  // = RUBRIC_FINGERPRINT of the shipped npm rubric (packages/coding-analyzer/
535
807
  // src/grade/criteria.ts). A unit test fails loud when the rubric changes
536
808
  // without this being updated (and re-pushed to the server).
@@ -626,13 +898,14 @@ var DEFAULT_CALIBRATION = {
626
898
  },
627
899
  codingBenchmarks: {
628
900
  flow: {
629
- // typical knowledge worker ≈ 35% of an 8h day focused; ~4h/day is the
630
- // recognized deep-work ceiling (Newport) 50% most sit far below it.
901
+ // typical knowledge worker ≈ 35% of an 8h day focused; the ~4h/day
902
+ // deep-work ceiling (Newport) sits nearer ~40% of a real (9-10h) top
903
+ // performer's day — 50% overstated it (owner call 2026-07-21).
631
904
  typicalPctOfDay: 0.35,
632
- topPctOfDay: 0.5,
905
+ topPctOfDay: 0.4,
633
906
  tag: "measured",
634
- source: "RescueTime 2019 (~2h48m focused/day) \xB7 Cal Newport, Deep Work (~4h/day deep-work ceiling)",
635
- line: "the best spend ~half the workday in true deep flow; ~4h/day is the human ceiling"
907
+ source: "RescueTime 2019 (~2h48m focused/day) \xB7 Cal Newport, Deep Work (~4h/day deep-work ceiling against a 9-10h day)",
908
+ line: "the best spend ~40% of the workday in true deep flow; ~4h/day is the human ceiling"
636
909
  },
637
910
  longestRun: {
638
911
  typicalHours: 0.67,
@@ -681,8 +954,8 @@ var BEST = DEFAULT_CALIBRATION.codingBenchmarks;
681
954
 
682
955
  // ../../lib/agents/coding/profile.ts
683
956
  var ROOT = process.cwd();
684
- var CODING_DIR = process.env.POLYMATH_DATA_DIR ? path.join(process.env.POLYMATH_DATA_DIR, "coding") : path.join(ROOT, ".data", "coding");
685
- var GRADES = path.join(CODING_DIR, "grades");
957
+ var CODING_DIR = process.env.POLYMATH_DATA_DIR ? path2.join(process.env.POLYMATH_DATA_DIR, "coding") : path2.join(ROOT, ".data", "coding");
958
+ var GRADES = path2.join(CODING_DIR, "grades");
686
959
 
687
960
  // ../../scripts/coding-gap-dist.mts
688
961
  var CODING = CODING_DIR;
@@ -690,7 +963,7 @@ var WPM = 130;
690
963
  var BIN = 0.5;
691
964
  var MAX = 20;
692
965
  async function main() {
693
- const sess = JSON.parse(await fs2.readFile(path2.join(CODING, "sessions.json"), "utf8")).filter((s) => !s.duplicateOf && s.klass === "interactive");
966
+ const sess = JSON.parse(await fs3.readFile(path3.join(CODING, "sessions.json"), "utf8")).filter((s) => !s.duplicateOf && s.klass === "interactive");
694
967
  const gaps = [];
695
968
  for (const s of sess) {
696
969
  let ms = [];
@@ -721,7 +994,7 @@ async function main() {
721
994
  for (let t = 0.5; t <= 15; t = Math.round((t + 0.5) * 10) / 10) curve.push({ t, fracUnder: Math.round(gaps.filter((g) => g < t).length / gaps.length * 1e3) / 1e3 });
722
995
  const pct = (p) => gaps[Math.min(gaps.length - 1, Math.floor(gaps.length * p))] ?? 0;
723
996
  const out = { generatedAt: (/* @__PURE__ */ new Date()).toISOString(), totalGaps: gaps.length, binMin: BIN, maxMin: MAX, bins, over, currentFlowGap: 5, curve, median: Math.round(pct(0.5) * 100) / 100, p25: Math.round(pct(0.25) * 100) / 100, p75: Math.round(pct(0.75) * 100) / 100, p90: Math.round(pct(0.9) * 100) / 100 };
724
- await fs2.writeFile(path2.join(CODING, "gap-dist.json"), JSON.stringify(out, null, 2));
997
+ await fs3.writeFile(path3.join(CODING, "gap-dist.json"), JSON.stringify(out, null, 2));
725
998
  const mx = Math.max(...bins.map((b) => b.count), 1);
726
999
  console.log(`gap-dist: ${gaps.length} gaps \xB7 median ${out.median}m \xB7 p75 ${out.p75}m \xB7 p90 ${out.p90}m \xB7 ${over} over ${MAX}m`);
727
1000
  bins.forEach((b) => {