polymath-society 0.2.13 → 0.2.14

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 CHANGED
@@ -1194,6 +1194,11 @@ var init_cliAdapter = __esm({
1194
1194
 
1195
1195
  // src/grade/codexAdapter.ts
1196
1196
  import { spawn as spawn3 } from "child_process";
1197
+ function mapCodexTier(model, env = process.env) {
1198
+ if (model && !/^(claude|haiku|sonnet|opus)/i.test(model)) return { model };
1199
+ if (model && /^haiku/i.test(model)) return { model: env.POLYMATH_CODEX_MODEL_MINI || CODEX_MINI_MODEL };
1200
+ return { model: env.POLYMATH_CODEX_MODEL || CODEX_DEFAULT_MODEL };
1201
+ }
1197
1202
  function composePrompt(inv, roots) {
1198
1203
  return [
1199
1204
  inv.systemPrompt ? `<system>
@@ -1204,12 +1209,14 @@ ${roots.map((r) => ` - ${r}`).join("\n")}` : "",
1204
1209
  inv.prompt
1205
1210
  ].filter(Boolean).join("\n\n");
1206
1211
  }
1207
- var codexAdapter;
1212
+ var CODEX_DEFAULT_MODEL, CODEX_MINI_MODEL, codexAdapter;
1208
1213
  var init_codexAdapter = __esm({
1209
1214
  "src/grade/codexAdapter.ts"() {
1210
1215
  "use strict";
1211
1216
  init_adapter();
1212
1217
  init_backends();
1218
+ CODEX_DEFAULT_MODEL = "gpt-5.5";
1219
+ CODEX_MINI_MODEL = "gpt-5.4-mini";
1213
1220
  codexAdapter = {
1214
1221
  name: "codex",
1215
1222
  async run(inv) {
@@ -1227,7 +1234,7 @@ var init_codexAdapter = __esm({
1227
1234
  "read-only",
1228
1235
  "--json"
1229
1236
  ];
1230
- if (inv.model && !/^claude/i.test(inv.model)) args.push("--model", inv.model);
1237
+ args.push("--model", mapCodexTier(inv.model).model);
1231
1238
  args.push(composePrompt(inv, roots));
1232
1239
  const started = Date.now();
1233
1240
  const toolCalls = [];
@@ -4185,7 +4192,10 @@ async function getAccessToken(dataDir) {
4185
4192
  headers: { "content-type": "application/json", apikey: supabaseAnonKey },
4186
4193
  body: JSON.stringify({ refresh_token: id.refreshToken })
4187
4194
  });
4188
- if (!r.ok) return null;
4195
+ if (!r.ok) {
4196
+ if (r.status >= 400 && r.status < 500) await signOut(dataDir);
4197
+ return null;
4198
+ }
4189
4199
  const fresh = await persistSession(dataDir, await r.json());
4190
4200
  return { token: fresh.accessToken, identity: fresh };
4191
4201
  } catch {
@@ -4195,7 +4205,7 @@ async function getAccessToken(dataDir) {
4195
4205
 
4196
4206
  // ../../lib/calibration/index.ts
4197
4207
  var DEFAULT_CALIBRATION = {
4198
- version: "2026-07-15.1",
4208
+ version: "2026-07-16.2",
4199
4209
  // = RUBRIC_FINGERPRINT of the shipped npm rubric (packages/coding-analyzer/
4200
4210
  // src/grade/criteria.ts). A unit test fails loud when the rubric changes
4201
4211
  // without this being updated (and re-pushed to the server).
@@ -4286,6 +4296,7 @@ var DEFAULT_CALIBRATION = {
4286
4296
  codingTiers: {
4287
4297
  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." },
4288
4298
  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." },
4299
+ hours: { median: 3, sigma: 0.4, tag: "estimated \u2014 proxy-anchored", source: "median: RescueTime-measured ~2h48m of real productive time/day (same source as the flow benchmark) \u2248 3h of active building; shape: sustaining ~7.5h/day \u2248 top 1%, a ~12h/day average \u2248 1-in-3,000. AVERAGE work-day length, cumulative not spiky." },
4289
4300
  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" }
4290
4301
  },
4291
4302
  codingBenchmarks: {
@@ -23773,6 +23784,8 @@ async function compileCodingProfile() {
23773
23784
  const avgWords = aggregate?.throughput?.avgWordsPerDay ?? null;
23774
23785
  const pushPctl = lognPct(avgWords, tiers?.push);
23775
23786
  const focusPctl = lognPct(flowPctDay, tiers?.focus);
23787
+ const workDayHrs = aggregate?.flow?.flow?.workDayHours ? Math.round(aggregate.flow.flow.workDayHours * 10) / 10 : null;
23788
+ const hoursPctl = lognPct(workDayHrs, tiers?.hours);
23776
23789
  const hoursAt = (min) => Object.entries(pHist).reduce((a, [k, v]) => Number(k) >= min ? a + v : a, 0) / 60;
23777
23790
  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;
23778
23791
  const stackUp = [
@@ -23782,14 +23795,25 @@ async function compileCodingProfile() {
23782
23795
  `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()}`
23783
23796
  ),
23784
23797
  sRow(
23785
- "How well you use AI",
23798
+ "Hours you put in",
23799
+ null,
23800
+ 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"
23801
+ ),
23802
+ sRow(
23803
+ "Your AI parallelism",
23786
23804
  ceilOf("delegation"),
23787
23805
  soloPct != null ? `~${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"
23788
23806
  ),
23807
+ // The evidence line cites the RANKING metric (flow as a share of the work
23808
+ // day), never absolute hours — a friend with MORE flow hours over a longer
23809
+ // day landed a WORSE percentile and the hours-based line read as a bug
23810
+ // (2026-07-16: "he has more hours but less percentile??"). The label says
23811
+ // "when you work" ON PURPOSE: this chip ranks quality of the hours, and
23812
+ // the volume of hours is its own chip above.
23789
23813
  sRow(
23790
- "How well you focus",
23814
+ "Focus quality when you work",
23791
23815
  focusScore,
23792
- flowHrsDay != null ? `only ~${flowHrsDay}h of your day is true deep flow \u2014 the best hold ~4h 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"
23816
+ 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"
23793
23817
  ),
23794
23818
  // The four estimates LEAD with a concrete moment from their own sessions, then an
23795
23819
  // HONEST caveat — how many graded sessions back the read. No invented weakness, no
@@ -23822,12 +23846,17 @@ async function compileCodingProfile() {
23822
23846
  r.metric = avgWords;
23823
23847
  r.curve = "push";
23824
23848
  }
23825
- if (r.label === "How well you focus" && focusPctl != null) {
23849
+ if (r.label === "Hours you put in" && hoursPctl != null) {
23850
+ r.percentile = hoursPctl;
23851
+ r.metric = workDayHrs;
23852
+ r.curve = "hours";
23853
+ }
23854
+ if (r.label === "Focus quality when you work" && focusPctl != null) {
23826
23855
  r.percentile = focusPctl;
23827
23856
  r.metric = flowPctDay;
23828
23857
  r.curve = "focus";
23829
23858
  }
23830
- if (r.label === "How well you use AI") r.percentile = orchPctl;
23859
+ if (r.label === "Your AI parallelism") r.percentile = orchPctl;
23831
23860
  }
23832
23861
  return { generatedAt: (/* @__PURE__ */ new Date()).toISOString(), gradedSessions: grades.length, agglomeration, outcomeCadence, dayDigest, dayChart, timeline, walkthroughs, rubric: rubric2, wordsByDay, dayThroughput, throughputCeiling: tCeiling, stackUp, criteria, parallelism, throughput, workstyle, flow, focus, expertiseMap, frontierArsenal, frontierDetail, coaching, gap, aggregate, delegationRollup, gapDist, projects };
23833
23862
  }
@@ -23933,7 +23962,7 @@ async function buildSkeleton(codingDir, stackUp) {
23933
23962
  ...thr.avgWordsPerDay ? [{ big: String(Math.round(thr.avgWordsPerDay).toLocaleString()), lab: "typed/dictated words per day, averaged (~300 for the median active user)" }] : [],
23934
23963
  ...thr.substantialDays ? [{ big: `${thr.substantialDays}/${thr.totalCodingDays}`, lab: "coding days were substantial (3h+ span)" }] : []
23935
23964
  ], moments: [] },
23936
- { key: "ai", label: "How they use AI", topPct: pct2("use ai"), sub: "orchestration, measured", claim: "", read: "", numbers: [
23965
+ { key: "ai", label: "How they use AI", topPct: pct2("parallelism"), sub: "orchestration, measured", claim: "", read: "", numbers: [
23937
23966
  ...par.max ? [{ big: String(par.max), lab: "agents at once, peak" }] : [],
23938
23967
  ...par.hours2plus ? [{ big: `${par.hours2plus}h`, lab: "working 2+ live agents" }] : [],
23939
23968
  ...par.queueOps ? [{ big: par.queueOps.toLocaleString(), lab: "instructions queued ahead" }] : []
@@ -24353,12 +24382,15 @@ async function handlePublicCodingPageShare(dataDir, body) {
24353
24382
  return { status: 409, json: { error: "nothing to share yet \u2014 generate your page first" } };
24354
24383
  }
24355
24384
  const chatReport = body.includeChat === false ? null : await localChatReport();
24385
+ const prior = await readOwnReportContent(cfg, auth.token, auth.identity.userId);
24356
24386
  try {
24357
- const payload = JSON.stringify({ format: "coding-pr1", page, ...chatReport ? { chatReport } : {} });
24387
+ const merged = { ...prior, format: "coding-pr1", page };
24388
+ if (chatReport) merged.chatReport = chatReport;
24389
+ else delete merged.chatReport;
24358
24390
  const up = await fetch(`${cfg.supabaseUrl}/rest/v1/rpc/submit_report`, {
24359
24391
  method: "POST",
24360
24392
  headers: { apikey: cfg.supabaseAnonKey, authorization: `Bearer ${auth.token}`, "content-type": "application/json" },
24361
- body: JSON.stringify({ p_session_id: null, p_content: payload })
24393
+ body: JSON.stringify({ p_session_id: null, p_content: JSON.stringify(merged) })
24362
24394
  });
24363
24395
  if (!up.ok) return { status: 502, json: { error: `share failed (HTTP ${up.status})` } };
24364
24396
  const verification = String(await up.json().catch(() => "unverified"));
@@ -24367,6 +24399,49 @@ async function handlePublicCodingPageShare(dataDir, body) {
24367
24399
  return { status: 502, json: { error: e.message.slice(0, 200) } };
24368
24400
  }
24369
24401
  }
24402
+ async function readOwnReportContent(cfg, token, userId) {
24403
+ try {
24404
+ const r = await fetch(`${cfg.supabaseUrl}/rest/v1/reports?user_id=eq.${encodeURIComponent(userId)}&select=content`, {
24405
+ headers: { apikey: cfg.supabaseAnonKey, authorization: `Bearer ${token}` }
24406
+ });
24407
+ if (!r.ok) return {};
24408
+ const rows = await r.json();
24409
+ const c = rows[0]?.content;
24410
+ return c && typeof c === "object" ? c : {};
24411
+ } catch {
24412
+ return {};
24413
+ }
24414
+ }
24415
+ async function handleAnalysisShare(dataDir, kind, full) {
24416
+ const cfg = centralConfig();
24417
+ if (!cfg.configured) return { status: 503, json: { error: "central services are disabled in this build" } };
24418
+ const auth = await getAccessToken(dataDir);
24419
+ if (!auth) return { status: 401, json: { error: "sign in with Google (top right) first" } };
24420
+ const slim = (p) => {
24421
+ if (!p || typeof p !== "object") return p;
24422
+ const { timeline: _t, walkthroughs: _w, dayDigest: _d, dayChart: _c, ...rest } = p;
24423
+ return rest;
24424
+ };
24425
+ const value = kind === "coding" ? slim(full.coding()) : await full.chat().catch(() => null);
24426
+ if (!value) return { status: 409, json: { error: "nothing to share yet \u2014 run the analysis first" } };
24427
+ const prior = await readOwnReportContent(cfg, auth.token, auth.identity.userId);
24428
+ try {
24429
+ const merged = {
24430
+ format: "coding-pr1",
24431
+ ...prior,
24432
+ [kind === "coding" ? "fullCoding" : "fullChat"]: value
24433
+ };
24434
+ const up = await fetch(`${cfg.supabaseUrl}/rest/v1/rpc/submit_report`, {
24435
+ method: "POST",
24436
+ headers: { apikey: cfg.supabaseAnonKey, authorization: `Bearer ${auth.token}`, "content-type": "application/json" },
24437
+ body: JSON.stringify({ p_session_id: null, p_content: JSON.stringify(merged) })
24438
+ });
24439
+ if (!up.ok) return { status: 502, json: { error: `share failed (HTTP ${up.status})` } };
24440
+ return { status: 200, json: { ok: true, kind } };
24441
+ } catch (e) {
24442
+ return { status: 502, json: { error: e.message.slice(0, 200) } };
24443
+ }
24444
+ }
24370
24445
 
24371
24446
  // src/server.ts
24372
24447
  var __dirname = path33.dirname(fileURLToPath2(import.meta.url));
@@ -24694,6 +24769,18 @@ function startServer(opts) {
24694
24769
  json(res, out.status, out.json);
24695
24770
  return;
24696
24771
  }
24772
+ if (req.method === "POST" && route === "/api/analysis/share") {
24773
+ const body = JSON.parse(await readBody(req) || "{}");
24774
+ const out = await handleAnalysisShare(dataDir, body.kind === "chat" ? "chat" : "coding", {
24775
+ coding: () => liveProfile,
24776
+ chat: async () => {
24777
+ const p = await handlePerson();
24778
+ return p.status === 200 ? p.json : null;
24779
+ }
24780
+ });
24781
+ json(res, out.status, out.json);
24782
+ return;
24783
+ }
24697
24784
  if (route.startsWith("/api/")) {
24698
24785
  json(res, 404, { error: `this viewer doesn't serve ${route}` });
24699
24786
  return;
@@ -24715,7 +24802,7 @@ function startServer(opts) {
24715
24802
  serverUrl = `http://${host}:${port}`;
24716
24803
  void getCalibration().then((cal) => {
24717
24804
  if (cal.source === "central" && cal.doc.rubricVersion !== RUBRIC_FINGERPRINT2) {
24718
- console.warn(`[polymath-society] a newer grading rubric is published (${cal.doc.rubricVersion}; this install: ${RUBRIC_FINGERPRINT2}) \u2014 update the package and re-grade to stay comparable.`);
24805
+ console.warn(`[polymath-society] you're not on the latest version \u2014 run: npm install -g polymath-society@latest`);
24719
24806
  }
24720
24807
  }).catch(() => {
24721
24808
  });
@@ -25046,15 +25133,19 @@ async function evalUpToDate(codingDir, threshold, regrade) {
25046
25133
  (await fs31.readdir(path36.join(codingDir, "grades")).catch(() => [])).filter((f) => f.endsWith(".json")).map((f) => f.slice(0, -5))
25047
25134
  );
25048
25135
  const agg = JSON.parse(await fs31.readFile(path36.join(codingDir, "aggregate.json"), "utf8").catch(() => "{}"));
25049
- return upToDateSkip({
25050
- gradableIds: gradable.map((s) => s.sessionId),
25051
- gradedIds: graded,
25052
- hasBigPicture: typeof agg.bigPicture === "string" && agg.bigPicture.trim().length > 0,
25053
- threshold,
25054
- regrade
25055
- });
25136
+ const hasPriorRun = typeof agg.bigPicture === "string" && agg.bigPicture.trim().length > 0;
25137
+ return {
25138
+ ...upToDateSkip({
25139
+ gradableIds: gradable.map((s) => s.sessionId),
25140
+ gradedIds: graded,
25141
+ hasBigPicture: hasPriorRun,
25142
+ threshold,
25143
+ regrade
25144
+ }),
25145
+ hasPriorRun
25146
+ };
25056
25147
  } catch {
25057
- return { skip: false, pending: -1 };
25148
+ return { skip: false, pending: -1, hasPriorRun: false };
25058
25149
  }
25059
25150
  }
25060
25151
  function startKeepAwake(o = {}) {
@@ -25163,6 +25254,10 @@ async function runPipeline(o) {
25163
25254
  o.onLine?.(
25164
25255
  `\u2713 report is up to date \u2014 ${gate2.pending} new session(s) since the last full run (below the ${threshold}-session threshold). Skipping the AI stages; free metrics still refresh. They'll be analyzed once ${threshold}+ accumulate (POLYMATH_MIN_NEW_SESSIONS=0 or --regrade to force now).`
25165
25256
  );
25257
+ } else if (gate2.hasPriorRun) {
25258
+ o.onLine?.(
25259
+ `\u2713 your finished report from the last run is safe and already serving at the link below \u2014 nothing restarts from scratch. ${gate2.pending >= 0 ? `${gate2.pending} pending session(s)` : "New work"} plus any stages added by an update run on top of it, and sections refresh in place as they finish.`
25260
+ );
25166
25261
  }
25167
25262
  }
25168
25263
  }
@@ -661,7 +661,7 @@ var GIFTS = [
661
661
 
662
662
  // ../../lib/calibration/index.ts
663
663
  var DEFAULT_CALIBRATION = {
664
- version: "2026-07-15.1",
664
+ version: "2026-07-16.2",
665
665
  // = RUBRIC_FINGERPRINT of the shipped npm rubric (packages/coding-analyzer/
666
666
  // src/grade/criteria.ts). A unit test fails loud when the rubric changes
667
667
  // without this being updated (and re-pushed to the server).
@@ -752,6 +752,7 @@ var DEFAULT_CALIBRATION = {
752
752
  codingTiers: {
753
753
  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." },
754
754
  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." },
755
+ hours: { median: 3, sigma: 0.4, tag: "estimated \u2014 proxy-anchored", source: "median: RescueTime-measured ~2h48m of real productive time/day (same source as the flow benchmark) \u2248 3h of active building; shape: sustaining ~7.5h/day \u2248 top 1%, a ~12h/day average \u2248 1-in-3,000. AVERAGE work-day length, cumulative not spiky." },
755
756
  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" }
756
757
  },
757
758
  codingBenchmarks: {
@@ -15656,7 +15656,7 @@ var ENGINE_DATA = process.env.POLYMATH_DATA_DIR ? path10.resolve(process.env.POL
15656
15656
 
15657
15657
  // ../../lib/calibration/index.ts
15658
15658
  var DEFAULT_CALIBRATION = {
15659
- version: "2026-07-15.1",
15659
+ version: "2026-07-16.2",
15660
15660
  // = RUBRIC_FINGERPRINT of the shipped npm rubric (packages/coding-analyzer/
15661
15661
  // src/grade/criteria.ts). A unit test fails loud when the rubric changes
15662
15662
  // without this being updated (and re-pushed to the server).
@@ -15747,6 +15747,7 @@ var DEFAULT_CALIBRATION = {
15747
15747
  codingTiers: {
15748
15748
  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." },
15749
15749
  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." },
15750
+ hours: { median: 3, sigma: 0.4, tag: "estimated \u2014 proxy-anchored", source: "median: RescueTime-measured ~2h48m of real productive time/day (same source as the flow benchmark) \u2248 3h of active building; shape: sustaining ~7.5h/day \u2248 top 1%, a ~12h/day average \u2248 1-in-3,000. AVERAGE work-day length, cumulative not spiky." },
15750
15751
  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" }
15751
15752
  },
15752
15753
  codingBenchmarks: {
@@ -15768,7 +15768,7 @@ async function materializeCorpus(importedDir, docsDir, opts = {}) {
15768
15768
  // ../../lib/agents/engine/explore.ts
15769
15769
  import { promises as fs7 } from "fs";
15770
15770
  async function runCorpusAgent(opts) {
15771
- const run2 = await invokeAgent({
15771
+ const run2 = await (opts.invoke ?? invokeAgent)({
15772
15772
  prompt: opts.prompt,
15773
15773
  systemPrompt: opts.systemPrompt,
15774
15774
  addDir: opts.docsDir,
@@ -15780,7 +15780,12 @@ async function runCorpusAgent(opts) {
15780
15780
  logPath: opts.logPath ?? opts.outFile?.replace(/\.json$/, ".toolcalls.log")
15781
15781
  });
15782
15782
  if (opts.outFile) {
15783
- const result = { generatedAt: (/* @__PURE__ */ new Date()).toISOString(), dimension: opts.dimension, raw: run2.json ?? run2.raw, costUsd: run2.costUsd };
15783
+ if (!run2.json || typeof run2.json !== "object") {
15784
+ const debris = { generatedAt: (/* @__PURE__ */ new Date()).toISOString(), dimension: opts.dimension, raw: run2.raw, costUsd: run2.costUsd };
15785
+ await fs7.writeFile(opts.outFile.replace(/\.json$/, ".failed.json"), JSON.stringify(debris, null, 2), "utf-8");
15786
+ throw new Error(`[${opts.dimension}] agent produced no JSON analysis \u2014 kept existing ${opts.outFile}, debris in .failed.json`);
15787
+ }
15788
+ const result = { generatedAt: (/* @__PURE__ */ new Date()).toISOString(), dimension: opts.dimension, raw: run2.json, costUsd: run2.costUsd };
15784
15789
  await fs7.writeFile(opts.outFile, JSON.stringify(result, null, 2), "utf-8");
15785
15790
  }
15786
15791
  return run2.json;
package/dist/index.js CHANGED
@@ -2064,6 +2064,13 @@ var cliAdapter = {
2064
2064
 
2065
2065
  // src/grade/codexAdapter.ts
2066
2066
  import { spawn as spawn2 } from "child_process";
2067
+ var CODEX_DEFAULT_MODEL = "gpt-5.5";
2068
+ var CODEX_MINI_MODEL = "gpt-5.4-mini";
2069
+ function mapCodexTier(model, env = process.env) {
2070
+ if (model && !/^(claude|haiku|sonnet|opus)/i.test(model)) return { model };
2071
+ if (model && /^haiku/i.test(model)) return { model: env.POLYMATH_CODEX_MODEL_MINI || CODEX_MINI_MODEL };
2072
+ return { model: env.POLYMATH_CODEX_MODEL || CODEX_DEFAULT_MODEL };
2073
+ }
2067
2074
  function composePrompt(inv, roots) {
2068
2075
  return [
2069
2076
  inv.systemPrompt ? `<system>
@@ -2091,7 +2098,7 @@ var codexAdapter = {
2091
2098
  "read-only",
2092
2099
  "--json"
2093
2100
  ];
2094
- if (inv.model && !/^claude/i.test(inv.model)) args.push("--model", inv.model);
2101
+ args.push("--model", mapCodexTier(inv.model).model);
2095
2102
  args.push(composePrompt(inv, roots));
2096
2103
  const started = Date.now();
2097
2104
  const toolCalls = [];
@@ -2671,7 +2678,7 @@ var LocalGradeProvider = class {
2671
2678
 
2672
2679
  // ../../lib/calibration/index.ts
2673
2680
  var DEFAULT_CALIBRATION = {
2674
- version: "2026-07-15.1",
2681
+ version: "2026-07-16.2",
2675
2682
  // = RUBRIC_FINGERPRINT of the shipped npm rubric (packages/coding-analyzer/
2676
2683
  // src/grade/criteria.ts). A unit test fails loud when the rubric changes
2677
2684
  // without this being updated (and re-pushed to the server).
@@ -2762,6 +2769,7 @@ var DEFAULT_CALIBRATION = {
2762
2769
  codingTiers: {
2763
2770
  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." },
2764
2771
  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." },
2772
+ hours: { median: 3, sigma: 0.4, tag: "estimated \u2014 proxy-anchored", source: "median: RescueTime-measured ~2h48m of real productive time/day (same source as the flow benchmark) \u2248 3h of active building; shape: sustaining ~7.5h/day \u2248 top 1%, a ~12h/day average \u2248 1-in-3,000. AVERAGE work-day length, cumulative not spiky." },
2765
2773
  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" }
2766
2774
  },
2767
2775
  codingBenchmarks: {
@@ -3135,7 +3143,10 @@ async function getAccessToken(dataDir) {
3135
3143
  headers: { "content-type": "application/json", apikey: supabaseAnonKey },
3136
3144
  body: JSON.stringify({ refresh_token: id.refreshToken })
3137
3145
  });
3138
- if (!r.ok) return null;
3146
+ if (!r.ok) {
3147
+ if (r.status >= 400 && r.status < 500) await signOut(dataDir);
3148
+ return null;
3149
+ }
3139
3150
  const fresh = await persistSession(dataDir, await r.json());
3140
3151
  return { token: fresh.accessToken, identity: fresh };
3141
3152
  } catch {
@@ -22609,6 +22620,8 @@ async function compileCodingProfile() {
22609
22620
  const avgWords = aggregate?.throughput?.avgWordsPerDay ?? null;
22610
22621
  const pushPctl = lognPct(avgWords, tiers?.push);
22611
22622
  const focusPctl = lognPct(flowPctDay, tiers?.focus);
22623
+ const workDayHrs = aggregate?.flow?.flow?.workDayHours ? Math.round(aggregate.flow.flow.workDayHours * 10) / 10 : null;
22624
+ const hoursPctl = lognPct(workDayHrs, tiers?.hours);
22612
22625
  const hoursAt = (min) => Object.entries(pHist).reduce((a, [k, v]) => Number(k) >= min ? a + v : a, 0) / 60;
22613
22626
  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;
22614
22627
  const stackUp = [
@@ -22618,14 +22631,25 @@ async function compileCodingProfile() {
22618
22631
  `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()}`
22619
22632
  ),
22620
22633
  sRow(
22621
- "How well you use AI",
22634
+ "Hours you put in",
22635
+ null,
22636
+ 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"
22637
+ ),
22638
+ sRow(
22639
+ "Your AI parallelism",
22622
22640
  ceilOf("delegation"),
22623
22641
  soloPct != null ? `~${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"
22624
22642
  ),
22643
+ // The evidence line cites the RANKING metric (flow as a share of the work
22644
+ // day), never absolute hours — a friend with MORE flow hours over a longer
22645
+ // day landed a WORSE percentile and the hours-based line read as a bug
22646
+ // (2026-07-16: "he has more hours but less percentile??"). The label says
22647
+ // "when you work" ON PURPOSE: this chip ranks quality of the hours, and
22648
+ // the volume of hours is its own chip above.
22625
22649
  sRow(
22626
- "How well you focus",
22650
+ "Focus quality when you work",
22627
22651
  focusScore,
22628
- flowHrsDay != null ? `only ~${flowHrsDay}h of your day is true deep flow \u2014 the best hold ~4h 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"
22652
+ 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"
22629
22653
  ),
22630
22654
  // The four estimates LEAD with a concrete moment from their own sessions, then an
22631
22655
  // HONEST caveat — how many graded sessions back the read. No invented weakness, no
@@ -22658,12 +22682,17 @@ async function compileCodingProfile() {
22658
22682
  r.metric = avgWords;
22659
22683
  r.curve = "push";
22660
22684
  }
22661
- if (r.label === "How well you focus" && focusPctl != null) {
22685
+ if (r.label === "Hours you put in" && hoursPctl != null) {
22686
+ r.percentile = hoursPctl;
22687
+ r.metric = workDayHrs;
22688
+ r.curve = "hours";
22689
+ }
22690
+ if (r.label === "Focus quality when you work" && focusPctl != null) {
22662
22691
  r.percentile = focusPctl;
22663
22692
  r.metric = flowPctDay;
22664
22693
  r.curve = "focus";
22665
22694
  }
22666
- if (r.label === "How well you use AI") r.percentile = orchPctl;
22695
+ if (r.label === "Your AI parallelism") r.percentile = orchPctl;
22667
22696
  }
22668
22697
  return { generatedAt: (/* @__PURE__ */ new Date()).toISOString(), gradedSessions: grades.length, agglomeration, outcomeCadence, dayDigest, dayChart, timeline, walkthroughs, rubric: rubric2, wordsByDay, dayThroughput, throughputCeiling: tCeiling, stackUp, criteria, parallelism, throughput, workstyle, flow, focus, expertiseMap, frontierArsenal, frontierDetail, coaching, gap, aggregate, delegationRollup, gapDist, projects };
22669
22698
  }
@@ -22769,7 +22798,7 @@ async function buildSkeleton(codingDir, stackUp) {
22769
22798
  ...thr.avgWordsPerDay ? [{ big: String(Math.round(thr.avgWordsPerDay).toLocaleString()), lab: "typed/dictated words per day, averaged (~300 for the median active user)" }] : [],
22770
22799
  ...thr.substantialDays ? [{ big: `${thr.substantialDays}/${thr.totalCodingDays}`, lab: "coding days were substantial (3h+ span)" }] : []
22771
22800
  ], moments: [] },
22772
- { key: "ai", label: "How they use AI", topPct: pct2("use ai"), sub: "orchestration, measured", claim: "", read: "", numbers: [
22801
+ { key: "ai", label: "How they use AI", topPct: pct2("parallelism"), sub: "orchestration, measured", claim: "", read: "", numbers: [
22773
22802
  ...par.max ? [{ big: String(par.max), lab: "agents at once, peak" }] : [],
22774
22803
  ...par.hours2plus ? [{ big: `${par.hours2plus}h`, lab: "working 2+ live agents" }] : [],
22775
22804
  ...par.queueOps ? [{ big: par.queueOps.toLocaleString(), lab: "instructions queued ahead" }] : []
@@ -23189,12 +23218,15 @@ async function handlePublicCodingPageShare(dataDir, body) {
23189
23218
  return { status: 409, json: { error: "nothing to share yet \u2014 generate your page first" } };
23190
23219
  }
23191
23220
  const chatReport = body.includeChat === false ? null : await localChatReport();
23221
+ const prior = await readOwnReportContent(cfg, auth.token, auth.identity.userId);
23192
23222
  try {
23193
- const payload = JSON.stringify({ format: "coding-pr1", page, ...chatReport ? { chatReport } : {} });
23223
+ const merged = { ...prior, format: "coding-pr1", page };
23224
+ if (chatReport) merged.chatReport = chatReport;
23225
+ else delete merged.chatReport;
23194
23226
  const up = await fetch(`${cfg.supabaseUrl}/rest/v1/rpc/submit_report`, {
23195
23227
  method: "POST",
23196
23228
  headers: { apikey: cfg.supabaseAnonKey, authorization: `Bearer ${auth.token}`, "content-type": "application/json" },
23197
- body: JSON.stringify({ p_session_id: null, p_content: payload })
23229
+ body: JSON.stringify({ p_session_id: null, p_content: JSON.stringify(merged) })
23198
23230
  });
23199
23231
  if (!up.ok) return { status: 502, json: { error: `share failed (HTTP ${up.status})` } };
23200
23232
  const verification = String(await up.json().catch(() => "unverified"));
@@ -23203,6 +23235,49 @@ async function handlePublicCodingPageShare(dataDir, body) {
23203
23235
  return { status: 502, json: { error: e.message.slice(0, 200) } };
23204
23236
  }
23205
23237
  }
23238
+ async function readOwnReportContent(cfg, token, userId) {
23239
+ try {
23240
+ const r = await fetch(`${cfg.supabaseUrl}/rest/v1/reports?user_id=eq.${encodeURIComponent(userId)}&select=content`, {
23241
+ headers: { apikey: cfg.supabaseAnonKey, authorization: `Bearer ${token}` }
23242
+ });
23243
+ if (!r.ok) return {};
23244
+ const rows = await r.json();
23245
+ const c = rows[0]?.content;
23246
+ return c && typeof c === "object" ? c : {};
23247
+ } catch {
23248
+ return {};
23249
+ }
23250
+ }
23251
+ async function handleAnalysisShare(dataDir, kind, full) {
23252
+ const cfg = centralConfig();
23253
+ if (!cfg.configured) return { status: 503, json: { error: "central services are disabled in this build" } };
23254
+ const auth = await getAccessToken(dataDir);
23255
+ if (!auth) return { status: 401, json: { error: "sign in with Google (top right) first" } };
23256
+ const slim = (p) => {
23257
+ if (!p || typeof p !== "object") return p;
23258
+ const { timeline: _t, walkthroughs: _w, dayDigest: _d, dayChart: _c, ...rest } = p;
23259
+ return rest;
23260
+ };
23261
+ const value = kind === "coding" ? slim(full.coding()) : await full.chat().catch(() => null);
23262
+ if (!value) return { status: 409, json: { error: "nothing to share yet \u2014 run the analysis first" } };
23263
+ const prior = await readOwnReportContent(cfg, auth.token, auth.identity.userId);
23264
+ try {
23265
+ const merged = {
23266
+ format: "coding-pr1",
23267
+ ...prior,
23268
+ [kind === "coding" ? "fullCoding" : "fullChat"]: value
23269
+ };
23270
+ const up = await fetch(`${cfg.supabaseUrl}/rest/v1/rpc/submit_report`, {
23271
+ method: "POST",
23272
+ headers: { apikey: cfg.supabaseAnonKey, authorization: `Bearer ${auth.token}`, "content-type": "application/json" },
23273
+ body: JSON.stringify({ p_session_id: null, p_content: JSON.stringify(merged) })
23274
+ });
23275
+ if (!up.ok) return { status: 502, json: { error: `share failed (HTTP ${up.status})` } };
23276
+ return { status: 200, json: { ok: true, kind } };
23277
+ } catch (e) {
23278
+ return { status: 502, json: { error: e.message.slice(0, 200) } };
23279
+ }
23280
+ }
23206
23281
 
23207
23282
  // src/server.ts
23208
23283
  var __dirname = path33.dirname(fileURLToPath2(import.meta.url));
@@ -23530,6 +23605,18 @@ function startServer(opts) {
23530
23605
  json(res, out.status, out.json);
23531
23606
  return;
23532
23607
  }
23608
+ if (req.method === "POST" && route === "/api/analysis/share") {
23609
+ const body = JSON.parse(await readBody(req) || "{}");
23610
+ const out = await handleAnalysisShare(dataDir, body.kind === "chat" ? "chat" : "coding", {
23611
+ coding: () => liveProfile,
23612
+ chat: async () => {
23613
+ const p = await handlePerson();
23614
+ return p.status === 200 ? p.json : null;
23615
+ }
23616
+ });
23617
+ json(res, out.status, out.json);
23618
+ return;
23619
+ }
23533
23620
  if (route.startsWith("/api/")) {
23534
23621
  json(res, 404, { error: `this viewer doesn't serve ${route}` });
23535
23622
  return;
@@ -23551,7 +23638,7 @@ function startServer(opts) {
23551
23638
  serverUrl = `http://${host}:${port}`;
23552
23639
  void getCalibration().then((cal) => {
23553
23640
  if (cal.source === "central" && cal.doc.rubricVersion !== RUBRIC_FINGERPRINT2) {
23554
- console.warn(`[polymath-society] a newer grading rubric is published (${cal.doc.rubricVersion}; this install: ${RUBRIC_FINGERPRINT2}) \u2014 update the package and re-grade to stay comparable.`);
23641
+ console.warn(`[polymath-society] you're not on the latest version \u2014 run: npm install -g polymath-society@latest`);
23555
23642
  }
23556
23643
  }).catch(() => {
23557
23644
  });
@@ -16127,7 +16127,7 @@ var TRANSCRIPT_LINE_RE = new RegExp(`^\\s*(${NOTE})((,| and) ${NOTE})*\\s*$|^\\s
16127
16127
 
16128
16128
  // ../../lib/calibration/index.ts
16129
16129
  var DEFAULT_CALIBRATION = {
16130
- version: "2026-07-15.1",
16130
+ version: "2026-07-16.2",
16131
16131
  // = RUBRIC_FINGERPRINT of the shipped npm rubric (packages/coding-analyzer/
16132
16132
  // src/grade/criteria.ts). A unit test fails loud when the rubric changes
16133
16133
  // without this being updated (and re-pushed to the server).
@@ -16218,6 +16218,7 @@ var DEFAULT_CALIBRATION = {
16218
16218
  codingTiers: {
16219
16219
  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." },
16220
16220
  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." },
16221
+ hours: { median: 3, sigma: 0.4, tag: "estimated \u2014 proxy-anchored", source: "median: RescueTime-measured ~2h48m of real productive time/day (same source as the flow benchmark) \u2248 3h of active building; shape: sustaining ~7.5h/day \u2248 top 1%, a ~12h/day average \u2248 1-in-3,000. AVERAGE work-day length, cumulative not spiky." },
16221
16222
  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" }
16222
16223
  },
16223
16224
  codingBenchmarks: {
@@ -431,7 +431,7 @@ var IDLE_CAP_MS = 12 * 6e4;
431
431
 
432
432
  // ../../lib/calibration/index.ts
433
433
  var DEFAULT_CALIBRATION = {
434
- version: "2026-07-15.1",
434
+ version: "2026-07-16.2",
435
435
  // = RUBRIC_FINGERPRINT of the shipped npm rubric (packages/coding-analyzer/
436
436
  // src/grade/criteria.ts). A unit test fails loud when the rubric changes
437
437
  // without this being updated (and re-pushed to the server).
@@ -522,6 +522,7 @@ var DEFAULT_CALIBRATION = {
522
522
  codingTiers: {
523
523
  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." },
524
524
  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." },
525
+ hours: { median: 3, sigma: 0.4, tag: "estimated \u2014 proxy-anchored", source: "median: RescueTime-measured ~2h48m of real productive time/day (same source as the flow benchmark) \u2248 3h of active building; shape: sustaining ~7.5h/day \u2248 top 1%, a ~12h/day average \u2248 1-in-3,000. AVERAGE work-day length, cumulative not spiky." },
525
526
  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" }
526
527
  },
527
528
  codingBenchmarks: {
@@ -1294,7 +1294,7 @@ var TRANSCRIPT_LINE_RE = new RegExp(`^\\s*(${NOTE})((,| and) ${NOTE})*\\s*$|^\\s
1294
1294
 
1295
1295
  // ../../lib/calibration/index.ts
1296
1296
  var DEFAULT_CALIBRATION = {
1297
- version: "2026-07-15.1",
1297
+ version: "2026-07-16.2",
1298
1298
  // = RUBRIC_FINGERPRINT of the shipped npm rubric (packages/coding-analyzer/
1299
1299
  // src/grade/criteria.ts). A unit test fails loud when the rubric changes
1300
1300
  // without this being updated (and re-pushed to the server).
@@ -1385,6 +1385,7 @@ var DEFAULT_CALIBRATION = {
1385
1385
  codingTiers: {
1386
1386
  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." },
1387
1387
  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." },
1388
+ hours: { median: 3, sigma: 0.4, tag: "estimated \u2014 proxy-anchored", source: "median: RescueTime-measured ~2h48m of real productive time/day (same source as the flow benchmark) \u2248 3h of active building; shape: sustaining ~7.5h/day \u2248 top 1%, a ~12h/day average \u2248 1-in-3,000. AVERAGE work-day length, cumulative not spiky." },
1388
1389
  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" }
1389
1390
  },
1390
1391
  codingBenchmarks: {