polymath-society 0.2.7 → 0.2.9

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
@@ -17,9 +17,9 @@ var __export = (target, all) => {
17
17
  };
18
18
  var __copyProps = (to, from, except, desc) => {
19
19
  if (from && typeof from === "object" || typeof from === "function") {
20
- for (let key of __getOwnPropNames(from))
21
- if (!__hasOwnProp.call(to, key) && key !== except)
22
- __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
20
+ for (let key2 of __getOwnPropNames(from))
21
+ if (!__hasOwnProp.call(to, key2) && key2 !== except)
22
+ __defProp(to, key2, { get: () => from[key2], enumerable: !(desc = __getOwnPropDesc(from, key2)) || desc.enumerable });
23
23
  }
24
24
  return to;
25
25
  };
@@ -507,9 +507,9 @@ async function openCursorDb(dbPath) {
507
507
  }
508
508
  }
509
509
  return {
510
- get(key) {
510
+ get(key2) {
511
511
  try {
512
- const row = db.prepare("SELECT value FROM ItemTable WHERE key = ?").get(key);
512
+ const row = db.prepare("SELECT value FROM ItemTable WHERE key = ?").get(key2);
513
513
  if (!row || row.value == null)
514
514
  return [];
515
515
  const txt = typeof row.value === "string" ? row.value : Buffer.from(row.value).toString("utf-8");
@@ -738,10 +738,10 @@ function demoteTemplateFanouts(sessions) {
738
738
  for (const s of sessions) {
739
739
  if (s.klass !== "interactive" || s.humanTurns > 2)
740
740
  continue;
741
- const key = s.firstHuman.replace(/\s+/g, " ").trim().slice(0, FANOUT_PREFIX);
742
- if (key.length < FANOUT_PREFIX)
741
+ const key2 = s.firstHuman.replace(/\s+/g, " ").trim().slice(0, FANOUT_PREFIX);
742
+ if (key2.length < FANOUT_PREFIX)
743
743
  continue;
744
- (groups.get(key) ?? groups.set(key, []).get(key)).push(s);
744
+ (groups.get(key2) ?? groups.set(key2, []).get(key2)).push(s);
745
745
  }
746
746
  for (const g of groups.values()) {
747
747
  if (g.length < FANOUT_MIN_SESSIONS)
@@ -824,7 +824,24 @@ function partition(sessions) {
824
824
  (isGradable(s) ? gradable : isTrivial(s) ? trivial : thin).push(s);
825
825
  return { gradable, thin, trivial };
826
826
  }
827
- var GATE;
827
+ function aiWindowCutoff(sessions, opts = {}) {
828
+ const envDays = Number(process.env.POLYMATH_AI_WINDOW_DAYS);
829
+ const days = opts.windowDays ?? (Number.isFinite(envDays) && envDays >= 0 ? envDays : AI_WINDOW.days);
830
+ const floor = opts.minSessions ?? AI_WINDOW.minSessions;
831
+ if (days === 0)
832
+ return "";
833
+ const starts = sessions.map((s) => s.start ?? "").filter(Boolean).sort();
834
+ const latest = starts[starts.length - 1];
835
+ if (!latest)
836
+ return "";
837
+ const windowCutoff = new Date(new Date(latest).getTime() - days * 864e5).toISOString();
838
+ const gradableStarts = sessions.filter(isGradable).map((s) => s.start ?? "").filter(Boolean).sort().reverse();
839
+ if (gradableStarts.length <= floor)
840
+ return "";
841
+ const floorStart = gradableStarts[floor - 1];
842
+ return floorStart < windowCutoff ? floorStart : windowCutoff;
843
+ }
844
+ var GATE, AI_WINDOW;
828
845
  var init_gate = __esm({
829
846
  "../coding-core/dist/gate.js"() {
830
847
  "use strict";
@@ -837,13 +854,21 @@ var init_gate = __esm({
837
854
  // below this = a one-liner, definitely trivial
838
855
  trivialHumanTurns: 2
839
856
  };
857
+ AI_WINDOW = {
858
+ days: 90,
859
+ // ~3 months
860
+ minSessions: 40
861
+ // extend the window back until this many gradable sessions
862
+ };
840
863
  }
841
864
  });
842
865
 
843
866
  // src/gate.ts
844
867
  var gate_exports = {};
845
868
  __export(gate_exports, {
869
+ AI_WINDOW: () => AI_WINDOW,
846
870
  GATE: () => GATE,
871
+ aiWindowCutoff: () => aiWindowCutoff,
847
872
  isGradable: () => isGradable,
848
873
  isTrivial: () => isTrivial,
849
874
  partition: () => partition
@@ -1323,8 +1348,8 @@ var require_secure_json_parse = __commonJS({
1323
1348
  }
1324
1349
  delete node.constructor;
1325
1350
  }
1326
- for (const key in node) {
1327
- const value = node[key];
1351
+ for (const key2 in node) {
1352
+ const value = node[key2];
1328
1353
  if (value && typeof value === "object") {
1329
1354
  next.push(value);
1330
1355
  }
@@ -2383,7 +2408,7 @@ async function runWizard() {
2383
2408
  if (est.chatUsd > 0) say(` \u2022 chats/notes: ${sched.chatReason}`);
2384
2409
  say(` ${bold("1) Full analysis on the schedule above \u2014 RECOMMENDED")}`);
2385
2410
  say();
2386
- say(` ${bold("2)")} Full analysis, everything overnight \u2014 all grading waits for the 02:00 window`);
2411
+ say(` ${bold("2)")} Full analysis, everything overnight (deterministic part runs now) \u2014 all AI grading waits for the 02:00 window`);
2387
2412
  say(dim(` \u2022 keep your laptop plugged in`));
2388
2413
  say(dim(` \u2022 keep the lid open \u2014 closed means sleep, and the run stalls until morning`));
2389
2414
  say(` ${bold("3)")} Just the numbers \u2014 instant deterministic metrics (words/day, flow, parallelism), free, ~a minute`);
@@ -2897,10 +2922,10 @@ async function extractUserMessages(file2) {
2897
2922
  function createMessageDeduper() {
2898
2923
  const seen = /* @__PURE__ */ new Set();
2899
2924
  return (m) => {
2900
- const key = m.uuid ?? `${m.t}|${m.text}`;
2901
- if (seen.has(key))
2925
+ const key2 = m.uuid ?? `${m.t}|${m.text}`;
2926
+ if (seen.has(key2))
2902
2927
  return false;
2903
- seen.add(key);
2928
+ seen.add(key2);
2904
2929
  return true;
2905
2930
  };
2906
2931
  }
@@ -3406,8 +3431,8 @@ async function analyze(opts = {}) {
3406
3431
  const agent = raw.filter((s) => s.klass === "agent");
3407
3432
  const byReason = /* @__PURE__ */ new Map();
3408
3433
  for (const s of agent) {
3409
- const key = s.klassReason.startsWith("cwd:") ? "cwd:<agent-dir>" : s.klassReason;
3410
- byReason.set(key, (byReason.get(key) ?? 0) + 1);
3434
+ const key2 = s.klassReason.startsWith("cwd:") ? "cwd:<agent-dir>" : s.klassReason;
3435
+ byReason.set(key2, (byReason.get(key2) ?? 0) + 1);
3411
3436
  }
3412
3437
  const records = toSessionRecords(interactive, idleGapMin);
3413
3438
  const dupCount = await markDuplicates(records);
@@ -3633,9 +3658,9 @@ var UIKEY_FOR = [
3633
3658
  ["delegation", "delegation"],
3634
3659
  ["frontier", "frontier"]
3635
3660
  ];
3636
- var GRADED_CRITERIA2 = UIKEY_FOR.map(([key, uiKey]) => {
3637
- const c = GRADED_CRITERIA.find((rc) => rc.key === key);
3638
- if (!c || !c.rungs?.length) throw new Error(`repo rubric (lib/agents/coding/criteria.ts) no longer defines graded criterion "${key}" with rungs`);
3661
+ var GRADED_CRITERIA2 = UIKEY_FOR.map(([key2, uiKey]) => {
3662
+ const c = GRADED_CRITERIA.find((rc) => rc.key === key2);
3663
+ if (!c || !c.rungs?.length) throw new Error(`repo rubric (lib/agents/coding/criteria.ts) no longer defines graded criterion "${key2}" with rungs`);
3639
3664
  return { key: c.key, uiKey, label: c.label, definition: c.definition, read: c.read, rungs: c.rungs };
3640
3665
  });
3641
3666
  var RUBRIC_FINGERPRINT2 = rubricFingerprint(GRADED_CRITERIA2);
@@ -3829,15 +3854,15 @@ function validate(raw) {
3829
3854
  for (const r of arr) {
3830
3855
  if (!r || typeof r !== "object") continue;
3831
3856
  const o = r;
3832
- const key = String(o.key ?? "");
3833
- if (!keys.has(key) || seen.has(key)) continue;
3834
- seen.add(key);
3857
+ const key2 = String(o.key ?? "");
3858
+ if (!keys.has(key2) || seen.has(key2)) continue;
3859
+ seen.add(key2);
3835
3860
  const num3 = (v) => {
3836
3861
  const n = typeof v === "number" ? v : typeof v === "string" ? Number(v) : NaN;
3837
3862
  return Number.isFinite(n) && n >= 1 && n <= 11 ? Math.round(n * 100) / 100 : null;
3838
3863
  };
3839
3864
  out.push({
3840
- key,
3865
+ key: key2,
3841
3866
  score: num3(o.score),
3842
3867
  confidence: String(o.confidence ?? "firm"),
3843
3868
  low: num3(o.low),
@@ -3997,14 +4022,14 @@ function buildShareSections(p) {
3997
4022
  const w = p.workstyle;
3998
4023
  if (w) s.workstyle = { daysObserved: w.daysObserved, activeHours: w.activeHours, flowPct: agg?.flow?.flow?.pctOfWorkDay ?? null, flowHoursPerDay: w.flowHoursPerDay, peakHours: w.peakHours };
3999
4024
  if (p.projects) s.snapshot = p.projects;
4000
- const grade = (key) => {
4001
- const c = (p.criteria ?? []).find((x) => x.key === key);
4025
+ const grade = (key2) => {
4026
+ const c = (p.criteria ?? []).find((x) => x.key === key2);
4002
4027
  if (!c) return void 0;
4003
4028
  const scores = (c.takes ?? []).map((t) => t.score ?? t.best).filter((x) => x != null).sort((a, b) => b - a);
4004
4029
  return scores.length ? { score: scores[Math.min(3, scores.length) - 1], sessions: scores.length } : void 0;
4005
4030
  };
4006
- for (const [key, out] of [["abstraction", "abstraction"], ["taste", "taste"], ["delegation", "delegation"]]) {
4007
- const g = grade(key === "abstraction" ? "generative" : key);
4031
+ for (const [key2, out] of [["abstraction", "abstraction"], ["taste", "taste"], ["delegation", "delegation"]]) {
4032
+ const g = grade(key2 === "abstraction" ? "generative" : key2);
4008
4033
  if (g) s[out] = g;
4009
4034
  }
4010
4035
  return s;
@@ -4026,8 +4051,8 @@ var DEFAULT_SUPABASE_URL = "https://zcbonfjgiorrxczyekxl.supabase.co";
4026
4051
  var DEFAULT_SUPABASE_ANON_KEY = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJzdXBhYmFzZSIsInJlZiI6InpjYm9uZmpnaW9ycnhjenlla3hsIiwicm9sZSI6ImFub24iLCJpYXQiOjE3ODA3MDI5MDIsImV4cCI6MjA5NjI3ODkwMn0.f2KAwstDU765i-sUucKuzA-j0xMsKRKHVHXPRNFoud4";
4027
4052
  function centralConfig() {
4028
4053
  const url = process.env.PS_SUPABASE_URL ?? DEFAULT_SUPABASE_URL;
4029
- const key = process.env.PS_SUPABASE_ANON_KEY ?? DEFAULT_SUPABASE_ANON_KEY;
4030
- return { supabaseUrl: url, supabaseAnonKey: key, configured: Boolean(url && key) };
4054
+ const key2 = process.env.PS_SUPABASE_ANON_KEY ?? DEFAULT_SUPABASE_ANON_KEY;
4055
+ return { supabaseUrl: url, supabaseAnonKey: key2, configured: Boolean(url && key2) };
4031
4056
  }
4032
4057
 
4033
4058
  // src/auth.ts
@@ -5317,8 +5342,8 @@ function splitLines(buffer, chunk) {
5317
5342
  }
5318
5343
  function extractResponseHeaders(response) {
5319
5344
  const headers = {};
5320
- response.headers.forEach((value, key) => {
5321
- headers[key] = value;
5345
+ response.headers.forEach((value, key2) => {
5346
+ headers[key2] = value;
5322
5347
  });
5323
5348
  return headers;
5324
5349
  }
@@ -5843,19 +5868,19 @@ var getRefs = (options) => {
5843
5868
  };
5844
5869
 
5845
5870
  // ../../node_modules/zod-to-json-schema/dist/esm/errorMessages.js
5846
- function addErrorMessage(res, key, errorMessage, refs) {
5871
+ function addErrorMessage(res, key2, errorMessage, refs) {
5847
5872
  if (!refs?.errorMessages)
5848
5873
  return;
5849
5874
  if (errorMessage) {
5850
5875
  res.errorMessage = {
5851
5876
  ...res.errorMessage,
5852
- [key]: errorMessage
5877
+ [key2]: errorMessage
5853
5878
  };
5854
5879
  }
5855
5880
  }
5856
- function setResponseValueAndErrors(res, key, value, errorMessage, refs) {
5857
- res[key] = value;
5858
- addErrorMessage(res, key, errorMessage, refs);
5881
+ function setResponseValueAndErrors(res, key2, value, errorMessage, refs) {
5882
+ res[key2] = value;
5883
+ addErrorMessage(res, key2, errorMessage, refs);
5859
5884
  }
5860
5885
 
5861
5886
  // ../../node_modules/zod-to-json-schema/dist/esm/getRelativePath.js
@@ -6014,9 +6039,9 @@ var util;
6014
6039
  };
6015
6040
  util2.objectKeys = typeof Object.keys === "function" ? (obj) => Object.keys(obj) : (object2) => {
6016
6041
  const keys = [];
6017
- for (const key in object2) {
6018
- if (Object.prototype.hasOwnProperty.call(object2, key)) {
6019
- keys.push(key);
6042
+ for (const key2 in object2) {
6043
+ if (Object.prototype.hasOwnProperty.call(object2, key2)) {
6044
+ keys.push(key2);
6020
6045
  }
6021
6046
  }
6022
6047
  return keys;
@@ -6416,10 +6441,10 @@ var ParseStatus = class _ParseStatus {
6416
6441
  static async mergeObjectAsync(status, pairs) {
6417
6442
  const syncPairs = [];
6418
6443
  for (const pair of pairs) {
6419
- const key = await pair.key;
6444
+ const key2 = await pair.key;
6420
6445
  const value = await pair.value;
6421
6446
  syncPairs.push({
6422
- key,
6447
+ key: key2,
6423
6448
  value
6424
6449
  });
6425
6450
  }
@@ -6428,17 +6453,17 @@ var ParseStatus = class _ParseStatus {
6428
6453
  static mergeObjectSync(status, pairs) {
6429
6454
  const finalObject = {};
6430
6455
  for (const pair of pairs) {
6431
- const { key, value } = pair;
6432
- if (key.status === "aborted")
6456
+ const { key: key2, value } = pair;
6457
+ if (key2.status === "aborted")
6433
6458
  return INVALID;
6434
6459
  if (value.status === "aborted")
6435
6460
  return INVALID;
6436
- if (key.status === "dirty")
6461
+ if (key2.status === "dirty")
6437
6462
  status.dirty();
6438
6463
  if (value.status === "dirty")
6439
6464
  status.dirty();
6440
- if (key.value !== "__proto__" && (typeof value.value !== "undefined" || pair.alwaysSet)) {
6441
- finalObject[key.value] = value.value;
6465
+ if (key2.value !== "__proto__" && (typeof value.value !== "undefined" || pair.alwaysSet)) {
6466
+ finalObject[key2.value] = value.value;
6442
6467
  }
6443
6468
  }
6444
6469
  return { status: status.value, value: finalObject };
@@ -6463,12 +6488,12 @@ var errorUtil;
6463
6488
 
6464
6489
  // ../../node_modules/zod/v3/types.js
6465
6490
  var ParseInputLazyPath = class {
6466
- constructor(parent, value, path42, key) {
6491
+ constructor(parent, value, path42, key2) {
6467
6492
  this._cachedPath = [];
6468
6493
  this.parent = parent;
6469
6494
  this.data = value;
6470
6495
  this._path = path42;
6471
- this._key = key;
6496
+ this._key = key2;
6472
6497
  }
6473
6498
  get path() {
6474
6499
  if (!this._cachedPath.length) {
@@ -8213,9 +8238,9 @@ ZodArray.create = (schema, params) => {
8213
8238
  function deepPartialify(schema) {
8214
8239
  if (schema instanceof ZodObject) {
8215
8240
  const newShape = {};
8216
- for (const key in schema.shape) {
8217
- const fieldSchema = schema.shape[key];
8218
- newShape[key] = ZodOptional.create(deepPartialify(fieldSchema));
8241
+ for (const key2 in schema.shape) {
8242
+ const fieldSchema = schema.shape[key2];
8243
+ newShape[key2] = ZodOptional.create(deepPartialify(fieldSchema));
8219
8244
  }
8220
8245
  return new ZodObject({
8221
8246
  ...schema._def,
@@ -8266,29 +8291,29 @@ var ZodObject = class _ZodObject extends ZodType {
8266
8291
  const { shape, keys: shapeKeys } = this._getCached();
8267
8292
  const extraKeys = [];
8268
8293
  if (!(this._def.catchall instanceof ZodNever && this._def.unknownKeys === "strip")) {
8269
- for (const key in ctx.data) {
8270
- if (!shapeKeys.includes(key)) {
8271
- extraKeys.push(key);
8294
+ for (const key2 in ctx.data) {
8295
+ if (!shapeKeys.includes(key2)) {
8296
+ extraKeys.push(key2);
8272
8297
  }
8273
8298
  }
8274
8299
  }
8275
8300
  const pairs = [];
8276
- for (const key of shapeKeys) {
8277
- const keyValidator = shape[key];
8278
- const value = ctx.data[key];
8301
+ for (const key2 of shapeKeys) {
8302
+ const keyValidator = shape[key2];
8303
+ const value = ctx.data[key2];
8279
8304
  pairs.push({
8280
- key: { status: "valid", value: key },
8281
- value: keyValidator._parse(new ParseInputLazyPath(ctx, value, ctx.path, key)),
8282
- alwaysSet: key in ctx.data
8305
+ key: { status: "valid", value: key2 },
8306
+ value: keyValidator._parse(new ParseInputLazyPath(ctx, value, ctx.path, key2)),
8307
+ alwaysSet: key2 in ctx.data
8283
8308
  });
8284
8309
  }
8285
8310
  if (this._def.catchall instanceof ZodNever) {
8286
8311
  const unknownKeys = this._def.unknownKeys;
8287
8312
  if (unknownKeys === "passthrough") {
8288
- for (const key of extraKeys) {
8313
+ for (const key2 of extraKeys) {
8289
8314
  pairs.push({
8290
- key: { status: "valid", value: key },
8291
- value: { status: "valid", value: ctx.data[key] }
8315
+ key: { status: "valid", value: key2 },
8316
+ value: { status: "valid", value: ctx.data[key2] }
8292
8317
  });
8293
8318
  }
8294
8319
  } else if (unknownKeys === "strict") {
@@ -8305,15 +8330,15 @@ var ZodObject = class _ZodObject extends ZodType {
8305
8330
  }
8306
8331
  } else {
8307
8332
  const catchall = this._def.catchall;
8308
- for (const key of extraKeys) {
8309
- const value = ctx.data[key];
8333
+ for (const key2 of extraKeys) {
8334
+ const value = ctx.data[key2];
8310
8335
  pairs.push({
8311
- key: { status: "valid", value: key },
8336
+ key: { status: "valid", value: key2 },
8312
8337
  value: catchall._parse(
8313
- new ParseInputLazyPath(ctx, value, ctx.path, key)
8338
+ new ParseInputLazyPath(ctx, value, ctx.path, key2)
8314
8339
  //, ctx.child(key), value, getParsedType(value)
8315
8340
  ),
8316
- alwaysSet: key in ctx.data
8341
+ alwaysSet: key2 in ctx.data
8317
8342
  });
8318
8343
  }
8319
8344
  }
@@ -8321,10 +8346,10 @@ var ZodObject = class _ZodObject extends ZodType {
8321
8346
  return Promise.resolve().then(async () => {
8322
8347
  const syncPairs = [];
8323
8348
  for (const pair of pairs) {
8324
- const key = await pair.key;
8349
+ const key2 = await pair.key;
8325
8350
  const value = await pair.value;
8326
8351
  syncPairs.push({
8327
- key,
8352
+ key: key2,
8328
8353
  value,
8329
8354
  alwaysSet: pair.alwaysSet
8330
8355
  });
@@ -8449,8 +8474,8 @@ var ZodObject = class _ZodObject extends ZodType {
8449
8474
  // }) as any;
8450
8475
  // return merged;
8451
8476
  // }
8452
- setKey(key, schema) {
8453
- return this.augment({ [key]: schema });
8477
+ setKey(key2, schema) {
8478
+ return this.augment({ [key2]: schema });
8454
8479
  }
8455
8480
  // merge<Incoming extends AnyZodObject>(
8456
8481
  // merging: Incoming
@@ -8481,9 +8506,9 @@ var ZodObject = class _ZodObject extends ZodType {
8481
8506
  }
8482
8507
  pick(mask) {
8483
8508
  const shape = {};
8484
- for (const key of util.objectKeys(mask)) {
8485
- if (mask[key] && this.shape[key]) {
8486
- shape[key] = this.shape[key];
8509
+ for (const key2 of util.objectKeys(mask)) {
8510
+ if (mask[key2] && this.shape[key2]) {
8511
+ shape[key2] = this.shape[key2];
8487
8512
  }
8488
8513
  }
8489
8514
  return new _ZodObject({
@@ -8493,9 +8518,9 @@ var ZodObject = class _ZodObject extends ZodType {
8493
8518
  }
8494
8519
  omit(mask) {
8495
8520
  const shape = {};
8496
- for (const key of util.objectKeys(this.shape)) {
8497
- if (!mask[key]) {
8498
- shape[key] = this.shape[key];
8521
+ for (const key2 of util.objectKeys(this.shape)) {
8522
+ if (!mask[key2]) {
8523
+ shape[key2] = this.shape[key2];
8499
8524
  }
8500
8525
  }
8501
8526
  return new _ZodObject({
@@ -8511,12 +8536,12 @@ var ZodObject = class _ZodObject extends ZodType {
8511
8536
  }
8512
8537
  partial(mask) {
8513
8538
  const newShape = {};
8514
- for (const key of util.objectKeys(this.shape)) {
8515
- const fieldSchema = this.shape[key];
8516
- if (mask && !mask[key]) {
8517
- newShape[key] = fieldSchema;
8539
+ for (const key2 of util.objectKeys(this.shape)) {
8540
+ const fieldSchema = this.shape[key2];
8541
+ if (mask && !mask[key2]) {
8542
+ newShape[key2] = fieldSchema;
8518
8543
  } else {
8519
- newShape[key] = fieldSchema.optional();
8544
+ newShape[key2] = fieldSchema.optional();
8520
8545
  }
8521
8546
  }
8522
8547
  return new _ZodObject({
@@ -8526,16 +8551,16 @@ var ZodObject = class _ZodObject extends ZodType {
8526
8551
  }
8527
8552
  required(mask) {
8528
8553
  const newShape = {};
8529
- for (const key of util.objectKeys(this.shape)) {
8530
- if (mask && !mask[key]) {
8531
- newShape[key] = this.shape[key];
8554
+ for (const key2 of util.objectKeys(this.shape)) {
8555
+ if (mask && !mask[key2]) {
8556
+ newShape[key2] = this.shape[key2];
8532
8557
  } else {
8533
- const fieldSchema = this.shape[key];
8558
+ const fieldSchema = this.shape[key2];
8534
8559
  let newField = fieldSchema;
8535
8560
  while (newField instanceof ZodOptional) {
8536
8561
  newField = newField._def.innerType;
8537
8562
  }
8538
- newShape[key] = newField;
8563
+ newShape[key2] = newField;
8539
8564
  }
8540
8565
  }
8541
8566
  return new _ZodObject({
@@ -8779,14 +8804,14 @@ function mergeValues(a, b) {
8779
8804
  return { valid: true, data: a };
8780
8805
  } else if (aType === ZodParsedType.object && bType === ZodParsedType.object) {
8781
8806
  const bKeys = util.objectKeys(b);
8782
- const sharedKeys = util.objectKeys(a).filter((key) => bKeys.indexOf(key) !== -1);
8807
+ const sharedKeys = util.objectKeys(a).filter((key2) => bKeys.indexOf(key2) !== -1);
8783
8808
  const newObj = { ...a, ...b };
8784
- for (const key of sharedKeys) {
8785
- const sharedValue = mergeValues(a[key], b[key]);
8809
+ for (const key2 of sharedKeys) {
8810
+ const sharedValue = mergeValues(a[key2], b[key2]);
8786
8811
  if (!sharedValue.valid) {
8787
8812
  return { valid: false };
8788
8813
  }
8789
- newObj[key] = sharedValue.data;
8814
+ newObj[key2] = sharedValue.data;
8790
8815
  }
8791
8816
  return { valid: true, data: newObj };
8792
8817
  } else if (aType === ZodParsedType.array && bType === ZodParsedType.array) {
@@ -8950,11 +8975,11 @@ var ZodRecord = class _ZodRecord extends ZodType {
8950
8975
  const pairs = [];
8951
8976
  const keyType = this._def.keyType;
8952
8977
  const valueType = this._def.valueType;
8953
- for (const key in ctx.data) {
8978
+ for (const key2 in ctx.data) {
8954
8979
  pairs.push({
8955
- key: keyType._parse(new ParseInputLazyPath(ctx, key, ctx.path, key)),
8956
- value: valueType._parse(new ParseInputLazyPath(ctx, ctx.data[key], ctx.path, key)),
8957
- alwaysSet: key in ctx.data
8980
+ key: keyType._parse(new ParseInputLazyPath(ctx, key2, ctx.path, key2)),
8981
+ value: valueType._parse(new ParseInputLazyPath(ctx, ctx.data[key2], ctx.path, key2)),
8982
+ alwaysSet: key2 in ctx.data
8958
8983
  });
8959
8984
  }
8960
8985
  if (ctx.common.async) {
@@ -9002,9 +9027,9 @@ var ZodMap = class extends ZodType {
9002
9027
  }
9003
9028
  const keyType = this._def.keyType;
9004
9029
  const valueType = this._def.valueType;
9005
- const pairs = [...ctx.data.entries()].map(([key, value], index) => {
9030
+ const pairs = [...ctx.data.entries()].map(([key2, value], index) => {
9006
9031
  return {
9007
- key: keyType._parse(new ParseInputLazyPath(ctx, key, ctx.path, [index, "key"])),
9032
+ key: keyType._parse(new ParseInputLazyPath(ctx, key2, ctx.path, [index, "key"])),
9008
9033
  value: valueType._parse(new ParseInputLazyPath(ctx, value, ctx.path, [index, "value"]))
9009
9034
  };
9010
9035
  });
@@ -9012,30 +9037,30 @@ var ZodMap = class extends ZodType {
9012
9037
  const finalMap = /* @__PURE__ */ new Map();
9013
9038
  return Promise.resolve().then(async () => {
9014
9039
  for (const pair of pairs) {
9015
- const key = await pair.key;
9040
+ const key2 = await pair.key;
9016
9041
  const value = await pair.value;
9017
- if (key.status === "aborted" || value.status === "aborted") {
9042
+ if (key2.status === "aborted" || value.status === "aborted") {
9018
9043
  return INVALID;
9019
9044
  }
9020
- if (key.status === "dirty" || value.status === "dirty") {
9045
+ if (key2.status === "dirty" || value.status === "dirty") {
9021
9046
  status.dirty();
9022
9047
  }
9023
- finalMap.set(key.value, value.value);
9048
+ finalMap.set(key2.value, value.value);
9024
9049
  }
9025
9050
  return { status: status.value, value: finalMap };
9026
9051
  });
9027
9052
  } else {
9028
9053
  const finalMap = /* @__PURE__ */ new Map();
9029
9054
  for (const pair of pairs) {
9030
- const key = pair.key;
9055
+ const key2 = pair.key;
9031
9056
  const value = pair.value;
9032
- if (key.status === "aborted" || value.status === "aborted") {
9057
+ if (key2.status === "aborted" || value.status === "aborted") {
9033
9058
  return INVALID;
9034
9059
  }
9035
- if (key.status === "dirty" || value.status === "dirty") {
9060
+ if (key2.status === "dirty" || value.status === "dirty") {
9036
9061
  status.dirty();
9037
9062
  }
9038
- finalMap.set(key.value, value.value);
9063
+ finalMap.set(key2.value, value.value);
9039
9064
  }
9040
9065
  return { status: status.value, value: finalMap };
9041
9066
  }
@@ -10488,11 +10513,11 @@ function parseRecordDef(def, refs) {
10488
10513
  return {
10489
10514
  type: "object",
10490
10515
  required: def.keyType._def.values,
10491
- properties: def.keyType._def.values.reduce((acc, key) => ({
10516
+ properties: def.keyType._def.values.reduce((acc, key2) => ({
10492
10517
  ...acc,
10493
- [key]: parseDef(def.valueType._def, {
10518
+ [key2]: parseDef(def.valueType._def, {
10494
10519
  ...refs,
10495
- currentPath: [...refs.currentPath, "properties", key]
10520
+ currentPath: [...refs.currentPath, "properties", key2]
10496
10521
  }) ?? parseAnyDef(refs)
10497
10522
  }), {}),
10498
10523
  additionalProperties: refs.rejectedAdditionalProperties
@@ -10559,10 +10584,10 @@ function parseMapDef(def, refs) {
10559
10584
  // ../../node_modules/zod-to-json-schema/dist/esm/parsers/nativeEnum.js
10560
10585
  function parseNativeEnumDef(def) {
10561
10586
  const object2 = def.values;
10562
- const actualKeys = Object.keys(def.values).filter((key) => {
10563
- return typeof object2[object2[key]] !== "number";
10587
+ const actualKeys = Object.keys(def.values).filter((key2) => {
10588
+ return typeof object2[object2[key2]] !== "number";
10564
10589
  });
10565
- const actualValues = actualKeys.map((key) => object2[key]);
10590
+ const actualValues = actualKeys.map((key2) => object2[key2]);
10566
10591
  const parsedTypes = Array.from(new Set(actualValues.map((values) => typeof values)));
10567
10592
  return {
10568
10593
  type: parsedTypes.length === 1 ? parsedTypes[0] === "string" ? "string" : "number" : ["string", "number"],
@@ -12175,17 +12200,17 @@ var BaseContext = (
12175
12200
  function BaseContext2(parentContext) {
12176
12201
  var self = this;
12177
12202
  self._currentContext = parentContext ? new Map(parentContext) : /* @__PURE__ */ new Map();
12178
- self.getValue = function(key) {
12179
- return self._currentContext.get(key);
12203
+ self.getValue = function(key2) {
12204
+ return self._currentContext.get(key2);
12180
12205
  };
12181
- self.setValue = function(key, value) {
12206
+ self.setValue = function(key2, value) {
12182
12207
  var context = new BaseContext2(self._currentContext);
12183
- context._currentContext.set(key, value);
12208
+ context._currentContext.set(key2, value);
12184
12209
  return context;
12185
12210
  };
12186
- self.deleteValue = function(key) {
12211
+ self.deleteValue = function(key2) {
12187
12212
  var context = new BaseContext2(self._currentContext);
12188
- context._currentContext.delete(key);
12213
+ context._currentContext.delete(key2);
12189
12214
  return context;
12190
12215
  };
12191
12216
  }
@@ -12763,22 +12788,22 @@ function getBaseTelemetryAttributes({
12763
12788
  "ai.model.provider": model.provider,
12764
12789
  "ai.model.id": model.modelId,
12765
12790
  // settings:
12766
- ...Object.entries(settings).reduce((attributes, [key, value]) => {
12767
- attributes[`ai.settings.${key}`] = value;
12791
+ ...Object.entries(settings).reduce((attributes, [key2, value]) => {
12792
+ attributes[`ai.settings.${key2}`] = value;
12768
12793
  return attributes;
12769
12794
  }, {}),
12770
12795
  // add metadata as attributes:
12771
12796
  ...Object.entries((_a17 = telemetry == null ? void 0 : telemetry.metadata) != null ? _a17 : {}).reduce(
12772
- (attributes, [key, value]) => {
12773
- attributes[`ai.telemetry.metadata.${key}`] = value;
12797
+ (attributes, [key2, value]) => {
12798
+ attributes[`ai.telemetry.metadata.${key2}`] = value;
12774
12799
  return attributes;
12775
12800
  },
12776
12801
  {}
12777
12802
  ),
12778
12803
  // request headers
12779
- ...Object.entries(headers != null ? headers : {}).reduce((attributes, [key, value]) => {
12804
+ ...Object.entries(headers != null ? headers : {}).reduce((attributes, [key2, value]) => {
12780
12805
  if (value !== void 0) {
12781
- attributes[`ai.request.headers.${key}`] = value;
12806
+ attributes[`ai.request.headers.${key2}`] = value;
12782
12807
  }
12783
12808
  return attributes;
12784
12809
  }, {})
@@ -12898,7 +12923,7 @@ function selectTelemetryAttributes({
12898
12923
  if ((telemetry == null ? void 0 : telemetry.isEnabled) !== true) {
12899
12924
  return {};
12900
12925
  }
12901
- return Object.entries(attributes).reduce((attributes2, [key, value]) => {
12926
+ return Object.entries(attributes).reduce((attributes2, [key2, value]) => {
12902
12927
  if (value === void 0) {
12903
12928
  return attributes2;
12904
12929
  }
@@ -12907,16 +12932,16 @@ function selectTelemetryAttributes({
12907
12932
  return attributes2;
12908
12933
  }
12909
12934
  const result = value.input();
12910
- return result === void 0 ? attributes2 : { ...attributes2, [key]: result };
12935
+ return result === void 0 ? attributes2 : { ...attributes2, [key2]: result };
12911
12936
  }
12912
12937
  if (typeof value === "object" && "output" in value && typeof value.output === "function") {
12913
12938
  if ((telemetry == null ? void 0 : telemetry.recordOutputs) === false) {
12914
12939
  return attributes2;
12915
12940
  }
12916
12941
  const result = value.output();
12917
- return result === void 0 ? attributes2 : { ...attributes2, [key]: result };
12942
+ return result === void 0 ? attributes2 : { ...attributes2, [key2]: result };
12918
12943
  }
12919
- return { ...attributes2, [key]: value };
12944
+ return { ...attributes2, [key2]: value };
12920
12945
  }, {});
12921
12946
  }
12922
12947
  var name32 = "AI_NoImageGeneratedError";
@@ -18214,10 +18239,10 @@ var OpenAITranscriptionModel = class {
18214
18239
  temperature: (_d = openAIOptions.temperature) != null ? _d : void 0,
18215
18240
  timestamp_granularities: (_e = openAIOptions.timestampGranularities) != null ? _e : void 0
18216
18241
  };
18217
- for (const key in transcriptionModelOptions) {
18218
- const value = transcriptionModelOptions[key];
18242
+ for (const key2 in transcriptionModelOptions) {
18243
+ const value = transcriptionModelOptions[key2];
18219
18244
  if (value !== void 0) {
18220
- formData.append(key, String(value));
18245
+ formData.append(key2, String(value));
18221
18246
  }
18222
18247
  }
18223
18248
  }
@@ -19190,10 +19215,10 @@ var OpenAISpeechModel = class {
19190
19215
  }
19191
19216
  if (openAIOptions) {
19192
19217
  const speechModelOptions = {};
19193
- for (const key in speechModelOptions) {
19194
- const value = speechModelOptions[key];
19218
+ for (const key2 in speechModelOptions) {
19219
+ const value = speechModelOptions[key2];
19195
19220
  if (value !== void 0) {
19196
- requestBody[key] = value;
19221
+ requestBody[key2] = value;
19197
19222
  }
19198
19223
  }
19199
19224
  }
@@ -21551,28 +21576,28 @@ function runDiagnostic(input) {
21551
21576
  var REG = globalThis.__polymathDiagJobs ??= /* @__PURE__ */ new Map();
21552
21577
  var MAX_ATTEMPTS = 3;
21553
21578
  var BACKOFF_MS = 3e4;
21554
- async function runWithRetries(key, input) {
21579
+ async function runWithRetries(key2, input) {
21555
21580
  let last;
21556
21581
  for (let attempt = 1; attempt <= MAX_ATTEMPTS; attempt++) {
21557
21582
  try {
21558
21583
  return await runDiagnostic(input);
21559
21584
  } catch (e) {
21560
21585
  last = e;
21561
- console.warn(`[feedback/diagnostic] ${key}: attempt ${attempt}/${MAX_ATTEMPTS} failed \u2014 ${String(e?.message || e).slice(0, 160)}`);
21586
+ console.warn(`[feedback/diagnostic] ${key2}: attempt ${attempt}/${MAX_ATTEMPTS} failed \u2014 ${String(e?.message || e).slice(0, 160)}`);
21562
21587
  if (attempt < MAX_ATTEMPTS) await new Promise((r) => setTimeout(r, BACKOFF_MS * attempt));
21563
21588
  }
21564
21589
  }
21565
21590
  throw last;
21566
21591
  }
21567
- function startDiagnosticJob(key, input) {
21568
- const cur = REG.get(key);
21592
+ function startDiagnosticJob(key2, input) {
21593
+ const cur = REG.get(key2);
21569
21594
  if (cur && cur.status === "running") return cur;
21570
21595
  const rec = { status: "running", startedAt: Date.now() };
21571
- REG.set(key, rec);
21572
- runWithRetries(key, input).then(async (result) => {
21596
+ REG.set(key2, rec);
21597
+ runWithRetries(key2, input).then(async (result) => {
21573
21598
  rec.status = "done";
21574
21599
  rec.result = result;
21575
- await mergeIntoStateFile(key, result).catch(() => {
21600
+ await mergeIntoStateFile(key2, result).catch(() => {
21576
21601
  });
21577
21602
  }).catch((e) => {
21578
21603
  rec.status = "failed";
@@ -21580,14 +21605,14 @@ function startDiagnosticJob(key, input) {
21580
21605
  });
21581
21606
  return rec;
21582
21607
  }
21583
- function diagnosticJobStatus(key) {
21584
- return REG.get(key) ?? null;
21608
+ function diagnosticJobStatus(key2) {
21609
+ return REG.get(key2) ?? null;
21585
21610
  }
21586
- async function mergeIntoStateFile(key, diagnostic) {
21611
+ async function mergeIntoStateFile(key2, diagnostic) {
21587
21612
  const FILE = path18.join(process.env.POLYMATH_DATA_DIR || path18.join(process.cwd(), ".data"), "engine-pilot", "feedback-jobs.json");
21588
21613
  const s = await fs13.readFile(FILE, "utf8").then(JSON.parse).catch(() => ({ version: 1, jobs: {} }));
21589
21614
  const jobs = s.jobs || {};
21590
- const j = jobs[key];
21615
+ const j = jobs[key2];
21591
21616
  if (!j) return;
21592
21617
  j.draft = j.draft || {};
21593
21618
  j.draft.evidence = { ...j.draft.evidence || {}, diagnostic };
@@ -21623,17 +21648,17 @@ async function readJobs(dataDir) {
21623
21648
  async function handleState(dataDir, method, body) {
21624
21649
  const s = await readJobs(dataDir);
21625
21650
  if (method === "GET") return { status: 200, json: { jobs: s.jobs || {} } };
21626
- const key = typeof body?.key === "string" ? body.key.slice(0, 120) : "";
21627
- if (!key) return { status: 400, json: { error: "missing key" } };
21651
+ const key2 = typeof body?.key === "string" ? body.key.slice(0, 120) : "";
21652
+ if (!key2) return { status: 400, json: { error: "missing key" } };
21628
21653
  const jobs = s.jobs || {};
21629
- if (body?.job == null) delete jobs[key];
21654
+ if (body?.job == null) delete jobs[key2];
21630
21655
  else {
21631
21656
  try {
21632
21657
  if (JSON.stringify(body.job).length > 3e5) return { status: 413, json: { error: "job too large" } };
21633
21658
  } catch {
21634
21659
  return { status: 400, json: { error: "bad job" } };
21635
21660
  }
21636
- jobs[key] = body.job;
21661
+ jobs[key2] = body.job;
21637
21662
  }
21638
21663
  await fs14.mkdir(dataDir, { recursive: true });
21639
21664
  await fs14.writeFile(jobsFile(dataDir), JSON.stringify({ version: 1, jobs }, null, 2), "utf8");
@@ -21690,7 +21715,7 @@ async function handleSubmit(dataDir, body) {
21690
21715
  console.error(` [feedback/submit] stored ${String(row.id)} (${sectionKey}) for ${auth.identity.email}`);
21691
21716
  return { status: 200, json: { ok: true, verified: row } };
21692
21717
  }
21693
- function handleDiagnostic(method, body, key) {
21718
+ function handleDiagnostic(method, body, key2) {
21694
21719
  if (method === "POST") {
21695
21720
  const b = body ?? {};
21696
21721
  if (!(b.rawFeedback || "").trim()) return { status: 400, json: { error: "no feedback" } };
@@ -21701,7 +21726,7 @@ function handleDiagnostic(method, body, key) {
21701
21726
  const job2 = startDiagnosticJob(k2, { reportKind, sectionLabel: b.sectionLabel, rawFeedback: b.rawFeedback, locus: b.locus, evidence: b.evidence });
21702
21727
  return { status: 200, json: { status: job2.status, startedAt: job2.startedAt, ...job2.status === "done" ? { diagnostic: job2.result } : {} } };
21703
21728
  }
21704
- const k = (key || "").trim().slice(0, 120);
21729
+ const k = (key2 || "").trim().slice(0, 120);
21705
21730
  if (!k) return { status: 400, json: { error: "missing key" } };
21706
21731
  const job = diagnosticJobStatus(k);
21707
21732
  if (!job) return { status: 200, json: { status: "none" } };
@@ -21874,8 +21899,8 @@ async function buildCorpusDocs(importedDir, opts = {}) {
21874
21899
  );
21875
21900
  const bySession = /* @__PURE__ */ new Map();
21876
21901
  for (const it of items) {
21877
- const key = it.sessionId ?? `${source}:${it.timestamp.slice(0, 10)}`;
21878
- (bySession.get(key) ?? bySession.set(key, []).get(key)).push(it);
21902
+ const key2 = it.sessionId ?? `${source}:${it.timestamp.slice(0, 10)}`;
21903
+ (bySession.get(key2) ?? bySession.set(key2, []).get(key2)).push(it);
21879
21904
  }
21880
21905
  for (const [, session] of bySession) {
21881
21906
  session.sort((a, b) => a.timestamp.localeCompare(b.timestamp));
@@ -21973,14 +21998,14 @@ async function loadFacetTakes(lensKey, idx) {
21973
21998
  if (!Array.isArray(facets2)) continue;
21974
21999
  const meta = idx[id] || { title: "", date: "", source: "" };
21975
22000
  for (const f of facets2) {
21976
- const key = String(f.facetKey || "");
21977
- if (!key) continue;
22001
+ const key2 = String(f.facetKey || "");
22002
+ if (!key2) continue;
21978
22003
  const score = typeof f.score === "number" ? f.score : null;
21979
22004
  const best = typeof f.bestEstimate === "number" ? f.bestEstimate : null;
21980
22005
  if (score == null && best == null) continue;
21981
22006
  const t = { id, title: meta.title || id, date: meta.date || "", source: meta.source || void 0, score, best, low: num2(f.low), high: num2(f.high), confidence: String(f.confidence || ""), gist: String(f.why || "").replace(/\s+/g, " ").trim().slice(0, 220) };
21982
- if (!byFacet.has(key)) byFacet.set(key, []);
21983
- byFacet.get(key).push(t);
22007
+ if (!byFacet.has(key2)) byFacet.set(key2, []);
22008
+ byFacet.get(key2).push(t);
21984
22009
  }
21985
22010
  }
21986
22011
  return byFacet;
@@ -22019,8 +22044,8 @@ async function readGrowthAgent() {
22019
22044
  return m ? { text: t.slice(0, m.index).trim(), docId: m[1] } : { text: t.trim(), docId: "" };
22020
22045
  };
22021
22046
  const facets2 = {};
22022
- const setFacet = (key, f) => {
22023
- if (key) facets2[key] = { score: num2(f.score), trajectory: String(f.trajectory || ""), rationale: g(f, "rationale", "reasoning") };
22047
+ const setFacet = (key2, f) => {
22048
+ if (key2) facets2[key2] = { score: num2(f.score), trajectory: String(f.trajectory || ""), rationale: g(f, "rationale", "reasoning") };
22024
22049
  };
22025
22050
  if (Array.isArray(raw.facets)) for (const f of raw.facets) setFacet(g(f, "key", "facetKey"), f);
22026
22051
  else for (const [k, v] of Object.entries(raw.facets)) setFacet(k, v || {});
@@ -22043,10 +22068,10 @@ async function compilePerson() {
22043
22068
  const idx = await loadIndex();
22044
22069
  const m = (id) => ({ id, title: idx[id]?.title || id, date: idx[id]?.date || "", source: idx[id]?.source || void 0 });
22045
22070
  const out = [];
22046
- for (const [key, lens] of PERSON_LENSES) {
22047
- const person = await fs16.readFile(path21.join(GRADES, key, "_person.json"), "utf8").then(JSON.parse).catch(() => null);
22048
- const growth = key === "growth" ? await readGrowthAgent() : null;
22049
- const byFacet = await loadFacetTakes(key, idx);
22071
+ for (const [key2, lens] of PERSON_LENSES) {
22072
+ const person = await fs16.readFile(path21.join(GRADES, key2, "_person.json"), "utf8").then(JSON.parse).catch(() => null);
22073
+ const growth = key2 === "growth" ? await readGrowthAgent() : null;
22074
+ const byFacet = await loadFacetTakes(key2, idx);
22050
22075
  const pf = (k) => (person?.facets || []).find((x) => String(x.facetKey) === k) || null;
22051
22076
  const facets2 = lens.facets.map((f) => {
22052
22077
  const g = pf(f.key);
@@ -22084,7 +22109,7 @@ async function compilePerson() {
22084
22109
  } : null;
22085
22110
  return { facetKey: f.key, name: f.name, definition: f.definition, scaleMax, grade, dist: distOf2(takes), takes };
22086
22111
  });
22087
- out.push({ key, label: lens.label, overall: String(person?.overall || ""), facets: facets2, present: !!person, ...growth ? { growthAxes: growth.axes } : {} });
22112
+ out.push({ key: key2, label: lens.label, overall: String(person?.overall || ""), facets: facets2, present: !!person, ...growth ? { growthAxes: growth.axes } : {} });
22088
22113
  }
22089
22114
  return out;
22090
22115
  }
@@ -22101,10 +22126,10 @@ async function gradeDetail(docId2, lensKey) {
22101
22126
  title: meta.title || docId2,
22102
22127
  date: meta.date || "",
22103
22128
  facets: facets2.map((f) => {
22104
- const key = String(f.facetKey || "");
22129
+ const key2 = String(f.facetKey || "");
22105
22130
  return {
22106
- facetKey: key,
22107
- name: FNAME[key] || key,
22131
+ facetKey: key2,
22132
+ name: FNAME[key2] || key2,
22108
22133
  score: num2(f.score),
22109
22134
  confidence: String(f.confidence || ""),
22110
22135
  low: num2(f.low),
@@ -22114,7 +22139,7 @@ async function gradeDetail(docId2, lensKey) {
22114
22139
  cleared: String(f.cleared || ""),
22115
22140
  penalized: String(f.penalized || ""),
22116
22141
  quotes: Array.isArray(f.quotes) ? f.quotes : [],
22117
- scaleMax: RUBRIC[key]?.rungs?.length ? 11 : 10
22142
+ scaleMax: RUBRIC[key2]?.rungs?.length ? 11 : 10
22118
22143
  };
22119
22144
  })
22120
22145
  };
@@ -22258,13 +22283,13 @@ async function loadFeedback() {
22258
22283
  }
22259
22284
  async function handlePersonFeedback(method, body) {
22260
22285
  if (method === "GET") return { status: 200, json: { entries: (await loadFeedback()).entries } };
22261
- const key = typeof body?.key === "string" ? body.key.replace(/[^a-z0-9:_-]/gi, "").slice(0, 80) : "";
22262
- if (!key) return { status: 400, json: { error: "missing key" } };
22286
+ const key2 = typeof body?.key === "string" ? body.key.replace(/[^a-z0-9:_-]/gi, "").slice(0, 80) : "";
22287
+ if (!key2) return { status: 400, json: { error: "missing key" } };
22263
22288
  const text2 = (typeof body?.text === "string" ? body.text : "").trim();
22264
22289
  const store = await loadFeedback();
22265
22290
  const updatedAt = (/* @__PURE__ */ new Date()).toISOString();
22266
- if (text2) store.entries[key] = { text: text2, updatedAt };
22267
- else delete store.entries[key];
22291
+ if (text2) store.entries[key2] = { text: text2, updatedAt };
22292
+ else delete store.entries[key2];
22268
22293
  await fs18.mkdir(path23.dirname(FEEDBACK_FILE()), { recursive: true });
22269
22294
  await fs18.writeFile(FEEDBACK_FILE(), JSON.stringify(store, null, 2));
22270
22295
  return { status: 200, json: { ok: true, updatedAt } };
@@ -22481,14 +22506,14 @@ ${clip2(headline, 1400)}`);
22481
22506
  for (const f of d.facets) {
22482
22507
  const g = f.grade;
22483
22508
  const sc = g && (g.score != null || g.bestEstimate != null) ? `${g.score ?? g.bestEstimate}/${f.scaleMax}` : "\u2014";
22484
- const key = `${d.key}:${f.facetKey}`;
22509
+ const key2 = `${d.key}:${f.facetKey}`;
22485
22510
  const parts = [`- ${f.name} (${sc})`];
22486
- const line = facetLines[key]?.line;
22511
+ const line = facetLines[key2]?.line;
22487
22512
  if (line) parts.push(`feel-seen: ${clip2(line, 280)}`);
22488
22513
  for (const spike of (g?.spikes || []).slice(0, 2)) {
22489
22514
  if (spike?.what) parts.push(`peak: ${clip2(spike.what, 300)}${spike.title ? ` [${clip2(spike.title, 80)}${spike.date ? `, ${spike.date}` : ""}]` : ""}${spike.quote ? ` \u2014 verbatim: "${clip2(spike.quote, 240)}"` : ""}`);
22490
22515
  }
22491
- for (const dm of (peakDemos[key] || []).slice(0, 2)) {
22516
+ for (const dm of (peakDemos[key2] || []).slice(0, 2)) {
22492
22517
  const steps = (dm.steps || []).map((x) => clip2(x, 500)).filter(Boolean);
22493
22518
  if (!steps.length && !dm.why) continue;
22494
22519
  parts.push(`demonstration${dm.title ? ` [${clip2(dm.title, 90)}${dm.date ? `, ${dm.date}` : ""}]` : ""} \u2014 ordered moves:`);
@@ -22983,7 +23008,7 @@ async function writeScoreboard(codingDir, docs) {
22983
23008
  }
22984
23009
  if (!byCriterion.size) return;
22985
23010
  const blocks = [...byCriterion.entries()].sort(([a], [b]) => a < b ? -1 : 1).map(
22986
- ([key, rows]) => `## ${key}
23011
+ ([key2, rows]) => `## ${key2}
22987
23012
  ${rows.sort((a, b) => b.s - a.s).map((r) => r.line).join("\n")}`
22988
23013
  );
22989
23014
  await fs23.writeFile(
@@ -23035,10 +23060,10 @@ function promptSha(parts) {
23035
23060
  }
23036
23061
  return h.digest("hex").slice(0, 16);
23037
23062
  }
23038
- async function reusableOutput(outPath, sha, valid, key = "promptSha") {
23063
+ async function reusableOutput(outPath, sha, valid, key2 = "promptSha") {
23039
23064
  try {
23040
23065
  const o = JSON.parse(await fs24.readFile(outPath, "utf8"));
23041
- if (o[key] === sha && valid(o)) return o;
23066
+ if (o[key2] === sha && valid(o)) return o;
23042
23067
  } catch {
23043
23068
  }
23044
23069
  return null;
@@ -23653,20 +23678,20 @@ async function compileCodingProfile() {
23653
23678
  const m = /([\d.]+)\s*%/.exec(label);
23654
23679
  return m ? 100 - parseFloat(m[1]) : null;
23655
23680
  };
23656
- const ceilOf = (key) => {
23657
- const c = criteria.find((x) => x.key === key);
23681
+ const ceilOf = (key2) => {
23682
+ const c = criteria.find((x) => x.key === key2);
23658
23683
  const scores = (c?.takes ?? []).map((t) => t.score ?? t.best).filter((x) => x != null).sort((a, b) => b - a);
23659
23684
  return scores.length ? scores[Math.min(3, scores.length) - 1] : null;
23660
23685
  };
23661
- const proud = (key, fallback) => {
23662
- const t = (criteria.find((x) => x.key === key)?.takes ?? [])[0];
23686
+ const proud = (key2, fallback) => {
23687
+ const t = (criteria.find((x) => x.key === key2)?.takes ?? [])[0];
23663
23688
  if (!t?.instance) return fallback;
23664
23689
  let h = t.instance.split(/:\s|\s[—–]\s|\swith an?\s/)[0].trim().replace(/\s+/g, " ");
23665
23690
  h = h.replace(/^The user\b/, "You").replace(/\bThe user\b/g, "you").replace(/([.?!]['"’”)\]]*\s+)you\b/g, (_m, p) => p + "You");
23666
23691
  if (h.length > 150) h = h.slice(0, 148).replace(/\s+\S*$/, "") + "\u2026";
23667
23692
  return h;
23668
23693
  };
23669
- const nTk = (key) => criteria.find((x) => x.key === key)?.takes.length ?? 0;
23694
+ const nTk = (key2) => criteria.find((x) => x.key === key2)?.takes.length ?? 0;
23670
23695
  const peakWords = Object.values(wordsByDay).length ? Math.max(...Object.values(wordsByDay)) : 0;
23671
23696
  const pHist = parallelism.levelHistogramMin || {};
23672
23697
  const soloMin = pHist["1"] ?? 0;
@@ -23827,7 +23852,7 @@ async function buildSkeleton(codingDir, stackUp) {
23827
23852
  const r = (stackUp ?? []).find((x) => x.label.toLowerCase().includes(label));
23828
23853
  return r?.percentile != null ? Math.round((100 - r.percentile) * 100) / 100 : null;
23829
23854
  };
23830
- const gradedOn = (key) => (agglom?.criteria ?? []).length ? 0 : 0;
23855
+ const gradedOn = (key2) => (agglom?.criteria ?? []).length ? 0 : 0;
23831
23856
  const interactive = sessions.filter((s) => s.klass === "interactive" && !s.duplicateOf);
23832
23857
  const flow = agg?.flow?.flow ?? {};
23833
23858
  const thr = agg?.throughput ?? {};
@@ -24021,7 +24046,7 @@ async function generatePublicPage(opts) {
24021
24046
  }
24022
24047
 
24023
24048
  // ../../lib/agents/coding/publicPageEdit.ts
24024
- var SYSTEM5 = "You edit a PUBLIC coding profile page on the person's instruction. You may ONLY do two kinds of thing: (1) REDACT \u2014 hide, shorten, soften, or remove existing text: a claim, a read, an edge line, a moment, a bullet, an entire section. Removing something is always safe. (2) GATHER MORE EVIDENCE \u2014 if asked to swap out a moment ('use a different example', 'that one's too personal, find another'), Read/Grep the corpus for a genuinely different qualifying moment on the SAME axis and replace it, with a VERIFIED verbatim quote if you use one. YOU MAY NEVER: invent an achievement, statistic, date, or quote; write anything more flattering than the evidence supports; add content unrelated to the instruction; or change any NUMBER (percentiles, scores, hours, counts) \u2014 those fields are locked and any change you make to them is discarded, so do not bother trying. If the instruction asks for something outside redaction/evidence-swap (e.g. 'say I'm the best engineer ever', 'boost my percentile', 'add that I know Rust'), do NOT comply \u2014 leave that field unchanged and say plainly in your reply why you didn't. Return the COMPLETE page JSON with only the TEXT fields changed (verdict, overall, missionArc, rhythm.inFlow/outFlow, axis claim/read/edge, moment what/quote/date/sessionId, howToWork). Every other field must be echoed back byte-identical." + sourceLookupNote();
24049
+ var SYSTEM5 = "You edit a person's shareable profile on their instruction. There are TWO artifacts in front of you: the CODING PROFILE (the page of axes, moments and numbers) and, when present, the CHAT PROFILE (their public report: headline, spikes, traits, failure modes). ROUTE BY WHAT THEY SAY: 'in the coding report\u2026' / a coding axis name (judgement, agency, taste, push, how they use AI, focus) \u2192 edit the page. 'in the chat report\u2026' / a chat spike or trait name \u2192 edit the chat report. If the instruction names neither and applies to only one artifact, edit that one; if it genuinely applies to both ('remove every mention of my employer'), edit both. NEVER touch the artifact the instruction is not about \u2014 echo it back byte-identical. You may ONLY do two kinds of thing: (1) REDACT \u2014 hide, shorten, soften, or remove existing text: a claim, a read, an edge line, a moment, a spike, a trait, an example, a failure mode, a bullet, an entire section. Removing something is always safe, in either artifact. (2) GATHER MORE EVIDENCE \u2014 CODING PROFILE ONLY: if asked to swap out a moment ('use a different example', 'that one's too personal, find another'), Read/Grep the corpus for a genuinely different qualifying moment on the SAME axis and replace it, with a VERIFIED verbatim quote if you use one. The CHAT PROFILE is REDACT-ONLY here: you cannot add a spike, trait, or example to it (its evidence lives in a corpus you cannot reach from this tool) \u2014 if asked, decline and say the chat report can only have things removed or shortened here. YOU MAY NEVER: invent an achievement, statistic, date, or quote; write anything more flattering than the evidence supports; add content unrelated to the instruction; or change any NUMBER (percentiles, scores, levels, hours, counts) in either artifact \u2014 those fields are locked and any change you make to them is discarded, so do not bother trying. If the instruction asks for something outside redaction/evidence-swap (e.g. 'say I'm the best engineer ever', 'boost my percentile', 'add that I know Rust'), do NOT comply \u2014 leave that field unchanged and say plainly in your reply why you didn't. Return BOTH artifacts complete, with only the TEXT fields changed (page: verdict, overall, missionArc, rhythm.inFlow/outFlow, axis claim/read/edge, moment what/quote/date/sessionId, howToWork; chat: headline, spike titles, trait label/body/con, example title/detail, failure modes, drives, wants, howToWorkWithHim). Every other field must be echoed back byte-identical." + sourceLookupNote();
24025
24050
  var norm = (s) => s.toLowerCase().replace(/[^a-z0-9\s]/g, " ").split(/\s+/).filter((w) => w.length > 2);
24026
24051
  function grounded(newText, contextText) {
24027
24052
  const nt = norm(newText);
@@ -24082,19 +24107,90 @@ function clampToProtected(edited, original) {
24082
24107
  });
24083
24108
  return out;
24084
24109
  }
24110
+ var key = (s) => (s ?? "").toLowerCase().replace(/[^a-z0-9]+/g, " ").trim();
24111
+ function matchBy(items, label) {
24112
+ const byFacet = /* @__PURE__ */ new Map(), byLabel = /* @__PURE__ */ new Map();
24113
+ for (const it of items) {
24114
+ if (it.facet) byFacet.set(key(it.facet), it);
24115
+ byLabel.set(key(label(it)), it);
24116
+ }
24117
+ return (e) => e.facet && byFacet.get(key(e.facet)) || byLabel.get(key(label(e)));
24118
+ }
24119
+ function clampChatExamples(edited, orig) {
24120
+ if (!orig?.length) return orig;
24121
+ if (!Array.isArray(edited)) return orig;
24122
+ const find = matchBy(orig, (e) => e.title ?? "");
24123
+ const out = edited.map((e) => ({ e, o: find(e) })).filter((p) => !!p.o).map(({ e, o }) => ({
24124
+ ...o,
24125
+ // date + provenance: from the original
24126
+ title: keepIfGrounded(e.title, o.title, `${o.title} ${[o.detail ?? []].flat().join(" ")}`).slice(0, 200),
24127
+ detail: Array.isArray(e.detail) ? e.detail.map((d, i) => keepIfGrounded(d, [o.detail ?? []].flat()[i] ?? "", [o.detail ?? []].flat().join(" "))).filter(Boolean).slice(0, 6) : o.detail
24128
+ }));
24129
+ return out.length ? out : void 0;
24130
+ }
24131
+ function clampChatReport(edited, original) {
24132
+ const findSpike = matchBy(original.spikes ?? [], (s) => s.title);
24133
+ const spikes = (Array.isArray(edited.spikes) ? edited.spikes : original.spikes ?? []).map((e) => ({ e, o: findSpike(e) })).filter((p) => !!p.o).map(({ e, o }) => {
24134
+ const findTrait = matchBy(o.traits ?? [], (t) => t.label);
24135
+ const traits = (Array.isArray(e.traits) ? e.traits : o.traits ?? []).map((te) => ({ te, to: findTrait(te) })).filter((p) => !!p.to).map(({ te, to }) => {
24136
+ const ctx = `${to.label} ${to.body} ${to.con ?? ""} ${(to.examples ?? []).map((x) => `${x.title} ${[x.detail ?? []].flat().join(" ")}`).join(" ")}`;
24137
+ return {
24138
+ ...to,
24139
+ // facet, score, percentile, fromPersonalLife: PROTECTED
24140
+ label: keepIfGrounded(te.label, to.label, ctx).slice(0, 200),
24141
+ body: keepIfGrounded(te.body, to.body, ctx).slice(0, 900),
24142
+ con: te.con === void 0 ? to.con : te.con ? keepIfGrounded(te.con, to.con ?? "", ctx).slice(0, 400) || void 0 : void 0,
24143
+ // personal-life traits never carry receipts, edited or not
24144
+ examples: to.fromPersonalLife ? void 0 : clampChatExamples(te.examples, to.examples)
24145
+ };
24146
+ });
24147
+ return {
24148
+ ...o,
24149
+ // facet, score, percentile: PROTECTED
24150
+ title: keepIfGrounded(e.title, o.title, `${o.title} ${(o.traits ?? []).map((t) => `${t.label} ${t.body}`).join(" ")}`).slice(0, 200),
24151
+ traits
24152
+ };
24153
+ });
24154
+ const findFm = matchBy(original.failureModes ?? [], (f) => f.label);
24155
+ const failureModes = Array.isArray(edited.failureModes) ? edited.failureModes.map((e) => ({ e, o: findFm(e) })).filter((p) => !!p.o).map(({ e, o }) => ({
24156
+ ...o,
24157
+ frequency: o.frequency,
24158
+ // an absolute count, framed by the grader: PROTECTED
24159
+ label: keepIfGrounded(e.label, o.label, `${o.label} ${o.body ?? ""}`).slice(0, 200),
24160
+ body: e.body === void 0 ? o.body : e.body ? keepIfGrounded(e.body, o.body ?? "", `${o.label} ${o.body ?? ""}`).slice(0, 600) || void 0 : void 0
24161
+ })) : original.failureModes;
24162
+ return {
24163
+ ...original,
24164
+ // level, radar, generatedAt, editLog: PROTECTED, always original
24165
+ headline: keepIfGrounded(edited.headline, original.headline, original.headline).slice(0, 300),
24166
+ spikes,
24167
+ failureModes: failureModes?.length ? failureModes : void 0,
24168
+ drives: edited.drives === void 0 ? original.drives : edited.drives ? keepIfGrounded(edited.drives, original.drives ?? "", original.drives ?? "").slice(0, 900) || void 0 : void 0,
24169
+ wants: Array.isArray(edited.wants) ? edited.wants.map((w) => keepIfGrounded(w, "", (original.wants ?? []).join(" "))).filter(Boolean).slice(0, 8) : original.wants,
24170
+ howToWorkWithHim: Array.isArray(edited.howToWorkWithHim) ? edited.howToWorkWithHim.map((b) => keepIfGrounded(b, "", (original.howToWorkWithHim ?? []).join(" "))).filter(Boolean).slice(0, 6) : original.howToWorkWithHim
24171
+ };
24172
+ }
24085
24173
  async function editPublicPage(opts) {
24086
24174
  const last = opts.messages.filter((m) => m.role === "user").pop();
24087
24175
  if (!last?.content?.trim()) return { status: 400, json: { error: "an instruction is required" } };
24088
24176
  const convo = opts.messages.slice(-6).map((m) => `${m.role === "user" ? "USER" : "EDITOR"}: ${m.content}`).join("\n");
24089
- const prompt = `CURRENT PAGE:
24177
+ const chat = opts.chatReport ?? null;
24178
+ const prompt = `CODING PROFILE (the page):
24090
24179
  \`\`\`json
24091
24180
  ${JSON.stringify(opts.page, null, 1)}
24092
24181
  \`\`\`
24093
24182
 
24094
- CONVERSATION:
24183
+ ` + (chat ? `CHAT PROFILE (their public report \u2014 REDACT-ONLY):
24184
+ \`\`\`json
24185
+ ${JSON.stringify({ ...chat, radar: void 0, level: void 0, editLog: void 0 }, null, 1)}
24186
+ \`\`\`
24187
+
24188
+ ` : `CHAT PROFILE: none exists yet \u2014 every instruction is about the coding profile.
24189
+
24190
+ `) + `CONVERSATION:
24095
24191
  ${convo}
24096
24192
 
24097
- Apply the user's LAST instruction within your allowed actions (redact, or gather-more-evidence). Output ONE fenced json block: { "page": <complete page, text fields updated>, "reply": "one short plain sentence on what you did or why you declined" }`;
24193
+ Apply the user's LAST instruction to the RIGHT artifact, within your allowed actions (redact; gather-more-evidence on the coding page only). Output ONE fenced json block: { "page": <complete page>, ${chat ? `"chatReport": <complete chat report>, ` : ""}"reply": "one short plain sentence naming WHICH report you changed and what you did, or why you declined" }`;
24098
24194
  try {
24099
24195
  const run4 = await invokeAgent2({
24100
24196
  prompt,
@@ -24111,7 +24207,11 @@ Apply the user's LAST instruction within your allowed actions (redact, or gather
24111
24207
  const originalIds = new Set(opts.page.axes.flatMap((a) => a.moments.map((m) => m.sessionId).filter(Boolean)));
24112
24208
  await verifyQuotes(opts.codingDir, clamped.axes);
24113
24209
  for (const ax of clamped.axes) ax.moments = ax.moments.filter((m) => m.sessionId && originalIds.has(m.sessionId) || m.quote);
24114
- return { status: 200, json: { page: clamped, reply: String(j.reply ?? "Done.").slice(0, 300) } };
24210
+ const chatOut = chat ? j.chatReport ? clampChatReport(j.chatReport, chat) : chat : void 0;
24211
+ return {
24212
+ status: 200,
24213
+ json: { page: clamped, ...chatOut ? { chatReport: chatOut } : {}, reply: String(j.reply ?? "Done.").slice(0, 300) }
24214
+ };
24115
24215
  } catch (e) {
24116
24216
  return { status: 502, json: { error: e.message.slice(0, 200) } };
24117
24217
  }
@@ -24123,6 +24223,40 @@ async function localChatReport() {
24123
24223
  const rep = await loadPublicReport().catch(() => null);
24124
24224
  return rep && hasContent(rep) ? rep : null;
24125
24225
  }
24226
+ async function handleSharedReportGet(dataDir) {
24227
+ const cfg = centralConfig();
24228
+ if (!cfg.configured) return { status: 200, json: { shared: null, reason: "central services are disabled in this build" } };
24229
+ const auth = await getAccessToken(dataDir);
24230
+ if (!auth) return { status: 200, json: { shared: null, reason: "signed-out" } };
24231
+ try {
24232
+ const r = await fetch(`${cfg.supabaseUrl}/rest/v1/reports?user_id=eq.${encodeURIComponent(auth.identity.userId)}&select=content,verification,created_at,updated_at`, {
24233
+ headers: { apikey: cfg.supabaseAnonKey, authorization: `Bearer ${auth.token}` }
24234
+ });
24235
+ if (!r.ok) return { status: 502, json: { error: `couldn't read your shared report (HTTP ${r.status})` } };
24236
+ const rows = await r.json();
24237
+ const row = rows[0];
24238
+ if (!row?.content) return { status: 200, json: { shared: null } };
24239
+ const c = row.content;
24240
+ return {
24241
+ status: 200,
24242
+ json: {
24243
+ shared: {
24244
+ // updated_at, NOT created_at: submit_report UPSERTS one row per user
24245
+ // (`on conflict (user_id) do update`), so created_at is the FIRST
24246
+ // share ever while the content is the LATEST — dating today's page
24247
+ // "July 3" would be a lie about the thing on screen.
24248
+ sharedAt: row.updated_at ?? row.created_at ?? null,
24249
+ verification: row.verification ?? null,
24250
+ // coding-pr1 carries {page, chatReport?}; the older pr1 is chat-only
24251
+ page: c.format === "coding-pr1" ? c.page ?? null : null,
24252
+ chatReport: c.chatReport ?? (c.format === "pr1" ? c.report ?? null : null)
24253
+ }
24254
+ }
24255
+ };
24256
+ } catch (e) {
24257
+ return { status: 502, json: { error: e.message.slice(0, 200) } };
24258
+ }
24259
+ }
24126
24260
  async function handlePublicCodingPageGet(dataDir) {
24127
24261
  const page = await readJson4(path32.join(dataDir, "coding", "coding-public.json"), null);
24128
24262
  const chatReport = await localChatReport();
@@ -24144,7 +24278,12 @@ async function handlePublicCodingPageEdit(dataDir, body) {
24144
24278
  const page = body.page;
24145
24279
  const messages = Array.isArray(body.messages) ? body.messages : [];
24146
24280
  if (!page || !Array.isArray(page.axes)) return { status: 400, json: { error: "page + messages are required" } };
24147
- const out = await editPublicPage({ page, messages, codingDir: path32.join(dataDir, "coding") });
24281
+ const chatReport = await localChatReport();
24282
+ const out = await editPublicPage({ page, chatReport, messages, codingDir: path32.join(dataDir, "coding") });
24283
+ const edited = out.json.chatReport;
24284
+ if (out.status === 200 && edited && chatReport && JSON.stringify(edited) !== JSON.stringify(chatReport)) {
24285
+ await savePublicReport({ ...edited, editLog: [...chatReport.editLog ?? [], { instruction: messages.filter((m) => m.role === "user").pop()?.content ?? "", at: (/* @__PURE__ */ new Date()).toISOString() }].slice(-50) });
24286
+ }
24148
24287
  return out;
24149
24288
  }
24150
24289
  async function handlePublicCodingPageShare(dataDir, body) {
@@ -24245,13 +24384,13 @@ async function handleShare(res, body, opts, dataDir) {
24245
24384
  const all = opts.shareSections ?? opts.profile?.sections ?? {};
24246
24385
  const sections = {};
24247
24386
  if (parsed.sectionsData && typeof parsed.sectionsData === "object" && !Array.isArray(parsed.sectionsData)) {
24248
- for (const key of Object.keys(parsed.sectionsData)) {
24249
- if (key in all && parsed.sectionsData[key] != null) sections[key] = parsed.sectionsData[key];
24387
+ for (const key2 of Object.keys(parsed.sectionsData)) {
24388
+ if (key2 in all && parsed.sectionsData[key2] != null) sections[key2] = parsed.sectionsData[key2];
24250
24389
  }
24251
24390
  } else {
24252
24391
  const wanted = parsed.all ? Object.keys(all) : Array.isArray(parsed.sections) ? parsed.sections : [];
24253
- for (const key of wanted) {
24254
- if (key in all && all[key] != null) sections[key] = all[key];
24392
+ for (const key2 of wanted) {
24393
+ if (key2 in all && all[key2] != null) sections[key2] = all[key2];
24255
24394
  }
24256
24395
  }
24257
24396
  if (Object.keys(sections).length === 0) {
@@ -24399,8 +24538,8 @@ function startServer(opts) {
24399
24538
  return;
24400
24539
  }
24401
24540
  }
24402
- const key = new URL(url, serverUrl || "http://localhost").searchParams.get("key") || void 0;
24403
- const out = handleDiagnostic(req.method || "GET", body, key);
24541
+ const key2 = new URL(url, serverUrl || "http://localhost").searchParams.get("key") || void 0;
24542
+ const out = handleDiagnostic(req.method || "GET", body, key2);
24404
24543
  json(res, out.status, out.json);
24405
24544
  return;
24406
24545
  }
@@ -24475,6 +24614,11 @@ function startServer(opts) {
24475
24614
  json(res, out.status, out.json);
24476
24615
  return;
24477
24616
  }
24617
+ if (req.method === "GET" && route === "/api/shared-report") {
24618
+ const out = await handleSharedReportGet(dataDir);
24619
+ json(res, out.status, out.json);
24620
+ return;
24621
+ }
24478
24622
  if (req.method === "POST" && route === "/api/public-coding-page/generate") {
24479
24623
  const out = await handlePublicCodingPageGenerate(dataDir, liveProfile);
24480
24624
  json(res, out.status, out.json);
@@ -24581,10 +24725,10 @@ function withTimeout(p) {
24581
24725
  new Promise((_, rej) => setTimeout(() => rej(new Error("runlog timeout")), RPC_TIMEOUT_MS).unref?.())
24582
24726
  ]);
24583
24727
  }
24584
- async function rpc(url, key, fn, args) {
24728
+ async function rpc(url, key2, fn, args) {
24585
24729
  const res = await fetch(`${url.replace(/\/$/, "")}/rest/v1/rpc/${fn}`, {
24586
24730
  method: "POST",
24587
- headers: { "content-type": "application/json", apikey: key, authorization: `Bearer ${key}` },
24731
+ headers: { "content-type": "application/json", apikey: key2, authorization: `Bearer ${key2}` },
24588
24732
  body: JSON.stringify(args)
24589
24733
  });
24590
24734
  if (!res.ok) throw new Error(`${fn} \u2192 HTTP ${res.status}`);
@@ -24599,9 +24743,9 @@ async function writeRef(refPath, ref) {
24599
24743
  }
24600
24744
  }
24601
24745
  var LiveRunLog = class {
24602
- constructor(url, key, sessionId, token, nonce, opts) {
24746
+ constructor(url, key2, sessionId, token, nonce, opts) {
24603
24747
  this.url = url;
24604
- this.key = key;
24748
+ this.key = key2;
24605
24749
  this.token = token;
24606
24750
  this.nonce = nonce;
24607
24751
  this.opts = opts;
@@ -24693,18 +24837,18 @@ function inertRunLog(refPath) {
24693
24837
  }
24694
24838
  async function startRunLog(clientInfo = {}, opts = {}) {
24695
24839
  const url = opts.supabaseUrl ?? process.env.NEXT_PUBLIC_SUPABASE_URL;
24696
- const key = opts.supabaseAnonKey ?? process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY;
24840
+ const key2 = opts.supabaseAnonKey ?? process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY;
24697
24841
  const refPath = opts.refPath ?? runRefPath();
24698
- if (!url || !key) return inertRunLog(refPath);
24842
+ if (!url || !key2) return inertRunLog(refPath);
24699
24843
  try {
24700
24844
  const data = await withTimeout(
24701
- rpc(url, key, "begin_analysis_session", {
24845
+ rpc(url, key2, "begin_analysis_session", {
24702
24846
  p_client_info: { platform: process.platform, ...clientInfo }
24703
24847
  })
24704
24848
  );
24705
24849
  const d = data ?? {};
24706
24850
  if (!d.session_id || !d.token || !d.nonce) return inertRunLog(refPath);
24707
- return new LiveRunLog(url, key, d.session_id, d.token, d.nonce, opts);
24851
+ return new LiveRunLog(url, key2, d.session_id, d.token, d.nonce, opts);
24708
24852
  } catch {
24709
24853
  return inertRunLog(refPath);
24710
24854
  }
@@ -24821,9 +24965,11 @@ function upToDateSkip(i) {
24821
24965
  }
24822
24966
  async function evalUpToDate(codingDir, threshold, regrade) {
24823
24967
  try {
24824
- const { partition: partition2 } = await Promise.resolve().then(() => (init_gate2(), gate_exports));
24968
+ const { partition: partition2, aiWindowCutoff: aiWindowCutoff2 } = await Promise.resolve().then(() => (init_gate2(), gate_exports));
24825
24969
  const sessions = JSON.parse(await fs31.readFile(path36.join(codingDir, "sessions.json"), "utf8"));
24826
- const { gradable } = partition2(sessions.filter((s) => s.klass === "interactive" && !s.duplicateOf));
24970
+ const live = sessions.filter((s) => s.klass === "interactive" && !s.duplicateOf);
24971
+ const cutoff = aiWindowCutoff2(live);
24972
+ const { gradable } = partition2(cutoff ? live.filter((s) => (s.start ?? "") >= cutoff) : live);
24827
24973
  const graded = new Set(
24828
24974
  (await fs31.readdir(path36.join(codingDir, "grades")).catch(() => [])).filter((f) => f.endsWith(".json")).map((f) => f.slice(0, -5))
24829
24975
  );
@@ -24839,6 +24985,44 @@ async function evalUpToDate(codingDir, threshold, regrade) {
24839
24985
  return { skip: false, pending: -1 };
24840
24986
  }
24841
24987
  }
24988
+ function startKeepAwake(o = {}) {
24989
+ const platform = o.platform ?? process.platform;
24990
+ if (platform !== "darwin") return () => {
24991
+ };
24992
+ const cmd = o.cmd ?? "caffeinate";
24993
+ const argv = o.argv ?? ["-ims", "-w", String(process.pid)];
24994
+ let stopped = false;
24995
+ let child = null;
24996
+ let timer = null;
24997
+ const up = () => {
24998
+ if (stopped) return;
24999
+ try {
25000
+ child = spawn6(cmd, argv, { detached: true, stdio: "ignore" });
25001
+ child.unref();
25002
+ child.on("error", () => {
25003
+ stopped = true;
25004
+ child = null;
25005
+ });
25006
+ child.on("exit", () => {
25007
+ child = null;
25008
+ if (stopped) return;
25009
+ timer = setTimeout(up, o.respawnDelayMs ?? 5e3);
25010
+ timer.unref?.();
25011
+ });
25012
+ } catch {
25013
+ stopped = true;
25014
+ }
25015
+ };
25016
+ up();
25017
+ return () => {
25018
+ stopped = true;
25019
+ if (timer) clearTimeout(timer);
25020
+ try {
25021
+ child?.kill();
25022
+ } catch {
25023
+ }
25024
+ };
25025
+ }
24842
25026
  async function runPipeline(o) {
24843
25027
  if (!hasPipeline(o.repoRoot)) {
24844
25028
  throw new Error(
@@ -24848,13 +25032,8 @@ async function runPipeline(o) {
24848
25032
  const dataRoot = codingDataRoot(o.repoRoot);
24849
25033
  const env = { ...process.env, POLYMATH_RESILIENT: "1", POLYMATH_DATA_DIR: dataRoot };
24850
25034
  if (!o.overnight) env.POLYMATH_RESILIENT_NO_WINDOW = "1";
24851
- if (o.overnight && process.platform === "darwin") {
24852
- try {
24853
- const { spawn: spawn10 } = await import("node:child_process");
24854
- spawn10("caffeinate", ["-ims", "-w", String(process.pid)], { detached: true, stdio: "ignore" }).unref();
24855
- } catch {
24856
- }
24857
- }
25035
+ const stopKeepAwake = o.overnight ? startKeepAwake() : () => {
25036
+ };
24858
25037
  const list = stages(o).filter((st) => !o.deterministicOnly || !st.llm);
24859
25038
  const codingDir = path36.join(dataRoot, "coding");
24860
25039
  const central = centralConfig();
@@ -24935,6 +25114,7 @@ async function runPipeline(o) {
24935
25114
  o.onLine?.(`\u23F1 run took ${fmt(totalMs)} (${record.kind}) \u2014 slowest: ${slowest} \xB7 ledger: .data/coding/run-times.jsonl`);
24936
25115
  } catch {
24937
25116
  }
25117
+ stopKeepAwake();
24938
25118
  return { failed, ...skippedLlm ? { skippedLlm } : {} };
24939
25119
  }
24940
25120
 
@@ -24959,6 +25139,7 @@ function chatEngineStages() {
24959
25139
  { script: "person-facet-lines.mts", label: "Facet lines", llm: true, args: [], out: "engine-pilot/person-facet-lines.json" },
24960
25140
  { script: "peak-demos.mts", label: "Peak demonstrations", llm: true, args: [], out: "engine-pilot/peak-demos.json" },
24961
25141
  { script: "person-dimension-summary.mts", label: "Dimension summaries", llm: true, args: [], out: "engine-pilot/dimension-summary.json" },
25142
+ { script: "chat-loops.mts", label: "Recurring patterns + growth loops", llm: true, args: [], out: "loops.json" },
24962
25143
  { script: "person-report.mts", label: "Report narrative", llm: true, args: [], out: "engine-pilot/report-narrative.json" },
24963
25144
  { script: "public-report.mts", label: "Public report", llm: true, args: [], out: "engine-pilot/public-report.json" }
24964
25145
  ];
@@ -25326,6 +25507,8 @@ Graded ${detail.gradedSessions} sessions \u2192 ${gradeOut}/graded.json`);
25326
25507
  process.exit(1);
25327
25508
  }
25328
25509
  const chatOvernight = opts.chatOvernight ?? opts.overnight;
25510
+ const stopKeepAwake = opts.overnight || chatOvernight ? startKeepAwake() : () => {
25511
+ };
25329
25512
  const when = (o) => o ? "at the 02:00 window tonight" : "now";
25330
25513
  console.error(`
25331
25514
  Running the full analysis on ${backend.name === "cli" ? "Claude Code" : "Codex"} \u2014 coding ${when(opts.overnight)}, chats ${when(chatOvernight)}.`);
@@ -25441,6 +25624,7 @@ Running the full analysis on ${backend.name === "cli" ? "Claude Code" : "Codex"}
25441
25624
  return chat2;
25442
25625
  })();
25443
25626
  const [codingRes, chat] = await Promise.all([codingDone, chatDone]);
25627
+ stopKeepAwake();
25444
25628
  const { failed } = codingRes;
25445
25629
  clearInterval(liveRefresh);
25446
25630
  mbar.done();
@@ -25524,7 +25708,7 @@ No analysis here yet \u2014 computing the instant deterministic metrics now (fre
25524
25708
  console.error(` Run from the directory where you ran the analysis, or set POLYMATH_DATA_DIR.`);
25525
25709
  }
25526
25710
  console.error(`
25527
- coding-analyzer is live \u2192 ${handle.url}`);
25711
+ your reports are live \u2192 ${handle.url}`);
25528
25712
  console.error(` ${nSessions} sessions \xB7 ${nGraded} graded${opts.grade ? "" : nGraded ? "" : " (add --grade to run the full AI analysis first)"}`);
25529
25713
  console.error(` share endpoint: ${shareUrl}`);
25530
25714
  console.error(` ${who ? `signed in as ${who.email}` : "not signed in \u2014 feedback + sharing ask for Google sign-in in the header"}`);