polymath-society 0.2.28 → 0.2.30
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 +169 -73
- package/dist/engine/chat-loops.js +1 -1
- package/dist/engine/exp-allfacets.js +1 -1
- package/dist/engine/exp-person.js +1 -1
- package/dist/engine/exp-pipeline.js +1 -1
- package/dist/engine/peak-demos.js +1 -1
- package/dist/engine/person-dimension-summary.js +1 -1
- package/dist/engine/person-facet-lines.js +1 -1
- package/dist/engine/person-headline.js +1 -1
- package/dist/engine/person-report.js +1 -1
- package/dist/engine/person-self-image.js +1 -1
- package/dist/engine/public-report.js +1 -1
- package/dist/engine/run-analysis.js +1 -1
- package/dist/engine/run-tagger.js +6 -5
- package/dist/index.js +26 -20
- package/dist/pipeline/coding-agglomerate.js +1 -1
- package/dist/pipeline/coding-build.js +25 -16
- package/dist/pipeline/coding-coaching.js +1 -1
- package/dist/pipeline/coding-day-digest.js +9 -7
- package/dist/pipeline/coding-delegation.js +6 -5
- package/dist/pipeline/coding-expertise.js +1 -1
- package/dist/pipeline/coding-focus.js +1 -1
- package/dist/pipeline/coding-frontier-detail.js +1 -1
- package/dist/pipeline/coding-gap.js +1 -1
- package/dist/pipeline/coding-grade.js +13 -8
- package/dist/pipeline/coding-growth.js +1 -1
- package/dist/pipeline/coding-nutshell.js +1 -1
- package/dist/pipeline/coding-walkthrough.js +7 -6
- package/dist/pipeline/coding-workbrief.js +1 -1
- package/dist/web/app.js +13 -10
- package/dist/web/styles.css +1 -1
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -55,13 +55,10 @@ function electronAppData() {
|
|
|
55
55
|
function resolveDataRoot(env = process.env, cwd = process.cwd(), appData = electronAppData, home = os.homedir()) {
|
|
56
56
|
const fromEnv = env.POLYMATH_DATA_DIR;
|
|
57
57
|
if (fromEnv && fromEnv.trim()) return path.resolve(fromEnv);
|
|
58
|
-
const local = path.join(cwd, ".data");
|
|
59
58
|
const dflt = path.join(home, ".polymath-society", "data");
|
|
60
|
-
if (existsSync(local) && hasCompletedAnalysis(local)) return local;
|
|
61
59
|
const fromApp = appData();
|
|
62
60
|
if (fromApp && hasCompletedAnalysis(fromApp)) return fromApp;
|
|
63
61
|
if (hasCompletedAnalysis(dflt)) return dflt;
|
|
64
|
-
if (existsSync(local)) return local;
|
|
65
62
|
if (fromApp) return fromApp;
|
|
66
63
|
return dflt;
|
|
67
64
|
}
|
|
@@ -484,7 +481,8 @@ var init_cursor = __esm({
|
|
|
484
481
|
});
|
|
485
482
|
|
|
486
483
|
// ../coding-core/dist/raw.js
|
|
487
|
-
import { promises as fs2 } from "fs";
|
|
484
|
+
import { promises as fs2, createReadStream } from "fs";
|
|
485
|
+
import readline from "readline";
|
|
488
486
|
import path2 from "path";
|
|
489
487
|
import os2 from "os";
|
|
490
488
|
function resolveSourceRoot(envVar, ...defaultSegments) {
|
|
@@ -600,10 +598,18 @@ function blank(sessionId, source, file2) {
|
|
|
600
598
|
klassReason: ""
|
|
601
599
|
};
|
|
602
600
|
}
|
|
603
|
-
function
|
|
601
|
+
function jsonlLines(file2) {
|
|
602
|
+
return readline.createInterface({ input: createReadStream(file2, { encoding: "utf-8" }), crlfDelay: Infinity });
|
|
603
|
+
}
|
|
604
|
+
function shedAgentBulk(s) {
|
|
605
|
+
if (s.klass === "agent" && s.events.length > 2)
|
|
606
|
+
s.events = [s.events[0], s.events[s.events.length - 1]];
|
|
607
|
+
return s;
|
|
608
|
+
}
|
|
609
|
+
async function parseClaudeCode(input, sessionId, file2) {
|
|
604
610
|
const s = blank(sessionId, "claude-code", file2);
|
|
605
611
|
const seen = /* @__PURE__ */ new Set();
|
|
606
|
-
for (const lineRaw of
|
|
612
|
+
for await (const lineRaw of typeof input === "string" ? input.split("\n") : input) {
|
|
607
613
|
const line = lineRaw.trim();
|
|
608
614
|
if (!line)
|
|
609
615
|
continue;
|
|
@@ -705,7 +711,7 @@ function parseClaudeCode(raw, sessionId, file2) {
|
|
|
705
711
|
const c = classify(s);
|
|
706
712
|
s.klass = c.klass;
|
|
707
713
|
s.klassReason = c.reason;
|
|
708
|
-
return s;
|
|
714
|
+
return shedAgentBulk(s);
|
|
709
715
|
}
|
|
710
716
|
function codexText(content) {
|
|
711
717
|
if (typeof content === "string")
|
|
@@ -727,10 +733,10 @@ function codexText(content) {
|
|
|
727
733
|
}
|
|
728
734
|
return "";
|
|
729
735
|
}
|
|
730
|
-
function parseCodex(
|
|
736
|
+
async function parseCodex(input, file2) {
|
|
731
737
|
let sessionId = path2.basename(file2, ".jsonl");
|
|
732
738
|
const s = blank(sessionId, "codex", file2);
|
|
733
|
-
for (const lineRaw of
|
|
739
|
+
for await (const lineRaw of typeof input === "string" ? input.split("\n") : input) {
|
|
734
740
|
const line = lineRaw.trim();
|
|
735
741
|
if (!line)
|
|
736
742
|
continue;
|
|
@@ -796,7 +802,7 @@ function parseCodex(raw, file2) {
|
|
|
796
802
|
const c = classify(s);
|
|
797
803
|
s.klass = c.klass;
|
|
798
804
|
s.klassReason = c.reason;
|
|
799
|
-
return s;
|
|
805
|
+
return shedAgentBulk(s);
|
|
800
806
|
}
|
|
801
807
|
async function readClaudeCodeAt(base2, machine) {
|
|
802
808
|
const out = [];
|
|
@@ -820,13 +826,12 @@ async function readClaudeCodeAt(base2, machine) {
|
|
|
820
826
|
}
|
|
821
827
|
for (const f of files) {
|
|
822
828
|
const file2 = path2.join(full, f);
|
|
823
|
-
let
|
|
829
|
+
let s = null;
|
|
824
830
|
try {
|
|
825
|
-
|
|
831
|
+
s = await parseClaudeCode(jsonlLines(file2), path2.basename(f, ".jsonl"), file2);
|
|
826
832
|
} catch {
|
|
827
833
|
continue;
|
|
828
834
|
}
|
|
829
|
-
const s = parseClaudeCode(raw, path2.basename(f, ".jsonl"), file2);
|
|
830
835
|
if (s) {
|
|
831
836
|
if (machine)
|
|
832
837
|
s.machine = machine;
|
|
@@ -861,13 +866,12 @@ async function readCodexAt(base2, machine) {
|
|
|
861
866
|
await walkJsonl(base2, files);
|
|
862
867
|
const out = [];
|
|
863
868
|
for (const file2 of files) {
|
|
864
|
-
let
|
|
869
|
+
let s = null;
|
|
865
870
|
try {
|
|
866
|
-
|
|
871
|
+
s = await parseCodex(jsonlLines(file2), file2);
|
|
867
872
|
} catch {
|
|
868
873
|
continue;
|
|
869
874
|
}
|
|
870
|
-
const s = parseCodex(raw, file2);
|
|
871
875
|
if (s) {
|
|
872
876
|
if (machine)
|
|
873
877
|
s.machine = machine;
|
|
@@ -1073,7 +1077,7 @@ function rawSessionFromCursorComposer(c, file2, cwd) {
|
|
|
1073
1077
|
const cl = classify(s);
|
|
1074
1078
|
s.klass = cl.klass;
|
|
1075
1079
|
s.klassReason = cl.reason;
|
|
1076
|
-
return s;
|
|
1080
|
+
return shedAgentBulk(s);
|
|
1077
1081
|
}
|
|
1078
1082
|
function parseCursorTranscript(raw, composerId, file2, ws, fileMtime) {
|
|
1079
1083
|
const s = blank(composerId, "cursor", file2);
|
|
@@ -1118,7 +1122,7 @@ function parseCursorTranscript(raw, composerId, file2, ws, fileMtime) {
|
|
|
1118
1122
|
const c = classify(s);
|
|
1119
1123
|
s.klass = c.klass;
|
|
1120
1124
|
s.klassReason = c.reason;
|
|
1121
|
-
return s;
|
|
1125
|
+
return shedAgentBulk(s);
|
|
1122
1126
|
}
|
|
1123
1127
|
function cursorWorkspaceSession(ws, idx) {
|
|
1124
1128
|
if (ws.generations.length === 0)
|
|
@@ -1140,7 +1144,7 @@ function cursorWorkspaceSession(ws, idx) {
|
|
|
1140
1144
|
const c = classify(s);
|
|
1141
1145
|
s.klass = c.klass;
|
|
1142
1146
|
s.klassReason = c.reason;
|
|
1143
|
-
return s;
|
|
1147
|
+
return shedAgentBulk(s);
|
|
1144
1148
|
}
|
|
1145
1149
|
async function readCursorAt(roots, machine) {
|
|
1146
1150
|
const workspaces = await readCursorWorkspaces(roots.workspace);
|
|
@@ -1254,6 +1258,8 @@ async function readAllSessions(opts2 = {}) {
|
|
|
1254
1258
|
]);
|
|
1255
1259
|
const all = [...cc, ...cx, ...cr, ...mm];
|
|
1256
1260
|
demoteTemplateFanouts(all);
|
|
1261
|
+
for (const s of all)
|
|
1262
|
+
shedAgentBulk(s);
|
|
1257
1263
|
return all;
|
|
1258
1264
|
}
|
|
1259
1265
|
var SOURCE_ROOT_ENV_VARS, anyRootOverridden, claudeProjectsRoot, codexSessionsRoot, cursorWorkspaceRoot, cursorProjectsRoot, cursorGlobalRoot, MACHINE_CURSOR_FILE_RE, SKIP_DIR_RE, AGENT_CWD_RE, PERSONA_RE, OUTPUT_CONTRACT_RES, CAPS_HEADER_RE, PING_RE, ms, CURSOR_USER_QUERY_RE2, NODE_SQLITE2, FANOUT_PREFIX, FANOUT_MIN_SESSIONS;
|
|
@@ -18779,7 +18785,7 @@ var init_runStats = __esm({
|
|
|
18779
18785
|
"../../lib/agents/shared/runStats.ts"() {
|
|
18780
18786
|
"use strict";
|
|
18781
18787
|
G = globalThis;
|
|
18782
|
-
file = () => path11.join(process.cwd(), ".data", "run-stats.jsonl");
|
|
18788
|
+
file = () => path11.join(process.env.POLYMATH_DATA_DIR || path11.join(process.cwd(), ".data"), "run-stats.jsonl");
|
|
18783
18789
|
}
|
|
18784
18790
|
});
|
|
18785
18791
|
|
|
@@ -22884,11 +22890,11 @@ function stages(o) {
|
|
|
22884
22890
|
// so they run WHILE grading runs (grading is the wall-clock giant; these
|
|
22885
22891
|
// finish inside its shadow). Budget: grade 8 + digest 3 + walkthrough 3 +
|
|
22886
22892
|
// two single-call stages ≈ 16 peak subprocesses (measured-safe envelope).
|
|
22887
|
-
{ script: "coding-grade.mts", label: "AI-grade every substantial session", llm: true, weight:
|
|
22888
|
-
{ script: "coding-day-digest.mts", label: "Day-by-day digests", llm: true, weight:
|
|
22889
|
-
// walkthrough weight
|
|
22890
|
-
{ script: "coding-walkthrough.mts", label: "Per-session walkthroughs", llm: true, weight:
|
|
22891
|
-
{ script: "coding-frontier-detail.mts", label: "What you're doing at the frontier", llm: true, weight:
|
|
22893
|
+
{ script: "coding-grade.mts", label: "AI-grade every substantial session", llm: true, weight: 32, args: gradeArgs, batch: "heavy" },
|
|
22894
|
+
{ script: "coding-day-digest.mts", label: "Day-by-day digests", llm: true, weight: 19, args: ["--model", narrativeModel, "--conc", String(h.digest)], out: "coding/day-digest.json", batch: "heavy" },
|
|
22895
|
+
// walkthrough weight 38 = MEASURED on the rebalanced 4 workers (2026-07-23 clean run; the 2→4 speedup was 1.5x, not 2x)
|
|
22896
|
+
{ script: "coding-walkthrough.mts", label: "Per-session walkthroughs", llm: true, weight: 38, args: ["--model", narrativeModel, "--conc", String(h.walkthrough)], batch: "heavy" },
|
|
22897
|
+
{ script: "coding-frontier-detail.mts", label: "What you're doing at the frontier", llm: true, weight: 2, args: [], out: "coding/frontier-detail.json", batch: "heavy" },
|
|
22892
22898
|
{ script: "coding-delegation.mts", label: "Delegation patterns", llm: true, weight: 2, args: ["--model", model, "--conc", String(h.delegation)], out: "coding/delegation-rollup.json", batch: "heavy" },
|
|
22893
22899
|
// The FULL focus stage: flow-rule judgment + the paste-into-CLAUDE.md block.
|
|
22894
22900
|
// The deterministic --skip-llm run above keeps the numbers current every
|
|
@@ -22925,7 +22931,7 @@ function stages(o) {
|
|
|
22925
22931
|
// calls — it deliberately ignores the AI recency window and covers the full
|
|
22926
22932
|
// history); disjoint output, so it rides the synthesis batch. Like
|
|
22927
22933
|
// agglomerate it defaults itself to Opus; an explicit model choice wins.
|
|
22928
|
-
{ script: "coding-growth.mts", label: "Growth arcs + learning rate", llm: true, weight:
|
|
22934
|
+
{ script: "coding-growth.mts", label: "Growth arcs + learning rate", llm: true, weight: 3, args: o.model ? ["--model", o.model] : [], out: "coding/growth.json", batch: "synthesis" },
|
|
22929
22935
|
// nutshell stays LAST + alone: it merges INTO aggregate.json while the two
|
|
22930
22936
|
// above read the compiled profile — racing them re-reads mid-write.
|
|
22931
22937
|
{ script: "coding-nutshell.mts", label: "Big-picture nutshell", llm: true, weight: 1, args: [], out: "coding/aggregate.json" }
|
|
@@ -23103,6 +23109,10 @@ async function runPipeline(o) {
|
|
|
23103
23109
|
}
|
|
23104
23110
|
const dataRoot = codingDataRoot(o.repoRoot);
|
|
23105
23111
|
const env = { ...process.env, POLYMATH_RESILIENT: "1", POLYMATH_DATA_DIR: dataRoot };
|
|
23112
|
+
if (!/max-old-space-size/.test(env.NODE_OPTIONS ?? "")) {
|
|
23113
|
+
const headroomMb = Math.min(12288, Math.max(4096, Math.round(os8.totalmem() / 2 ** 20 * 0.6)));
|
|
23114
|
+
env.NODE_OPTIONS = `${env.NODE_OPTIONS ?? ""} --max-old-space-size=${headroomMb}`.trim();
|
|
23115
|
+
}
|
|
23106
23116
|
if (!o.overnight) env.POLYMATH_RESILIENT_NO_WINDOW = "1";
|
|
23107
23117
|
const stopKeepAwake = o.overnight ? startKeepAwake() : () => {
|
|
23108
23118
|
};
|
|
@@ -23220,6 +23230,7 @@ __export(chatPipeline_exports, {
|
|
|
23220
23230
|
runChatPipeline: () => runChatPipeline
|
|
23221
23231
|
});
|
|
23222
23232
|
import { spawn as spawn8 } from "child_process";
|
|
23233
|
+
import os9 from "os";
|
|
23223
23234
|
import path39 from "path";
|
|
23224
23235
|
import { existsSync as existsSync6, promises as fs33 } from "fs";
|
|
23225
23236
|
import { fileURLToPath as fileURLToPath4 } from "url";
|
|
@@ -23323,6 +23334,10 @@ async function runChatPipeline(o) {
|
|
|
23323
23334
|
AGENT_MODEL: o.model ?? process.env.AGENT_MODEL ?? "sonnet"
|
|
23324
23335
|
};
|
|
23325
23336
|
if (!o.overnight) env.POLYMATH_RESILIENT_NO_WINDOW = "1";
|
|
23337
|
+
if (!/max-old-space-size/.test(env.NODE_OPTIONS ?? "")) {
|
|
23338
|
+
const headroomMb = Math.min(12288, Math.max(4096, Math.round(os9.totalmem() / 2 ** 20 * 0.6)));
|
|
23339
|
+
env.NODE_OPTIONS = `${env.NODE_OPTIONS ?? ""} --max-old-space-size=${headroomMb}`.trim();
|
|
23340
|
+
}
|
|
23326
23341
|
const failed = [];
|
|
23327
23342
|
const ingested = [];
|
|
23328
23343
|
const notIngestable = [];
|
|
@@ -23415,6 +23430,74 @@ var init_chatPipeline = __esm({
|
|
|
23415
23430
|
}
|
|
23416
23431
|
});
|
|
23417
23432
|
|
|
23433
|
+
// src/ttyGuard.ts
|
|
23434
|
+
import { spawnSync as spawnSync3 } from "node:child_process";
|
|
23435
|
+
function stty(...args) {
|
|
23436
|
+
try {
|
|
23437
|
+
const r = spawnSync3("stty", args, { stdio: ["inherit", "pipe", "ignore"] });
|
|
23438
|
+
return r.status === 0 ? String(r.stdout ?? "").trim() : null;
|
|
23439
|
+
} catch {
|
|
23440
|
+
return null;
|
|
23441
|
+
}
|
|
23442
|
+
}
|
|
23443
|
+
function guardTty() {
|
|
23444
|
+
if (guarded || process.platform === "win32" || !process.stdin.isTTY) return;
|
|
23445
|
+
guarded = true;
|
|
23446
|
+
stty("isig", "icrnl");
|
|
23447
|
+
const saved = stty("-g");
|
|
23448
|
+
if (saved) process.on("exit", () => void stty(saved));
|
|
23449
|
+
}
|
|
23450
|
+
function attachPromptAbort(rl) {
|
|
23451
|
+
rl.on("SIGINT", () => {
|
|
23452
|
+
process.stderr.write("^C\n");
|
|
23453
|
+
rl.close();
|
|
23454
|
+
process.exit(130);
|
|
23455
|
+
});
|
|
23456
|
+
}
|
|
23457
|
+
function watchCtrlC(onCtrlC) {
|
|
23458
|
+
const stdin = process.stdin;
|
|
23459
|
+
if (process.platform === "win32" || !stdin.isTTY || typeof stdin.setRawMode !== "function") {
|
|
23460
|
+
return () => {
|
|
23461
|
+
};
|
|
23462
|
+
}
|
|
23463
|
+
const onData = (b) => {
|
|
23464
|
+
for (const byte of b) {
|
|
23465
|
+
if (byte === 3 || byte === 28) {
|
|
23466
|
+
onCtrlC();
|
|
23467
|
+
return;
|
|
23468
|
+
}
|
|
23469
|
+
if (byte === 26) {
|
|
23470
|
+
stdin.setRawMode(false);
|
|
23471
|
+
process.once("SIGCONT", () => {
|
|
23472
|
+
try {
|
|
23473
|
+
stdin.setRawMode(true);
|
|
23474
|
+
} catch {
|
|
23475
|
+
}
|
|
23476
|
+
});
|
|
23477
|
+
process.kill(process.pid, "SIGTSTP");
|
|
23478
|
+
}
|
|
23479
|
+
}
|
|
23480
|
+
};
|
|
23481
|
+
stdin.setRawMode(true);
|
|
23482
|
+
stdin.resume();
|
|
23483
|
+
stdin.on("data", onData);
|
|
23484
|
+
return () => {
|
|
23485
|
+
stdin.off("data", onData);
|
|
23486
|
+
try {
|
|
23487
|
+
stdin.setRawMode(false);
|
|
23488
|
+
} catch {
|
|
23489
|
+
}
|
|
23490
|
+
stdin.pause();
|
|
23491
|
+
};
|
|
23492
|
+
}
|
|
23493
|
+
var guarded;
|
|
23494
|
+
var init_ttyGuard = __esm({
|
|
23495
|
+
"src/ttyGuard.ts"() {
|
|
23496
|
+
"use strict";
|
|
23497
|
+
guarded = false;
|
|
23498
|
+
}
|
|
23499
|
+
});
|
|
23500
|
+
|
|
23418
23501
|
// src/notify.ts
|
|
23419
23502
|
import { spawn as spawn9 } from "node:child_process";
|
|
23420
23503
|
function systemNotify(title, body) {
|
|
@@ -24047,7 +24130,7 @@ __export(plan_exports, {
|
|
|
24047
24130
|
tierFromStrings: () => tierFromStrings
|
|
24048
24131
|
});
|
|
24049
24132
|
import { promises as fs36 } from "fs";
|
|
24050
|
-
import
|
|
24133
|
+
import os10 from "os";
|
|
24051
24134
|
import path42 from "path";
|
|
24052
24135
|
function supportsFullAnalysis(tier) {
|
|
24053
24136
|
if (process.env.POLYMATH_FORCE_FULL === "1") return true;
|
|
@@ -24072,7 +24155,7 @@ function tierFromChatgptPlan(planType) {
|
|
|
24072
24155
|
if (s === "free") return "gpt_free";
|
|
24073
24156
|
return "unknown";
|
|
24074
24157
|
}
|
|
24075
|
-
async function detectCodexPlan(home =
|
|
24158
|
+
async function detectCodexPlan(home = os10.homedir()) {
|
|
24076
24159
|
try {
|
|
24077
24160
|
const raw = JSON.parse(await fs36.readFile(path42.join(home, ".codex", "auth.json"), "utf8"));
|
|
24078
24161
|
for (const tok of [raw.tokens?.id_token, raw.tokens?.access_token]) {
|
|
@@ -24088,7 +24171,7 @@ async function detectCodexPlan(home = os9.homedir()) {
|
|
|
24088
24171
|
}
|
|
24089
24172
|
return "unknown";
|
|
24090
24173
|
}
|
|
24091
|
-
async function detectPlan(home =
|
|
24174
|
+
async function detectPlan(home = os10.homedir()) {
|
|
24092
24175
|
let tier = "unknown";
|
|
24093
24176
|
try {
|
|
24094
24177
|
const raw = JSON.parse(await fs36.readFile(path42.join(home, ".claude.json"), "utf8"));
|
|
@@ -24200,9 +24283,9 @@ __export(wizard_exports, {
|
|
|
24200
24283
|
scanJsonlDir: () => scanJsonlDir
|
|
24201
24284
|
});
|
|
24202
24285
|
import { promises as fs37 } from "fs";
|
|
24203
|
-
import
|
|
24286
|
+
import os11 from "os";
|
|
24204
24287
|
import path43 from "path";
|
|
24205
|
-
import * as
|
|
24288
|
+
import * as readline2 from "node:readline/promises";
|
|
24206
24289
|
async function scanJsonlDir(label, dir, maxDepth = 1) {
|
|
24207
24290
|
let files = 0;
|
|
24208
24291
|
let newest = 0;
|
|
@@ -24315,7 +24398,8 @@ function describeExport(f, i, included, hadPrevious) {
|
|
|
24315
24398
|
${dim(path43.basename(f.path))} ${dim(`(${f.note})`)}`;
|
|
24316
24399
|
}
|
|
24317
24400
|
async function runWizard() {
|
|
24318
|
-
const rl =
|
|
24401
|
+
const rl = readline2.createInterface({ input: process.stdin, output: process.stderr });
|
|
24402
|
+
attachPromptAbort(rl);
|
|
24319
24403
|
const say = (s = "") => console.error(s);
|
|
24320
24404
|
const lineQueue = [];
|
|
24321
24405
|
let waiting = null;
|
|
@@ -24393,7 +24477,7 @@ async function runWizard() {
|
|
|
24393
24477
|
for (let i = 0; i < agentScans.length; i++) {
|
|
24394
24478
|
const s = agentScans[i];
|
|
24395
24479
|
const idx = present.indexOf(agentIds[i]);
|
|
24396
|
-
say(s.files > 0 ? ` ${idx + 1}. ${green("\u2713")} ${bold(s.label)} \u2014 ${s.files.toLocaleString()} log files \xB7 newest ${s.newest} ${dim(s.dir.replace(
|
|
24480
|
+
say(s.files > 0 ? ` ${idx + 1}. ${green("\u2713")} ${bold(s.label)} \u2014 ${s.files.toLocaleString()} log files \xB7 newest ${s.newest} ${dim(s.dir.replace(os11.homedir(), "~"))}` : ` ${dim("\xB7")} ${dim(`${s.label} \u2014 none found`)} ${dim(s.dir.replace(os11.homedir(), "~"))}`);
|
|
24397
24481
|
}
|
|
24398
24482
|
say(dim(" (log files include forks and agent runs \u2014 the report separates your real sessions out)"));
|
|
24399
24483
|
if (present.length === 0) {
|
|
@@ -24445,22 +24529,19 @@ async function runWizard() {
|
|
|
24445
24529
|
{
|
|
24446
24530
|
const { looksLikeEmail: looksLikeEmail2, recordContact: recordContact2 } = await Promise.resolve().then(() => (init_reminderEmail(), reminderEmail_exports));
|
|
24447
24531
|
say();
|
|
24448
|
-
|
|
24449
|
-
|
|
24450
|
-
|
|
24451
|
-
|
|
24452
|
-
|
|
24453
|
-
|
|
24454
|
-
|
|
24455
|
-
|
|
24456
|
-
await fs37.writeFile(path43.join(dataDir, "notify-email.json"), JSON.stringify({ email: e }));
|
|
24457
|
-
} catch {
|
|
24458
|
-
}
|
|
24459
|
-
await recordContact2(e, "wizard", reminderState.token).catch(() => false);
|
|
24460
|
-
say(` ${green("\u2713")} Got it, we'll keep you posted at ${bold(e)}.`);
|
|
24461
|
-
} else if (e) {
|
|
24462
|
-
say(dim(` "${e}" doesn't look like an email \u2014 skipping.`));
|
|
24532
|
+
const e = (await ask(notifyEmail ? ` Your email ${dim(`(currently ${notifyEmail} \u2014 Enter if this is correct, or type a new one)`)}: ` : ` Your email ${dim("(recommended \u2014 we'll send your report link and occasional Polymath updates, and can nudge you when an export arrives; Enter to skip)")}: `)).trim();
|
|
24533
|
+
if (e && looksLikeEmail2(e)) {
|
|
24534
|
+
const correcting = !!notifyEmail;
|
|
24535
|
+
notifyEmail = e;
|
|
24536
|
+
try {
|
|
24537
|
+
await fs37.mkdir(dataDir, { recursive: true });
|
|
24538
|
+
await fs37.writeFile(path43.join(dataDir, "notify-email.json"), JSON.stringify({ email: e }));
|
|
24539
|
+
} catch {
|
|
24463
24540
|
}
|
|
24541
|
+
await recordContact2(e, correcting ? "wizard-correction" : "wizard", reminderState.token).catch(() => false);
|
|
24542
|
+
say(` ${green("\u2713")} Got it, we'll keep you posted at ${bold(e)}.`);
|
|
24543
|
+
} else if (e) {
|
|
24544
|
+
say(dim(notifyEmail ? ` "${e}" doesn't look like an email \u2014 keeping ${notifyEmail}.` : ` "${e}" doesn't look like an email \u2014 skipping.`));
|
|
24464
24545
|
}
|
|
24465
24546
|
}
|
|
24466
24547
|
const tracked = { token: reminderState.token };
|
|
@@ -24476,9 +24557,9 @@ async function runWizard() {
|
|
|
24476
24557
|
}
|
|
24477
24558
|
};
|
|
24478
24559
|
say(dim(" Scanning for known export formats (Spotlight + the usual folders, a few seconds)..."));
|
|
24479
|
-
for (const c of await deterministicDiscover(
|
|
24480
|
-
for (const f of await scanForExports(path43.join(
|
|
24481
|
-
for (const f of await scanForObsidianVaults(
|
|
24560
|
+
for (const c of await deterministicDiscover(os11.homedir())) add(await identifyPath(c));
|
|
24561
|
+
for (const f of await scanForExports(path43.join(os11.homedir(), "Downloads"))) add(f);
|
|
24562
|
+
for (const f of await scanForObsidianVaults(os11.homedir())) add(f);
|
|
24482
24563
|
for (const f of [...previous?.exports.included ?? [], ...previous?.exports.excluded ?? []]) add(f);
|
|
24483
24564
|
let linksShown = false;
|
|
24484
24565
|
if (!found.length) {
|
|
@@ -24489,7 +24570,7 @@ async function runWizard() {
|
|
|
24489
24570
|
try {
|
|
24490
24571
|
const { invokeAgent: invokeAgent3 } = await Promise.resolve().then(() => (init_agent(), agent_exports));
|
|
24491
24572
|
say(dim(" Searching (your agent writes its own filesystem searches; nothing leaves this machine; 90s max)..."));
|
|
24492
|
-
const candidates = await agentDiscoverCandidates((inv) => invokeAgent3(inv),
|
|
24573
|
+
const candidates = await agentDiscoverCandidates((inv) => invokeAgent3(inv), os11.homedir(), []);
|
|
24493
24574
|
for (const c of candidates) add(await identifyPath(c));
|
|
24494
24575
|
} catch (e) {
|
|
24495
24576
|
say(dim(` Agent search unavailable (${e instanceof Error ? e.message.slice(0, 80) : "failed"}).`));
|
|
@@ -24497,7 +24578,7 @@ async function runWizard() {
|
|
|
24497
24578
|
}
|
|
24498
24579
|
if (!found.length) {
|
|
24499
24580
|
const folder = await ask(` Got them in a specific folder? ${dim("(path, or Enter to skip)")}: `);
|
|
24500
|
-
if (folder) for (const f of await scanForExports(folder.replace(/^~(?=$|\/)/,
|
|
24581
|
+
if (folder) for (const f of await scanForExports(folder.replace(/^~(?=$|\/)/, os11.homedir()))) add(f);
|
|
24501
24582
|
}
|
|
24502
24583
|
}
|
|
24503
24584
|
if (found.length) {
|
|
@@ -24522,7 +24603,7 @@ async function runWizard() {
|
|
|
24522
24603
|
approvedExports = manifest.exports.included;
|
|
24523
24604
|
await writeManifest(dataDir, manifest);
|
|
24524
24605
|
const nIn = manifest.exports.included.length;
|
|
24525
|
-
say(` ${green("\u2713")} Saved to ${path43.join(dataDir, "exports-manifest.json").replace(
|
|
24606
|
+
say(` ${green("\u2713")} Saved to ${path43.join(dataDir, "exports-manifest.json").replace(os11.homedir(), "~")} \u2014 ${nIn} source${nIn === 1 ? "" : "s"} approved, ${manifest.exports.excluded.length} excluded (re-run anytime to change).`);
|
|
24526
24607
|
for (const f of manifest.exports.excluded) say(` ${dim(`\u2717 ${path43.basename(f.path)} \u2014 excluded, never read past identification.`)}`);
|
|
24527
24608
|
if (manifest.exports.included.some((f) => f.kind !== "unknown")) {
|
|
24528
24609
|
say(` ${dim("These are ingested and analyzed locally when you pick the full analysis below.")}`);
|
|
@@ -24573,7 +24654,8 @@ async function runWizard() {
|
|
|
24573
24654
|
say(` ${bold("Proposed schedule")} \u2014 sized to your plan (${plan.label}):`);
|
|
24574
24655
|
say();
|
|
24575
24656
|
say(` ${bold("Your analysis")} runs now \u2014 everything measured from your logs: words/day, flow state, focus, projects, parallelism`);
|
|
24576
|
-
|
|
24657
|
+
const planPhrase = plan.tier === "pro" ? "the $20 Claude Pro plan" : plan.tier === "gpt_plus" ? "the $20 ChatGPT Plus plan" : "the free ChatGPT plan";
|
|
24658
|
+
say(` ${bold("AI sections")} not supported on ${planPhrase} just yet \u2014 coming soon! Only the AI-graded sections (judgement, agency, taste, growth) won't be visible`);
|
|
24577
24659
|
say();
|
|
24578
24660
|
await ask(` Press Enter to run your analysis`).catch(() => "");
|
|
24579
24661
|
say(dim(" On it. The report link appears right away.\n"));
|
|
@@ -24636,7 +24718,8 @@ function newExportsSince(found, m) {
|
|
|
24636
24718
|
}
|
|
24637
24719
|
async function returningUserFlow(dataDir) {
|
|
24638
24720
|
const say = (s = "") => console.error(s);
|
|
24639
|
-
const rl =
|
|
24721
|
+
const rl = readline2.createInterface({ input: process.stdin, output: process.stderr });
|
|
24722
|
+
attachPromptAbort(rl);
|
|
24640
24723
|
try {
|
|
24641
24724
|
say();
|
|
24642
24725
|
say(bold(" What would you like to do?"));
|
|
@@ -24683,17 +24766,18 @@ async function askEmailAndQueueReminder(dataDir, say, ask) {
|
|
|
24683
24766
|
}
|
|
24684
24767
|
const clicked = await fetchClickedKinds2(state.token);
|
|
24685
24768
|
if (!clicked.length) return;
|
|
24686
|
-
|
|
24687
|
-
const e = (await ask(` Leave your email and we'll remind you when your exports should be ready ${dim("(Enter to skip)")}`)).trim();
|
|
24769
|
+
{
|
|
24770
|
+
const e = (await ask(email ? ` Your email ${dim(`(currently ${email} \u2014 Enter if this is correct, or type a new one)`)}: ` : ` Leave your email and we'll remind you when your exports should be ready ${dim("(Enter to skip)")}`)).trim();
|
|
24688
24771
|
if (e && looksLikeEmail2(e)) {
|
|
24772
|
+
const correcting = !!email;
|
|
24689
24773
|
email = e;
|
|
24690
24774
|
await fs37.mkdir(dataDir, { recursive: true }).catch(() => {
|
|
24691
24775
|
});
|
|
24692
24776
|
await fs37.writeFile(path43.join(dataDir, "notify-email.json"), JSON.stringify({ email: e })).catch(() => {
|
|
24693
24777
|
});
|
|
24694
|
-
await recordContact2(e, "add-sources", state.token).catch(() => false);
|
|
24778
|
+
await recordContact2(e, correcting ? "wizard-correction" : "add-sources", state.token).catch(() => false);
|
|
24695
24779
|
} else if (e) {
|
|
24696
|
-
say(dim(` "${e}" doesn't look like an email \u2014 skipping the reminder.`));
|
|
24780
|
+
say(dim(email ? ` "${e}" doesn't look like an email \u2014 keeping ${email}.` : ` "${e}" doesn't look like an email \u2014 skipping the reminder.`));
|
|
24697
24781
|
}
|
|
24698
24782
|
}
|
|
24699
24783
|
if (!email) return;
|
|
@@ -24731,9 +24815,9 @@ async function addSourcesFlow(dataDir, say, rl) {
|
|
|
24731
24815
|
found.push(f);
|
|
24732
24816
|
}
|
|
24733
24817
|
};
|
|
24734
|
-
for (const c of await deterministicDiscover(
|
|
24735
|
-
for (const f of await scanForExports(path43.join(
|
|
24736
|
-
for (const f of await scanForObsidianVaults(
|
|
24818
|
+
for (const c of await deterministicDiscover(os11.homedir())) add(await identifyPath(c));
|
|
24819
|
+
for (const f of await scanForExports(path43.join(os11.homedir(), "Downloads"))) add(f);
|
|
24820
|
+
for (const f of await scanForObsidianVaults(os11.homedir())) add(f);
|
|
24737
24821
|
for (const f of [...previous?.exports.included ?? [], ...previous?.exports.excluded ?? []]) {
|
|
24738
24822
|
if (await fs37.stat(f.path).then(() => true, () => false)) add(f);
|
|
24739
24823
|
}
|
|
@@ -24835,6 +24919,7 @@ var init_wizard = __esm({
|
|
|
24835
24919
|
init_exportScan();
|
|
24836
24920
|
init_manifest();
|
|
24837
24921
|
init_dataHome();
|
|
24922
|
+
init_ttyGuard();
|
|
24838
24923
|
init_raw2();
|
|
24839
24924
|
color = process.stdout.isTTY && !process.env.NO_COLOR;
|
|
24840
24925
|
dim = (s) => color ? `\x1B[2m${s}\x1B[0m` : s;
|
|
@@ -24882,6 +24967,7 @@ function makeMultiBar(out = process.stderr) {
|
|
|
24882
24967
|
return ` ${name17.padEnd(6)} [${"\u2588".repeat(fill)}${"\u2591".repeat(width - fill)}] ${String(Math.round(l.shown * 100)).padStart(3)}%`;
|
|
24883
24968
|
};
|
|
24884
24969
|
const out2 = [];
|
|
24970
|
+
out2.push("");
|
|
24885
24971
|
out2.push("This is a background process. We'll let you know when it's finished.");
|
|
24886
24972
|
out2.push("It may take anywhere from 30 minutes to an hour.");
|
|
24887
24973
|
out2.push("");
|
|
@@ -25059,8 +25145,8 @@ try {
|
|
|
25059
25145
|
import { promises as fs38, existsSync as existsSync7 } from "fs";
|
|
25060
25146
|
import path44 from "path";
|
|
25061
25147
|
import { fileURLToPath as fileURLToPath5 } from "url";
|
|
25062
|
-
import { spawnSync as
|
|
25063
|
-
import
|
|
25148
|
+
import { spawnSync as spawnSync4 } from "child_process";
|
|
25149
|
+
import readline3 from "readline";
|
|
25064
25150
|
|
|
25065
25151
|
// src/openBrowser.ts
|
|
25066
25152
|
import { spawn } from "child_process";
|
|
@@ -28096,6 +28182,7 @@ init_auth();
|
|
|
28096
28182
|
init_pipeline2();
|
|
28097
28183
|
init_chatPipeline();
|
|
28098
28184
|
init_manifest();
|
|
28185
|
+
init_ttyGuard();
|
|
28099
28186
|
init_profile();
|
|
28100
28187
|
var __dirname2 = path44.dirname(fileURLToPath5(import.meta.url));
|
|
28101
28188
|
var REPO_ROOT = path44.resolve(__dirname2, "..", "..", "..");
|
|
@@ -28247,8 +28334,9 @@ PROJECTS`);
|
|
|
28247
28334
|
log(``);
|
|
28248
28335
|
}
|
|
28249
28336
|
async function askYesNo(q, def = true) {
|
|
28250
|
-
const
|
|
28251
|
-
const rl =
|
|
28337
|
+
const readline4 = await import("node:readline/promises");
|
|
28338
|
+
const rl = readline4.createInterface({ input: process.stdin, output: process.stderr });
|
|
28339
|
+
attachPromptAbort(rl);
|
|
28252
28340
|
try {
|
|
28253
28341
|
for (; ; ) {
|
|
28254
28342
|
const a = (await rl.question(`${q} `)).trim().toLowerCase();
|
|
@@ -28277,6 +28365,7 @@ async function runGrade(opts2, provider, profile) {
|
|
|
28277
28365
|
await provider.criteriaMean(profile.sessions);
|
|
28278
28366
|
}
|
|
28279
28367
|
async function main() {
|
|
28368
|
+
guardTty();
|
|
28280
28369
|
if (process.argv[2] === "remind-exports") {
|
|
28281
28370
|
const { runReminder: runReminder2 } = await Promise.resolve().then(() => (init_remind(), remind_exports));
|
|
28282
28371
|
const argv = process.argv.slice(3);
|
|
@@ -28304,8 +28393,13 @@ async function main() {
|
|
|
28304
28393
|
await printBanner2();
|
|
28305
28394
|
console.error("");
|
|
28306
28395
|
await maybePrintUpdateNotice(opts2);
|
|
28307
|
-
|
|
28308
|
-
|
|
28396
|
+
{
|
|
28397
|
+
const { osc8: osc82 } = await Promise.resolve().then(() => (init_exportLinks(), exportLinks_exports));
|
|
28398
|
+
const boldTty = process.stderr.isTTY && !process.env.NO_COLOR;
|
|
28399
|
+
const b = (t) => boldTty ? `\x1B[1m${t}\x1B[0m` : t;
|
|
28400
|
+
console.error(` ${b("Step 0 \xB7 Want to see some sample reports before you run?")} ${osc82("https://polymathsociety.us/sample", "https://polymathsociety.us/sample")}`);
|
|
28401
|
+
console.error("");
|
|
28402
|
+
}
|
|
28309
28403
|
const prior = process.env.POLYMATH_WIZARD === "1" ? null : await readPriorAnalysis();
|
|
28310
28404
|
if (prior) {
|
|
28311
28405
|
console.error(` Found your finished report \u2014 ${prior.graded} graded sessions, last updated ${prior.when}.`);
|
|
@@ -28540,7 +28634,7 @@ Running the full analysis on ${backend.name === "cli" ? "Claude Code" : "Codex"}
|
|
|
28540
28634
|
codingLane.stageDone(key2);
|
|
28541
28635
|
const f = codingFrac();
|
|
28542
28636
|
codingLane.setFrac(f);
|
|
28543
|
-
progress.coding = { ...progress.coding, i: Math.min(aiDone.coding + 1, aiCount.coding), total: aiCount.coding, done: false, frac: f, withinFrac: Math.round(sumFracs("coding") * 1e3) / 1e3 };
|
|
28637
|
+
progress.coding = { ...progress.coding, label: progress.coding?.label ?? label, i: Math.min(aiDone.coding + 1, aiCount.coding), total: aiCount.coding, done: false, frac: f, withinFrac: Math.round(sumFracs("coding") * 1e3) / 1e3 };
|
|
28544
28638
|
earlyHandle.setProgress(progress);
|
|
28545
28639
|
},
|
|
28546
28640
|
// While pinned, the scrolling stage output stays quiet ("prints hella
|
|
@@ -28760,6 +28854,7 @@ No analysis here yet \u2014 computing the instant deterministic metrics now (fre
|
|
|
28760
28854
|
};
|
|
28761
28855
|
process.on("SIGINT", shutdown(130));
|
|
28762
28856
|
process.on("SIGTERM", shutdown(143));
|
|
28857
|
+
watchCtrlC(() => void shutdown(130)());
|
|
28763
28858
|
return;
|
|
28764
28859
|
}
|
|
28765
28860
|
const profile = await analyze({ codex: opts2.codex, idleGapMin: opts2.idleGapMin, tz: opts2.tz, spanHourMin: opts2.spanHourMin });
|
|
@@ -28796,7 +28891,8 @@ async function promptAutoUpdate(current, latest) {
|
|
|
28796
28891
|
console.error(`
|
|
28797
28892
|
New version available: polymath-society ${current} \u2192 ${latest}`);
|
|
28798
28893
|
const answer = await new Promise((resolve2) => {
|
|
28799
|
-
const rl =
|
|
28894
|
+
const rl = readline3.createInterface({ input: process.stdin, output: process.stderr });
|
|
28895
|
+
attachPromptAbort(rl);
|
|
28800
28896
|
const timer = setTimeout(() => {
|
|
28801
28897
|
rl.close();
|
|
28802
28898
|
resolve2("");
|
|
@@ -28814,7 +28910,7 @@ async function promptAutoUpdate(current, latest) {
|
|
|
28814
28910
|
console.error(`
|
|
28815
28911
|
Updating\u2026
|
|
28816
28912
|
`);
|
|
28817
|
-
const install =
|
|
28913
|
+
const install = spawnSync4("npm", ["install", "-g", "polymath-society@latest"], {
|
|
28818
28914
|
stdio: "inherit",
|
|
28819
28915
|
shell: process.platform === "win32"
|
|
28820
28916
|
});
|
|
@@ -28828,7 +28924,7 @@ async function promptAutoUpdate(current, latest) {
|
|
|
28828
28924
|
console.error(`
|
|
28829
28925
|
Updated to ${latest}. Relaunching\u2026
|
|
28830
28926
|
`);
|
|
28831
|
-
const relaunch =
|
|
28927
|
+
const relaunch = spawnSync4("polymath-society", process.argv.slice(2), {
|
|
28832
28928
|
stdio: "inherit",
|
|
28833
28929
|
shell: process.platform === "win32"
|
|
28834
28930
|
});
|
|
@@ -16505,7 +16505,7 @@ import path7 from "path";
|
|
|
16505
16505
|
import { appendFileSync, mkdirSync } from "fs";
|
|
16506
16506
|
import path6 from "path";
|
|
16507
16507
|
var G = globalThis;
|
|
16508
|
-
var file = () => path6.join(process.cwd(), ".data", "run-stats.jsonl");
|
|
16508
|
+
var file = () => path6.join(process.env.POLYMATH_DATA_DIR || path6.join(process.cwd(), ".data"), "run-stats.jsonl");
|
|
16509
16509
|
function write(ev) {
|
|
16510
16510
|
try {
|
|
16511
16511
|
mkdirSync(path6.dirname(file()), { recursive: true });
|
|
@@ -15302,7 +15302,7 @@ import path8 from "path";
|
|
|
15302
15302
|
import { appendFileSync, mkdirSync } from "fs";
|
|
15303
15303
|
import path7 from "path";
|
|
15304
15304
|
var G = globalThis;
|
|
15305
|
-
var file = () => path7.join(process.cwd(), ".data", "run-stats.jsonl");
|
|
15305
|
+
var file = () => path7.join(process.env.POLYMATH_DATA_DIR || path7.join(process.cwd(), ".data"), "run-stats.jsonl");
|
|
15306
15306
|
function write(ev) {
|
|
15307
15307
|
try {
|
|
15308
15308
|
mkdirSync(path7.dirname(file()), { recursive: true });
|
|
@@ -15302,7 +15302,7 @@ import path8 from "path";
|
|
|
15302
15302
|
import { appendFileSync, mkdirSync } from "fs";
|
|
15303
15303
|
import path7 from "path";
|
|
15304
15304
|
var G = globalThis;
|
|
15305
|
-
var file = () => path7.join(process.cwd(), ".data", "run-stats.jsonl");
|
|
15305
|
+
var file = () => path7.join(process.env.POLYMATH_DATA_DIR || path7.join(process.cwd(), ".data"), "run-stats.jsonl");
|
|
15306
15306
|
function write(ev) {
|
|
15307
15307
|
try {
|
|
15308
15308
|
mkdirSync(path7.dirname(file()), { recursive: true });
|
|
@@ -15297,7 +15297,7 @@ import path7 from "path";
|
|
|
15297
15297
|
import { appendFileSync, mkdirSync } from "fs";
|
|
15298
15298
|
import path6 from "path";
|
|
15299
15299
|
var G = globalThis;
|
|
15300
|
-
var file = () => path6.join(process.cwd(), ".data", "run-stats.jsonl");
|
|
15300
|
+
var file = () => path6.join(process.env.POLYMATH_DATA_DIR || path6.join(process.cwd(), ".data"), "run-stats.jsonl");
|
|
15301
15301
|
function write(ev) {
|
|
15302
15302
|
try {
|
|
15303
15303
|
mkdirSync(path6.dirname(file()), { recursive: true });
|
|
@@ -16293,7 +16293,7 @@ import path9 from "path";
|
|
|
16293
16293
|
import { appendFileSync, mkdirSync } from "fs";
|
|
16294
16294
|
import path8 from "path";
|
|
16295
16295
|
var G = globalThis;
|
|
16296
|
-
var file = () => path8.join(process.cwd(), ".data", "run-stats.jsonl");
|
|
16296
|
+
var file = () => path8.join(process.env.POLYMATH_DATA_DIR || path8.join(process.cwd(), ".data"), "run-stats.jsonl");
|
|
16297
16297
|
function write(ev) {
|
|
16298
16298
|
try {
|
|
16299
16299
|
mkdirSync(path8.dirname(file()), { recursive: true });
|
|
@@ -16293,7 +16293,7 @@ import path9 from "path";
|
|
|
16293
16293
|
import { appendFileSync, mkdirSync } from "fs";
|
|
16294
16294
|
import path8 from "path";
|
|
16295
16295
|
var G = globalThis;
|
|
16296
|
-
var file = () => path8.join(process.cwd(), ".data", "run-stats.jsonl");
|
|
16296
|
+
var file = () => path8.join(process.env.POLYMATH_DATA_DIR || path8.join(process.cwd(), ".data"), "run-stats.jsonl");
|
|
16297
16297
|
function write(ev) {
|
|
16298
16298
|
try {
|
|
16299
16299
|
mkdirSync(path8.dirname(file()), { recursive: true });
|
|
@@ -16293,7 +16293,7 @@ import path9 from "path";
|
|
|
16293
16293
|
import { appendFileSync, mkdirSync } from "fs";
|
|
16294
16294
|
import path8 from "path";
|
|
16295
16295
|
var G = globalThis;
|
|
16296
|
-
var file = () => path8.join(process.cwd(), ".data", "run-stats.jsonl");
|
|
16296
|
+
var file = () => path8.join(process.env.POLYMATH_DATA_DIR || path8.join(process.cwd(), ".data"), "run-stats.jsonl");
|
|
16297
16297
|
function write(ev) {
|
|
16298
16298
|
try {
|
|
16299
16299
|
mkdirSync(path8.dirname(file()), { recursive: true });
|