polymath-society 0.2.19 → 0.2.21

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 (40) hide show
  1. package/dist/cli.js +24620 -22073
  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 +19600 -17706
  17. package/dist/pipeline/FOCUS-EXAMPLES.md +127 -0
  18. package/dist/pipeline/FOCUS-RUBRIC.md +418 -0
  19. package/dist/pipeline/coding-agglomerate.js +947 -79
  20. package/dist/pipeline/coding-aggregate.js +443 -23
  21. package/dist/pipeline/coding-build.js +569 -97
  22. package/dist/pipeline/coding-coaching.js +651 -101
  23. package/dist/pipeline/coding-day-digest.js +417 -36
  24. package/dist/pipeline/coding-delegation.js +564 -68
  25. package/dist/pipeline/coding-expertise.js +477 -59
  26. package/dist/pipeline/coding-flow.js +424 -15
  27. package/dist/pipeline/coding-focus.js +507 -51
  28. package/dist/pipeline/coding-frontier-detail.js +465 -47
  29. package/dist/pipeline/coding-frontier.js +7 -6
  30. package/dist/pipeline/coding-gap-dist.js +424 -15
  31. package/dist/pipeline/coding-gap.js +679 -128
  32. package/dist/pipeline/coding-grade.js +469 -42
  33. package/dist/pipeline/coding-growth.js +17041 -0
  34. package/dist/pipeline/coding-nutshell.js +168 -151
  35. package/dist/pipeline/coding-projects.js +7 -6
  36. package/dist/pipeline/coding-walkthrough.js +461 -37
  37. package/dist/pipeline/coding-workbrief.js +16387 -0
  38. package/dist/web/app.js +2095 -1396
  39. package/dist/web/styles.css +1 -1
  40. 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;
@@ -15811,6 +15865,377 @@ function isHarnessEntry(e) {
15811
15865
  return e.isMeta === true || e.isCompactSummary === true;
15812
15866
  }
15813
15867
 
15868
+ // ../coding-core/dist/codex.js
15869
+ var SYSTEM_REMINDER_RE2 = /<system-reminder>[\s\S]*?<\/system-reminder>/g;
15870
+ var CODEX_INJECTED_TEXT_RE = /^\s*(<(environment_context|user_instructions|ENVIRONMENT_CONTEXT|turn_aborted)\b|#\s*AGENTS\.md instructions\b)/;
15871
+ function isCodexInjectedUserText(text2) {
15872
+ return CODEX_INJECTED_TEXT_RE.test(text2);
15873
+ }
15874
+ function codexContentText(content) {
15875
+ if (typeof content === "string")
15876
+ return content;
15877
+ if (!Array.isArray(content))
15878
+ return "";
15879
+ const parts = [];
15880
+ for (const item of content) {
15881
+ if (typeof item === "string") {
15882
+ parts.push(item);
15883
+ continue;
15884
+ }
15885
+ if (item && typeof item === "object") {
15886
+ const it = item;
15887
+ if (it.type === "input_text" || it.type === "output_text" || it.type === "text")
15888
+ parts.push(it.text || "");
15889
+ }
15890
+ }
15891
+ return parts.join("\n");
15892
+ }
15893
+ function sniffCodexRaw(raw) {
15894
+ let checked = 0;
15895
+ for (const lineRaw of raw.split("\n")) {
15896
+ const line = lineRaw.trim();
15897
+ if (!line)
15898
+ continue;
15899
+ if (checked++ >= 5)
15900
+ break;
15901
+ try {
15902
+ const e = JSON.parse(line);
15903
+ if (e.type === "session_meta" || e.type === "response_item" || e.type === "turn_context")
15904
+ return true;
15905
+ if (e.type === "user" || e.type === "assistant" || e.type === "summary" || e.type === "queue-operation")
15906
+ return false;
15907
+ } catch {
15908
+ }
15909
+ }
15910
+ return false;
15911
+ }
15912
+ var EXIT_CODE_RE = /(?:Process exited with code|Exit code:)\s+(\d+)/;
15913
+ function extractCodexEvents(raw) {
15914
+ const out = [];
15915
+ for (const lineRaw of raw.split("\n")) {
15916
+ const line = lineRaw.trim();
15917
+ if (!line)
15918
+ continue;
15919
+ let e;
15920
+ try {
15921
+ e = JSON.parse(line);
15922
+ } catch {
15923
+ continue;
15924
+ }
15925
+ if (e.type !== "response_item")
15926
+ continue;
15927
+ const p = e.payload ?? {};
15928
+ const t = typeof e.timestamp === "string" ? Date.parse(e.timestamp) : NaN;
15929
+ const ptype = p.type;
15930
+ if (ptype === "message") {
15931
+ const role = p.role;
15932
+ const text2 = codexContentText(p.content).replace(SYSTEM_REMINDER_RE2, "").trim();
15933
+ if (!text2)
15934
+ continue;
15935
+ if (role === "user") {
15936
+ if (isCodexInjectedUserText(text2))
15937
+ continue;
15938
+ out.push({ kind: "user", t, text: text2 });
15939
+ } else if (role === "assistant") {
15940
+ out.push({ kind: "assistant", t, text: text2 });
15941
+ }
15942
+ continue;
15943
+ }
15944
+ if (ptype === "function_call" || ptype === "custom_tool_call" || ptype === "local_shell_call") {
15945
+ const name17 = typeof p.name === "string" && p.name ? p.name : ptype === "local_shell_call" ? "shell" : String(ptype);
15946
+ const input = typeof p.arguments === "string" ? p.arguments : typeof p.input === "string" ? p.input : "";
15947
+ out.push({ kind: "tool", t, name: name17, input });
15948
+ continue;
15949
+ }
15950
+ if (ptype === "function_call_output" || ptype === "custom_tool_call_output") {
15951
+ const output = typeof p.output === "string" ? p.output : "";
15952
+ const m = EXIT_CODE_RE.exec(output.slice(0, 200));
15953
+ out.push({ kind: "tool_output", t, output, isError: !!m && m[1] !== "0" });
15954
+ }
15955
+ }
15956
+ return out;
15957
+ }
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
+
15814
16239
  // ../coding-core/dist/messages.js
15815
16240
  function extractText(content) {
15816
16241
  if (typeof content === "string")
@@ -15822,13 +16247,51 @@ function extractText(content) {
15822
16247
  function isToolResultOnly(content) {
15823
16248
  return Array.isArray(content) && content.length > 0 && content.every((c) => c && typeof c === "object" && c.type === "tool_result");
15824
16249
  }
16250
+ function extractUserMessagesCodex(raw) {
16251
+ const out = [];
16252
+ let lastTs = null;
16253
+ for (const ev of extractCodexEvents(raw)) {
16254
+ const t = ev.t;
16255
+ const gapMs = Number.isFinite(t) && lastTs != null ? t - lastTs : NaN;
16256
+ if (Number.isFinite(t))
16257
+ lastTs = t;
16258
+ if (ev.kind !== "user")
16259
+ continue;
16260
+ const text2 = humanTypedText(ev.text);
16261
+ if (text2 && Number.isFinite(t))
16262
+ out.push({ t, text: text2, gapMs });
16263
+ }
16264
+ return out.sort((a, b) => a.t - b.t);
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
+ }
15825
16282
  async function extractUserMessages(file2) {
15826
16283
  let raw;
15827
16284
  try {
15828
- raw = await fs4.readFile(file2, "utf-8");
16285
+ raw = await fs6.readFile(file2, "utf-8");
15829
16286
  } catch {
15830
16287
  return [];
15831
16288
  }
16289
+ if (sniffCodexRaw(raw))
16290
+ return extractUserMessagesCodex(raw);
16291
+ if (sniffCursorRaw(raw)) {
16292
+ const c = await loadCursorComposer(file2, raw, cursorDbPathForFile(file2));
16293
+ return c ? extractUserMessagesCursor(c) : [];
16294
+ }
15832
16295
  const out = [];
15833
16296
  const userTexts = /* @__PURE__ */ new Set();
15834
16297
  const seenUuids = /* @__PURE__ */ new Set();
@@ -15875,11 +16338,11 @@ async function extractUserMessages(file2) {
15875
16338
  }
15876
16339
 
15877
16340
  // ../../lib/agents/coding/walkthrough.ts
15878
- import { promises as fs5 } from "fs";
15879
- import path9 from "path";
16341
+ import { promises as fs7 } from "fs";
16342
+ import path10 from "path";
15880
16343
  var IDLE_CAP_MS = 12 * 6e4;
15881
16344
  async function readWalkthrough(outDir, sessionId) {
15882
- 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);
15883
16346
  }
15884
16347
 
15885
16348
  // ../coding-core/dist/words.js
@@ -16291,7 +16754,7 @@ function computeWorkstyle(inp) {
16291
16754
 
16292
16755
  // ../../lib/calibration/index.ts
16293
16756
  var DEFAULT_CALIBRATION = {
16294
- version: "2026-07-16.2",
16757
+ version: "2026-07-21.1",
16295
16758
  // = RUBRIC_FINGERPRINT of the shipped npm rubric (packages/coding-analyzer/
16296
16759
  // src/grade/criteria.ts). A unit test fails loud when the rubric changes
16297
16760
  // without this being updated (and re-pushed to the server).
@@ -16387,13 +16850,14 @@ var DEFAULT_CALIBRATION = {
16387
16850
  },
16388
16851
  codingBenchmarks: {
16389
16852
  flow: {
16390
- // typical knowledge worker ≈ 35% of an 8h day focused; ~4h/day is the
16391
- // 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).
16392
16856
  typicalPctOfDay: 0.35,
16393
- topPctOfDay: 0.5,
16857
+ topPctOfDay: 0.4,
16394
16858
  tag: "measured",
16395
- source: "RescueTime 2019 (~2h48m focused/day) \xB7 Cal Newport, Deep Work (~4h/day deep-work ceiling)",
16396
- 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"
16397
16861
  },
16398
16862
  longestRun: {
16399
16863
  typicalHours: 0.67,
@@ -16442,13 +16906,20 @@ function bandLabel(score, doc = DEFAULT_CALIBRATION) {
16442
16906
  for (const b of doc.scoreBands) if (b.score <= s && (!best || b.score > best.score)) best = b;
16443
16907
  return (best ?? doc.scoreBands[0]).label;
16444
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
+ }
16445
16916
 
16446
16917
  // ../../lib/agents/coding/benchmarks.ts
16447
16918
  var BEST = DEFAULT_CALIBRATION.codingBenchmarks;
16448
16919
 
16449
16920
  // ../../lib/agents/coding/profile.ts
16450
16921
  var ROOT = process.cwd();
16451
- 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");
16452
16923
  var UMETA = /* @__PURE__ */ new Map();
16453
16924
  async function userMeta(sessionId, file2) {
16454
16925
  const hit = UMETA.get(sessionId);
@@ -16458,9 +16929,9 @@ async function userMeta(sessionId, file2) {
16458
16929
  UMETA.set(sessionId, meta);
16459
16930
  return meta;
16460
16931
  }
16461
- var GRADES = path10.join(CODING_DIR, "grades");
16932
+ var GRADES = path11.join(CODING_DIR, "grades");
16462
16933
  async function readJson(p, fallback) {
16463
- 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);
16464
16935
  }
16465
16936
  function cadenceScore(fraction, multiRatio) {
16466
16937
  let s;
@@ -16488,21 +16959,39 @@ function distOf(takes) {
16488
16959
  const hist = [...h.keys()].sort((a, b) => b - a).map((level) => ({ level, count: h.get(level) }));
16489
16960
  return { n, observed, mean, median: median2, hist };
16490
16961
  }
16962
+ var phi = (z) => {
16963
+ const t = 1 / (1 + 0.2316419 * Math.abs(z));
16964
+ const d = 0.3989423 * Math.exp(-z * z / 2);
16965
+ let pr = d * t * (0.3193815 + t * (-0.3565638 + t * (1.781478 + t * (-1.821256 + t * 1.330274))));
16966
+ if (z > 0) pr = 1 - pr;
16967
+ return pr;
16968
+ };
16969
+ var lognPct = (x, c) => x == null || !c || x <= 0 ? null : Math.min(99.9, Math.max(0.1, Math.round(phi(Math.log(x / c.median) / c.sigma) * 1e3) / 10));
16970
+ var NO_GRADES_GAP = "no sessions graded for this yet \u2014 this fills in once grading has run";
16971
+ function estimateRowParts(score, nTakes, evidenceGap) {
16972
+ return nTakes === 0 && score == null ? { score: null, gap: NO_GRADES_GAP } : { score, gap: evidenceGap };
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
+ }
16491
16980
  async function compileCodingProfile() {
16492
- const allRecords = await readJson(path10.join(CODING_DIR, "sessions.json"), []);
16981
+ const allRecords = await readJson(path11.join(CODING_DIR, "sessions.json"), []);
16493
16982
  const dupIds = new Set(allRecords.filter((s) => s.duplicateOf).map((s) => s.sessionId));
16494
16983
  const sessions = allRecords.filter((s) => !s.duplicateOf);
16495
- const conc = await readJson(path10.join(CODING_DIR, "concurrency.json"), null);
16496
- 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"), []);
16497
16986
  const byId = new Map(sessions.map((s) => [s.sessionId, s]));
16498
16987
  let gradeFiles = [];
16499
16988
  try {
16500
- gradeFiles = (await fs6.readdir(GRADES)).filter((f) => f.endsWith(".json"));
16989
+ gradeFiles = (await fs8.readdir(GRADES)).filter((f) => f.endsWith(".json"));
16501
16990
  } catch {
16502
16991
  }
16503
16992
  const grades = [];
16504
16993
  for (const f of gradeFiles) {
16505
- const g = await readJson(path10.join(GRADES, f), null);
16994
+ const g = await readJson(path11.join(GRADES, f), null);
16506
16995
  if (g && byId.has(g.sessionId)) grades.push(g);
16507
16996
  }
16508
16997
  const takesByCriterion = /* @__PURE__ */ new Map();
@@ -16579,9 +17068,12 @@ async function compileCodingProfile() {
16579
17068
  const timeline = [...dayMap.values()].sort((a, b) => b.date.localeCompare(a.date));
16580
17069
  const levelHist = conc?.levelHistogramMin ?? {};
16581
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;
16582
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))] }));
16583
17074
  const parallelism = {
16584
17075
  maxConcurrency: conc?.maxConcurrency ?? 0,
17076
+ avgConcurrency,
16585
17077
  levelHistogramMin: levelHist,
16586
17078
  minutesAt2plus: Math.round(sumFrom(2)),
16587
17079
  minutesAt6plus: Math.round(sumFrom(6)),
@@ -16611,13 +17103,13 @@ async function compileCodingProfile() {
16611
17103
  models: Object.fromEntries([...models.entries()].sort((a, b) => b[1] - a[1])),
16612
17104
  lateNightSessions: lateNight
16613
17105
  };
16614
- const agglomeration = await readJson(path10.join(CODING_DIR, "agglomerate.json"), null);
16615
- 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);
16616
17108
  if (dayDigest?.days) dayDigest.days = dayDigest.days.map((day) => {
16617
17109
  const convs = day.conversations.filter((c) => byId.has(c.sessionId));
16618
17110
  return { ...day, conversations: convs, conversationsTouched: convs.length, totalMessages: convs.reduce((a, c) => a + c.messageCount, 0) };
16619
17111
  }).filter((day) => day.conversations.length > 0);
16620
- const dayChart = await readJson(path10.join(CODING_DIR, "day-chart.json"), []);
17112
+ const dayChart = await readJson(path11.join(CODING_DIR, "day-chart.json"), []);
16621
17113
  const intervalsBy = /* @__PURE__ */ new Map();
16622
17114
  const titleBy = /* @__PURE__ */ new Map();
16623
17115
  const fileById = new Map(sessions.map((s) => [s.sessionId, s.file]));
@@ -16636,8 +17128,8 @@ async function compileCodingProfile() {
16636
17128
  return ms;
16637
17129
  };
16638
17130
  const walkthroughs = {};
16639
- const wdir = path10.join(CODING_DIR, "walkthroughs");
16640
- 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(() => [])) {
16641
17133
  if (!f.endsWith(".json")) continue;
16642
17134
  const w = await readWalkthrough(wdir, f.replace(".json", ""));
16643
17135
  if (!w || !byId.has(w.sessionId)) continue;
@@ -16684,17 +17176,19 @@ async function compileCodingProfile() {
16684
17176
  const tCeiling = throughputCeiling(Object.values(wordsByDay));
16685
17177
  const criteriaMean = {};
16686
17178
  for (const c of criteria) criteriaMean[c.key] = { mean: c.dist.mean, n: c.dist.n };
16687
- const flow = await readJson(path10.join(CODING_DIR, "flow.json"), null);
16688
- const focus = await readJson(path10.join(CODING_DIR, "focus.json"), null);
16689
- const expertiseMap = await readJson(path10.join(CODING_DIR, "expertise.json"), null);
16690
- const frontierArsenal = await readJson(path10.join(CODING_DIR, "frontier.json"), null);
16691
- const frontierDetail = await readJson(path10.join(CODING_DIR, "frontier-detail.json"), null);
16692
- const coaching = await readJson(path10.join(CODING_DIR, "coaching.json"), null);
16693
- const gap = await readJson(path10.join(CODING_DIR, "gap.json"), null);
16694
- const aggregate = await readJson(path10.join(CODING_DIR, "aggregate.json"), null);
16695
- const delegationRollup = await readJson(path10.join(CODING_DIR, "delegation-rollup.json"), null);
16696
- const gapDist = await readJson(path10.join(CODING_DIR, "gap-dist.json"), null);
16697
- 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);
16698
17192
  const workstyle = computeWorkstyle({
16699
17193
  dayChart,
16700
17194
  tz,
@@ -16742,15 +17236,11 @@ async function compileCodingProfile() {
16742
17236
  const unb = ceilOf("unblocking");
16743
17237
  const agency = out2 != null && unb != null ? Math.round((out2 + unb) / 2) : out2 ?? unb;
16744
17238
  const sRow = (label, score, gap2) => ({ label, score, percentile: pctOf(score), gap: gap2 });
16745
- const tiers = DEFAULT_CALIBRATION.codingTiers;
16746
- const phi = (z) => {
16747
- const t = 1 / (1 + 0.2316419 * Math.abs(z));
16748
- const d = 0.3989423 * Math.exp(-z * z / 2);
16749
- let pr = d * t * (0.3193815 + t * (-0.3565638 + t * (1.781478 + t * (-1.821256 + t * 1.330274))));
16750
- if (z > 0) pr = 1 - pr;
16751
- return pr;
17239
+ const est = (label, score, key, evidenceGap) => {
17240
+ const e = estimateRowParts(score, nTk(key), evidenceGap);
17241
+ return sRow(label, e.score, e.gap);
16752
17242
  };
16753
- const lognPct = (x, c) => x == null || !c || x <= 0 ? null : Math.round(phi(Math.log(x / c.median) / c.sigma) * 1e3) / 10;
17243
+ const tiers = DEFAULT_CALIBRATION.codingTiers;
16754
17244
  const avgWords = aggregate?.throughput?.avgWordsPerDay ?? null;
16755
17245
  const pushPctl = lognPct(avgWords, tiers?.push);
16756
17246
  const focusPctl = lognPct(flowPctDay, tiers?.focus);
@@ -16758,21 +17248,37 @@ async function compileCodingProfile() {
16758
17248
  const hoursPctl = lognPct(workDayHrs, tiers?.hours);
16759
17249
  const hoursAt = (min) => Object.entries(pHist).reduce((a, [k, v]) => Number(k) >= min ? a + v : a, 0) / 60;
16760
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);
16761
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.
16762
17257
  sRow(
16763
17258
  "How hard you push",
16764
- aggregate?.throughput?.score ?? tCeiling,
16765
- `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`
16766
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).
16767
17267
  sRow(
16768
17268
  "Hours you put in",
16769
- null,
17269
+ estScore(hoursPctl),
16770
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"
16771
17271
  ),
17272
+ // The copy FOLLOWS the person's actual orchestration band (orchPctl above) —
17273
+ // a hardcoded "single biggest speed-up still on the table" once shipped to a
17274
+ // user at orchPctl 99.5 (18 agents peak, 48% of hours at 2+), flatly
17275
+ // contradicting the gap section's "already strong" on the same page
17276
+ // (2026-07-17). The still-on-the-table claim is reserved for genuinely low
17277
+ // orchestration.
16772
17278
  sRow(
16773
17279
  "Your AI parallelism",
16774
- ceilOf("delegation"),
16775
- 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"
17280
+ estScore(orchPctl),
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"
16776
17282
  ),
16777
17283
  // The evidence line cites the RANKING metric (flow as a share of the work
16778
17284
  // day), never absolute hours — a friend with MORE flow hours over a longer
@@ -16782,28 +17288,31 @@ async function compileCodingProfile() {
16782
17288
  // the volume of hours is its own chip above.
16783
17289
  sRow(
16784
17290
  "Focus quality when you work",
16785
- focusScore,
17291
+ estScore(focusPctl) ?? focusScore,
16786
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"
16787
17293
  ),
16788
17294
  // The four estimates LEAD with a concrete moment from their own sessions, then an
16789
17295
  // HONEST caveat — how many graded sessions back the read. No invented weakness, no
16790
17296
  // claim about what they "didn't" do (false specifics churn a real user); it's an estimate.
16791
- sRow(
17297
+ est(
16792
17298
  "Agency",
16793
17299
  agency,
17300
+ "outcomes",
16794
17301
  `${proud("outcomes", "you ship working systems and unblock yourself")} \u2014 one of ${nTk("outcomes")} sessions behind this read; a strong, consistent signal, still an estimate from your logs`
16795
17302
  ),
16796
17303
  // Judgement/Taste use the SAME numbers their ability cards prove (aggregate
16797
17304
  // peak-with-consistency over near-peak instances) — a chip saying "top 1%"
16798
17305
  // above a card proving 10/Top 0.1% with ten receipts reads as a bug.
16799
- sRow(
17306
+ est(
16800
17307
  "Judgement",
16801
17308
  aggregate?.ability?.abstraction?.score ?? ceilOf("generative"),
17309
+ "generative",
16802
17310
  `${proud("generative", "you make sharp, non-obvious calls on what actually matters")} \u2014 one of ${nTk("generative")} sessions we've graded for this; clear so far, not yet a final verdict`
16803
17311
  ),
16804
- sRow(
17312
+ est(
16805
17313
  "Taste",
16806
17314
  aggregate?.ability?.taste?.score ?? ceilOf("taste"),
17315
+ "taste",
16807
17316
  `${proud("taste", "you hold a high, opinionated quality bar")} \u2014 one of ${nTk("taste")} sessions behind this read; a real signal, still an estimate`
16808
17317
  )
16809
17318
  // Expertise: NO chip — the scored criterion is deprecated; the real judge is
@@ -16828,24 +17337,39 @@ async function compileCodingProfile() {
16828
17337
  }
16829
17338
  if (r.label === "Your AI parallelism") r.percentile = orchPctl;
16830
17339
  }
16831
- 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 };
16832
17356
  }
16833
17357
 
16834
17358
  // ../../lib/agents/coding/assets.ts
16835
- import { promises as fs7 } from "fs";
16836
- import path11 from "path";
17359
+ import { promises as fs9 } from "fs";
17360
+ import path12 from "path";
16837
17361
  import { fileURLToPath } from "url";
16838
- var MODULE_DIR = path11.dirname(fileURLToPath(import.meta.url));
17362
+ var MODULE_DIR = path12.dirname(fileURLToPath(import.meta.url));
16839
17363
  async function readCodingAsset(name17) {
16840
17364
  const candidates = [
16841
- path11.join(MODULE_DIR, name17),
17365
+ path12.join(MODULE_DIR, name17),
16842
17366
  // dev: beside this file · bundled: beside the bundle
16843
- path11.resolve("lib", "agents", "coding", name17)
17367
+ path12.resolve("lib", "agents", "coding", name17)
16844
17368
  // legacy cwd-relative (repo-root cwd)
16845
17369
  ];
16846
17370
  for (const p of candidates) {
16847
17371
  try {
16848
- return { text: await fs7.readFile(p, "utf8"), path: p };
17372
+ return { text: await fs9.readFile(p, "utf8"), path: p };
16849
17373
  } catch {
16850
17374
  }
16851
17375
  }
@@ -16855,12 +17379,12 @@ async function readCodingAsset(name17) {
16855
17379
  }
16856
17380
 
16857
17381
  // ../../lib/agents/coding/docsDir.ts
16858
- import { promises as fs9 } from "fs";
16859
- import path12 from "path";
17382
+ import { promises as fs11 } from "fs";
17383
+ import path13 from "path";
16860
17384
 
16861
17385
  // ../../lib/agents/coding/materialize.ts
16862
- import { promises as fs8 } from "fs";
16863
- var SYSTEM_REMINDER_RE2 = /<system-reminder>[\s\S]*?<\/system-reminder>/g;
17386
+ import { promises as fs10 } from "fs";
17387
+ var SYSTEM_REMINDER_RE3 = /<system-reminder>[\s\S]*?<\/system-reminder>/g;
16864
17388
  var INJECT_GIST = 120;
16865
17389
  var INJECTED = [
16866
17390
  { re: /<task-notification>[\s\S]*?<\/task-notification>/g, label: "bg task", gistRe: /<summary>([\s\S]*?)<\/summary>/ },
@@ -16880,7 +17404,7 @@ function collapseInjected(input) {
16880
17404
  return "";
16881
17405
  });
16882
17406
  }
16883
- return { text: text2.replace(SYSTEM_REMINDER_RE2, "").trim(), markers };
17407
+ return { text: text2.replace(SYSTEM_REMINDER_RE3, "").trim(), markers };
16884
17408
  }
16885
17409
  function extractText2(content) {
16886
17410
  if (typeof content === "string") return content;
@@ -16896,14 +17420,52 @@ function extractText2(content) {
16896
17420
  function isToolResultOnly2(content) {
16897
17421
  return Array.isArray(content) && content.length > 0 && content.every((c) => c && typeof c === "object" && c.type === "tool_result");
16898
17422
  }
16899
- var AI_GIST = 160;
17423
+ var AI_GIST2 = 160;
17424
+ function materializeCodex(raw) {
17425
+ const lines = [];
17426
+ let humanTurns = 0, humanChars = 0;
17427
+ let aiLastProse = "";
17428
+ const aiTools = /* @__PURE__ */ new Map();
17429
+ const flushAI = () => {
17430
+ if (!aiLastProse && aiTools.size === 0) return;
17431
+ const tools = [...aiTools.entries()].map(([n, c]) => c > 1 ? `${n}\xD7${c}` : n).join(", ");
17432
+ const gist = aiLastProse ? aiLastProse.length > AI_GIST2 ? aiLastProse.slice(0, AI_GIST2) + "\u2026" : aiLastProse : "";
17433
+ const bits = [];
17434
+ if (gist) bits.push(gist);
17435
+ if (tools) bits.push(`ran ${tools}`);
17436
+ lines.push(`[AI: ${bits.join(" \xB7 ")}]`);
17437
+ aiLastProse = "";
17438
+ aiTools.clear();
17439
+ };
17440
+ for (const ev of extractCodexEvents(raw)) {
17441
+ if (ev.kind === "user") {
17442
+ flushAI();
17443
+ humanTurns++;
17444
+ humanChars += ev.text.length;
17445
+ lines.push(`>> ${ev.text}`);
17446
+ } else if (ev.kind === "assistant") {
17447
+ const prose = ev.text.replace(/\s+/g, " ").trim();
17448
+ if (prose) aiLastProse = prose;
17449
+ } else if (ev.kind === "tool") {
17450
+ aiTools.set(ev.name, (aiTools.get(ev.name) ?? 0) + 1);
17451
+ }
17452
+ }
17453
+ flushAI();
17454
+ return { text: lines.join("\n"), humanTurns, humanChars };
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
+ }
16900
17460
  async function materializeSession(file2) {
16901
17461
  let raw;
16902
17462
  try {
16903
- raw = await fs8.readFile(file2, "utf-8");
17463
+ raw = await fs10.readFile(file2, "utf-8");
16904
17464
  } catch {
16905
17465
  return null;
16906
17466
  }
17467
+ if (sniffCodexRaw(raw)) return materializeCodex(raw);
17468
+ if (sniffCursorRaw(raw)) return materializeCursor(file2, raw);
16907
17469
  const lines = [];
16908
17470
  let humanTurns = 0, humanChars = 0;
16909
17471
  const pendingQueued = [];
@@ -16916,7 +17478,7 @@ async function materializeSession(file2) {
16916
17478
  const flushAI = () => {
16917
17479
  if (!aiLastProse && aiTools.size === 0) return;
16918
17480
  const tools = [...aiTools.entries()].map(([n, c]) => c > 1 ? `${n}\xD7${c}` : n).join(", ");
16919
- 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 : "";
16920
17482
  const bits = [];
16921
17483
  if (gist) bits.push(gist);
16922
17484
  if (tools) bits.push(`ran ${tools}`);
@@ -16996,10 +17558,10 @@ async function materializeSession(file2) {
16996
17558
 
16997
17559
  // ../../lib/agents/coding/docsDir.ts
16998
17560
  async function writeScoreboard(codingDir, docs) {
16999
- const gradesDir = path12.join(codingDir, "grades");
17561
+ const gradesDir = path13.join(codingDir, "grades");
17000
17562
  let files = [];
17001
17563
  try {
17002
- files = (await fs9.readdir(gradesDir)).filter((f) => f.endsWith(".json")).sort();
17564
+ files = (await fs11.readdir(gradesDir)).filter((f) => f.endsWith(".json")).sort();
17003
17565
  } catch {
17004
17566
  return;
17005
17567
  }
@@ -17007,7 +17569,7 @@ async function writeScoreboard(codingDir, docs) {
17007
17569
  for (const f of files) {
17008
17570
  let g;
17009
17571
  try {
17010
- g = JSON.parse(await fs9.readFile(path12.join(gradesDir, f), "utf8"));
17572
+ g = JSON.parse(await fs11.readFile(path13.join(gradesDir, f), "utf8"));
17011
17573
  } catch {
17012
17574
  continue;
17013
17575
  }
@@ -17023,8 +17585,8 @@ async function writeScoreboard(codingDir, docs) {
17023
17585
  ([key, rows]) => `## ${key}
17024
17586
  ${rows.sort((a, b) => b.s - a.s).map((r) => r.line).join("\n")}`
17025
17587
  );
17026
- await fs9.writeFile(
17027
- path12.join(docs, "_scoreboard.md"),
17588
+ await fs11.writeFile(
17589
+ path13.join(docs, "_scoreboard.md"),
17028
17590
  `# Scoreboard \u2014 every graded session per criterion, best first.
17029
17591
  # Lx~ = estimate. Format: level \xB7 date \xB7 title \xB7 sessionId \u2014 graded instance.
17030
17592
 
@@ -17033,24 +17595,24 @@ ${blocks.join("\n\n")}
17033
17595
  );
17034
17596
  }
17035
17597
  async function ensureCodingDocs(codingDir, sessions) {
17036
- const docs = path12.join(codingDir, "docs");
17037
- await fs9.mkdir(docs, { recursive: true });
17598
+ const docs = path13.join(codingDir, "docs");
17599
+ await fs11.mkdir(docs, { recursive: true });
17038
17600
  const user = sessions.filter((s) => s.sessionId && !s.duplicateOf && (!("klass" in s) || s.klass === "interactive"));
17039
17601
  let written = 0;
17040
17602
  for (const s of user) {
17041
- const out = path12.join(docs, `${s.sessionId}.txt`);
17603
+ const out = path13.join(docs, `${s.sessionId}.txt`);
17042
17604
  try {
17043
- await fs9.access(out);
17605
+ await fs11.access(out);
17044
17606
  continue;
17045
17607
  } catch {
17046
17608
  }
17047
17609
  const mat = await materializeSession(s.file).catch(() => null);
17048
17610
  if (!mat?.text) continue;
17049
- await fs9.writeFile(out, mat.text);
17611
+ await fs11.writeFile(out, mat.text);
17050
17612
  written++;
17051
17613
  }
17052
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}`);
17053
- 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");
17054
17616
  await writeScoreboard(codingDir, docs);
17055
17617
  if (written) console.log(`[docs] materialized ${written} new transcript(s) \u2192 ${docs}`);
17056
17618
  return docs;
@@ -17063,7 +17625,7 @@ SOURCE LOOKUP \u2014 you have Read/Grep/Glob over the working directory, which h
17063
17625
 
17064
17626
  // ../../lib/agents/coding/promptCache.ts
17065
17627
  import { createHash as createHash2 } from "crypto";
17066
- import { promises as fs10 } from "fs";
17628
+ import { promises as fs12 } from "fs";
17067
17629
  function promptSha(parts) {
17068
17630
  const h = createHash2("sha256");
17069
17631
  for (const p of parts) {
@@ -17074,7 +17636,7 @@ function promptSha(parts) {
17074
17636
  }
17075
17637
  async function reusableOutput(outPath, sha, valid, key = "promptSha") {
17076
17638
  try {
17077
- const o = JSON.parse(await fs10.readFile(outPath, "utf8"));
17639
+ const o = JSON.parse(await fs12.readFile(outPath, "utf8"));
17078
17640
  if (o[key] === sha && valid(o)) return o;
17079
17641
  } catch {
17080
17642
  }
@@ -17094,7 +17656,7 @@ var CLAUDE_AUTO_CAP = /* @__PURE__ */ new Set(["queue-ahead", "deferred-tools",
17094
17656
  var CLAUDE_AUTO_MCP = /^(visualize|Claude[_ ]?Preview|ccd[_ ]?session|ccd[_ ]?session[_ ]?mgmt|mcp[_ ]?registry)$/i;
17095
17657
  async function entrypointOf(file2) {
17096
17658
  try {
17097
- const head = (await fs11.readFile(file2, "utf8")).slice(0, 2e4);
17659
+ const head = (await fs13.readFile(file2, "utf8")).slice(0, 2e4);
17098
17660
  if (/[\/."]\.?conductor/i.test(head)) return "conductor";
17099
17661
  const m = /"entrypoint":"([^"]+)"/.exec(head);
17100
17662
  return m ? m[1] : "unknown";
@@ -17116,25 +17678,15 @@ var MOBILE_WEB = /^claude-(web|mobile|ios|android)$/;
17116
17678
  function sumTool(recs, name17) {
17117
17679
  return recs.reduce((a, s) => a + (s.toolCounts?.[name17] ?? 0), 0);
17118
17680
  }
17119
- var LOCK = path13.join(CODING, ".gap.lock");
17120
- var lockHeld = false;
17121
- async function acquireLock() {
17122
- try {
17123
- await fs11.writeFile(LOCK, String(process.pid), { flag: "wx" });
17124
- lockHeld = true;
17125
- } catch {
17126
- const pid = await fs11.readFile(LOCK, "utf8").catch(() => "?");
17127
- 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.`);
17128
- }
17129
- }
17681
+ var LOCK = path14.join(CODING, ".gap.lock");
17130
17682
  async function main() {
17131
- await acquireLock();
17683
+ releaseLock = await acquireStageLock(LOCK, "coding-gap");
17132
17684
  const p = await compileCodingProfile();
17133
17685
  const techniquesAsset = await readCodingAsset("TECHNIQUES.md");
17134
17686
  const techniques = techniquesAsset.text;
17135
- 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()})`);
17136
17688
  const writing = (await readCodingAsset("WRITING.md")).text;
17137
- 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"));
17138
17690
  const interactive = all.filter((s) => s.klass === "interactive" && s.start);
17139
17691
  const latestMs = Math.max(...interactive.map((s) => Date.parse(s.start)));
17140
17692
  const cutoffMs = latestMs - 14 * 864e5;
@@ -17191,7 +17743,7 @@ async function main() {
17191
17743
  return m ? `--- "${s.title}" \xB7 ${(s.start || "").slice(0, 10)} ---
17192
17744
  ${m.text.slice(0, 3e3)}` : "";
17193
17745
  }))).filter(Boolean);
17194
- 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 ?? [];
17195
17747
  const digestLines = digestDays.slice().sort((a, b) => a.date < b.date ? -1 : 1).slice(-21).map((d) => `${d.date}: ${d.overall ?? ""}
17196
17748
  ${(d.conversations ?? []).slice(0, 4).map((c) => ` - ${c.title ?? ""}: ${c.summary ?? ""}`).join("\n")}`).join("\n").slice(0, 12e3);
17197
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();
@@ -17221,7 +17773,7 @@ Produce the gap analysis. Be thorough: cover every relevant catalog item they're
17221
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.`;
17222
17774
  const sha = promptSha([SYS, prompt, "sonnet"]);
17223
17775
  if (!process.argv.includes("--refresh")) {
17224
- 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);
17225
17777
  if (prev) {
17226
17778
  console.log(`[gap] inputs unchanged \u2014 reusing output from ${prev.generatedAt} (--refresh to regenerate)`);
17227
17779
  return;
@@ -17244,13 +17796,12 @@ Produce the gap analysis. Be thorough: cover every relevant catalog item they're
17244
17796
  throw new Error("gap run produced 0 recommendations \u2014 refusing to overwrite the existing gap.json. Re-run the builder.");
17245
17797
  }
17246
17798
  const result = { generatedAt: (/* @__PURE__ */ new Date()).toISOString(), promptSha: sha, ...out };
17247
- 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));
17248
17800
  console.log(`WROTE ${CODING}/gap.json \u2014 recommendations:${(out.recommendations || []).length} \xB7 alreadyStrong:${(out.alreadyStrong || []).length}`);
17249
17801
  }
17802
+ var releaseLock = null;
17250
17803
  main().catch((e) => {
17251
17804
  console.error(e);
17252
17805
  process.exitCode = 1;
17253
- }).finally(() => {
17254
- if (lockHeld) fs11.rm(LOCK, { force: true }).catch(() => {
17255
- });
17256
- });
17806
+ }).finally(() => releaseLock?.().catch(() => {
17807
+ }));