polymath-society 0.2.4 → 0.2.5
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 +1024 -379
- package/dist/index.js +57 -23
- package/dist/pipeline/coding-agglomerate.js +174 -15
- package/dist/pipeline/coding-aggregate.js +306 -8
- package/dist/pipeline/coding-build.js +355 -8
- package/dist/pipeline/coding-coaching.js +1 -1
- package/dist/pipeline/coding-day-digest.js +343 -32
- package/dist/pipeline/coding-delegation.js +319 -17
- package/dist/pipeline/coding-expertise.js +324 -22
- package/dist/pipeline/coding-flow.js +302 -4
- package/dist/pipeline/coding-focus.js +16306 -0
- package/dist/pipeline/coding-frontier-detail.js +316 -14
- package/dist/pipeline/coding-frontier.js +350 -1
- package/dist/pipeline/coding-gap-dist.js +302 -4
- package/dist/pipeline/coding-gap.js +1 -1
- package/dist/pipeline/coding-grade.js +180 -20
- package/dist/pipeline/coding-nutshell.js +318 -16
- package/dist/pipeline/coding-projects.js +354 -5
- package/dist/pipeline/coding-walkthrough.js +317 -18
- package/dist/web/app.js +69 -19
- package/dist/web/styles.css +1 -1
- package/package.json +2 -2
package/dist/cli.js
CHANGED
|
@@ -32,6 +32,33 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
|
|
|
32
32
|
mod
|
|
33
33
|
));
|
|
34
34
|
|
|
35
|
+
// src/dataHome.ts
|
|
36
|
+
import { existsSync } from "fs";
|
|
37
|
+
import os from "os";
|
|
38
|
+
import path from "path";
|
|
39
|
+
function electronAppData() {
|
|
40
|
+
const candidates = [
|
|
41
|
+
"/Applications/Polymath.app/Contents/Resources/standalone/.data",
|
|
42
|
+
path.join(os.homedir(), "Applications", "Polymath.app", "Contents", "Resources", "standalone", ".data")
|
|
43
|
+
];
|
|
44
|
+
for (const c of candidates) if (existsSync(path.join(c, "coding"))) return c;
|
|
45
|
+
return null;
|
|
46
|
+
}
|
|
47
|
+
function resolveDataRoot(env = process.env, cwd = process.cwd(), appData = electronAppData) {
|
|
48
|
+
const fromEnv = env.POLYMATH_DATA_DIR;
|
|
49
|
+
if (fromEnv && fromEnv.trim()) return path.resolve(fromEnv);
|
|
50
|
+
const local = path.join(cwd, ".data");
|
|
51
|
+
if (existsSync(local)) return local;
|
|
52
|
+
const fromApp = appData();
|
|
53
|
+
if (fromApp) return fromApp;
|
|
54
|
+
return path.join(os.homedir(), ".polymath-society", "data");
|
|
55
|
+
}
|
|
56
|
+
var init_dataHome = __esm({
|
|
57
|
+
"src/dataHome.ts"() {
|
|
58
|
+
"use strict";
|
|
59
|
+
}
|
|
60
|
+
});
|
|
61
|
+
|
|
35
62
|
// ../coding-core/dist/injected.js
|
|
36
63
|
function stripInjected(t) {
|
|
37
64
|
for (const re2 of INJECTED_RES)
|
|
@@ -73,15 +100,15 @@ var init_injected = __esm({
|
|
|
73
100
|
|
|
74
101
|
// ../coding-core/dist/raw.js
|
|
75
102
|
import { promises as fs } from "fs";
|
|
76
|
-
import
|
|
77
|
-
import
|
|
103
|
+
import path2 from "path";
|
|
104
|
+
import os2 from "os";
|
|
78
105
|
function resolveSourceRoot(envVar, ...defaultSegments) {
|
|
79
106
|
const explicit = process.env[envVar];
|
|
80
107
|
if (explicit)
|
|
81
108
|
return explicit;
|
|
82
109
|
if (anyRootOverridden())
|
|
83
110
|
return null;
|
|
84
|
-
return
|
|
111
|
+
return path2.join(os2.homedir(), ...defaultSegments);
|
|
85
112
|
}
|
|
86
113
|
function sourceRoots() {
|
|
87
114
|
return {
|
|
@@ -305,7 +332,7 @@ function codexText(content) {
|
|
|
305
332
|
return "";
|
|
306
333
|
}
|
|
307
334
|
function parseCodex(raw, file2) {
|
|
308
|
-
let sessionId =
|
|
335
|
+
let sessionId = path2.basename(file2, ".jsonl");
|
|
309
336
|
const s = blank(sessionId, "codex", file2);
|
|
310
337
|
for (const lineRaw of raw.split("\n")) {
|
|
311
338
|
const line = lineRaw.trim();
|
|
@@ -389,7 +416,7 @@ async function readClaudeCode() {
|
|
|
389
416
|
for (const dir of dirs) {
|
|
390
417
|
if (SKIP_DIR_RE.test(dir))
|
|
391
418
|
continue;
|
|
392
|
-
const full =
|
|
419
|
+
const full = path2.join(base2, dir);
|
|
393
420
|
let files = [];
|
|
394
421
|
try {
|
|
395
422
|
files = (await fs.readdir(full)).filter((f) => f.endsWith(".jsonl"));
|
|
@@ -397,14 +424,14 @@ async function readClaudeCode() {
|
|
|
397
424
|
continue;
|
|
398
425
|
}
|
|
399
426
|
for (const f of files) {
|
|
400
|
-
const file2 =
|
|
427
|
+
const file2 = path2.join(full, f);
|
|
401
428
|
let raw;
|
|
402
429
|
try {
|
|
403
430
|
raw = await fs.readFile(file2, "utf-8");
|
|
404
431
|
} catch {
|
|
405
432
|
continue;
|
|
406
433
|
}
|
|
407
|
-
const s = parseClaudeCode(raw,
|
|
434
|
+
const s = parseClaudeCode(raw, path2.basename(f, ".jsonl"), file2);
|
|
408
435
|
if (s)
|
|
409
436
|
out.push(s);
|
|
410
437
|
}
|
|
@@ -419,7 +446,7 @@ async function walkJsonl(dir, acc) {
|
|
|
419
446
|
return;
|
|
420
447
|
}
|
|
421
448
|
for (const ent of entries) {
|
|
422
|
-
const full =
|
|
449
|
+
const full = path2.join(dir, ent.name);
|
|
423
450
|
if (ent.isDirectory())
|
|
424
451
|
await walkJsonl(full, acc);
|
|
425
452
|
else if (ent.name.endsWith(".jsonl"))
|
|
@@ -514,15 +541,15 @@ async function readCursorWorkspaces() {
|
|
|
514
541
|
for (const d of dirs) {
|
|
515
542
|
if (!d.isDirectory())
|
|
516
543
|
continue;
|
|
517
|
-
const wsDir =
|
|
544
|
+
const wsDir = path2.join(base2, d.name);
|
|
518
545
|
let folder = null;
|
|
519
546
|
try {
|
|
520
|
-
folder = fileUriToPath(JSON.parse(await fs.readFile(
|
|
547
|
+
folder = fileUriToPath(JSON.parse(await fs.readFile(path2.join(wsDir, "workspace.json"), "utf-8")).folder);
|
|
521
548
|
} catch {
|
|
522
549
|
}
|
|
523
550
|
if (!folder)
|
|
524
551
|
continue;
|
|
525
|
-
const dbFile =
|
|
552
|
+
const dbFile = path2.join(wsDir, "state.vscdb");
|
|
526
553
|
try {
|
|
527
554
|
await fs.access(dbFile);
|
|
528
555
|
} catch {
|
|
@@ -664,7 +691,7 @@ async function readCursor() {
|
|
|
664
691
|
const slug = d.name;
|
|
665
692
|
if (SKIP_DIR_RE.test(slug))
|
|
666
693
|
continue;
|
|
667
|
-
const transcriptsDir =
|
|
694
|
+
const transcriptsDir = path2.join(projects, slug, "agent-transcripts");
|
|
668
695
|
let composers = [];
|
|
669
696
|
try {
|
|
670
697
|
composers = await fs.readdir(transcriptsDir, { withFileTypes: true });
|
|
@@ -679,7 +706,7 @@ async function readCursor() {
|
|
|
679
706
|
if (!c.isDirectory())
|
|
680
707
|
continue;
|
|
681
708
|
const composerId = c.name;
|
|
682
|
-
const jf =
|
|
709
|
+
const jf = path2.join(transcriptsDir, composerId, `${composerId}.jsonl`);
|
|
683
710
|
let raw;
|
|
684
711
|
let mtime = Date.now();
|
|
685
712
|
try {
|
|
@@ -812,9 +839,9 @@ var init_adapter = __esm({
|
|
|
812
839
|
|
|
813
840
|
// src/grade/backends.ts
|
|
814
841
|
import { spawnSync } from "child_process";
|
|
815
|
-
import { existsSync } from "fs";
|
|
816
|
-
import
|
|
817
|
-
import
|
|
842
|
+
import { existsSync as existsSync2 } from "fs";
|
|
843
|
+
import os3 from "os";
|
|
844
|
+
import path3 from "path";
|
|
818
845
|
function run(bin, args) {
|
|
819
846
|
try {
|
|
820
847
|
const r = spawnSync(bin, args, { encoding: "utf-8", timeout: PROBE_TIMEOUT_MS });
|
|
@@ -827,14 +854,14 @@ function resolveBin(envOverride, name17, candidates) {
|
|
|
827
854
|
if (envOverride) return envOverride;
|
|
828
855
|
const found = run("/bin/sh", ["-c", `command -v ${name17}`]);
|
|
829
856
|
if (found.code === 0 && found.text) return found.text.split("\n")[0];
|
|
830
|
-
for (const c of candidates) if (
|
|
857
|
+
for (const c of candidates) if (existsSync2(c)) return c;
|
|
831
858
|
return null;
|
|
832
859
|
}
|
|
833
860
|
function claudeBin() {
|
|
834
861
|
return resolveBin(process.env.CLAUDE_BIN, "claude", [
|
|
835
862
|
"/opt/homebrew/bin/claude",
|
|
836
863
|
"/usr/local/bin/claude",
|
|
837
|
-
|
|
864
|
+
path3.join(HOME, ".local/bin/claude")
|
|
838
865
|
]);
|
|
839
866
|
}
|
|
840
867
|
function codexBin() {
|
|
@@ -855,7 +882,7 @@ function probeCli() {
|
|
|
855
882
|
const kc = run("security", ["find-generic-password", "-s", "Claude Code-credentials"]);
|
|
856
883
|
if (kc.code === 0) return { name: "cli", bin, authed: true, detail: "Keychain OAuth credentials", loginCmd };
|
|
857
884
|
}
|
|
858
|
-
if (
|
|
885
|
+
if (existsSync2(path3.join(HOME, ".claude/.credentials.json")))
|
|
859
886
|
return { name: "cli", bin, authed: true, detail: "~/.claude/.credentials.json", loginCmd };
|
|
860
887
|
return { name: "cli", bin, authed: false, detail: "not logged in", loginCmd };
|
|
861
888
|
}
|
|
@@ -902,7 +929,7 @@ var HOME, PROBE_TIMEOUT_MS, cached;
|
|
|
902
929
|
var init_backends = __esm({
|
|
903
930
|
"src/grade/backends.ts"() {
|
|
904
931
|
"use strict";
|
|
905
|
-
HOME =
|
|
932
|
+
HOME = os3.homedir();
|
|
906
933
|
PROBE_TIMEOUT_MS = 15e3;
|
|
907
934
|
cached = null;
|
|
908
935
|
}
|
|
@@ -1292,9 +1319,9 @@ var require_secure_json_parse = __commonJS({
|
|
|
1292
1319
|
|
|
1293
1320
|
// src/manifest.ts
|
|
1294
1321
|
import { promises as fs24 } from "fs";
|
|
1295
|
-
import
|
|
1322
|
+
import path30 from "path";
|
|
1296
1323
|
function manifestPath(dataDir) {
|
|
1297
|
-
return
|
|
1324
|
+
return path30.join(dataDir, MANIFEST_BASENAME);
|
|
1298
1325
|
}
|
|
1299
1326
|
async function readManifest(dataDir) {
|
|
1300
1327
|
const p = manifestPath(dataDir);
|
|
@@ -1333,15 +1360,15 @@ async function writeManifest(dataDir, m) {
|
|
|
1333
1360
|
function parsePicker(input, defaults) {
|
|
1334
1361
|
const t = input.trim().toLowerCase();
|
|
1335
1362
|
if (t === "") return [...defaults];
|
|
1336
|
-
if (t === "
|
|
1337
|
-
if (t === "
|
|
1363
|
+
if (t === "none" || t === "n") return defaults.map(() => true);
|
|
1364
|
+
if (t === "all" || t === "a") return defaults.map(() => false);
|
|
1338
1365
|
const tokens = t.split(/[\s,]+/).filter(Boolean);
|
|
1339
|
-
const out =
|
|
1366
|
+
const out = defaults.map(() => true);
|
|
1340
1367
|
for (const tok of tokens) {
|
|
1341
1368
|
if (!/^\d+$/.test(tok)) return null;
|
|
1342
1369
|
const i = Number(tok) - 1;
|
|
1343
1370
|
if (i < 0 || i >= defaults.length) return null;
|
|
1344
|
-
out[i] =
|
|
1371
|
+
out[i] = false;
|
|
1345
1372
|
}
|
|
1346
1373
|
return out;
|
|
1347
1374
|
}
|
|
@@ -1460,7 +1487,7 @@ var init_remind = __esm({
|
|
|
1460
1487
|
import { promises as fs28 } from "fs";
|
|
1461
1488
|
import { execFile as execFile2 } from "child_process";
|
|
1462
1489
|
import { promisify as promisify2 } from "util";
|
|
1463
|
-
import
|
|
1490
|
+
import path34 from "path";
|
|
1464
1491
|
async function zipEntries(zip) {
|
|
1465
1492
|
try {
|
|
1466
1493
|
const { stdout } = await run3("unzip", ["-Z1", zip], { maxBuffer: 8 * 1024 * 1024 });
|
|
@@ -1514,7 +1541,7 @@ async function identifyZip(zip, stat) {
|
|
|
1514
1541
|
note: ""
|
|
1515
1542
|
};
|
|
1516
1543
|
if (!entries) {
|
|
1517
|
-
const n =
|
|
1544
|
+
const n = path34.basename(zip).toLowerCase();
|
|
1518
1545
|
if (n.includes("chatgpt") || n.includes("openai")) {
|
|
1519
1546
|
found.kind = "chatgpt";
|
|
1520
1547
|
found.note = "matched by filename only (no unzip binary to verify)";
|
|
@@ -1525,15 +1552,30 @@ async function identifyZip(zip, stat) {
|
|
|
1525
1552
|
found.note = "matched by filename only (no unzip binary to verify)";
|
|
1526
1553
|
return found;
|
|
1527
1554
|
}
|
|
1528
|
-
if (n.includes("notion") ||
|
|
1555
|
+
if (n.includes("notion") || /(^|[-_ ])export-/.test(n)) {
|
|
1529
1556
|
found.kind = "notion";
|
|
1530
1557
|
found.note = "matched by filename only (no unzip binary to verify)";
|
|
1531
1558
|
return found;
|
|
1532
1559
|
}
|
|
1533
1560
|
return null;
|
|
1534
1561
|
}
|
|
1535
|
-
|
|
1536
|
-
if (kind === "unknown")
|
|
1562
|
+
let { kind, note } = classify2(entries);
|
|
1563
|
+
if (kind === "unknown") {
|
|
1564
|
+
const nb = path34.basename(zip).toLowerCase();
|
|
1565
|
+
const nameHint = nb.includes("notion") || /(^|[-_ ])export-/.test(nb);
|
|
1566
|
+
const inner = entries.filter((e) => e.toLowerCase().endsWith(".zip"));
|
|
1567
|
+
const partZips = inner.some((e) => /export[^/]*part[-_ ]?\d+\.zip$/i.test(e.toLowerCase()));
|
|
1568
|
+
const pages = entries.filter((e) => /\.(md|html)$/.test(e)).length;
|
|
1569
|
+
if (partZips || inner.length > 0 && nameHint) {
|
|
1570
|
+
kind = "notion";
|
|
1571
|
+
note = `nested export zip${inner.length === 1 ? "" : "s"} (${inner.length}) \u2014 Notion multi-part layout`;
|
|
1572
|
+
} else if (pages >= 1 && nameHint) {
|
|
1573
|
+
kind = "notion";
|
|
1574
|
+
note = `${pages} .md/.html page${pages === 1 ? "" : "s"} + export filename (Notion layout)`;
|
|
1575
|
+
} else {
|
|
1576
|
+
return null;
|
|
1577
|
+
}
|
|
1578
|
+
}
|
|
1537
1579
|
found.kind = kind;
|
|
1538
1580
|
found.note = note;
|
|
1539
1581
|
if (kind === "chatgpt") {
|
|
@@ -1558,7 +1600,7 @@ async function identifyDir(dir) {
|
|
|
1558
1600
|
const found = { kind, path: dir, account: null, sizeMB: 0, modified: st.mtime.toISOString().slice(0, 10), note };
|
|
1559
1601
|
const read = async (n) => {
|
|
1560
1602
|
try {
|
|
1561
|
-
return await fs28.readFile(
|
|
1603
|
+
return await fs28.readFile(path34.join(dir, n), "utf8");
|
|
1562
1604
|
} catch {
|
|
1563
1605
|
return null;
|
|
1564
1606
|
}
|
|
@@ -1579,8 +1621,33 @@ async function identifyPath(p) {
|
|
|
1579
1621
|
if (st.isDirectory()) return identifyDir(p);
|
|
1580
1622
|
return null;
|
|
1581
1623
|
}
|
|
1582
|
-
async function
|
|
1583
|
-
const
|
|
1624
|
+
async function deterministicDiscover(home) {
|
|
1625
|
+
const out = [];
|
|
1626
|
+
if (process.platform === "darwin") {
|
|
1627
|
+
const { execFile: execFile3 } = await import("node:child_process");
|
|
1628
|
+
const run4 = (q) => new Promise((resolve2) => {
|
|
1629
|
+
execFile3("mdfind", ["-onlyin", home, q], { timeout: 1e4, maxBuffer: 4 << 20 }, (err, stdout) => {
|
|
1630
|
+
resolve2(err ? [] : stdout.split("\n").filter(Boolean));
|
|
1631
|
+
});
|
|
1632
|
+
});
|
|
1633
|
+
for (const q of MDFIND_QUERIES) {
|
|
1634
|
+
for (const hit of (await run4(q)).slice(0, 40)) {
|
|
1635
|
+
out.push(hit.endsWith("conversations.json") ? hit.slice(0, hit.lastIndexOf("/")) : hit);
|
|
1636
|
+
}
|
|
1637
|
+
}
|
|
1638
|
+
}
|
|
1639
|
+
const path38 = await import("node:path");
|
|
1640
|
+
for (const dir of ["Downloads", "Desktop", "Documents"]) {
|
|
1641
|
+
for (const f of await scanForExports(path38.join(home, dir)).catch(() => [])) out.push(f.path);
|
|
1642
|
+
}
|
|
1643
|
+
return [...new Set(out)].slice(0, 80);
|
|
1644
|
+
}
|
|
1645
|
+
async function agentDiscoverCandidates(invoke, home, alreadyFound = []) {
|
|
1646
|
+
const seeded = alreadyFound.length ? `
|
|
1647
|
+
|
|
1648
|
+
Already located by a deterministic scan (do NOT re-report these; look for anything ELSE):
|
|
1649
|
+
${alreadyFound.slice(0, 30).map((p) => `- ${p}`).join("\n")}` : "";
|
|
1650
|
+
const prompt = `Search this machine for AI-chat export artifacts the user downloaded. You are running locally on the user's own computer with their consent; nothing you find leaves the machine.${seeded}
|
|
1584
1651
|
|
|
1585
1652
|
Look for:
|
|
1586
1653
|
- ChatGPT data exports: zips or unzipped folders containing conversations.json (or conversations-000.json shards) plus user.json / chat.html
|
|
@@ -1615,7 +1682,7 @@ async function countMdNotes(root, cap = 2e3) {
|
|
|
1615
1682
|
for (const e of entries) {
|
|
1616
1683
|
if (n >= cap) return;
|
|
1617
1684
|
if (e.name.startsWith(".")) continue;
|
|
1618
|
-
if (e.isDirectory()) await walk(
|
|
1685
|
+
if (e.isDirectory()) await walk(path34.join(d, e.name), depth + 1);
|
|
1619
1686
|
else if (e.name.endsWith(".md")) n++;
|
|
1620
1687
|
}
|
|
1621
1688
|
}
|
|
@@ -1624,7 +1691,7 @@ async function countMdNotes(root, cap = 2e3) {
|
|
|
1624
1691
|
}
|
|
1625
1692
|
async function identifyObsidianVault(dir) {
|
|
1626
1693
|
try {
|
|
1627
|
-
const st = await fs28.stat(
|
|
1694
|
+
const st = await fs28.stat(path34.join(dir, ".obsidian"));
|
|
1628
1695
|
if (!st.isDirectory()) return null;
|
|
1629
1696
|
} catch {
|
|
1630
1697
|
return null;
|
|
@@ -1651,9 +1718,9 @@ async function scanForObsidianVaults(home) {
|
|
|
1651
1718
|
}
|
|
1652
1719
|
};
|
|
1653
1720
|
const roots = [
|
|
1654
|
-
|
|
1655
|
-
|
|
1656
|
-
|
|
1721
|
+
path34.join(home, "Library", "Mobile Documents", "iCloud~md~obsidian", "Documents"),
|
|
1722
|
+
path34.join(home, "Documents"),
|
|
1723
|
+
path34.join(home, "Desktop"),
|
|
1657
1724
|
home
|
|
1658
1725
|
];
|
|
1659
1726
|
for (const root of roots) {
|
|
@@ -1665,7 +1732,7 @@ async function scanForObsidianVaults(home) {
|
|
|
1665
1732
|
}
|
|
1666
1733
|
for (const name17 of names) {
|
|
1667
1734
|
if (name17.startsWith(".")) continue;
|
|
1668
|
-
add(await identifyObsidianVault(
|
|
1735
|
+
add(await identifyObsidianVault(path34.join(root, name17)));
|
|
1669
1736
|
}
|
|
1670
1737
|
}
|
|
1671
1738
|
return out;
|
|
@@ -1680,7 +1747,7 @@ async function scanForExports(root) {
|
|
|
1680
1747
|
}
|
|
1681
1748
|
for (const name17 of names) {
|
|
1682
1749
|
if (name17.startsWith(".")) continue;
|
|
1683
|
-
const p =
|
|
1750
|
+
const p = path34.join(root, name17);
|
|
1684
1751
|
let st;
|
|
1685
1752
|
try {
|
|
1686
1753
|
st = await fs28.stat(p);
|
|
@@ -1697,11 +1764,86 @@ async function scanForExports(root) {
|
|
|
1697
1764
|
}
|
|
1698
1765
|
return out.sort((a, b) => a.modified < b.modified ? 1 : -1);
|
|
1699
1766
|
}
|
|
1700
|
-
var run3;
|
|
1767
|
+
var run3, MDFIND_QUERIES;
|
|
1701
1768
|
var init_exportScan = __esm({
|
|
1702
1769
|
"src/exportScan.ts"() {
|
|
1703
1770
|
"use strict";
|
|
1704
1771
|
run3 = promisify2(execFile2);
|
|
1772
|
+
MDFIND_QUERIES = [
|
|
1773
|
+
// ChatGPT exports: the conversations.json inside the zip/folder
|
|
1774
|
+
`kMDItemFSName == "conversations.json"`,
|
|
1775
|
+
// claude.ai export zips: data-<uuid>-...-batch-0000.zip
|
|
1776
|
+
`kMDItemFSName == "data-*batch-*.zip"`,
|
|
1777
|
+
// Notion workspace exports
|
|
1778
|
+
`kMDItemFSName == "*Export-*.zip"`
|
|
1779
|
+
];
|
|
1780
|
+
}
|
|
1781
|
+
});
|
|
1782
|
+
|
|
1783
|
+
// src/banner.ts
|
|
1784
|
+
var banner_exports = {};
|
|
1785
|
+
__export(banner_exports, {
|
|
1786
|
+
banner: () => banner,
|
|
1787
|
+
printBanner: () => printBanner
|
|
1788
|
+
});
|
|
1789
|
+
function banner(version, out = process.stderr) {
|
|
1790
|
+
const tty = !!out.isTTY && !process.env.NO_COLOR;
|
|
1791
|
+
const cols = out.columns || 80;
|
|
1792
|
+
if (!tty) return `
|
|
1793
|
+
Polymath Society v${version}
|
|
1794
|
+
${TAGLINE}
|
|
1795
|
+
${PRIVACY}
|
|
1796
|
+
`;
|
|
1797
|
+
if (cols >= 74) {
|
|
1798
|
+
const lines = KEYBLOCK.map((l) => ` ${GOLD}${l}${RESET}`);
|
|
1799
|
+
lines.push(` ${DIM} \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 S O C I E T Y \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500${RESET}`);
|
|
1800
|
+
lines.push("");
|
|
1801
|
+
lines.push(` ${TAGLINE} ${DIM}v${version}${RESET}`);
|
|
1802
|
+
lines.push(` ${DIM}${PRIVACY}${RESET}`);
|
|
1803
|
+
return `
|
|
1804
|
+
${lines.join("\n")}
|
|
1805
|
+
`;
|
|
1806
|
+
}
|
|
1807
|
+
const right = ["", "POLYMATH", "SOCIETY", "", `${DIM}v${version}${RESET}`, ""];
|
|
1808
|
+
const mark = MONOGRAM.map((l, i) => ` ${GOLD}${l}${RESET} ${right[i]}`.trimEnd());
|
|
1809
|
+
return `
|
|
1810
|
+
${mark.join("\n")}
|
|
1811
|
+
|
|
1812
|
+
${TAGLINE}
|
|
1813
|
+
${DIM}${PRIVACY}${RESET}
|
|
1814
|
+
`;
|
|
1815
|
+
}
|
|
1816
|
+
async function printBanner(out = process.stderr) {
|
|
1817
|
+
let version = "0.0.0";
|
|
1818
|
+
try {
|
|
1819
|
+
const { promises: fs32 } = await import("fs");
|
|
1820
|
+
const path38 = await import("path");
|
|
1821
|
+
const { fileURLToPath: fileURLToPath6 } = await import("url");
|
|
1822
|
+
const here = path38.dirname(fileURLToPath6(import.meta.url));
|
|
1823
|
+
const pkg = JSON.parse(await fs32.readFile(path38.join(here, "..", "package.json"), "utf-8"));
|
|
1824
|
+
version = String(pkg.version || version);
|
|
1825
|
+
} catch {
|
|
1826
|
+
}
|
|
1827
|
+
out.write(banner(version, out));
|
|
1828
|
+
}
|
|
1829
|
+
var GOLD, DIM, RESET, KEYBLOCK, MONOGRAM, TAGLINE, PRIVACY;
|
|
1830
|
+
var init_banner = __esm({
|
|
1831
|
+
"src/banner.ts"() {
|
|
1832
|
+
"use strict";
|
|
1833
|
+
GOLD = "\x1B[38;5;179m";
|
|
1834
|
+
DIM = "\x1B[2m";
|
|
1835
|
+
RESET = "\x1B[0m";
|
|
1836
|
+
KEYBLOCK = [
|
|
1837
|
+
"\u2588\u2588\u2588\u2588\u2588\u2588\u2557 \u2588\u2588\u2588\u2588\u2588\u2588\u2557 \u2588\u2588\u2557 \u2588\u2588\u2557 \u2588\u2588\u2557\u2588\u2588\u2588\u2557 \u2588\u2588\u2588\u2557 \u2588\u2588\u2588\u2588\u2588\u2557 \u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2557\u2588\u2588\u2557 \u2588\u2588\u2557",
|
|
1838
|
+
"\u2588\u2588\u2554\u2550\u2550\u2588\u2588\u2557\u2588\u2588\u2554\u2550\u2550\u2550\u2588\u2588\u2557\u2588\u2588\u2551 \u255A\u2588\u2588\u2557 \u2588\u2588\u2554\u255D\u2588\u2588\u2588\u2588\u2557 \u2588\u2588\u2588\u2588\u2551\u2588\u2588\u2554\u2550\u2550\u2588\u2588\u2557\u255A\u2550\u2550\u2588\u2588\u2554\u2550\u2550\u255D\u2588\u2588\u2551 \u2588\u2588\u2551",
|
|
1839
|
+
"\u2588\u2588\u2588\u2588\u2588\u2588\u2554\u255D\u2588\u2588\u2551 \u2588\u2588\u2551\u2588\u2588\u2551 \u255A\u2588\u2588\u2588\u2588\u2554\u255D \u2588\u2588\u2554\u2588\u2588\u2588\u2588\u2554\u2588\u2588\u2551\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2551 \u2588\u2588\u2551 \u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2551",
|
|
1840
|
+
"\u2588\u2588\u2554\u2550\u2550\u2550\u255D \u2588\u2588\u2551 \u2588\u2588\u2551\u2588\u2588\u2551 \u255A\u2588\u2588\u2554\u255D \u2588\u2588\u2551\u255A\u2588\u2588\u2554\u255D\u2588\u2588\u2551\u2588\u2588\u2554\u2550\u2550\u2588\u2588\u2551 \u2588\u2588\u2551 \u2588\u2588\u2554\u2550\u2550\u2588\u2588\u2551",
|
|
1841
|
+
"\u2588\u2588\u2551 \u255A\u2588\u2588\u2588\u2588\u2588\u2588\u2554\u255D\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2557 \u2588\u2588\u2551 \u2588\u2588\u2551 \u255A\u2550\u255D \u2588\u2588\u2551\u2588\u2588\u2551 \u2588\u2588\u2551 \u2588\u2588\u2551 \u2588\u2588\u2551 \u2588\u2588\u2551",
|
|
1842
|
+
"\u255A\u2550\u255D \u255A\u2550\u2550\u2550\u2550\u2550\u255D \u255A\u2550\u2550\u2550\u2550\u2550\u2550\u255D \u255A\u2550\u255D \u255A\u2550\u255D \u255A\u2550\u255D\u255A\u2550\u255D \u255A\u2550\u255D \u255A\u2550\u255D \u255A\u2550\u255D \u255A\u2550\u255D"
|
|
1843
|
+
];
|
|
1844
|
+
MONOGRAM = ["\u2588\u2588\u2588\u2588\u2588\u2588\u2557 ", "\u2588\u2588\u2554\u2550\u2550\u2588\u2588\u2557", "\u2588\u2588\u2588\u2588\u2588\u2588\u2554\u255D", "\u2588\u2588\u2554\u2550\u2550\u2550\u255D ", "\u2588\u2588\u2551 ", "\u255A\u2550\u255D "];
|
|
1845
|
+
TAGLINE = "see how you actually work, from your own agent logs";
|
|
1846
|
+
PRIVACY = "private by construction \xB7 everything runs on this machine";
|
|
1705
1847
|
}
|
|
1706
1848
|
});
|
|
1707
1849
|
|
|
@@ -1742,14 +1884,150 @@ var init_reminderEmail = __esm({
|
|
|
1742
1884
|
}
|
|
1743
1885
|
});
|
|
1744
1886
|
|
|
1887
|
+
// src/plan.ts
|
|
1888
|
+
var plan_exports = {};
|
|
1889
|
+
__export(plan_exports, {
|
|
1890
|
+
detectCodexPlan: () => detectCodexPlan,
|
|
1891
|
+
detectPlan: () => detectPlan,
|
|
1892
|
+
estimateLaneCosts: () => estimateLaneCosts,
|
|
1893
|
+
remainingFractions: () => remainingFractions,
|
|
1894
|
+
scheduleLanes: () => scheduleLanes,
|
|
1895
|
+
tierFromChatgptPlan: () => tierFromChatgptPlan,
|
|
1896
|
+
tierFromStrings: () => tierFromStrings
|
|
1897
|
+
});
|
|
1898
|
+
import { promises as fs29 } from "fs";
|
|
1899
|
+
import os7 from "os";
|
|
1900
|
+
import path35 from "path";
|
|
1901
|
+
function tierFromStrings(...hints) {
|
|
1902
|
+
for (const h of hints) {
|
|
1903
|
+
if (!h) continue;
|
|
1904
|
+
const s = h.toLowerCase();
|
|
1905
|
+
if (s.includes("max_20x") || s.includes("max20x")) return "max_20x";
|
|
1906
|
+
if (s.includes("max_5x") || s.includes("max5x")) return "max_5x";
|
|
1907
|
+
if (s.includes("pro")) return "pro";
|
|
1908
|
+
if (s.includes("claude_max")) return "max_5x";
|
|
1909
|
+
}
|
|
1910
|
+
return "unknown";
|
|
1911
|
+
}
|
|
1912
|
+
function tierFromChatgptPlan(planType) {
|
|
1913
|
+
const s = (planType ?? "").toLowerCase();
|
|
1914
|
+
if (s === "pro") return "gpt_pro";
|
|
1915
|
+
if (s === "plus") return "gpt_plus";
|
|
1916
|
+
if (s === "team" || s === "enterprise" || s === "business") return "gpt_team";
|
|
1917
|
+
if (s === "free") return "gpt_free";
|
|
1918
|
+
return "unknown";
|
|
1919
|
+
}
|
|
1920
|
+
async function detectCodexPlan(home = os7.homedir()) {
|
|
1921
|
+
try {
|
|
1922
|
+
const raw = JSON.parse(await fs29.readFile(path35.join(home, ".codex", "auth.json"), "utf8"));
|
|
1923
|
+
for (const tok of [raw.tokens?.id_token, raw.tokens?.access_token]) {
|
|
1924
|
+
if (!tok) continue;
|
|
1925
|
+
try {
|
|
1926
|
+
const payload = JSON.parse(Buffer.from(tok.split(".")[1], "base64url").toString("utf8"));
|
|
1927
|
+
const t = tierFromChatgptPlan(payload["https://api.openai.com/auth"]?.chatgpt_plan_type);
|
|
1928
|
+
if (t !== "unknown") return t;
|
|
1929
|
+
} catch {
|
|
1930
|
+
}
|
|
1931
|
+
}
|
|
1932
|
+
} catch {
|
|
1933
|
+
}
|
|
1934
|
+
return "unknown";
|
|
1935
|
+
}
|
|
1936
|
+
async function detectPlan(home = os7.homedir()) {
|
|
1937
|
+
let tier = "unknown";
|
|
1938
|
+
try {
|
|
1939
|
+
const raw = JSON.parse(await fs29.readFile(path35.join(home, ".claude.json"), "utf8"));
|
|
1940
|
+
const oa = raw.oauthAccount ?? {};
|
|
1941
|
+
tier = tierFromStrings(oa.userRateLimitTier, oa.organizationRateLimitTier, oa.organizationType);
|
|
1942
|
+
} catch {
|
|
1943
|
+
}
|
|
1944
|
+
if (tier === "unknown") tier = await detectCodexPlan(home);
|
|
1945
|
+
return { tier, label: LABEL[tier], windowUsd: WINDOW_USD[tier] };
|
|
1946
|
+
}
|
|
1947
|
+
function estimateLaneCosts(input) {
|
|
1948
|
+
const codingUsd = Math.max(5, Math.round(input.agentLogFiles * 13e-4));
|
|
1949
|
+
const chatUsd = input.chatIncluded ? Math.round(40 + input.exportTotalMB * 0.8) : 0;
|
|
1950
|
+
return { codingUsd, chatUsd };
|
|
1951
|
+
}
|
|
1952
|
+
async function remainingFractions(dataRoot, agentLogFiles) {
|
|
1953
|
+
const clamp = (v, lo, hi) => Math.min(hi, Math.max(lo, v));
|
|
1954
|
+
let coding = 1;
|
|
1955
|
+
try {
|
|
1956
|
+
const graded = (await fs29.readdir(path35.join(dataRoot, "coding", "grades"))).filter((f) => f.endsWith(".json")).length;
|
|
1957
|
+
const expected = Math.max(1, agentLogFiles * 56e-4);
|
|
1958
|
+
coding = clamp(1 - graded / expected, 0.05, 1);
|
|
1959
|
+
} catch {
|
|
1960
|
+
}
|
|
1961
|
+
let chatDone = 0;
|
|
1962
|
+
try {
|
|
1963
|
+
const st = await fs29.stat(path35.join(dataRoot, "signals", "index.jsonl"));
|
|
1964
|
+
if (st.size > 0) chatDone += 0.3;
|
|
1965
|
+
} catch {
|
|
1966
|
+
}
|
|
1967
|
+
try {
|
|
1968
|
+
const lenses = await fs29.readdir(path35.join(dataRoot, "engine-pilot", "grades"));
|
|
1969
|
+
let withPerson = 0;
|
|
1970
|
+
for (const l of lenses) {
|
|
1971
|
+
try {
|
|
1972
|
+
await fs29.stat(path35.join(dataRoot, "engine-pilot", "grades", l, "_person.json"));
|
|
1973
|
+
withPerson++;
|
|
1974
|
+
} catch {
|
|
1975
|
+
}
|
|
1976
|
+
}
|
|
1977
|
+
chatDone += 0.6 * Math.min(1, withPerson / 5);
|
|
1978
|
+
} catch {
|
|
1979
|
+
}
|
|
1980
|
+
return { coding, chat: clamp(1 - chatDone, 0.1, 1) };
|
|
1981
|
+
}
|
|
1982
|
+
function scheduleLanes(plan, est) {
|
|
1983
|
+
const fits = (usd) => usd <= plan.windowUsd * 0.5;
|
|
1984
|
+
const coding = fits(est.codingUsd) ? "now" : "overnight";
|
|
1985
|
+
const chat = est.chatUsd === 0 || fits(est.chatUsd) ? "now" : "overnight";
|
|
1986
|
+
return {
|
|
1987
|
+
coding,
|
|
1988
|
+
chat,
|
|
1989
|
+
codingReason: coding === "now" ? `runs now (fits comfortably inside one 5-hour window on ${plan.label})` : `starts at 2:00 am tonight (a full grade would eat most of your daytime window on ${plan.label})`,
|
|
1990
|
+
chatReason: est.chatUsd === 0 ? "no chat/notes sources included" : chat === "now" ? `runs now alongside coding (your chat corpus is small enough for ${plan.label})` : `starts at 2:00 am tonight (your chat corpus is large; this protects your daytime quota on ${plan.label})`
|
|
1991
|
+
};
|
|
1992
|
+
}
|
|
1993
|
+
var WINDOW_USD, LABEL;
|
|
1994
|
+
var init_plan = __esm({
|
|
1995
|
+
"src/plan.ts"() {
|
|
1996
|
+
"use strict";
|
|
1997
|
+
WINDOW_USD = {
|
|
1998
|
+
max_20x: 300,
|
|
1999
|
+
max_5x: 75,
|
|
2000
|
+
pro: 15,
|
|
2001
|
+
// ChatGPT tiers, mapped to rough Claude-window parity by monthly price
|
|
2002
|
+
// ($200 Pro ≈ Max 20x; $20 Plus ≈ Claude Pro; Team between; free ≈ nothing).
|
|
2003
|
+
gpt_pro: 300,
|
|
2004
|
+
gpt_plus: 20,
|
|
2005
|
+
gpt_team: 50,
|
|
2006
|
+
gpt_free: 5,
|
|
2007
|
+
unknown: 15
|
|
2008
|
+
// conservative: schedule like Pro when we can't tell
|
|
2009
|
+
};
|
|
2010
|
+
LABEL = {
|
|
2011
|
+
max_20x: "Claude Max 20x",
|
|
2012
|
+
max_5x: "Claude Max 5x",
|
|
2013
|
+
pro: "Claude Pro",
|
|
2014
|
+
gpt_pro: "ChatGPT Pro (Codex)",
|
|
2015
|
+
gpt_plus: "ChatGPT Plus (Codex)",
|
|
2016
|
+
gpt_team: "ChatGPT Team (Codex)",
|
|
2017
|
+
gpt_free: "ChatGPT Free (Codex)",
|
|
2018
|
+
unknown: "an undetected plan (scheduling conservatively)"
|
|
2019
|
+
};
|
|
2020
|
+
}
|
|
2021
|
+
});
|
|
2022
|
+
|
|
1745
2023
|
// src/wizard.ts
|
|
1746
2024
|
var wizard_exports = {};
|
|
1747
2025
|
__export(wizard_exports, {
|
|
1748
2026
|
runWizard: () => runWizard
|
|
1749
2027
|
});
|
|
1750
|
-
import { promises as
|
|
1751
|
-
import
|
|
1752
|
-
import
|
|
2028
|
+
import { promises as fs30 } from "fs";
|
|
2029
|
+
import os8 from "os";
|
|
2030
|
+
import path36 from "path";
|
|
1753
2031
|
import * as readline from "node:readline/promises";
|
|
1754
2032
|
async function scanJsonlDir(label, dir) {
|
|
1755
2033
|
let files = 0;
|
|
@@ -1758,15 +2036,15 @@ async function scanJsonlDir(label, dir) {
|
|
|
1758
2036
|
if (depth > 1) return;
|
|
1759
2037
|
let names = [];
|
|
1760
2038
|
try {
|
|
1761
|
-
names = await
|
|
2039
|
+
names = await fs30.readdir(d);
|
|
1762
2040
|
} catch {
|
|
1763
2041
|
return;
|
|
1764
2042
|
}
|
|
1765
2043
|
for (const n of names) {
|
|
1766
|
-
const p =
|
|
2044
|
+
const p = path36.join(d, n);
|
|
1767
2045
|
let st;
|
|
1768
2046
|
try {
|
|
1769
|
-
st = await
|
|
2047
|
+
st = await fs30.stat(p);
|
|
1770
2048
|
} catch {
|
|
1771
2049
|
continue;
|
|
1772
2050
|
}
|
|
@@ -1792,7 +2070,7 @@ function describeExport(f, i, included, hadPrevious) {
|
|
|
1792
2070
|
const size = f.sizeMB ? ` \xB7 ${f.sizeMB} MB` : "";
|
|
1793
2071
|
const state = hadPrevious ? included ? green(" [use]") : dim(" [skip \u2014 previously excluded]") : "";
|
|
1794
2072
|
return ` ${i + 1}. ${bold(kind)}${who}${size} \xB7 ${f.modified}${state}
|
|
1795
|
-
${dim(
|
|
2073
|
+
${dim(path36.basename(f.path))} ${dim(`(${f.note})`)}`;
|
|
1796
2074
|
}
|
|
1797
2075
|
async function runWizard() {
|
|
1798
2076
|
const rl = readline.createInterface({ input: process.stdin, output: process.stderr });
|
|
@@ -1835,20 +2113,19 @@ async function runWizard() {
|
|
|
1835
2113
|
return a === "" ? def : a.startsWith("y");
|
|
1836
2114
|
};
|
|
1837
2115
|
const pick2 = async (defaults, hadPrevious) => {
|
|
1838
|
-
const hint =
|
|
2116
|
+
const hint = "(Enter = take everything into account \xB7 numbers to exclude, e.g. '2 4' \xB7 'all' = exclude everything)";
|
|
1839
2117
|
for (; ; ) {
|
|
1840
|
-
const a = await ask(`
|
|
2118
|
+
const a = await ask(` Exclude any? ${dim(hint)} `);
|
|
1841
2119
|
const r = parsePicker(a, defaults);
|
|
1842
2120
|
if (r) return r;
|
|
1843
2121
|
say(dim(` Didn't understand "${a}" \u2014 numbers between 1 and ${defaults.length}, or all/none.`));
|
|
1844
2122
|
}
|
|
1845
2123
|
};
|
|
1846
2124
|
try {
|
|
2125
|
+
const { printBanner: printBanner2 } = await Promise.resolve().then(() => (init_banner(), banner_exports));
|
|
2126
|
+
await printBanner2();
|
|
1847
2127
|
say();
|
|
1848
|
-
|
|
1849
|
-
say(` ${dim("Private by construction: everything runs on this machine. Nothing is uploaded.")}`);
|
|
1850
|
-
say();
|
|
1851
|
-
const dataDir = path34.join(process.cwd(), ".data");
|
|
2128
|
+
const dataDir = resolveDataRoot();
|
|
1852
2129
|
const previous = await readManifest(dataDir).catch((e) => {
|
|
1853
2130
|
say(dim(` (couldn't read previous choices: ${e.message})`));
|
|
1854
2131
|
return null;
|
|
@@ -1863,7 +2140,7 @@ async function runWizard() {
|
|
|
1863
2140
|
for (let i = 0; i < agentScans.length; i++) {
|
|
1864
2141
|
const s = agentScans[i];
|
|
1865
2142
|
const idx = present.indexOf(agentIds[i]);
|
|
1866
|
-
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(
|
|
2143
|
+
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(os8.homedir(), "~"))}` : ` ${dim("\xB7")} ${dim(`${s.label} \u2014 none found`)} ${dim(s.dir.replace(os8.homedir(), "~"))}`);
|
|
1867
2144
|
}
|
|
1868
2145
|
say(dim(" (log files include forks and agent runs \u2014 the report separates your real sessions out)"));
|
|
1869
2146
|
if (present.length === 0) {
|
|
@@ -1889,6 +2166,32 @@ async function runWizard() {
|
|
|
1889
2166
|
excluded: present.filter((_, i) => !agentInclude[i])
|
|
1890
2167
|
};
|
|
1891
2168
|
for (const id of agents.excluded) say(` ${dim(`\u2717 ${id} excluded \u2014 its logs will not be read.`)}`);
|
|
2169
|
+
let notifyEmail = null;
|
|
2170
|
+
try {
|
|
2171
|
+
notifyEmail = JSON.parse(await fs30.readFile(path36.join(dataDir, "notify-email.json"), "utf8")).email ?? null;
|
|
2172
|
+
} catch {
|
|
2173
|
+
}
|
|
2174
|
+
{
|
|
2175
|
+
const { looksLikeEmail: looksLikeEmail2 } = await Promise.resolve().then(() => (init_reminderEmail(), reminderEmail_exports));
|
|
2176
|
+
say();
|
|
2177
|
+
if (notifyEmail) {
|
|
2178
|
+
say(` Updates go to ${bold(notifyEmail)} ${dim("(stored only on this machine)")}`);
|
|
2179
|
+
} else {
|
|
2180
|
+
const e = (await ask(` Your email ${dim("(recommended \u2014 a heads-up when your report is ready or your exports arrive; Enter to skip)")}: `)).trim();
|
|
2181
|
+
if (e && looksLikeEmail2(e)) {
|
|
2182
|
+
notifyEmail = e;
|
|
2183
|
+
try {
|
|
2184
|
+
await fs30.mkdir(dataDir, { recursive: true });
|
|
2185
|
+
await fs30.writeFile(path36.join(dataDir, "notify-email.json"), JSON.stringify({ email: e }));
|
|
2186
|
+
} catch {
|
|
2187
|
+
}
|
|
2188
|
+
say(` ${green("\u2713")} Saved on this machine only.`);
|
|
2189
|
+
} else if (e) {
|
|
2190
|
+
say(dim(` "${e}" doesn't look like an email \u2014 skipping.`));
|
|
2191
|
+
}
|
|
2192
|
+
}
|
|
2193
|
+
}
|
|
2194
|
+
let approvedExports = [];
|
|
1892
2195
|
say();
|
|
1893
2196
|
say(bold(" Step 2 \xB7 Chat + notes sources") + dim(" (optional \u2014 ChatGPT / claude.ai / Notion exports, Obsidian vaults)"));
|
|
1894
2197
|
let found = [];
|
|
@@ -1899,32 +2202,32 @@ async function runWizard() {
|
|
|
1899
2202
|
found.push(f);
|
|
1900
2203
|
}
|
|
1901
2204
|
};
|
|
1902
|
-
|
|
1903
|
-
|
|
1904
|
-
|
|
1905
|
-
|
|
1906
|
-
const { invokeAgent: invokeAgent3 } = await Promise.resolve().then(() => (init_agent(), agent_exports));
|
|
1907
|
-
say(dim(" Searching (your agent is writing its own filesystem searches; nothing leaves this machine)..."));
|
|
1908
|
-
const candidates = await agentDiscoverCandidates((inv) => invokeAgent3(inv), os6.homedir());
|
|
1909
|
-
for (const c of candidates) add(await identifyPath(c));
|
|
1910
|
-
} catch (e) {
|
|
1911
|
-
say(dim(` Agent search unavailable (${e instanceof Error ? e.message.slice(0, 80) : "failed"}) \u2014 checking ~/Downloads instead.`));
|
|
1912
|
-
}
|
|
1913
|
-
}
|
|
1914
|
-
for (const f of await scanForExports(path34.join(os6.homedir(), "Downloads"))) add(f);
|
|
1915
|
-
for (const f of await scanForObsidianVaults(os6.homedir())) add(f);
|
|
2205
|
+
say(dim(" Scanning for known export formats (Spotlight + the usual folders, a few seconds)..."));
|
|
2206
|
+
for (const c of await deterministicDiscover(os8.homedir())) add(await identifyPath(c));
|
|
2207
|
+
for (const f of await scanForExports(path36.join(os8.homedir(), "Downloads"))) add(f);
|
|
2208
|
+
for (const f of await scanForObsidianVaults(os8.homedir())) add(f);
|
|
1916
2209
|
for (const f of [...previous?.exports.included ?? [], ...previous?.exports.excluded ?? []]) add(f);
|
|
1917
2210
|
if (!found.length) {
|
|
1918
|
-
say(dim(
|
|
1919
|
-
|
|
1920
|
-
|
|
2211
|
+
say(dim(" Nothing found in the usual places."));
|
|
2212
|
+
if (await yes(` Search deeper with your own local agent? ${dim("(capped at ~90s)")}`, false)) {
|
|
2213
|
+
try {
|
|
2214
|
+
const { invokeAgent: invokeAgent3 } = await Promise.resolve().then(() => (init_agent(), agent_exports));
|
|
2215
|
+
say(dim(" Searching (your agent writes its own filesystem searches; nothing leaves this machine; 90s max)..."));
|
|
2216
|
+
const candidates = await agentDiscoverCandidates((inv) => invokeAgent3(inv), os8.homedir(), []);
|
|
2217
|
+
for (const c of candidates) add(await identifyPath(c));
|
|
2218
|
+
} catch (e) {
|
|
2219
|
+
say(dim(` Agent search unavailable (${e instanceof Error ? e.message.slice(0, 80) : "failed"}).`));
|
|
2220
|
+
}
|
|
2221
|
+
}
|
|
2222
|
+
if (!found.length) {
|
|
2223
|
+
const folder = await ask(` Got them in a specific folder? ${dim("(path, or Enter to skip)")}: `);
|
|
2224
|
+
if (folder) for (const f of await scanForExports(folder.replace(/^~(?=$|\/)/, os8.homedir()))) add(f);
|
|
2225
|
+
}
|
|
1921
2226
|
}
|
|
1922
2227
|
if (found.length) {
|
|
1923
2228
|
found.sort((a, b) => a.modified < b.modified ? 1 : -1);
|
|
1924
|
-
const
|
|
1925
|
-
const
|
|
1926
|
-
const hadPrevious = found.some((f) => prevKnownPaths.has(f.path));
|
|
1927
|
-
const defaults = found.map((f) => !prevExcludedPaths.has(f.path));
|
|
2229
|
+
const hadPrevious = false;
|
|
2230
|
+
const defaults = found.map(() => true);
|
|
1928
2231
|
say(` Found ${dim("(identified locally from the files themselves)")}:`);
|
|
1929
2232
|
found.forEach((f, i) => say(describeExport(f, i, defaults[i], hadPrevious)));
|
|
1930
2233
|
{
|
|
@@ -1950,10 +2253,11 @@ async function runWizard() {
|
|
|
1950
2253
|
excluded: found.filter((_, i) => !include[i])
|
|
1951
2254
|
}
|
|
1952
2255
|
};
|
|
2256
|
+
approvedExports = manifest.exports.included;
|
|
1953
2257
|
await writeManifest(dataDir, manifest);
|
|
1954
2258
|
const nIn = manifest.exports.included.length;
|
|
1955
|
-
say(` ${green("\u2713")} Saved to .
|
|
1956
|
-
for (const f of manifest.exports.excluded) say(` ${dim(`\u2717 ${
|
|
2259
|
+
say(` ${green("\u2713")} Saved to ${path36.join(dataDir, "exports-manifest.json").replace(os8.homedir(), "~")} \u2014 ${nIn} source${nIn === 1 ? "" : "s"} approved, ${manifest.exports.excluded.length} excluded (re-run anytime to change).`);
|
|
2260
|
+
for (const f of manifest.exports.excluded) say(` ${dim(`\u2717 ${path36.basename(f.path)} \u2014 excluded, never read past identification.`)}`);
|
|
1957
2261
|
if (manifest.exports.included.some((f) => f.kind !== "unknown")) {
|
|
1958
2262
|
say(` ${dim("These are ingested and analyzed locally when you pick the full analysis below.")}`);
|
|
1959
2263
|
}
|
|
@@ -1974,64 +2278,231 @@ async function runWizard() {
|
|
|
1974
2278
|
const { EXPORT_LINKS: EXPORT_LINKS2 } = await Promise.resolve().then(() => (init_exportLinks(), exportLinks_exports));
|
|
1975
2279
|
const haveKinds = new Set(found.map((f) => f.kind));
|
|
1976
2280
|
const missing = EXPORT_LINKS2.filter((l) => l.requestUrl && !haveKinds.has(l.kind));
|
|
1977
|
-
if (missing.length) {
|
|
1978
|
-
|
|
1979
|
-
say(bold(" Step 2b \xB7 Want a reminder?"));
|
|
1980
|
-
const { requestEmailReminder: requestEmailReminder2, looksLikeEmail: looksLikeEmail2 } = await Promise.resolve().then(() => (init_reminderEmail(), reminderEmail_exports));
|
|
2281
|
+
if (missing.length && notifyEmail) {
|
|
2282
|
+
const { requestEmailReminder: requestEmailReminder2 } = await Promise.resolve().then(() => (init_reminderEmail(), reminderEmail_exports));
|
|
1981
2283
|
const kinds = missing.map((l) => l.kind);
|
|
1982
|
-
const
|
|
1983
|
-
|
|
1984
|
-
|
|
1985
|
-
|
|
1986
|
-
|
|
1987
|
-
|
|
1988
|
-
if (email && looksLikeEmail2(email)) {
|
|
1989
|
-
say(dim(" (your address is stored only until that one reminder email sends, then deleted)"));
|
|
1990
|
-
const r = await requestEmailReminder2(email, kinds, 48);
|
|
1991
|
-
if (r.ok) {
|
|
1992
|
-
say(` ${green("\u2713")} ${r.alreadySet ? "A reminder is already set for this email \u2014 you're covered." : "Reminder set \u2014 check your inbox in ~2 days."}`);
|
|
1993
|
-
} else {
|
|
1994
|
-
say(` Couldn't reach the server (${r.error}) \u2014 set a local notification instead; it won't survive a reboot.`);
|
|
1995
|
-
const { spawn: spawn10 } = await import("node:child_process");
|
|
1996
|
-
spawn10(process.execPath, [process.argv[1], "remind-exports", "--hours", "48", "--kinds", kinds.join(",")], { detached: true, stdio: "ignore" }).unref();
|
|
1997
|
-
}
|
|
1998
|
-
} else if (email) {
|
|
1999
|
-
say(` Still doesn't look like an email \u2014 skipping the reminder.`);
|
|
2284
|
+
const r = await requestEmailReminder2(notifyEmail, kinds, 48);
|
|
2285
|
+
if (r.ok) say(` ${green("\u2713")} We'll email ${notifyEmail} in ~2 days, when the ${missing.map((l) => l.label).join(" / ")} export${missing.length === 1 ? "" : "s"} should be ready.`);
|
|
2286
|
+
else {
|
|
2287
|
+
const { spawn: spawn10 } = await import("node:child_process");
|
|
2288
|
+
spawn10(process.execPath, [process.argv[1], "remind-exports", "--hours", "48", "--kinds", kinds.join(",")], { detached: true, stdio: "ignore" }).unref();
|
|
2289
|
+
say(dim(` (couldn't reach the server \u2014 set a local notification instead)`));
|
|
2000
2290
|
}
|
|
2001
2291
|
}
|
|
2002
2292
|
}
|
|
2293
|
+
const { detectPlan: detectPlan2, estimateLaneCosts: estimateLaneCosts2, scheduleLanes: scheduleLanes2, remainingFractions: remainingFractions2 } = await Promise.resolve().then(() => (init_plan(), plan_exports));
|
|
2294
|
+
const plan = await detectPlan2();
|
|
2295
|
+
const agentLogFiles = agentScans.reduce((a, s2) => a + s2.files, 0);
|
|
2296
|
+
const full = estimateLaneCosts2({
|
|
2297
|
+
agentLogFiles,
|
|
2298
|
+
exportTotalMB: approvedExports.reduce((a, f) => a + (f.sizeMB || 0), 0),
|
|
2299
|
+
chatIncluded: approvedExports.length > 0
|
|
2300
|
+
});
|
|
2301
|
+
const remain = await remainingFractions2(dataDir, agentLogFiles);
|
|
2302
|
+
const est = { codingUsd: Math.round(full.codingUsd * remain.coding), chatUsd: Math.round(full.chatUsd * remain.chat) };
|
|
2303
|
+
const sched = scheduleLanes2(plan, est);
|
|
2304
|
+
const resumed = full.codingUsd > 0 && remain.coding < 0.5 || full.chatUsd > 0 && remain.chat < 0.5;
|
|
2305
|
+
const anyOvernight = sched.coding === "overnight" || est.chatUsd > 0 && sched.chat === "overnight";
|
|
2003
2306
|
say();
|
|
2004
2307
|
say(bold(" Step 3 \xB7 How deep?"));
|
|
2005
|
-
say(` ${bold(
|
|
2006
|
-
say(
|
|
2007
|
-
say(`
|
|
2308
|
+
say(` You're on ${bold(plan.label)}. The schedule below is sized to your plan + corpus:`);
|
|
2309
|
+
if (resumed) say(dim(" (an earlier run already processed most of this \u2014 the estimate covers only what's new; nothing done is redone)"));
|
|
2310
|
+
say(` \u2022 coding: ${sched.codingReason}`);
|
|
2311
|
+
if (est.chatUsd > 0) say(` \u2022 chats/notes: ${sched.chatReason}`);
|
|
2312
|
+
say(` ${bold("1)")} Full analysis on the schedule above ${dim("(recommended)")}`);
|
|
2313
|
+
say(` ${bold("2)")} Full analysis, everything overnight \u2014 all grading waits for the 02:00 window`);
|
|
2314
|
+
say(` ${bold("VERY IMPORTANT")} whenever anything runs overnight:`);
|
|
2315
|
+
say(` \u2022 keep your laptop plugged in`);
|
|
2316
|
+
say(` \u2022 keep the lid open \u2014 closed means sleep, and the run stalls until morning`);
|
|
2008
2317
|
say(` ${bold("3)")} Just the numbers \u2014 instant deterministic metrics (words/day, flow, parallelism), free, ~a minute`);
|
|
2009
2318
|
const depth = await ask(` Choose ${dim("[1/2/3, default 1]")}: `) || "1";
|
|
2319
|
+
const chosenOvernight = depth === "2" || depth === "1" && anyOvernight;
|
|
2320
|
+
if (depth !== "3" && chosenOvernight) {
|
|
2321
|
+
say();
|
|
2322
|
+
say(` ${bold("Reminder for the overnight part:")} laptop plugged in, lid open. The report page shows this too.`);
|
|
2323
|
+
}
|
|
2010
2324
|
say();
|
|
2011
|
-
say(dim(" On it. The report link appears
|
|
2012
|
-
return {
|
|
2325
|
+
say(dim(" On it. The report link appears right away and fills in as stages finish \u2014 Ctrl-C anytime.\n"));
|
|
2326
|
+
return {
|
|
2327
|
+
cmd: "serve",
|
|
2328
|
+
grade: depth !== "3",
|
|
2329
|
+
overnight: depth === "2" ? true : sched.coding === "overnight",
|
|
2330
|
+
chatOvernight: depth === "2" ? true : sched.chat === "overnight",
|
|
2331
|
+
open: true
|
|
2332
|
+
};
|
|
2013
2333
|
} finally {
|
|
2014
2334
|
rl.close();
|
|
2015
2335
|
}
|
|
2016
2336
|
}
|
|
2017
|
-
var color, dim, bold,
|
|
2337
|
+
var color, dim, bold, green;
|
|
2018
2338
|
var init_wizard = __esm({
|
|
2019
2339
|
"src/wizard.ts"() {
|
|
2020
2340
|
"use strict";
|
|
2021
2341
|
init_exportScan();
|
|
2022
2342
|
init_manifest();
|
|
2343
|
+
init_dataHome();
|
|
2023
2344
|
init_raw2();
|
|
2024
2345
|
color = process.stdout.isTTY && !process.env.NO_COLOR;
|
|
2025
2346
|
dim = (s) => color ? `\x1B[2m${s}\x1B[0m` : s;
|
|
2026
2347
|
bold = (s) => color ? `\x1B[1m${s}\x1B[0m` : s;
|
|
2027
|
-
accent = (s) => color ? `\x1B[38;5;173m${s}\x1B[0m` : s;
|
|
2028
2348
|
green = (s) => color ? `\x1B[32m${s}\x1B[0m` : s;
|
|
2029
2349
|
}
|
|
2030
2350
|
});
|
|
2031
2351
|
|
|
2352
|
+
// src/progressBar.ts
|
|
2353
|
+
var progressBar_exports = {};
|
|
2354
|
+
__export(progressBar_exports, {
|
|
2355
|
+
makeMultiBar: () => makeMultiBar,
|
|
2356
|
+
makeProgressBar: () => makeProgressBar
|
|
2357
|
+
});
|
|
2358
|
+
function makeMultiBar(out = process.stderr) {
|
|
2359
|
+
const tty = !!out.isTTY;
|
|
2360
|
+
const t0 = Date.now();
|
|
2361
|
+
const lanes = /* @__PURE__ */ new Map();
|
|
2362
|
+
let link = "";
|
|
2363
|
+
let paintedRows = 0;
|
|
2364
|
+
const laneText = (name17, l) => {
|
|
2365
|
+
const w = l.within ? ` ${l.within.done}/${l.within.total}` : "";
|
|
2366
|
+
return `${name17} ${l.i}/${l.total} ${l.label.slice(0, 26)}${w}`;
|
|
2367
|
+
};
|
|
2368
|
+
const rows = () => {
|
|
2369
|
+
const frac = (l) => l.total ? (l.i - 1 + (l.within && l.within.total ? l.within.done / l.within.total : 0)) / l.total : 0;
|
|
2370
|
+
const parts = [...lanes.entries()].map(([n, l]) => laneText(n, l));
|
|
2371
|
+
const avg2 = lanes.size ? [...lanes.values()].reduce((a, l) => a + frac(l), 0) / lanes.size : 0;
|
|
2372
|
+
const width = 14;
|
|
2373
|
+
const fill = Math.max(0, Math.min(width, Math.round(avg2 * width)));
|
|
2374
|
+
const elapsedMin = Math.round((Date.now() - t0) / 6e4);
|
|
2375
|
+
const bar = `[${"\u2588".repeat(fill)}${"\u2591".repeat(width - fill)}] ${parts.join(" \xB7 ")} \xB7 ${elapsedMin}m`;
|
|
2376
|
+
return link ? [bar, `\u21B3 report (live, fills in as stages finish) \u2192 ${link}`] : [bar];
|
|
2377
|
+
};
|
|
2378
|
+
const clearPinned = () => {
|
|
2379
|
+
if (!paintedRows) return;
|
|
2380
|
+
out.write(CLEAR);
|
|
2381
|
+
for (let r = 1; r < paintedRows; r++) out.write(UP + CLEAR);
|
|
2382
|
+
paintedRows = 0;
|
|
2383
|
+
};
|
|
2384
|
+
const paint = () => {
|
|
2385
|
+
if (!tty) return;
|
|
2386
|
+
const r = rows();
|
|
2387
|
+
out.write(r.join("\n"));
|
|
2388
|
+
paintedRows = r.length;
|
|
2389
|
+
};
|
|
2390
|
+
const repaintAround = (line) => {
|
|
2391
|
+
if (!tty) {
|
|
2392
|
+
if (line != null) out.write(line + "\n");
|
|
2393
|
+
return;
|
|
2394
|
+
}
|
|
2395
|
+
clearPinned();
|
|
2396
|
+
if (line != null) out.write(line + "\n");
|
|
2397
|
+
paint();
|
|
2398
|
+
};
|
|
2399
|
+
return {
|
|
2400
|
+
lane(name17) {
|
|
2401
|
+
return {
|
|
2402
|
+
stage(i, total, label) {
|
|
2403
|
+
const l = lanes.get(name17) ?? { i: 0, total: 0, label: "", within: null };
|
|
2404
|
+
l.i = i;
|
|
2405
|
+
l.total = total;
|
|
2406
|
+
l.label = label;
|
|
2407
|
+
l.within = null;
|
|
2408
|
+
lanes.set(name17, l);
|
|
2409
|
+
repaintAround(`\u25B8 ${name17} [${i}/${total}] ${label}`);
|
|
2410
|
+
},
|
|
2411
|
+
log(line) {
|
|
2412
|
+
const l = lanes.get(name17);
|
|
2413
|
+
if (l) {
|
|
2414
|
+
const m = /Σ\s+(\d+)\/(\d+)/.exec(line);
|
|
2415
|
+
if (m) l.within = { done: Number(m[1]), total: Number(m[2]) };
|
|
2416
|
+
}
|
|
2417
|
+
repaintAround(tty ? line : `[${name17}] ${line.trimStart()}`);
|
|
2418
|
+
}
|
|
2419
|
+
};
|
|
2420
|
+
},
|
|
2421
|
+
setLink(url) {
|
|
2422
|
+
link = url;
|
|
2423
|
+
if (tty) repaintAround();
|
|
2424
|
+
else out.write(`report \u2192 ${url}
|
|
2425
|
+
`);
|
|
2426
|
+
},
|
|
2427
|
+
done() {
|
|
2428
|
+
clearPinned();
|
|
2429
|
+
}
|
|
2430
|
+
};
|
|
2431
|
+
}
|
|
2432
|
+
function makeProgressBar(out = process.stderr) {
|
|
2433
|
+
const tty = !!out.isTTY;
|
|
2434
|
+
const t0 = Date.now();
|
|
2435
|
+
let stageI = 0, stageN = 0, label = "";
|
|
2436
|
+
let within = null;
|
|
2437
|
+
let etaH = null;
|
|
2438
|
+
let painted = false;
|
|
2439
|
+
const bar = () => {
|
|
2440
|
+
const frac = stageN ? (stageI - 1 + (within && within.total ? within.done / within.total : 0)) / stageN : 0;
|
|
2441
|
+
const width = 18;
|
|
2442
|
+
const fill = Math.max(0, Math.min(width, Math.round(frac * width)));
|
|
2443
|
+
const elapsedMin = Math.round((Date.now() - t0) / 6e4);
|
|
2444
|
+
const eta = etaH != null ? ` \xB7 ~${etaH.toFixed(1)}h total` : "";
|
|
2445
|
+
const w = within ? ` \xB7 ${within.done}/${within.total}` : "";
|
|
2446
|
+
return `[${"\u2588".repeat(fill)}${"\u2591".repeat(width - fill)}] stage ${stageI}/${stageN} ${label.slice(0, 38)}${w} \xB7 ${elapsedMin}m${eta}`;
|
|
2447
|
+
};
|
|
2448
|
+
const paint = () => {
|
|
2449
|
+
if (!tty) return;
|
|
2450
|
+
out.write(CLEAR + bar());
|
|
2451
|
+
painted = true;
|
|
2452
|
+
};
|
|
2453
|
+
return {
|
|
2454
|
+
stage(i, total, lbl) {
|
|
2455
|
+
stageI = i;
|
|
2456
|
+
stageN = total;
|
|
2457
|
+
label = lbl;
|
|
2458
|
+
within = null;
|
|
2459
|
+
if (tty) {
|
|
2460
|
+
if (painted) out.write(CLEAR);
|
|
2461
|
+
out.write(`\u25B8 [${i}/${total}] ${lbl}
|
|
2462
|
+
`);
|
|
2463
|
+
paint();
|
|
2464
|
+
} else out.write(`\u25B8 [${i}/${total}] ${lbl}
|
|
2465
|
+
`);
|
|
2466
|
+
},
|
|
2467
|
+
log(line) {
|
|
2468
|
+
const m = /Σ\s+(\d+)\/(\d+)/.exec(line);
|
|
2469
|
+
if (m) within = { done: Number(m[1]), total: Number(m[2]) };
|
|
2470
|
+
const e = /~([\d.]+)h total/.exec(line);
|
|
2471
|
+
if (e) etaH = Number(e[1]);
|
|
2472
|
+
if (tty) {
|
|
2473
|
+
if (painted) out.write(CLEAR);
|
|
2474
|
+
out.write(line + "\n");
|
|
2475
|
+
paint();
|
|
2476
|
+
} else out.write(line + "\n");
|
|
2477
|
+
},
|
|
2478
|
+
done() {
|
|
2479
|
+
if (tty && painted) out.write(CLEAR);
|
|
2480
|
+
painted = false;
|
|
2481
|
+
}
|
|
2482
|
+
};
|
|
2483
|
+
}
|
|
2484
|
+
var CLEAR, UP;
|
|
2485
|
+
var init_progressBar = __esm({
|
|
2486
|
+
"src/progressBar.ts"() {
|
|
2487
|
+
"use strict";
|
|
2488
|
+
CLEAR = "\r\x1B[2K";
|
|
2489
|
+
UP = "\x1B[1A";
|
|
2490
|
+
}
|
|
2491
|
+
});
|
|
2492
|
+
|
|
2493
|
+
// src/dataHomeBoot.ts
|
|
2494
|
+
init_dataHome();
|
|
2495
|
+
import { mkdirSync } from "fs";
|
|
2496
|
+
var DATA_ROOT = resolveDataRoot();
|
|
2497
|
+
process.env.POLYMATH_DATA_DIR = DATA_ROOT;
|
|
2498
|
+
try {
|
|
2499
|
+
mkdirSync(DATA_ROOT, { recursive: true });
|
|
2500
|
+
} catch {
|
|
2501
|
+
}
|
|
2502
|
+
|
|
2032
2503
|
// src/cli.ts
|
|
2033
|
-
import { promises as
|
|
2034
|
-
import
|
|
2504
|
+
import { promises as fs31, existsSync as existsSync7 } from "fs";
|
|
2505
|
+
import path37 from "path";
|
|
2035
2506
|
import { fileURLToPath as fileURLToPath5 } from "url";
|
|
2036
2507
|
import { spawn as spawn9 } from "child_process";
|
|
2037
2508
|
|
|
@@ -2947,8 +3418,8 @@ async function analyze(opts = {}) {
|
|
|
2947
3418
|
// src/grade/grade.ts
|
|
2948
3419
|
init_agent();
|
|
2949
3420
|
import { promises as fs4 } from "fs";
|
|
2950
|
-
import
|
|
2951
|
-
import
|
|
3421
|
+
import os4 from "os";
|
|
3422
|
+
import path4 from "path";
|
|
2952
3423
|
|
|
2953
3424
|
// ../../lib/calibration/fingerprint.ts
|
|
2954
3425
|
import { createHash } from "node:crypto";
|
|
@@ -3321,7 +3792,7 @@ function validate(raw) {
|
|
|
3321
3792
|
async function gradeSession(rec, opts = {}) {
|
|
3322
3793
|
const mat = await materializeSession(rec.file);
|
|
3323
3794
|
if (!mat || mat.humanChars < 200) return null;
|
|
3324
|
-
const sandbox = await fs4.mkdtemp(
|
|
3795
|
+
const sandbox = await fs4.mkdtemp(path4.join(os4.tmpdir(), "ca-grade-"));
|
|
3325
3796
|
try {
|
|
3326
3797
|
const run4 = await invokeAgent(
|
|
3327
3798
|
{
|
|
@@ -3349,7 +3820,7 @@ async function gradeSession(rec, opts = {}) {
|
|
|
3349
3820
|
};
|
|
3350
3821
|
if (opts.outDir) {
|
|
3351
3822
|
await fs4.mkdir(opts.outDir, { recursive: true });
|
|
3352
|
-
await fs4.writeFile(
|
|
3823
|
+
await fs4.writeFile(path4.join(opts.outDir, `${rec.sessionId}.json`), JSON.stringify(grade, null, 2));
|
|
3353
3824
|
}
|
|
3354
3825
|
return grade;
|
|
3355
3826
|
} finally {
|
|
@@ -3481,13 +3952,13 @@ function buildShareSections(p) {
|
|
|
3481
3952
|
// src/server.ts
|
|
3482
3953
|
import http from "http";
|
|
3483
3954
|
import { promises as fs21 } from "fs";
|
|
3484
|
-
import
|
|
3955
|
+
import path26 from "path";
|
|
3485
3956
|
import { fileURLToPath as fileURLToPath2 } from "url";
|
|
3486
3957
|
|
|
3487
3958
|
// src/auth.ts
|
|
3488
3959
|
import { createHash as createHash2, randomBytes } from "crypto";
|
|
3489
3960
|
import { promises as fs5 } from "fs";
|
|
3490
|
-
import
|
|
3961
|
+
import path5 from "path";
|
|
3491
3962
|
|
|
3492
3963
|
// src/central.ts
|
|
3493
3964
|
var DEFAULT_SUPABASE_URL = "https://zcbonfjgiorrxczyekxl.supabase.co";
|
|
@@ -3499,7 +3970,7 @@ function centralConfig() {
|
|
|
3499
3970
|
}
|
|
3500
3971
|
|
|
3501
3972
|
// src/auth.ts
|
|
3502
|
-
var identityFile = (dataDir) =>
|
|
3973
|
+
var identityFile = (dataDir) => path5.join(dataDir, "identity.json");
|
|
3503
3974
|
var pending = /* @__PURE__ */ new Map();
|
|
3504
3975
|
var b64url = (b) => b.toString("base64").replace(/\+/g, "-").replace(/\//g, "_").replace(/=+$/, "");
|
|
3505
3976
|
function beginLogin(serverUrl) {
|
|
@@ -3793,16 +4264,16 @@ async function getCalibration() {
|
|
|
3793
4264
|
|
|
3794
4265
|
// src/feedback.ts
|
|
3795
4266
|
import { promises as fs14 } from "fs";
|
|
3796
|
-
import
|
|
4267
|
+
import path19 from "path";
|
|
3797
4268
|
|
|
3798
4269
|
// ../../lib/agents/shared/agent.ts
|
|
3799
4270
|
import { readFileSync } from "fs";
|
|
3800
|
-
import
|
|
4271
|
+
import path13 from "path";
|
|
3801
4272
|
|
|
3802
4273
|
// ../../lib/agents/shared/cliAdapter.ts
|
|
3803
4274
|
import { spawn as spawn3 } from "child_process";
|
|
3804
4275
|
import { promises as fs7 } from "fs";
|
|
3805
|
-
import
|
|
4276
|
+
import path7 from "path";
|
|
3806
4277
|
|
|
3807
4278
|
// ../../lib/agents/shared/adapter.ts
|
|
3808
4279
|
function extractJson2(text2) {
|
|
@@ -3827,7 +4298,7 @@ function extractJson2(text2) {
|
|
|
3827
4298
|
|
|
3828
4299
|
// ../../lib/agents/shared/toolLog.ts
|
|
3829
4300
|
import { promises as fs6 } from "fs";
|
|
3830
|
-
import
|
|
4301
|
+
import path6 from "path";
|
|
3831
4302
|
async function writeToolLog(logPath, d) {
|
|
3832
4303
|
const counts = {};
|
|
3833
4304
|
for (const c of d.toolCalls) counts[c.tool] = (counts[c.tool] ?? 0) + 1;
|
|
@@ -3843,7 +4314,7 @@ async function writeToolLog(logPath, d) {
|
|
|
3843
4314
|
L.push(``);
|
|
3844
4315
|
L.push(`## Full call sequence (${d.toolCalls.length})`);
|
|
3845
4316
|
d.toolCalls.forEach((c, i) => L.push(` ${String(i + 1).padStart(3, "0")} ${c.tool.padEnd(5)} ${c.target}`));
|
|
3846
|
-
await fs6.mkdir(
|
|
4317
|
+
await fs6.mkdir(path6.dirname(logPath), { recursive: true });
|
|
3847
4318
|
await fs6.writeFile(logPath, L.join("\n"), "utf-8");
|
|
3848
4319
|
const json = {
|
|
3849
4320
|
roots: d.roots,
|
|
@@ -3859,11 +4330,11 @@ async function writeToolLog(logPath, d) {
|
|
|
3859
4330
|
|
|
3860
4331
|
// ../../lib/agents/shared/cliAdapter.ts
|
|
3861
4332
|
var CLAUDE_BIN = process.env.CLAUDE_BIN || "claude";
|
|
3862
|
-
var USAGE_LEDGER = () =>
|
|
4333
|
+
var USAGE_LEDGER = () => path7.join(process.env.POLYMATH_DATA_DIR ? path7.resolve(process.env.POLYMATH_DATA_DIR) : path7.join(process.cwd(), ".data"), "usage.jsonl");
|
|
3863
4334
|
async function appendUsageLedger(line) {
|
|
3864
4335
|
try {
|
|
3865
4336
|
const f = USAGE_LEDGER();
|
|
3866
|
-
await fs7.mkdir(
|
|
4337
|
+
await fs7.mkdir(path7.dirname(f), { recursive: true });
|
|
3867
4338
|
await fs7.appendFile(f, JSON.stringify(line) + "\n", "utf8");
|
|
3868
4339
|
} catch {
|
|
3869
4340
|
}
|
|
@@ -4007,8 +4478,8 @@ var cliAdapter2 = {
|
|
|
4007
4478
|
}
|
|
4008
4479
|
await appendUsageLedger({
|
|
4009
4480
|
at: new Date(started).toISOString(),
|
|
4010
|
-
script:
|
|
4011
|
-
label: inv.logPath ?
|
|
4481
|
+
script: path7.basename(process.argv[1] ?? "unknown").replace(/\.(mts|ts|mjs|js)$/, ""),
|
|
4482
|
+
label: inv.logPath ? path7.basename(inv.logPath).replace(/\.log$/, "") : void 0,
|
|
4012
4483
|
// Never blank: an unstamped model made 3 calls ($19.51) unattributable in
|
|
4013
4484
|
// the 2026-07-06 usage audit. "cli-default" = no --model flag was passed.
|
|
4014
4485
|
model: inv.model ?? "cli-default",
|
|
@@ -4035,15 +4506,15 @@ var cliAdapter2 = {
|
|
|
4035
4506
|
|
|
4036
4507
|
// ../../lib/agents/shared/codexAdapter.ts
|
|
4037
4508
|
import { spawn as spawn4 } from "child_process";
|
|
4038
|
-
import { existsSync as
|
|
4039
|
-
import
|
|
4509
|
+
import { existsSync as existsSync4, statSync } from "fs";
|
|
4510
|
+
import path9 from "path";
|
|
4040
4511
|
|
|
4041
4512
|
// ../../lib/agents/shared/backends.ts
|
|
4042
4513
|
import { spawnSync as spawnSync2 } from "child_process";
|
|
4043
|
-
import { existsSync as
|
|
4044
|
-
import
|
|
4045
|
-
import
|
|
4046
|
-
var HOME2 =
|
|
4514
|
+
import { existsSync as existsSync3 } from "fs";
|
|
4515
|
+
import os5 from "os";
|
|
4516
|
+
import path8 from "path";
|
|
4517
|
+
var HOME2 = os5.homedir();
|
|
4047
4518
|
var PROBE_TIMEOUT_MS2 = 15e3;
|
|
4048
4519
|
function run2(bin, args) {
|
|
4049
4520
|
try {
|
|
@@ -4057,7 +4528,7 @@ function resolveBin2(envOverride, name17, candidates) {
|
|
|
4057
4528
|
if (envOverride) return envOverride;
|
|
4058
4529
|
const found = run2("/bin/sh", ["-c", `command -v ${name17}`]);
|
|
4059
4530
|
if (found.code === 0 && found.text) return found.text.split("\n")[0];
|
|
4060
|
-
for (const c of candidates) if (
|
|
4531
|
+
for (const c of candidates) if (existsSync3(c)) return c;
|
|
4061
4532
|
return null;
|
|
4062
4533
|
}
|
|
4063
4534
|
function codexBin2() {
|
|
@@ -4068,14 +4539,14 @@ function codexBin2() {
|
|
|
4068
4539
|
}
|
|
4069
4540
|
function cursorAgentBin() {
|
|
4070
4541
|
return resolveBin2(process.env.CURSOR_AGENT_BIN, "cursor-agent", [
|
|
4071
|
-
|
|
4542
|
+
path8.join(HOME2, ".local/bin/cursor-agent")
|
|
4072
4543
|
]);
|
|
4073
4544
|
}
|
|
4074
4545
|
function claudeBin2() {
|
|
4075
4546
|
return resolveBin2(process.env.CLAUDE_BIN, "claude", [
|
|
4076
4547
|
"/opt/homebrew/bin/claude",
|
|
4077
4548
|
"/usr/local/bin/claude",
|
|
4078
|
-
|
|
4549
|
+
path8.join(HOME2, ".local/bin/claude")
|
|
4079
4550
|
]);
|
|
4080
4551
|
}
|
|
4081
4552
|
function probeCli2() {
|
|
@@ -4089,7 +4560,7 @@ function probeCli2() {
|
|
|
4089
4560
|
const kc = run2("security", ["find-generic-password", "-s", "Claude Code-credentials"]);
|
|
4090
4561
|
if (kc.code === 0) return { name: "cli", bin, authed: true, detail: "Keychain OAuth credentials" };
|
|
4091
4562
|
}
|
|
4092
|
-
if (
|
|
4563
|
+
if (existsSync3(path8.join(HOME2, ".claude/.credentials.json")))
|
|
4093
4564
|
return { name: "cli", bin, authed: true, detail: "~/.claude/.credentials.json" };
|
|
4094
4565
|
return { name: "cli", bin, authed: false, detail: "no Claude credentials (run `claude` once to log in)" };
|
|
4095
4566
|
}
|
|
@@ -4154,10 +4625,10 @@ function filesUnderRoots(command, roots, cwd) {
|
|
|
4154
4625
|
const hits = [];
|
|
4155
4626
|
for (const tok of command.split(/[\s'"`;|&()<>]+/)) {
|
|
4156
4627
|
if (!tok || tok.startsWith("-") || !tok.includes("/") && !tok.includes(".")) continue;
|
|
4157
|
-
const abs =
|
|
4158
|
-
if (!roots.some((r) => abs === r || abs.startsWith(r +
|
|
4628
|
+
const abs = path9.isAbsolute(tok) ? tok : path9.resolve(cwd, tok);
|
|
4629
|
+
if (!roots.some((r) => abs === r || abs.startsWith(r + path9.sep))) continue;
|
|
4159
4630
|
try {
|
|
4160
|
-
if (
|
|
4631
|
+
if (existsSync4(abs) && statSync(abs).isFile()) hits.push(abs);
|
|
4161
4632
|
} catch {
|
|
4162
4633
|
}
|
|
4163
4634
|
}
|
|
@@ -5808,8 +6279,8 @@ function getErrorMap() {
|
|
|
5808
6279
|
|
|
5809
6280
|
// ../../node_modules/zod/v3/helpers/parseUtil.js
|
|
5810
6281
|
var makeIssue = (params) => {
|
|
5811
|
-
const { data, path:
|
|
5812
|
-
const fullPath = [...
|
|
6282
|
+
const { data, path: path38, errorMaps, issueData } = params;
|
|
6283
|
+
const fullPath = [...path38, ...issueData.path || []];
|
|
5813
6284
|
const fullIssue = {
|
|
5814
6285
|
...issueData,
|
|
5815
6286
|
path: fullPath
|
|
@@ -5925,11 +6396,11 @@ var errorUtil;
|
|
|
5925
6396
|
|
|
5926
6397
|
// ../../node_modules/zod/v3/types.js
|
|
5927
6398
|
var ParseInputLazyPath = class {
|
|
5928
|
-
constructor(parent, value,
|
|
6399
|
+
constructor(parent, value, path38, key) {
|
|
5929
6400
|
this._cachedPath = [];
|
|
5930
6401
|
this.parent = parent;
|
|
5931
6402
|
this.data = value;
|
|
5932
|
-
this._path =
|
|
6403
|
+
this._path = path38;
|
|
5933
6404
|
this._key = key;
|
|
5934
6405
|
}
|
|
5935
6406
|
get path() {
|
|
@@ -18716,39 +19187,39 @@ function createOpenAI(options = {}) {
|
|
|
18716
19187
|
});
|
|
18717
19188
|
const createChatModel = (modelId, settings = {}) => new OpenAIChatLanguageModel(modelId, settings, {
|
|
18718
19189
|
provider: `${providerName}.chat`,
|
|
18719
|
-
url: ({ path:
|
|
19190
|
+
url: ({ path: path38 }) => `${baseURL}${path38}`,
|
|
18720
19191
|
headers: getHeaders,
|
|
18721
19192
|
compatibility,
|
|
18722
19193
|
fetch: options.fetch
|
|
18723
19194
|
});
|
|
18724
19195
|
const createCompletionModel = (modelId, settings = {}) => new OpenAICompletionLanguageModel(modelId, settings, {
|
|
18725
19196
|
provider: `${providerName}.completion`,
|
|
18726
|
-
url: ({ path:
|
|
19197
|
+
url: ({ path: path38 }) => `${baseURL}${path38}`,
|
|
18727
19198
|
headers: getHeaders,
|
|
18728
19199
|
compatibility,
|
|
18729
19200
|
fetch: options.fetch
|
|
18730
19201
|
});
|
|
18731
19202
|
const createEmbeddingModel = (modelId, settings = {}) => new OpenAIEmbeddingModel(modelId, settings, {
|
|
18732
19203
|
provider: `${providerName}.embedding`,
|
|
18733
|
-
url: ({ path:
|
|
19204
|
+
url: ({ path: path38 }) => `${baseURL}${path38}`,
|
|
18734
19205
|
headers: getHeaders,
|
|
18735
19206
|
fetch: options.fetch
|
|
18736
19207
|
});
|
|
18737
19208
|
const createImageModel = (modelId, settings = {}) => new OpenAIImageModel(modelId, settings, {
|
|
18738
19209
|
provider: `${providerName}.image`,
|
|
18739
|
-
url: ({ path:
|
|
19210
|
+
url: ({ path: path38 }) => `${baseURL}${path38}`,
|
|
18740
19211
|
headers: getHeaders,
|
|
18741
19212
|
fetch: options.fetch
|
|
18742
19213
|
});
|
|
18743
19214
|
const createTranscriptionModel = (modelId) => new OpenAITranscriptionModel(modelId, {
|
|
18744
19215
|
provider: `${providerName}.transcription`,
|
|
18745
|
-
url: ({ path:
|
|
19216
|
+
url: ({ path: path38 }) => `${baseURL}${path38}`,
|
|
18746
19217
|
headers: getHeaders,
|
|
18747
19218
|
fetch: options.fetch
|
|
18748
19219
|
});
|
|
18749
19220
|
const createSpeechModel = (modelId) => new OpenAISpeechModel(modelId, {
|
|
18750
19221
|
provider: `${providerName}.speech`,
|
|
18751
|
-
url: ({ path:
|
|
19222
|
+
url: ({ path: path38 }) => `${baseURL}${path38}`,
|
|
18752
19223
|
headers: getHeaders,
|
|
18753
19224
|
fetch: options.fetch
|
|
18754
19225
|
});
|
|
@@ -18769,7 +19240,7 @@ function createOpenAI(options = {}) {
|
|
|
18769
19240
|
const createResponsesModel = (modelId) => {
|
|
18770
19241
|
return new OpenAIResponsesLanguageModel(modelId, {
|
|
18771
19242
|
provider: `${providerName}.responses`,
|
|
18772
|
-
url: ({ path:
|
|
19243
|
+
url: ({ path: path38 }) => `${baseURL}${path38}`,
|
|
18773
19244
|
headers: getHeaders,
|
|
18774
19245
|
fetch: options.fetch
|
|
18775
19246
|
});
|
|
@@ -18802,12 +19273,12 @@ var openai = createOpenAI({
|
|
|
18802
19273
|
import { promises as fs8 } from "fs";
|
|
18803
19274
|
import { execFile } from "child_process";
|
|
18804
19275
|
import { promisify } from "util";
|
|
18805
|
-
import
|
|
19276
|
+
import path10 from "path";
|
|
18806
19277
|
var exec = promisify(execFile);
|
|
18807
19278
|
function safeResolve(root, p) {
|
|
18808
|
-
const abs =
|
|
18809
|
-
const rel =
|
|
18810
|
-
if (rel.startsWith("..") ||
|
|
19279
|
+
const abs = path10.resolve(root, p);
|
|
19280
|
+
const rel = path10.relative(root, abs);
|
|
19281
|
+
if (rel.startsWith("..") || path10.isAbsolute(rel)) {
|
|
18811
19282
|
throw new Error(`path escapes sandbox: ${p}`);
|
|
18812
19283
|
}
|
|
18813
19284
|
return abs;
|
|
@@ -18919,16 +19390,16 @@ var apiAdapter = {
|
|
|
18919
19390
|
// ../../lib/agents/shared/limitGate.ts
|
|
18920
19391
|
import { AsyncLocalStorage } from "async_hooks";
|
|
18921
19392
|
import { appendFile, mkdir } from "fs/promises";
|
|
18922
|
-
import
|
|
19393
|
+
import path12 from "path";
|
|
18923
19394
|
|
|
18924
19395
|
// ../../lib/agents/shared/runStats.ts
|
|
18925
|
-
import { appendFileSync, mkdirSync } from "fs";
|
|
18926
|
-
import
|
|
19396
|
+
import { appendFileSync, mkdirSync as mkdirSync2 } from "fs";
|
|
19397
|
+
import path11 from "path";
|
|
18927
19398
|
var G = globalThis;
|
|
18928
|
-
var file = () =>
|
|
19399
|
+
var file = () => path11.join(process.cwd(), ".data", "run-stats.jsonl");
|
|
18929
19400
|
function write(ev) {
|
|
18930
19401
|
try {
|
|
18931
|
-
|
|
19402
|
+
mkdirSync2(path11.dirname(file()), { recursive: true });
|
|
18932
19403
|
appendFileSync(file(), JSON.stringify({ at: (/* @__PURE__ */ new Date()).toISOString(), ...ev }) + "\n");
|
|
18933
19404
|
} catch {
|
|
18934
19405
|
}
|
|
@@ -19216,7 +19687,7 @@ function logGate(msg) {
|
|
|
19216
19687
|
}
|
|
19217
19688
|
async function recordRawForm(label, info, error, result) {
|
|
19218
19689
|
try {
|
|
19219
|
-
const dir = process.env.POLYMATH_DATA_DIR ?
|
|
19690
|
+
const dir = process.env.POLYMATH_DATA_DIR ? path12.resolve(process.env.POLYMATH_DATA_DIR) : path12.join(process.cwd(), ".data");
|
|
19220
19691
|
await mkdir(dir, { recursive: true });
|
|
19221
19692
|
const raw = error instanceof Error ? error.message : result && typeof result === "object" && "raw" in result ? String(result.raw) : String(error ?? "");
|
|
19222
19693
|
const line = JSON.stringify({
|
|
@@ -19227,7 +19698,7 @@ async function recordRawForm(label, info, error, result) {
|
|
|
19227
19698
|
resetAt: info.resetAt ? new Date(info.resetAt).toISOString() : null,
|
|
19228
19699
|
sample: raw.slice(0, 600)
|
|
19229
19700
|
}) + "\n";
|
|
19230
|
-
await appendFile(
|
|
19701
|
+
await appendFile(path12.join(dir, "limit-gate.log"), line);
|
|
19231
19702
|
} catch {
|
|
19232
19703
|
}
|
|
19233
19704
|
}
|
|
@@ -19241,7 +19712,7 @@ var ADAPTERS2 = {
|
|
|
19241
19712
|
};
|
|
19242
19713
|
function preferredEngine() {
|
|
19243
19714
|
try {
|
|
19244
|
-
const p = JSON.parse(readFileSync(
|
|
19715
|
+
const p = JSON.parse(readFileSync(path13.join(process.cwd(), ".data", "profile.json"), "utf-8"));
|
|
19245
19716
|
const e = p?.preferredEngine;
|
|
19246
19717
|
return e === "cli" || e === "codex" || e === "cursor" || e === "api" ? e : null;
|
|
19247
19718
|
} catch {
|
|
@@ -19261,7 +19732,7 @@ function getAdapter2(name17) {
|
|
|
19261
19732
|
function invokeAgent2(inv, opts = {}) {
|
|
19262
19733
|
const once = () => getAdapter2(opts.adapter).run(inv);
|
|
19263
19734
|
if (!resilientActive()) return once();
|
|
19264
|
-
const label = inv.logPath ?
|
|
19735
|
+
const label = inv.logPath ? path13.basename(inv.logPath) : "agent";
|
|
19265
19736
|
return withLimitRetry(once, { label });
|
|
19266
19737
|
}
|
|
19267
19738
|
|
|
@@ -19461,22 +19932,22 @@ Return the updated redacted feedback + context + rich evidence package (keep any
|
|
|
19461
19932
|
|
|
19462
19933
|
// ../../lib/agents/feedback/jobs.ts
|
|
19463
19934
|
import { promises as fs13 } from "fs";
|
|
19464
|
-
import
|
|
19935
|
+
import path18 from "path";
|
|
19465
19936
|
|
|
19466
19937
|
// ../../lib/agents/feedback/diagnostic.ts
|
|
19467
19938
|
import { promises as fs10 } from "node:fs";
|
|
19468
|
-
import
|
|
19939
|
+
import path16 from "node:path";
|
|
19469
19940
|
|
|
19470
19941
|
// ../../lib/agents/engine/data-dir.ts
|
|
19471
|
-
import
|
|
19472
|
-
var ENGINE_DATA = process.env.POLYMATH_DATA_DIR ?
|
|
19942
|
+
import path14 from "path";
|
|
19943
|
+
var ENGINE_DATA = process.env.POLYMATH_DATA_DIR ? path14.resolve(process.env.POLYMATH_DATA_DIR) : path14.join(process.cwd(), ".data");
|
|
19473
19944
|
|
|
19474
19945
|
// ../../lib/agents/engine/select.ts
|
|
19475
19946
|
import { promises as fs9 } from "fs";
|
|
19476
|
-
import
|
|
19947
|
+
import path15 from "path";
|
|
19477
19948
|
var CODING_SOURCES = /* @__PURE__ */ new Set(["claude-code", "codex"]);
|
|
19478
19949
|
async function loadSignalIndex(signalsDir) {
|
|
19479
|
-
const file2 =
|
|
19950
|
+
const file2 = path15.join(signalsDir, "index.jsonl");
|
|
19480
19951
|
const recs = [];
|
|
19481
19952
|
try {
|
|
19482
19953
|
for (const line of (await fs9.readFile(file2, "utf-8")).split("\n")) {
|
|
@@ -20323,8 +20794,8 @@ var growthLens = {
|
|
|
20323
20794
|
};
|
|
20324
20795
|
|
|
20325
20796
|
// ../../lib/agents/feedback/diagnostic.ts
|
|
20326
|
-
var ENGINE_DIR =
|
|
20327
|
-
var SIGNALS_DIR =
|
|
20797
|
+
var ENGINE_DIR = path16.join(ENGINE_DATA, "engine-pilot");
|
|
20798
|
+
var SIGNALS_DIR = path16.join(ENGINE_DATA, "signals");
|
|
20328
20799
|
var LENS_SPECS = { reasoning: reasoningLens, agency: agencyLens, interpersonal: interpersonalLens, ocean: oceanLens, growth: growthLens };
|
|
20329
20800
|
var GATE_SYSTEM = `You triage feedback on a personality/reasoning/agency analysis. Decide whether the feedback alleges the analysis is WRONG, MISSED something, or is drawing on the WRONG EVIDENCE \u2014 vs. mere agreement/thanks with no claim. A REDIRECT counts as a miss: "stop leaning on my love life, read this from how I treat other people" alleges the current read is mis-sourced \u2192 investigate: true.
|
|
20330
20801
|
|
|
@@ -20377,10 +20848,10 @@ async function facetScoreFor(lensDir, docId2, facetKey) {
|
|
|
20377
20848
|
const s = typeof f.score === "number" ? f.score : typeof f.bestEstimate === "number" ? f.bestEstimate : null;
|
|
20378
20849
|
return s == null ? null : { analyzed: true, score: s };
|
|
20379
20850
|
};
|
|
20380
|
-
const af = await fs10.readFile(
|
|
20851
|
+
const af = await fs10.readFile(path16.join(lensDir, `${docId2}.allfacets.json`), "utf8").then(JSON.parse).catch(() => null);
|
|
20381
20852
|
const a = tryFacets(af?.result?.facets);
|
|
20382
20853
|
if (a) return a;
|
|
20383
|
-
const pc = await fs10.readFile(
|
|
20854
|
+
const pc = await fs10.readFile(path16.join(lensDir, `${docId2}.json`), "utf8").then(JSON.parse).catch(() => null);
|
|
20384
20855
|
const b = tryFacets(pc?.result?.facets ?? pc?.facets);
|
|
20385
20856
|
if (b) return b;
|
|
20386
20857
|
return { analyzed: false, score: null };
|
|
@@ -20389,7 +20860,7 @@ async function runFeedbackDiagnostic(input) {
|
|
|
20389
20860
|
const rawFeedback = (input.rawFeedback || "").trim().slice(0, 4e3);
|
|
20390
20861
|
const lens = (input.locus?.lens || "").trim();
|
|
20391
20862
|
const facetKey = (input.locus?.facetKey || "").trim();
|
|
20392
|
-
const lensDir =
|
|
20863
|
+
const lensDir = path16.join(ENGINE_DIR, "grades", lens);
|
|
20393
20864
|
const facetSpec = LENS_SPECS[lens]?.facets.find((f) => f.key === facetKey);
|
|
20394
20865
|
const facetDef = facetSpec ? `${facetSpec.name}: ${String(facetSpec.definition || "").slice(0, 1600)}` : "";
|
|
20395
20866
|
let usedEvidence = "";
|
|
@@ -20430,7 +20901,7 @@ Does this allege the analysis missed / got-wrong / mis-sourced a pattern (a redi
|
|
|
20430
20901
|
used += line.length + 1;
|
|
20431
20902
|
shown++;
|
|
20432
20903
|
}
|
|
20433
|
-
const lensJson = await fs10.readFile(
|
|
20904
|
+
const lensJson = await fs10.readFile(path16.join(ENGINE_DIR, `${lens}-latest.json`), "utf8").then((s) => s.slice(0, 3e3)).catch(() => "");
|
|
20434
20905
|
let active = 0;
|
|
20435
20906
|
const queue = [];
|
|
20436
20907
|
const limit = async (fn) => {
|
|
@@ -20504,7 +20975,7 @@ Pick up to ${perChunkPick} docIds whose summaries plausibly show the TRAIT per t
|
|
|
20504
20975
|
cand.splice(14);
|
|
20505
20976
|
const rowByld = new Map(rows.map((r) => [r.docId, r]));
|
|
20506
20977
|
const verdicts = await Promise.all(cand.map((c) => limit(async () => {
|
|
20507
|
-
const full = await fs10.readFile(
|
|
20978
|
+
const full = await fs10.readFile(path16.join(ENGINE_DIR, "docs", `${c.docId}.txt`), "utf8").catch(() => "");
|
|
20508
20979
|
if (!full) return null;
|
|
20509
20980
|
const body = full.length > 45e3 ? `${full.slice(0, 32e3)}
|
|
20510
20981
|
|
|
@@ -20589,7 +21060,7 @@ Output ONE fenced json block:
|
|
|
20589
21060
|
|
|
20590
21061
|
// ../../lib/agents/feedback/coding-diagnostic.ts
|
|
20591
21062
|
import { promises as fs12 } from "node:fs";
|
|
20592
|
-
import
|
|
21063
|
+
import path17 from "node:path";
|
|
20593
21064
|
|
|
20594
21065
|
// ../../lib/agents/coding/materialize.ts
|
|
20595
21066
|
init_injected();
|
|
@@ -20729,8 +21200,8 @@ async function materializeSession2(file2) {
|
|
|
20729
21200
|
}
|
|
20730
21201
|
|
|
20731
21202
|
// ../../lib/agents/feedback/coding-diagnostic.ts
|
|
20732
|
-
var CODING_DIR =
|
|
20733
|
-
var GRADES_DIR =
|
|
21203
|
+
var CODING_DIR = path17.join(ENGINE_DATA, "coding");
|
|
21204
|
+
var GRADES_DIR = path17.join(CODING_DIR, "grades");
|
|
20734
21205
|
var GRADED_KEYS = new Set(GRADED_CRITERIA.map((c) => c.key));
|
|
20735
21206
|
var scoreOf = (c) => typeof c.score === "number" ? c.score : typeof c.bestEstimate === "number" ? c.bestEstimate : null;
|
|
20736
21207
|
function criteriaRubric(keys) {
|
|
@@ -20743,13 +21214,13 @@ async function loadGrades() {
|
|
|
20743
21214
|
const out = [];
|
|
20744
21215
|
for (const f of files) {
|
|
20745
21216
|
if (!f.endsWith(".json")) continue;
|
|
20746
|
-
const g = await fs12.readFile(
|
|
21217
|
+
const g = await fs12.readFile(path17.join(GRADES_DIR, f), "utf8").then(JSON.parse).catch(() => null);
|
|
20747
21218
|
if (g && g.sessionId && Array.isArray(g.criteria)) out.push(g);
|
|
20748
21219
|
}
|
|
20749
21220
|
return out;
|
|
20750
21221
|
}
|
|
20751
21222
|
async function loadSessMeta() {
|
|
20752
|
-
const arr = await fs12.readFile(
|
|
21223
|
+
const arr = await fs12.readFile(path17.join(CODING_DIR, "sessions.json"), "utf8").then(JSON.parse).catch(() => []);
|
|
20753
21224
|
const m = /* @__PURE__ */ new Map();
|
|
20754
21225
|
if (Array.isArray(arr)) {
|
|
20755
21226
|
for (const s of arr) {
|
|
@@ -21046,7 +21517,7 @@ function diagnosticJobStatus(key) {
|
|
|
21046
21517
|
return REG.get(key) ?? null;
|
|
21047
21518
|
}
|
|
21048
21519
|
async function mergeIntoStateFile(key, diagnostic) {
|
|
21049
|
-
const FILE =
|
|
21520
|
+
const FILE = path18.join(process.env.POLYMATH_DATA_DIR || path18.join(process.cwd(), ".data"), "engine-pilot", "feedback-jobs.json");
|
|
21050
21521
|
const s = await fs13.readFile(FILE, "utf8").then(JSON.parse).catch(() => ({ version: 1, jobs: {} }));
|
|
21051
21522
|
const jobs = s.jobs || {};
|
|
21052
21523
|
const j = jobs[key];
|
|
@@ -21056,12 +21527,12 @@ async function mergeIntoStateFile(key, diagnostic) {
|
|
|
21056
21527
|
j.diagRunning = false;
|
|
21057
21528
|
j.status = "ready";
|
|
21058
21529
|
j.evidenceFailed = false;
|
|
21059
|
-
await fs13.mkdir(
|
|
21530
|
+
await fs13.mkdir(path18.dirname(FILE), { recursive: true });
|
|
21060
21531
|
await fs13.writeFile(FILE, JSON.stringify({ version: 1, jobs }, null, 2), "utf8");
|
|
21061
21532
|
}
|
|
21062
21533
|
|
|
21063
21534
|
// src/feedback.ts
|
|
21064
|
-
var jobsFile = (dataDir) =>
|
|
21535
|
+
var jobsFile = (dataDir) => path19.join(dataDir, "feedback-jobs.json");
|
|
21065
21536
|
var PAYLOAD_CAP = 6e4;
|
|
21066
21537
|
async function handlePreview(body) {
|
|
21067
21538
|
if (!String(body.rawFeedback || "").trim()) return { status: 400, json: { error: "no feedback" } };
|
|
@@ -21146,7 +21617,7 @@ async function handleSubmit(dataDir, body) {
|
|
|
21146
21617
|
}
|
|
21147
21618
|
try {
|
|
21148
21619
|
await fs14.mkdir(dataDir, { recursive: true });
|
|
21149
|
-
await fs14.appendFile(
|
|
21620
|
+
await fs14.appendFile(path19.join(dataDir, "feedback-submits.log"), JSON.stringify({ at: (/* @__PURE__ */ new Date()).toISOString(), ...row }) + "\n");
|
|
21150
21621
|
} catch {
|
|
21151
21622
|
}
|
|
21152
21623
|
console.error(` [feedback/submit] stored ${String(row.id)} (${sectionKey}) for ${auth.identity.email}`);
|
|
@@ -21294,16 +21765,16 @@ async function handleCodingChat(profile, dataDir, body, res) {
|
|
|
21294
21765
|
// src/personApi.ts
|
|
21295
21766
|
init_agent();
|
|
21296
21767
|
import { promises as fs18 } from "fs";
|
|
21297
|
-
import
|
|
21768
|
+
import path23 from "path";
|
|
21298
21769
|
import { fileURLToPath } from "url";
|
|
21299
21770
|
|
|
21300
21771
|
// ../../lib/agents/engine/person-profile.ts
|
|
21301
21772
|
import { promises as fs16 } from "fs";
|
|
21302
|
-
import
|
|
21773
|
+
import path21 from "path";
|
|
21303
21774
|
|
|
21304
21775
|
// ../../lib/agents/engine/corpus.ts
|
|
21305
21776
|
import { promises as fs15 } from "fs";
|
|
21306
|
-
import
|
|
21777
|
+
import path20 from "path";
|
|
21307
21778
|
import crypto2 from "crypto";
|
|
21308
21779
|
var CHAT_SOURCES = /* @__PURE__ */ new Set(["claude", "chatgpt"]);
|
|
21309
21780
|
var NOTE_FILES = ["obsidian.json", "apple-notes.json", "notion.json"];
|
|
@@ -21321,7 +21792,7 @@ var NAME_REDACT = /akshay\s*g?\.?\s*iyer|akshaygiyer|akshay|iyer|flomi|polymath\
|
|
|
21321
21792
|
var redactName = (text2) => text2.replace(NAME_REDACT, "[X]");
|
|
21322
21793
|
async function loadJson(importedDir, file2) {
|
|
21323
21794
|
try {
|
|
21324
|
-
return JSON.parse(await fs15.readFile(
|
|
21795
|
+
return JSON.parse(await fs15.readFile(path20.join(importedDir, file2), "utf-8"));
|
|
21325
21796
|
} catch {
|
|
21326
21797
|
return [];
|
|
21327
21798
|
}
|
|
@@ -21387,11 +21858,11 @@ ${body}`;
|
|
|
21387
21858
|
|
|
21388
21859
|
// ../../lib/agents/engine/person-profile.ts
|
|
21389
21860
|
var ROOT = process.cwd();
|
|
21390
|
-
var OUT =
|
|
21391
|
-
var DOCS =
|
|
21392
|
-
var IMPORTED =
|
|
21393
|
-
var SIGNALS =
|
|
21394
|
-
var GRADES =
|
|
21861
|
+
var OUT = path21.join(ENGINE_DATA, "engine-pilot");
|
|
21862
|
+
var DOCS = path21.join(OUT, "docs");
|
|
21863
|
+
var IMPORTED = path21.join(ENGINE_DATA, "imported");
|
|
21864
|
+
var SIGNALS = path21.join(ENGINE_DATA, "signals");
|
|
21865
|
+
var GRADES = path21.join(OUT, "grades");
|
|
21395
21866
|
var DIMF = {
|
|
21396
21867
|
reasoning: reasoningLens.facets.map((f) => [f.key, f.name]),
|
|
21397
21868
|
agency: agencyLens.facets.map((f) => [f.key, f.name]),
|
|
@@ -21414,7 +21885,7 @@ var PERSON_LENSES = [
|
|
|
21414
21885
|
var num2 = (v) => v == null || v === "" ? null : Number(v);
|
|
21415
21886
|
async function loadIndex() {
|
|
21416
21887
|
const m = {};
|
|
21417
|
-
for (const line of (await fs16.readFile(
|
|
21888
|
+
for (const line of (await fs16.readFile(path21.join(SIGNALS, "index.jsonl"), "utf8").catch(() => "")).split("\n")) {
|
|
21418
21889
|
if (!line.trim()) continue;
|
|
21419
21890
|
try {
|
|
21420
21891
|
const r = JSON.parse(line);
|
|
@@ -21425,12 +21896,12 @@ async function loadIndex() {
|
|
|
21425
21896
|
return m;
|
|
21426
21897
|
}
|
|
21427
21898
|
async function loadFacetTakes(lensKey, idx) {
|
|
21428
|
-
const dir =
|
|
21899
|
+
const dir = path21.join(GRADES, lensKey);
|
|
21429
21900
|
const files = (await fs16.readdir(dir).catch(() => [])).filter((f) => f.endsWith(".allfacets.json") && !f.startsWith("_"));
|
|
21430
21901
|
const byFacet = /* @__PURE__ */ new Map();
|
|
21431
21902
|
for (const file2 of files) {
|
|
21432
21903
|
const id = file2.replace(".allfacets.json", "");
|
|
21433
|
-
const d = await fs16.readFile(
|
|
21904
|
+
const d = await fs16.readFile(path21.join(dir, file2), "utf8").then(JSON.parse).catch(() => null);
|
|
21434
21905
|
const facets2 = d?.result?.facets;
|
|
21435
21906
|
if (!Array.isArray(facets2)) continue;
|
|
21436
21907
|
const meta = idx[id] || { title: "", date: "", source: "" };
|
|
@@ -21461,7 +21932,7 @@ function distOf2(takes) {
|
|
|
21461
21932
|
return { n, observed, mean: Math.round(mean2 * 100) / 100, median: median2, hist };
|
|
21462
21933
|
}
|
|
21463
21934
|
async function readGrowthAgent() {
|
|
21464
|
-
const j = await fs16.readFile(
|
|
21935
|
+
const j = await fs16.readFile(path21.join(OUT, "growth-latest.json"), "utf8").then(JSON.parse).catch(() => null);
|
|
21465
21936
|
const raw = j?.raw;
|
|
21466
21937
|
if (!raw || !raw.facets) return null;
|
|
21467
21938
|
const arr = (v) => Array.isArray(v) ? v : [];
|
|
@@ -21506,7 +21977,7 @@ async function compilePerson() {
|
|
|
21506
21977
|
const m = (id) => ({ id, title: idx[id]?.title || id, date: idx[id]?.date || "", source: idx[id]?.source || void 0 });
|
|
21507
21978
|
const out = [];
|
|
21508
21979
|
for (const [key, lens] of PERSON_LENSES) {
|
|
21509
|
-
const person = await fs16.readFile(
|
|
21980
|
+
const person = await fs16.readFile(path21.join(GRADES, key, "_person.json"), "utf8").then(JSON.parse).catch(() => null);
|
|
21510
21981
|
const growth = key === "growth" ? await readGrowthAgent() : null;
|
|
21511
21982
|
const byFacet = await loadFacetTakes(key, idx);
|
|
21512
21983
|
const pf = (k) => (person?.facets || []).find((x) => String(x.facetKey) === k) || null;
|
|
@@ -21553,7 +22024,7 @@ async function compilePerson() {
|
|
|
21553
22024
|
async function gradeDetail(docId2, lensKey) {
|
|
21554
22025
|
const idx = await loadIndex();
|
|
21555
22026
|
const meta = idx[docId2] || { title: docId2, date: "", source: "" };
|
|
21556
|
-
const af = await fs16.readFile(
|
|
22027
|
+
const af = await fs16.readFile(path21.join(GRADES, lensKey, `${docId2}.allfacets.json`), "utf8").then(JSON.parse).catch(() => null);
|
|
21557
22028
|
const facets2 = af?.result?.facets || [];
|
|
21558
22029
|
const lensLabel = PERSON_LENSES.find(([k]) => k === lensKey)?.[1].label || lensKey;
|
|
21559
22030
|
return {
|
|
@@ -21595,14 +22066,14 @@ function stripCitations(s) {
|
|
|
21595
22066
|
return s.replace(/[\s\S]*?/g, "").replace(/[-]/g, "").replace(/ +\n/g, "\n");
|
|
21596
22067
|
}
|
|
21597
22068
|
async function readTranscript(id) {
|
|
21598
|
-
const txt = (await fullDocs()).get(id) ?? await fs16.readFile(
|
|
22069
|
+
const txt = (await fullDocs()).get(id) ?? await fs16.readFile(path21.join(DOCS, `${id}.txt`), "utf8").catch(() => null);
|
|
21599
22070
|
return txt == null ? null : stripCitations(txt);
|
|
21600
22071
|
}
|
|
21601
22072
|
|
|
21602
22073
|
// ../../lib/agents/engine/self-image-ref.ts
|
|
21603
22074
|
import { promises as fs17 } from "fs";
|
|
21604
|
-
import
|
|
21605
|
-
var SELF_IMAGE_PATH =
|
|
22075
|
+
import path22 from "path";
|
|
22076
|
+
var SELF_IMAGE_PATH = path22.join(ENGINE_DATA, "engine-pilot", "self-image.json");
|
|
21606
22077
|
async function loadSelfImage() {
|
|
21607
22078
|
try {
|
|
21608
22079
|
return JSON.parse(await fs17.readFile(SELF_IMAGE_PATH, "utf8"));
|
|
@@ -21641,8 +22112,8 @@ ${parts.join("\n\n")}`;
|
|
|
21641
22112
|
}
|
|
21642
22113
|
|
|
21643
22114
|
// src/personApi.ts
|
|
21644
|
-
var MODULE_DIR =
|
|
21645
|
-
var PILOT = (f) =>
|
|
22115
|
+
var MODULE_DIR = path23.dirname(fileURLToPath(import.meta.url));
|
|
22116
|
+
var PILOT = (f) => path23.join(ENGINE_DATA, "engine-pilot", f);
|
|
21646
22117
|
var memo2 = null;
|
|
21647
22118
|
var TTL2 = 6e4;
|
|
21648
22119
|
function deSlop(v) {
|
|
@@ -21727,12 +22198,12 @@ async function handlePersonFeedback(method, body) {
|
|
|
21727
22198
|
const updatedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
21728
22199
|
if (text2) store.entries[key] = { text: text2, updatedAt };
|
|
21729
22200
|
else delete store.entries[key];
|
|
21730
|
-
await fs18.mkdir(
|
|
22201
|
+
await fs18.mkdir(path23.dirname(FEEDBACK_FILE()), { recursive: true });
|
|
21731
22202
|
await fs18.writeFile(FEEDBACK_FILE(), JSON.stringify(store, null, 2));
|
|
21732
22203
|
return { status: 200, json: { ok: true, updatedAt } };
|
|
21733
22204
|
}
|
|
21734
22205
|
async function handleLoops() {
|
|
21735
|
-
const loops = await fs18.readFile(
|
|
22206
|
+
const loops = await fs18.readFile(path23.join(ENGINE_DATA, "loops.json"), "utf8").then((s) => JSON.parse(s)).catch(() => null);
|
|
21736
22207
|
return { status: 200, json: { loops } };
|
|
21737
22208
|
}
|
|
21738
22209
|
async function handleGrade(params) {
|
|
@@ -21780,9 +22251,9 @@ USE THEIR SELF-IMAGE SILENTLY (a separate read of how THEY see themselves, given
|
|
|
21780
22251
|
You can OPEN their actual conversations: each cited one is a file named <id>.txt in the directory you have Read access to. When grounding or quoting would help (or they ask "where did you see that?"), Read the file and quote what they actually said. Output ONLY your reply to them \u2014 no preamble, no meta.`;
|
|
21781
22252
|
async function readDataMap() {
|
|
21782
22253
|
const candidates = [
|
|
21783
|
-
|
|
21784
|
-
|
|
21785
|
-
|
|
22254
|
+
path23.join(MODULE_DIR, "DATA-MAP.md"),
|
|
22255
|
+
path23.resolve(MODULE_DIR, "..", "..", "..", "lib", "agents", "DATA-MAP.md"),
|
|
22256
|
+
path23.join(process.cwd(), "lib", "agents", "DATA-MAP.md")
|
|
21786
22257
|
];
|
|
21787
22258
|
for (const p of candidates) {
|
|
21788
22259
|
try {
|
|
@@ -21858,16 +22329,16 @@ init_agent();
|
|
|
21858
22329
|
|
|
21859
22330
|
// ../../lib/agents/engine/public-report.ts
|
|
21860
22331
|
import { promises as fs19 } from "fs";
|
|
21861
|
-
import
|
|
21862
|
-
var ENGINE = (f) =>
|
|
21863
|
-
var CODING = (f) =>
|
|
22332
|
+
import path24 from "path";
|
|
22333
|
+
var ENGINE = (f) => path24.join(ENGINE_DATA, "engine-pilot", f);
|
|
22334
|
+
var CODING = (f) => path24.join(ENGINE_DATA, "coding", f);
|
|
21864
22335
|
var PUBLIC_REPORT_PATH = ENGINE("public-report.json");
|
|
21865
22336
|
var readJson = async (f, d) => fs19.readFile(f, "utf8").then((t) => JSON.parse(t)).catch(() => d);
|
|
21866
22337
|
async function loadPublicReport() {
|
|
21867
22338
|
return readJson(PUBLIC_REPORT_PATH, null);
|
|
21868
22339
|
}
|
|
21869
22340
|
async function savePublicReport(r) {
|
|
21870
|
-
await fs19.mkdir(
|
|
22341
|
+
await fs19.mkdir(path24.dirname(PUBLIC_REPORT_PATH), { recursive: true });
|
|
21871
22342
|
await fs19.writeFile(PUBLIC_REPORT_PATH, JSON.stringify(r, null, 2), "utf8");
|
|
21872
22343
|
}
|
|
21873
22344
|
var facetScore = (f) => {
|
|
@@ -22211,9 +22682,9 @@ async function buildGroundingDigest() {
|
|
|
22211
22682
|
|
|
22212
22683
|
// ../../lib/agents/engine/external-ref.ts
|
|
22213
22684
|
import { promises as fs20 } from "fs";
|
|
22214
|
-
import
|
|
22215
|
-
var EXTERNAL_PATH =
|
|
22216
|
-
var RESUME_PDF_PATH =
|
|
22685
|
+
import path25 from "path";
|
|
22686
|
+
var EXTERNAL_PATH = path25.join(ENGINE_DATA, "engine-pilot", "external.json");
|
|
22687
|
+
var RESUME_PDF_PATH = path25.join(ENGINE_DATA, "engine-pilot", "resume.pdf");
|
|
22217
22688
|
async function loadExternalFacts() {
|
|
22218
22689
|
try {
|
|
22219
22690
|
return JSON.parse(await fs20.readFile(EXTERNAL_PATH, "utf8"));
|
|
@@ -22344,8 +22815,9 @@ async function handleVisibility(dataDir, method, body) {
|
|
|
22344
22815
|
}
|
|
22345
22816
|
|
|
22346
22817
|
// src/server.ts
|
|
22347
|
-
|
|
22348
|
-
var
|
|
22818
|
+
init_dataHome();
|
|
22819
|
+
var __dirname = path26.dirname(fileURLToPath2(import.meta.url));
|
|
22820
|
+
var UI_DIR = path26.join(__dirname, "web");
|
|
22349
22821
|
var DEFAULT_SHARE_URL = "https://polymathsociety.us/api/coding-share";
|
|
22350
22822
|
var MIME = {
|
|
22351
22823
|
".html": "text/html; charset=utf-8",
|
|
@@ -22376,19 +22848,19 @@ async function readBody(req, maxBytes = 8e6) {
|
|
|
22376
22848
|
async function serveStatic(res, urlPath) {
|
|
22377
22849
|
const clean = urlPath.split("?")[0];
|
|
22378
22850
|
const rel = clean === "/" ? "index.html" : clean.replace(/^\/+/, "");
|
|
22379
|
-
const full =
|
|
22851
|
+
const full = path26.normalize(path26.join(UI_DIR, rel));
|
|
22380
22852
|
if (!full.startsWith(UI_DIR)) {
|
|
22381
22853
|
res.writeHead(403).end("forbidden");
|
|
22382
22854
|
return;
|
|
22383
22855
|
}
|
|
22384
22856
|
try {
|
|
22385
22857
|
const data = await fs21.readFile(full);
|
|
22386
|
-
res.writeHead(200, { "content-type": MIME[
|
|
22858
|
+
res.writeHead(200, { "content-type": MIME[path26.extname(full)] ?? "application/octet-stream" });
|
|
22387
22859
|
res.end(data);
|
|
22388
22860
|
} catch {
|
|
22389
|
-
if (!
|
|
22861
|
+
if (!path26.extname(full)) {
|
|
22390
22862
|
try {
|
|
22391
|
-
const idx = await fs21.readFile(
|
|
22863
|
+
const idx = await fs21.readFile(path26.join(UI_DIR, "index.html"));
|
|
22392
22864
|
res.writeHead(200, { "content-type": MIME[".html"] }).end(idx);
|
|
22393
22865
|
return;
|
|
22394
22866
|
} catch {
|
|
@@ -22413,7 +22885,7 @@ async function handleShare(res, body, opts, dataDir) {
|
|
|
22413
22885
|
res.writeHead(400, { "content-type": "application/json" }).end(JSON.stringify({ ok: false, error: "bad JSON" }));
|
|
22414
22886
|
return;
|
|
22415
22887
|
}
|
|
22416
|
-
const all = opts.profile?.sections ?? {};
|
|
22888
|
+
const all = opts.shareSections ?? opts.profile?.sections ?? {};
|
|
22417
22889
|
const wanted = parsed.all ? Object.keys(all) : Array.isArray(parsed.sections) ? parsed.sections : [];
|
|
22418
22890
|
const sections = {};
|
|
22419
22891
|
for (const key of wanted) {
|
|
@@ -22453,8 +22925,10 @@ async function handleShare(res, body, opts, dataDir) {
|
|
|
22453
22925
|
}
|
|
22454
22926
|
}
|
|
22455
22927
|
function startServer(opts) {
|
|
22928
|
+
let liveProfile = opts.profile;
|
|
22929
|
+
let liveProgress = {};
|
|
22456
22930
|
const host = opts.host ?? "127.0.0.1";
|
|
22457
|
-
const dataDir = opts.dataDir ??
|
|
22931
|
+
const dataDir = opts.dataDir ?? resolveDataRoot();
|
|
22458
22932
|
let serverUrl = "";
|
|
22459
22933
|
const json = (res, status, body) => res.writeHead(status, { "content-type": MIME[".json"] }).end(JSON.stringify(body));
|
|
22460
22934
|
const server = http.createServer(async (req, res) => {
|
|
@@ -22462,7 +22936,11 @@ function startServer(opts) {
|
|
|
22462
22936
|
const url = req.url ?? "/";
|
|
22463
22937
|
const route = url.split("?")[0];
|
|
22464
22938
|
if (req.method === "GET" && (url === "/api/coding" || url === "/profile.json" || url.startsWith("/profile.json?"))) {
|
|
22465
|
-
res.writeHead(200, { "content-type": MIME[".json"] }).end(JSON.stringify(
|
|
22939
|
+
res.writeHead(200, { "content-type": MIME[".json"] }).end(JSON.stringify(liveProfile));
|
|
22940
|
+
return;
|
|
22941
|
+
}
|
|
22942
|
+
if (req.method === "GET" && url === "/api/progress") {
|
|
22943
|
+
res.writeHead(200, { "content-type": MIME[".json"] }).end(JSON.stringify(liveProgress));
|
|
22466
22944
|
return;
|
|
22467
22945
|
}
|
|
22468
22946
|
if (req.method === "GET" && route === "/meta.json") {
|
|
@@ -22602,7 +23080,7 @@ function startServer(opts) {
|
|
|
22602
23080
|
}
|
|
22603
23081
|
if (route === "/api/coding/chat" && req.method === "POST") {
|
|
22604
23082
|
const body = JSON.parse(await readBody(req) || "{}");
|
|
22605
|
-
await handleCodingChat(
|
|
23083
|
+
await handleCodingChat(liveProfile, dataDir, body, res);
|
|
22606
23084
|
return;
|
|
22607
23085
|
}
|
|
22608
23086
|
if (req.method === "POST" && url === "/share") {
|
|
@@ -22638,7 +23116,13 @@ function startServer(opts) {
|
|
|
22638
23116
|
resolve2({
|
|
22639
23117
|
url: serverUrl,
|
|
22640
23118
|
port,
|
|
22641
|
-
close: () => new Promise((r) => server.close(() => r()))
|
|
23119
|
+
close: () => new Promise((r) => server.close(() => r())),
|
|
23120
|
+
setProfile: (p) => {
|
|
23121
|
+
liveProfile = p;
|
|
23122
|
+
},
|
|
23123
|
+
setProgress: (p) => {
|
|
23124
|
+
liveProgress = p;
|
|
23125
|
+
}
|
|
22642
23126
|
});
|
|
22643
23127
|
});
|
|
22644
23128
|
});
|
|
@@ -22646,28 +23130,29 @@ function startServer(opts) {
|
|
|
22646
23130
|
|
|
22647
23131
|
// src/pipeline.ts
|
|
22648
23132
|
import { spawn as spawn6 } from "child_process";
|
|
22649
|
-
import
|
|
22650
|
-
import { existsSync as
|
|
23133
|
+
import path29 from "path";
|
|
23134
|
+
import { existsSync as existsSync5, promises as fs23 } from "fs";
|
|
22651
23135
|
import { fileURLToPath as fileURLToPath3 } from "url";
|
|
23136
|
+
init_dataHome();
|
|
22652
23137
|
|
|
22653
23138
|
// ../../lib/agents/shared/runLog.ts
|
|
22654
23139
|
import { createHash as createHash3 } from "crypto";
|
|
22655
23140
|
import { promises as fs22 } from "fs";
|
|
22656
|
-
import
|
|
23141
|
+
import path28 from "path";
|
|
22657
23142
|
|
|
22658
23143
|
// ../../lib/agents/shared/paths.ts
|
|
22659
|
-
import
|
|
22660
|
-
import
|
|
23144
|
+
import os6 from "os";
|
|
23145
|
+
import path27 from "path";
|
|
22661
23146
|
function polymathHome() {
|
|
22662
|
-
return process.env.POLYMATH_HOME ||
|
|
23147
|
+
return process.env.POLYMATH_HOME || path27.join(os6.homedir(), ".polymath-society");
|
|
22663
23148
|
}
|
|
22664
23149
|
function agentDir(agent) {
|
|
22665
|
-
return
|
|
23150
|
+
return path27.join(polymathHome(), agent);
|
|
22666
23151
|
}
|
|
22667
23152
|
|
|
22668
23153
|
// ../../lib/agents/shared/runLog.ts
|
|
22669
23154
|
function runRefPath() {
|
|
22670
|
-
return
|
|
23155
|
+
return path28.join(agentDir("report"), "latest.run.json");
|
|
22671
23156
|
}
|
|
22672
23157
|
function sha256Hex(s) {
|
|
22673
23158
|
return createHash3("sha256").update(s, "utf8").digest("hex");
|
|
@@ -22699,7 +23184,7 @@ async function rpc(url, key, fn, args) {
|
|
|
22699
23184
|
}
|
|
22700
23185
|
async function writeRef(refPath, ref) {
|
|
22701
23186
|
try {
|
|
22702
|
-
await fs22.mkdir(
|
|
23187
|
+
await fs22.mkdir(path28.dirname(refPath), { recursive: true });
|
|
22703
23188
|
await fs22.writeFile(refPath, JSON.stringify(ref, null, 2), "utf-8");
|
|
22704
23189
|
} catch {
|
|
22705
23190
|
}
|
|
@@ -22750,7 +23235,7 @@ var LiveRunLog = class {
|
|
|
22750
23235
|
if (this.finished) return;
|
|
22751
23236
|
this.finished = true;
|
|
22752
23237
|
const legacy = this.opts.artifacts === void 0;
|
|
22753
|
-
const list = legacy ? [
|
|
23238
|
+
const list = legacy ? [path28.join(agentDir("report"), "latest.json")] : typeof this.opts.artifacts === "function" ? await this.opts.artifacts().catch(() => []) : this.opts.artifacts;
|
|
22754
23239
|
const refPath = this.opts.refPath ?? runRefPath();
|
|
22755
23240
|
const shas = {};
|
|
22756
23241
|
const ordered = [];
|
|
@@ -22764,7 +23249,7 @@ var LiveRunLog = class {
|
|
|
22764
23249
|
}
|
|
22765
23250
|
if (firstRaw === null) firstRaw = raw;
|
|
22766
23251
|
const sha = sha256Hex(raw);
|
|
22767
|
-
shas[
|
|
23252
|
+
shas[path28.relative(path28.dirname(refPath), p).split(path28.sep).join("/")] = sha;
|
|
22768
23253
|
ordered.push(sha);
|
|
22769
23254
|
}
|
|
22770
23255
|
this.post(async () => {
|
|
@@ -22817,10 +23302,10 @@ async function startRunLog(clientInfo = {}, opts = {}) {
|
|
|
22817
23302
|
}
|
|
22818
23303
|
|
|
22819
23304
|
// src/pipeline.ts
|
|
22820
|
-
var MODULE_DIR2 =
|
|
23305
|
+
var MODULE_DIR2 = path29.dirname(fileURLToPath3(import.meta.url));
|
|
22821
23306
|
function stages(o) {
|
|
22822
23307
|
const model = o.model ?? "sonnet";
|
|
22823
|
-
const conc = String(o.conc ??
|
|
23308
|
+
const conc = String(o.conc ?? 8);
|
|
22824
23309
|
const buildArgs = [];
|
|
22825
23310
|
if (o.codex === false) buildArgs.push("--no-codex");
|
|
22826
23311
|
if (o.idleGapMin != null) buildArgs.push("--idle", String(o.idleGapMin));
|
|
@@ -22829,42 +23314,50 @@ function stages(o) {
|
|
|
22829
23314
|
return [
|
|
22830
23315
|
// ---- deterministic foundation (fast, free) ----
|
|
22831
23316
|
{ script: "coding-build.mts", label: "Scrape + classify your sessions", llm: false, args: buildArgs, out: "coding/sessions.json" },
|
|
22832
|
-
|
|
22833
|
-
{ script: "coding-
|
|
22834
|
-
{ script: "coding-
|
|
22835
|
-
{ script: "coding-
|
|
22836
|
-
|
|
22837
|
-
{ script: "coding-
|
|
23317
|
+
// ---- deterministic metrics: all read ONLY sessions.json, disjoint outputs ----
|
|
23318
|
+
{ script: "coding-flow.mts", label: "Flow-state slots", llm: false, args: [], out: "coding/flow.json", batch: "metrics" },
|
|
23319
|
+
{ script: "coding-focus.mts", label: "Focus map + breaks (deterministic)", llm: false, args: ["--skip-llm"], out: "coding/focus.json", batch: "metrics" },
|
|
23320
|
+
{ script: "coding-gap-dist.mts", label: "Inter-prompt gap distribution", llm: false, args: [], out: "coding/gap-dist.json", batch: "metrics" },
|
|
23321
|
+
{ script: "coding-frontier.mts", label: "Frontier tech arsenal", llm: false, args: [], out: "coding/frontier.json", batch: "metrics" },
|
|
23322
|
+
{ script: "coding-projects.mts", label: "Projects + contributions", llm: false, args: [], out: "coding/projects.json", batch: "metrics" },
|
|
23323
|
+
// ---- THE HEAVY BATCH — grading + everything that needs ONLY sessions.json.
|
|
23324
|
+
// Digests, walkthroughs, frontier detail, and delegation never read grades,
|
|
23325
|
+
// so they run WHILE grading runs (grading is the wall-clock giant; these
|
|
23326
|
+
// finish inside its shadow). Budget: grade 8 + digest 3 + walkthrough 3 +
|
|
23327
|
+
// two single-call stages ≈ 16 peak subprocesses (measured-safe envelope).
|
|
23328
|
+
{ script: "coding-grade.mts", label: "AI-grade every substantial session", llm: true, args: gradeArgs, batch: "heavy" },
|
|
23329
|
+
{ script: "coding-day-digest.mts", label: "Day-by-day digests", llm: true, args: ["--model", model, "--conc", "3"], out: "coding/day-digest.json", batch: "heavy" },
|
|
23330
|
+
{ script: "coding-walkthrough.mts", label: "Per-session walkthroughs", llm: true, args: ["--model", model, "--conc", "3"], batch: "heavy" },
|
|
23331
|
+
{ script: "coding-frontier-detail.mts", label: "What you're doing at the frontier", llm: true, args: [], out: "coding/frontier-detail.json", batch: "heavy" },
|
|
23332
|
+
{ script: "coding-delegation.mts", label: "Delegation patterns", llm: true, args: ["--model", model], out: "coding/delegation-rollup.json", batch: "heavy" },
|
|
22838
23333
|
// ---- corpus aggregate (reads grades; deterministic rollup) ----
|
|
22839
23334
|
{ script: "coding-aggregate.mts", label: "Corpus aggregate \u2014 ability ceiling + flow", llm: false, args: [], out: "coding/aggregate.json" },
|
|
22840
|
-
// ----
|
|
22841
|
-
{ script: "coding-agglomerate.mts", label: "Agglomerated criteria + signature moves", llm: true, args: ["--model", model], out: "coding/agglomerate.json" },
|
|
22842
|
-
{ script: "coding-expertise.mts", label: "Domain-expertise map", llm: true, args: [], out: "coding/expertise.json" },
|
|
22843
|
-
|
|
22844
|
-
{ script: "coding-
|
|
22845
|
-
{ script: "coding-
|
|
22846
|
-
|
|
22847
|
-
//
|
|
22848
|
-
{ script: "coding-coaching.mts", label: "Coaching + feel-seen copy", llm: true, args: [], out: "coding/coaching.json" },
|
|
22849
|
-
{ script: "coding-gap.mts", label: "Gap-to-close vs best practice", llm: true, args: [], out: "coding/gap.json" },
|
|
23335
|
+
// ---- grade readers (grades/* is complete once aggregate ran) ----
|
|
23336
|
+
{ script: "coding-agglomerate.mts", label: "Agglomerated criteria + signature moves", llm: true, args: ["--model", model], out: "coding/agglomerate.json", batch: "grade-readers" },
|
|
23337
|
+
{ script: "coding-expertise.mts", label: "Domain-expertise map", llm: true, args: [], out: "coding/expertise.json", batch: "grade-readers" },
|
|
23338
|
+
// ---- final synthesis (reads the finished aggregates + batch outputs) ----
|
|
23339
|
+
{ script: "coding-coaching.mts", label: "Coaching + feel-seen copy", llm: true, args: [], out: "coding/coaching.json", batch: "synthesis" },
|
|
23340
|
+
{ script: "coding-gap.mts", label: "Gap-to-close vs best practice", llm: true, args: [], out: "coding/gap.json", batch: "synthesis" },
|
|
23341
|
+
// nutshell stays LAST + alone: it merges INTO aggregate.json while the two
|
|
23342
|
+
// above read the compiled profile — racing them re-reads mid-write.
|
|
22850
23343
|
{ script: "coding-nutshell.mts", label: "Big-picture nutshell", llm: true, args: [], out: "coding/aggregate.json" }
|
|
22851
23344
|
// merges bigPicture INTO aggregate.json
|
|
22852
23345
|
];
|
|
22853
23346
|
}
|
|
22854
23347
|
function bundledPipelineDir() {
|
|
22855
|
-
const d =
|
|
22856
|
-
return
|
|
23348
|
+
const d = path29.join(MODULE_DIR2, "pipeline");
|
|
23349
|
+
return existsSync5(path29.join(d, "coding-build.js")) ? d : null;
|
|
22857
23350
|
}
|
|
22858
23351
|
function stageInvocation(repoRoot, scriptRel, args) {
|
|
22859
|
-
const scriptAbs =
|
|
22860
|
-
if (
|
|
22861
|
-
const local =
|
|
22862
|
-
if (
|
|
23352
|
+
const scriptAbs = path29.join(repoRoot, "scripts", scriptRel);
|
|
23353
|
+
if (existsSync5(scriptAbs)) {
|
|
23354
|
+
const local = path29.join(repoRoot, "node_modules", ".bin", "tsx");
|
|
23355
|
+
if (existsSync5(local)) return { cmd: local, argv: [scriptAbs, ...args], cwd: repoRoot };
|
|
22863
23356
|
return { cmd: "npx", argv: ["tsx", scriptAbs, ...args], cwd: repoRoot };
|
|
22864
23357
|
}
|
|
22865
23358
|
const bundled = bundledPipelineDir();
|
|
22866
23359
|
if (bundled) {
|
|
22867
|
-
const js =
|
|
23360
|
+
const js = path29.join(bundled, scriptRel.replace(/\.mts$/, ".js"));
|
|
22868
23361
|
return { cmd: process.execPath, argv: [js, ...args], cwd: process.cwd() };
|
|
22869
23362
|
}
|
|
22870
23363
|
throw new Error(`pipeline stage ${scriptRel}: neither repo scripts/ nor bundled dist/pipeline/ found`);
|
|
@@ -22884,14 +23377,17 @@ function runStage(repoRoot, st, env, onLine) {
|
|
|
22884
23377
|
});
|
|
22885
23378
|
}
|
|
22886
23379
|
function hasPipeline(repoRoot) {
|
|
22887
|
-
return
|
|
23380
|
+
return existsSync5(path29.join(repoRoot, "scripts", "coding-build.mts")) || bundledPipelineDir() != null;
|
|
22888
23381
|
}
|
|
22889
23382
|
function codingDataRoot(repoRoot) {
|
|
22890
|
-
|
|
23383
|
+
if (!process.env.POLYMATH_DATA_DIR && existsSync5(path29.join(repoRoot, "scripts", "coding-build.mts"))) {
|
|
23384
|
+
return path29.join(repoRoot, ".data");
|
|
23385
|
+
}
|
|
23386
|
+
return resolveDataRoot();
|
|
22891
23387
|
}
|
|
22892
23388
|
async function finalCodingArtifacts(codingDir) {
|
|
22893
23389
|
const files = await fs23.readdir(codingDir).catch(() => []);
|
|
22894
|
-
return files.filter((f) => f.endsWith(".json") && f !== "report-run.json" && !f.startsWith(".")).sort().map((f) =>
|
|
23390
|
+
return files.filter((f) => f.endsWith(".json") && f !== "report-run.json" && !f.startsWith(".")).sort().map((f) => path29.join(codingDir, f));
|
|
22895
23391
|
}
|
|
22896
23392
|
async function runPipeline(o) {
|
|
22897
23393
|
if (!hasPipeline(o.repoRoot)) {
|
|
@@ -22899,11 +23395,18 @@ async function runPipeline(o) {
|
|
|
22899
23395
|
"full-pipeline refresh: neither the polymath repo (scripts/coding-*.mts at " + o.repoRoot + ") nor the bundled pipeline (dist/pipeline/) was found \u2014 the package build is broken."
|
|
22900
23396
|
);
|
|
22901
23397
|
}
|
|
22902
|
-
const env = { ...process.env, POLYMATH_RESILIENT: "1" };
|
|
22903
|
-
if (!o.overnight) env.POLYMATH_RESILIENT_NO_WINDOW = "1";
|
|
22904
|
-
const list = stages(o);
|
|
22905
23398
|
const dataRoot = codingDataRoot(o.repoRoot);
|
|
22906
|
-
const
|
|
23399
|
+
const env = { ...process.env, POLYMATH_RESILIENT: "1", POLYMATH_DATA_DIR: dataRoot };
|
|
23400
|
+
if (!o.overnight) env.POLYMATH_RESILIENT_NO_WINDOW = "1";
|
|
23401
|
+
if (o.overnight && process.platform === "darwin") {
|
|
23402
|
+
try {
|
|
23403
|
+
const { spawn: spawn10 } = await import("node:child_process");
|
|
23404
|
+
spawn10("caffeinate", ["-ims", "-w", String(process.pid)], { detached: true, stdio: "ignore" }).unref();
|
|
23405
|
+
} catch {
|
|
23406
|
+
}
|
|
23407
|
+
}
|
|
23408
|
+
const list = stages(o).filter((st) => !o.deterministicOnly || !st.llm);
|
|
23409
|
+
const codingDir = path29.join(dataRoot, "coding");
|
|
22907
23410
|
const central = centralConfig();
|
|
22908
23411
|
const t0 = Date.now();
|
|
22909
23412
|
const log = await startRunLog(
|
|
@@ -22912,26 +23415,35 @@ async function runPipeline(o) {
|
|
|
22912
23415
|
supabaseUrl: central.supabaseUrl,
|
|
22913
23416
|
supabaseAnonKey: central.supabaseAnonKey,
|
|
22914
23417
|
artifacts: () => finalCodingArtifacts(codingDir),
|
|
22915
|
-
refPath:
|
|
23418
|
+
refPath: path29.join(codingDir, "report-run.json")
|
|
22916
23419
|
// next to the served artifacts
|
|
22917
23420
|
}
|
|
22918
23421
|
);
|
|
22919
23422
|
const failed = [];
|
|
22920
|
-
|
|
22921
|
-
|
|
22922
|
-
|
|
22923
|
-
|
|
22924
|
-
|
|
22925
|
-
|
|
22926
|
-
|
|
22927
|
-
|
|
22928
|
-
|
|
22929
|
-
|
|
22930
|
-
|
|
22931
|
-
|
|
22932
|
-
|
|
22933
|
-
|
|
22934
|
-
|
|
23423
|
+
const groups = [];
|
|
23424
|
+
for (const st of list) {
|
|
23425
|
+
const g = groups[groups.length - 1];
|
|
23426
|
+
if (g && st.batch && g[0].batch === st.batch) g.push(st);
|
|
23427
|
+
else groups.push([st]);
|
|
23428
|
+
}
|
|
23429
|
+
let stageNo = 0;
|
|
23430
|
+
for (const group of groups) {
|
|
23431
|
+
await Promise.all(group.map(async (st) => {
|
|
23432
|
+
o.onStage?.(++stageNo, list.length, group.length > 1 ? `${st.label} (parallel \xD7${group.length})` : st.label, st.llm);
|
|
23433
|
+
const stStart = Date.now();
|
|
23434
|
+
let ok = true;
|
|
23435
|
+
const tag = group.length > 1 ? `[${st.script.replace(/^coding-|\.mts$/g, "")}] ` : "";
|
|
23436
|
+
try {
|
|
23437
|
+
await runStage(o.repoRoot, st, env, o.onLine && ((line) => o.onLine(`${tag}${line}`)));
|
|
23438
|
+
} catch (e) {
|
|
23439
|
+
ok = false;
|
|
23440
|
+
const error = e.message.slice(0, 200);
|
|
23441
|
+
failed.push({ label: st.label, script: st.script, error });
|
|
23442
|
+
o.onLine?.(`\u26A0\uFE0F stage FAILED (continuing): ${st.label} \u2014 ${error}`);
|
|
23443
|
+
}
|
|
23444
|
+
const sha = st.out ? await fileSha(path29.join(dataRoot, st.out)) : null;
|
|
23445
|
+
log.event(st.script.replace(/\.mts$/, ""), { ok, ms: Date.now() - stStart, ...sha ? { sha } : {} });
|
|
23446
|
+
}));
|
|
22935
23447
|
}
|
|
22936
23448
|
log.event("pipeline_completed", { ok: failed.length === 0, failedStages: failed.length, ms: Date.now() - t0 });
|
|
22937
23449
|
await log.finish();
|
|
@@ -22941,10 +23453,11 @@ async function runPipeline(o) {
|
|
|
22941
23453
|
// src/chatPipeline.ts
|
|
22942
23454
|
init_manifest();
|
|
22943
23455
|
import { spawn as spawn7 } from "child_process";
|
|
22944
|
-
import
|
|
22945
|
-
import { existsSync as
|
|
23456
|
+
import path31 from "path";
|
|
23457
|
+
import { existsSync as existsSync6, promises as fs25 } from "fs";
|
|
22946
23458
|
import { fileURLToPath as fileURLToPath4 } from "url";
|
|
22947
|
-
|
|
23459
|
+
init_dataHome();
|
|
23460
|
+
var MODULE_DIR3 = path31.dirname(fileURLToPath4(import.meta.url));
|
|
22948
23461
|
var INGESTABLE_KINDS = ["chatgpt", "claude", "notion", "obsidian"];
|
|
22949
23462
|
function chatEngineStages() {
|
|
22950
23463
|
return [
|
|
@@ -22963,37 +23476,40 @@ function chatEngineStages() {
|
|
|
22963
23476
|
];
|
|
22964
23477
|
}
|
|
22965
23478
|
function bundledEngineDir() {
|
|
22966
|
-
const d =
|
|
22967
|
-
return
|
|
23479
|
+
const d = path31.join(MODULE_DIR3, "engine");
|
|
23480
|
+
return existsSync6(path31.join(d, "run-tagger.js")) ? d : null;
|
|
22968
23481
|
}
|
|
22969
23482
|
function stageInvocation2(repoRoot, scriptRel, args) {
|
|
22970
|
-
const scriptAbs =
|
|
22971
|
-
if (
|
|
22972
|
-
const local =
|
|
22973
|
-
if (
|
|
23483
|
+
const scriptAbs = path31.join(repoRoot, "scripts", scriptRel);
|
|
23484
|
+
if (existsSync6(scriptAbs)) {
|
|
23485
|
+
const local = path31.join(repoRoot, "node_modules", ".bin", "tsx");
|
|
23486
|
+
if (existsSync6(local)) return { cmd: local, argv: [scriptAbs, ...args], cwd: repoRoot };
|
|
22974
23487
|
return { cmd: "npx", argv: ["tsx", scriptAbs, ...args], cwd: repoRoot };
|
|
22975
23488
|
}
|
|
22976
23489
|
const bundled = bundledEngineDir();
|
|
22977
23490
|
if (bundled) {
|
|
22978
|
-
const js =
|
|
23491
|
+
const js = path31.join(bundled, scriptRel.replace(/\.mts$/, ".js"));
|
|
22979
23492
|
return { cmd: process.execPath, argv: [js, ...args], cwd: process.cwd() };
|
|
22980
23493
|
}
|
|
22981
23494
|
throw new Error(`chat-engine stage ${scriptRel}: neither repo scripts/ nor bundled dist/engine/ found`);
|
|
22982
23495
|
}
|
|
22983
23496
|
function hasChatPipeline(repoRoot) {
|
|
22984
|
-
return
|
|
23497
|
+
return existsSync6(path31.join(repoRoot, "scripts", "run-tagger.mts")) || bundledEngineDir() != null;
|
|
22985
23498
|
}
|
|
22986
23499
|
function chatDataRoot(repoRoot) {
|
|
22987
|
-
|
|
23500
|
+
if (!process.env.POLYMATH_DATA_DIR && existsSync6(path31.join(repoRoot, "scripts", "run-tagger.mts"))) {
|
|
23501
|
+
return path31.join(repoRoot, ".data");
|
|
23502
|
+
}
|
|
23503
|
+
return resolveDataRoot();
|
|
22988
23504
|
}
|
|
22989
23505
|
async function finalChatArtifacts(dataRoot) {
|
|
22990
|
-
const gradesDir =
|
|
23506
|
+
const gradesDir = path31.join(dataRoot, "engine-pilot", "grades");
|
|
22991
23507
|
const out = [];
|
|
22992
23508
|
for (const lens of (await fs25.readdir(gradesDir).catch(() => [])).sort()) {
|
|
22993
|
-
const p =
|
|
22994
|
-
if (
|
|
23509
|
+
const p = path31.join(gradesDir, lens, "_person.json");
|
|
23510
|
+
if (existsSync6(p)) out.push(p);
|
|
22995
23511
|
}
|
|
22996
|
-
out.push(
|
|
23512
|
+
out.push(path31.join(dataRoot, "engine-pilot", "public-report.json"));
|
|
22997
23513
|
return out;
|
|
22998
23514
|
}
|
|
22999
23515
|
function runStage2(repoRoot, st, env, onLine) {
|
|
@@ -23051,12 +23567,12 @@ async function runChatPipeline(o) {
|
|
|
23051
23567
|
supabaseUrl: central.supabaseUrl,
|
|
23052
23568
|
supabaseAnonKey: central.supabaseAnonKey,
|
|
23053
23569
|
artifacts: () => finalChatArtifacts(dataRoot),
|
|
23054
|
-
refPath:
|
|
23570
|
+
refPath: path31.join(dataRoot, "report-run.json")
|
|
23055
23571
|
}
|
|
23056
23572
|
);
|
|
23057
23573
|
let idx = 0;
|
|
23058
23574
|
for (const f of ingestable) {
|
|
23059
|
-
const st = { script: "ingest-export.mts", label: `Ingest ${f.kind} \u2014 ${
|
|
23575
|
+
const st = { script: "ingest-export.mts", label: `Ingest ${f.kind} \u2014 ${path31.basename(f.path)}`, llm: false, args: [f.kind, f.path] };
|
|
23060
23576
|
o.onStage?.(++idx, total, st.label, false);
|
|
23061
23577
|
const stStart = Date.now();
|
|
23062
23578
|
let ok = true;
|
|
@@ -23083,7 +23599,7 @@ async function runChatPipeline(o) {
|
|
|
23083
23599
|
failed.push({ label: st.label, script: st.script, error });
|
|
23084
23600
|
o.onLine?.(`\u26A0\uFE0F stage FAILED (continuing): ${st.label} \u2014 ${error}`);
|
|
23085
23601
|
}
|
|
23086
|
-
const sha = st.out ? await fileSha(
|
|
23602
|
+
const sha = st.out ? await fileSha(path31.join(dataRoot, st.out)) : null;
|
|
23087
23603
|
log.event(st.script.replace(/\.mts$/, ""), { ok, ms: Date.now() - stStart, ...sha ? { sha } : {} });
|
|
23088
23604
|
}
|
|
23089
23605
|
log.event("pipeline_completed", { ok: failed.length === 0, failedStages: failed.length, ms: Date.now() - t0 });
|
|
@@ -23096,14 +23612,14 @@ init_manifest();
|
|
|
23096
23612
|
|
|
23097
23613
|
// ../../lib/agents/coding/profile.ts
|
|
23098
23614
|
import { promises as fs27 } from "fs";
|
|
23099
|
-
import
|
|
23615
|
+
import path33 from "path";
|
|
23100
23616
|
|
|
23101
23617
|
// ../../lib/agents/coding/walkthrough.ts
|
|
23102
23618
|
import { promises as fs26 } from "fs";
|
|
23103
|
-
import
|
|
23619
|
+
import path32 from "path";
|
|
23104
23620
|
var IDLE_CAP_MS = 12 * 6e4;
|
|
23105
23621
|
async function readWalkthrough(outDir, sessionId) {
|
|
23106
|
-
return fs26.readFile(
|
|
23622
|
+
return fs26.readFile(path32.join(outDir, `${sessionId}.json`), "utf8").then(JSON.parse).catch(() => null);
|
|
23107
23623
|
}
|
|
23108
23624
|
|
|
23109
23625
|
// ../../lib/agents/coding/workstyle.ts
|
|
@@ -23435,7 +23951,7 @@ var BEST = DEFAULT_CALIBRATION.codingBenchmarks;
|
|
|
23435
23951
|
|
|
23436
23952
|
// ../../lib/agents/coding/profile.ts
|
|
23437
23953
|
var ROOT2 = process.cwd();
|
|
23438
|
-
var CODING_DIR2 = process.env.POLYMATH_DATA_DIR ?
|
|
23954
|
+
var CODING_DIR2 = process.env.POLYMATH_DATA_DIR ? path33.join(process.env.POLYMATH_DATA_DIR, "coding") : path33.join(ROOT2, ".data", "coding");
|
|
23439
23955
|
var UMETA = /* @__PURE__ */ new Map();
|
|
23440
23956
|
async function userMeta(sessionId, file2) {
|
|
23441
23957
|
const hit = UMETA.get(sessionId);
|
|
@@ -23445,7 +23961,7 @@ async function userMeta(sessionId, file2) {
|
|
|
23445
23961
|
UMETA.set(sessionId, meta);
|
|
23446
23962
|
return meta;
|
|
23447
23963
|
}
|
|
23448
|
-
var GRADES2 =
|
|
23964
|
+
var GRADES2 = path33.join(CODING_DIR2, "grades");
|
|
23449
23965
|
async function readJson2(p, fallback) {
|
|
23450
23966
|
return fs27.readFile(p, "utf8").then((s) => JSON.parse(s)).catch(() => fallback);
|
|
23451
23967
|
}
|
|
@@ -23476,11 +23992,11 @@ function distOf3(takes) {
|
|
|
23476
23992
|
return { n, observed, mean: mean2, median: median2, hist };
|
|
23477
23993
|
}
|
|
23478
23994
|
async function compileCodingProfile() {
|
|
23479
|
-
const allRecords = await readJson2(
|
|
23995
|
+
const allRecords = await readJson2(path33.join(CODING_DIR2, "sessions.json"), []);
|
|
23480
23996
|
const dupIds = new Set(allRecords.filter((s) => s.duplicateOf).map((s) => s.sessionId));
|
|
23481
23997
|
const sessions = allRecords.filter((s) => !s.duplicateOf);
|
|
23482
|
-
const conc = await readJson2(
|
|
23483
|
-
const renames = await readJson2(
|
|
23998
|
+
const conc = await readJson2(path33.join(CODING_DIR2, "concurrency.json"), null);
|
|
23999
|
+
const renames = await readJson2(path33.join(CODING_DIR2, "renames.json"), []);
|
|
23484
24000
|
const byId = new Map(sessions.map((s) => [s.sessionId, s]));
|
|
23485
24001
|
let gradeFiles = [];
|
|
23486
24002
|
try {
|
|
@@ -23489,7 +24005,7 @@ async function compileCodingProfile() {
|
|
|
23489
24005
|
}
|
|
23490
24006
|
const grades = [];
|
|
23491
24007
|
for (const f of gradeFiles) {
|
|
23492
|
-
const g = await readJson2(
|
|
24008
|
+
const g = await readJson2(path33.join(GRADES2, f), null);
|
|
23493
24009
|
if (g && byId.has(g.sessionId)) grades.push(g);
|
|
23494
24010
|
}
|
|
23495
24011
|
const takesByCriterion = /* @__PURE__ */ new Map();
|
|
@@ -23598,13 +24114,13 @@ async function compileCodingProfile() {
|
|
|
23598
24114
|
models: Object.fromEntries([...models.entries()].sort((a, b) => b[1] - a[1])),
|
|
23599
24115
|
lateNightSessions: lateNight
|
|
23600
24116
|
};
|
|
23601
|
-
const agglomeration = await readJson2(
|
|
23602
|
-
const dayDigest = await readJson2(
|
|
24117
|
+
const agglomeration = await readJson2(path33.join(CODING_DIR2, "agglomerate.json"), null);
|
|
24118
|
+
const dayDigest = await readJson2(path33.join(CODING_DIR2, "day-digest.json"), null);
|
|
23603
24119
|
if (dayDigest?.days) dayDigest.days = dayDigest.days.map((day) => {
|
|
23604
24120
|
const convs = day.conversations.filter((c) => byId.has(c.sessionId));
|
|
23605
24121
|
return { ...day, conversations: convs, conversationsTouched: convs.length, totalMessages: convs.reduce((a, c) => a + c.messageCount, 0) };
|
|
23606
24122
|
}).filter((day) => day.conversations.length > 0);
|
|
23607
|
-
const dayChart = await readJson2(
|
|
24123
|
+
const dayChart = await readJson2(path33.join(CODING_DIR2, "day-chart.json"), []);
|
|
23608
24124
|
const intervalsBy = /* @__PURE__ */ new Map();
|
|
23609
24125
|
const titleBy = /* @__PURE__ */ new Map();
|
|
23610
24126
|
const fileById = new Map(sessions.map((s) => [s.sessionId, s.file]));
|
|
@@ -23623,7 +24139,7 @@ async function compileCodingProfile() {
|
|
|
23623
24139
|
return ms2;
|
|
23624
24140
|
};
|
|
23625
24141
|
const walkthroughs = {};
|
|
23626
|
-
const wdir =
|
|
24142
|
+
const wdir = path33.join(CODING_DIR2, "walkthroughs");
|
|
23627
24143
|
for (const f of await fs27.readdir(wdir).catch(() => [])) {
|
|
23628
24144
|
if (!f.endsWith(".json")) continue;
|
|
23629
24145
|
const w = await readWalkthrough(wdir, f.replace(".json", ""));
|
|
@@ -23671,17 +24187,17 @@ async function compileCodingProfile() {
|
|
|
23671
24187
|
const tCeiling = throughputCeiling(Object.values(wordsByDay));
|
|
23672
24188
|
const criteriaMean = {};
|
|
23673
24189
|
for (const c of criteria) criteriaMean[c.key] = { mean: c.dist.mean, n: c.dist.n };
|
|
23674
|
-
const flow = await readJson2(
|
|
23675
|
-
const focus = await readJson2(
|
|
23676
|
-
const expertiseMap = await readJson2(
|
|
23677
|
-
const frontierArsenal = await readJson2(
|
|
23678
|
-
const frontierDetail = await readJson2(
|
|
23679
|
-
const coaching = await readJson2(
|
|
23680
|
-
const gap = await readJson2(
|
|
23681
|
-
const aggregate = await readJson2(
|
|
23682
|
-
const delegationRollup = await readJson2(
|
|
23683
|
-
const gapDist = await readJson2(
|
|
23684
|
-
const projects = await readJson2(
|
|
24190
|
+
const flow = await readJson2(path33.join(CODING_DIR2, "flow.json"), null);
|
|
24191
|
+
const focus = await readJson2(path33.join(CODING_DIR2, "focus.json"), null);
|
|
24192
|
+
const expertiseMap = await readJson2(path33.join(CODING_DIR2, "expertise.json"), null);
|
|
24193
|
+
const frontierArsenal = await readJson2(path33.join(CODING_DIR2, "frontier.json"), null);
|
|
24194
|
+
const frontierDetail = await readJson2(path33.join(CODING_DIR2, "frontier-detail.json"), null);
|
|
24195
|
+
const coaching = await readJson2(path33.join(CODING_DIR2, "coaching.json"), null);
|
|
24196
|
+
const gap = await readJson2(path33.join(CODING_DIR2, "gap.json"), null);
|
|
24197
|
+
const aggregate = await readJson2(path33.join(CODING_DIR2, "aggregate.json"), null);
|
|
24198
|
+
const delegationRollup = await readJson2(path33.join(CODING_DIR2, "delegation-rollup.json"), null);
|
|
24199
|
+
const gapDist = await readJson2(path33.join(CODING_DIR2, "gap-dist.json"), null);
|
|
24200
|
+
const projects = await readJson2(path33.join(CODING_DIR2, "projects.json"), null);
|
|
23685
24201
|
const workstyle = computeWorkstyle({
|
|
23686
24202
|
dayChart,
|
|
23687
24203
|
tz,
|
|
@@ -23801,8 +24317,8 @@ async function compileCodingProfile() {
|
|
|
23801
24317
|
}
|
|
23802
24318
|
|
|
23803
24319
|
// src/cli.ts
|
|
23804
|
-
var __dirname2 =
|
|
23805
|
-
var REPO_ROOT =
|
|
24320
|
+
var __dirname2 = path37.dirname(fileURLToPath5(import.meta.url));
|
|
24321
|
+
var REPO_ROOT = path37.resolve(__dirname2, "..", "..", "..");
|
|
23806
24322
|
function parseArgs(argv) {
|
|
23807
24323
|
const p = {
|
|
23808
24324
|
cmd: "profile",
|
|
@@ -23814,6 +24330,7 @@ function parseArgs(argv) {
|
|
|
23814
24330
|
spanHourMin: void 0,
|
|
23815
24331
|
grade: false,
|
|
23816
24332
|
overnight: false,
|
|
24333
|
+
chatOvernight: void 0,
|
|
23817
24334
|
regrade: false,
|
|
23818
24335
|
conc: void 0,
|
|
23819
24336
|
adapter: void 0,
|
|
@@ -23835,6 +24352,7 @@ function parseArgs(argv) {
|
|
|
23835
24352
|
else if (a === "--span") p.spanHourMin = Number(argv[++i]);
|
|
23836
24353
|
else if (a === "--grade") p.grade = true;
|
|
23837
24354
|
else if (a === "--overnight") p.overnight = true;
|
|
24355
|
+
else if (a === "--chat-overnight") p.chatOvernight = true;
|
|
23838
24356
|
else if (a === "--regrade") p.regrade = true;
|
|
23839
24357
|
else if (a === "--conc") p.conc = Number(argv[++i]);
|
|
23840
24358
|
else if (a === "--adapter") {
|
|
@@ -23897,8 +24415,9 @@ CLAUDE_PROJECTS_DIR / CODEX_SESSIONS_DIR / CURSOR_WORKSPACE_DIR /
|
|
|
23897
24415
|
CURSOR_PROJECTS_DIR. Setting ANY of these isolates the run: every source you
|
|
23898
24416
|
did not explicitly point somewhere is skipped, never read from this machine.
|
|
23899
24417
|
Grading spends YOUR Claude/ChatGPT subscription, never an API key.
|
|
23900
|
-
|
|
23901
|
-
|
|
24418
|
+
ALL analysis artifacts land under ONE data home, printed at startup:
|
|
24419
|
+
POLYMATH_DATA_DIR if set, else ./.data when it already exists, else
|
|
24420
|
+
~/.polymath-society/data. Re-run anywhere \u2014 it resumes from that same folder.`;
|
|
23902
24421
|
var round13 = (x) => Math.round(x * 10) / 10;
|
|
23903
24422
|
function printProfileSummary(p) {
|
|
23904
24423
|
const t = p.throughput;
|
|
@@ -23966,6 +24485,7 @@ async function main() {
|
|
|
23966
24485
|
console.log(USAGE);
|
|
23967
24486
|
return;
|
|
23968
24487
|
}
|
|
24488
|
+
console.error(` data home: ${DATA_ROOT}`);
|
|
23969
24489
|
const wantWizard = process.env.POLYMATH_WIZARD === "1" || process.env.POLYMATH_WIZARD !== "0" && process.argv.length <= 2 && !!process.stdin.isTTY && !!process.stdout.isTTY;
|
|
23970
24490
|
if (wantWizard) {
|
|
23971
24491
|
const { runWizard: runWizard2 } = await Promise.resolve().then(() => (init_wizard(), wizard_exports));
|
|
@@ -23974,13 +24494,14 @@ async function main() {
|
|
|
23974
24494
|
opts.cmd = w.cmd;
|
|
23975
24495
|
opts.grade = w.grade;
|
|
23976
24496
|
opts.overnight = w.overnight;
|
|
24497
|
+
opts.chatOvernight = w.chatOvernight;
|
|
23977
24498
|
opts.open = w.open;
|
|
23978
24499
|
}
|
|
23979
24500
|
if (opts.cmd === "grade") {
|
|
23980
24501
|
const backend = ensureBackend(opts.adapter);
|
|
23981
24502
|
if (!backend) process.exit(1);
|
|
23982
24503
|
console.error(`Using ${backend.name === "cli" ? "Claude Code" : "Codex"} (${backend.detail}).`);
|
|
23983
|
-
const gradeOut =
|
|
24504
|
+
const gradeOut = path37.resolve(opts.out || ".coding-analyzer-grades");
|
|
23984
24505
|
const provider = new LocalGradeProvider({
|
|
23985
24506
|
adapter: opts.adapter,
|
|
23986
24507
|
model: opts.model,
|
|
@@ -23989,8 +24510,8 @@ async function main() {
|
|
|
23989
24510
|
});
|
|
23990
24511
|
const profile2 = await analyze({ codex: opts.codex, idleGapMin: opts.idleGapMin, tz: opts.tz, spanHourMin: opts.spanHourMin, gradeProvider: provider });
|
|
23991
24512
|
const detail = provider.detail();
|
|
23992
|
-
await
|
|
23993
|
-
await
|
|
24513
|
+
await fs31.mkdir(gradeOut, { recursive: true });
|
|
24514
|
+
await fs31.writeFile(path37.join(gradeOut, "graded.json"), JSON.stringify(detail, null, 2));
|
|
23994
24515
|
console.error(`
|
|
23995
24516
|
Graded ${detail.gradedSessions} sessions \u2192 ${gradeOut}/graded.json`);
|
|
23996
24517
|
for (const c of detail.criteria) console.error(` ${c.key.padEnd(12)} ${c.mean != null ? `mean ${c.mean} \xB7 ${c.n} sessions` : "no signal"}`);
|
|
@@ -23998,6 +24519,20 @@ Graded ${detail.gradedSessions} sessions \u2192 ${gradeOut}/graded.json`);
|
|
|
23998
24519
|
return;
|
|
23999
24520
|
}
|
|
24000
24521
|
if (opts.cmd === "serve") {
|
|
24522
|
+
let earlyHandle = null;
|
|
24523
|
+
const runMarker = path37.join(DATA_ROOT, "coding", ".grade-run.json");
|
|
24524
|
+
if (!opts.grade) {
|
|
24525
|
+
try {
|
|
24526
|
+
const mk = JSON.parse(await fs31.readFile(runMarker, "utf8"));
|
|
24527
|
+
if (mk && mk.done === false) {
|
|
24528
|
+
console.error(`
|
|
24529
|
+
\u26A0\uFE0F An analysis started ${mk.startedAt ?? "earlier"} never finished (the process died mid-run).`);
|
|
24530
|
+
console.error(" Resuming it now \u2014 already-completed work is never redone.\n");
|
|
24531
|
+
opts.grade = true;
|
|
24532
|
+
}
|
|
24533
|
+
} catch {
|
|
24534
|
+
}
|
|
24535
|
+
}
|
|
24001
24536
|
if (opts.grade) {
|
|
24002
24537
|
if (!hasPipeline(REPO_ROOT)) {
|
|
24003
24538
|
console.error("Can't run the full analysis \u2014 the bundled pipeline (dist/pipeline/) is missing from this install.");
|
|
@@ -24009,12 +24544,51 @@ Graded ${detail.gradedSessions} sessions \u2192 ${gradeOut}/graded.json`);
|
|
|
24009
24544
|
console.error("Log in to Claude Code (or Codex) first \u2014 grading runs on YOUR subscription, no API key.\n");
|
|
24010
24545
|
process.exit(1);
|
|
24011
24546
|
}
|
|
24012
|
-
const
|
|
24547
|
+
const chatOvernight = opts.chatOvernight ?? opts.overnight;
|
|
24548
|
+
const when = (o) => o ? "at the 02:00 window tonight" : "now";
|
|
24013
24549
|
console.error(`
|
|
24014
|
-
Running the full analysis on ${backend.name === "cli" ? "Claude Code" : "Codex"} \u2014 ${
|
|
24015
|
-
console.error("This spends your subscription tokens and can take a while. The link appears
|
|
24550
|
+
Running the full analysis on ${backend.name === "cli" ? "Claude Code" : "Codex"} \u2014 coding ${when(opts.overnight)}, chats ${when(chatOvernight)}.`);
|
|
24551
|
+
console.error("This spends your subscription tokens and can take a while. The report link appears right away and fills in as stages finish.\n");
|
|
24016
24552
|
const t0 = Date.now();
|
|
24017
|
-
|
|
24553
|
+
try {
|
|
24554
|
+
await fs31.mkdir(path37.dirname(runMarker), { recursive: true });
|
|
24555
|
+
await fs31.writeFile(runMarker, JSON.stringify({ startedAt: (/* @__PURE__ */ new Date()).toISOString(), done: false }));
|
|
24556
|
+
} catch {
|
|
24557
|
+
}
|
|
24558
|
+
earlyHandle = await startServer({
|
|
24559
|
+
profile: await compileCodingProfile(),
|
|
24560
|
+
shareSections: {},
|
|
24561
|
+
version: await pkgVersion(),
|
|
24562
|
+
shareUrl: opts.shareUrl || process.env.PS_SHARE_URL || DEFAULT_SHARE_URL,
|
|
24563
|
+
port: opts.port,
|
|
24564
|
+
dataDir: DATA_ROOT
|
|
24565
|
+
});
|
|
24566
|
+
const progress = {
|
|
24567
|
+
coding: { i: 0, total: 0, label: "starting", done: false, overnight: !!opts.overnight },
|
|
24568
|
+
chat: { i: 0, total: 0, label: "starting", done: false, overnight: chatOvernight }
|
|
24569
|
+
};
|
|
24570
|
+
earlyHandle.setProgress(progress);
|
|
24571
|
+
const refreshProfile = async () => {
|
|
24572
|
+
try {
|
|
24573
|
+
earlyHandle.setProfile(await compileCodingProfile());
|
|
24574
|
+
} catch {
|
|
24575
|
+
}
|
|
24576
|
+
};
|
|
24577
|
+
const liveRefresh = setInterval(() => {
|
|
24578
|
+
void refreshProfile();
|
|
24579
|
+
}, Number(process.env.POLYMATH_LIVE_REFRESH_MS || 45e3));
|
|
24580
|
+
const { makeMultiBar: makeMultiBar2 } = await Promise.resolve().then(() => (init_progressBar(), progressBar_exports));
|
|
24581
|
+
const mbar = makeMultiBar2();
|
|
24582
|
+
const harvestWithin = (lane, line) => {
|
|
24583
|
+
const m = /Σ\s+(\d+)\/(\d+)/.exec(line);
|
|
24584
|
+
if (m && progress[lane] && !progress[lane].done) {
|
|
24585
|
+
progress[lane].within = { done: Number(m[1]), total: Number(m[2]) };
|
|
24586
|
+
earlyHandle.setProgress(progress);
|
|
24587
|
+
}
|
|
24588
|
+
};
|
|
24589
|
+
mbar.setLink(earlyHandle.url);
|
|
24590
|
+
const codingLane = mbar.lane("coding");
|
|
24591
|
+
const codingDone = runPipeline({
|
|
24018
24592
|
repoRoot: REPO_ROOT,
|
|
24019
24593
|
model: opts.model,
|
|
24020
24594
|
conc: opts.conc,
|
|
@@ -24022,64 +24596,135 @@ Running the full analysis on ${backend.name === "cli" ? "Claude Code" : "Codex"}
|
|
|
24022
24596
|
codex: opts.codex,
|
|
24023
24597
|
idleGapMin: opts.idleGapMin,
|
|
24024
24598
|
regrade: opts.regrade,
|
|
24025
|
-
onStage: (i, total, label, llm) =>
|
|
24026
|
-
|
|
24027
|
-
|
|
24599
|
+
onStage: (i, total, label, llm) => {
|
|
24600
|
+
progress.coding = { ...progress.coding, i, total, label, done: false };
|
|
24601
|
+
earlyHandle.setProgress(progress);
|
|
24602
|
+
codingLane.stage(i, total, `${label}${llm ? " (AI)" : ""}`);
|
|
24603
|
+
},
|
|
24604
|
+
onLine: (line) => {
|
|
24605
|
+
harvestWithin("coding", line);
|
|
24606
|
+
codingLane.log(` ${line}`);
|
|
24607
|
+
}
|
|
24608
|
+
}).then(async ({ failed: failed2 }) => {
|
|
24609
|
+
progress.coding = { ...progress.coding ?? { i: 0, total: 0, label: "" }, done: true, failed: failed2.length };
|
|
24610
|
+
earlyHandle.setProgress(progress);
|
|
24611
|
+
await refreshProfile();
|
|
24612
|
+
openBrowser(earlyHandle.url);
|
|
24613
|
+
try {
|
|
24614
|
+
const stored = JSON.parse(await fs31.readFile(path37.join(DATA_ROOT, "notify-email.json"), "utf8"));
|
|
24615
|
+
if (stored.email) {
|
|
24616
|
+
const { requestEmailReminder: requestEmailReminder2 } = await Promise.resolve().then(() => (init_reminderEmail(), reminderEmail_exports));
|
|
24617
|
+
const r = await requestEmailReminder2(stored.email, ["report-ready"], 1);
|
|
24618
|
+
if (r.ok) codingLane.log(` \u2713 We'll also email ${stored.email} that the report is ready.`);
|
|
24619
|
+
}
|
|
24620
|
+
} catch {
|
|
24621
|
+
}
|
|
24622
|
+
return { failed: failed2 };
|
|
24028
24623
|
});
|
|
24624
|
+
const chatLane = mbar.lane("chat");
|
|
24625
|
+
const chatDone = (async () => {
|
|
24626
|
+
if (!hasChatPipeline(REPO_ROOT)) return null;
|
|
24627
|
+
const manifest = await readManifest(chatDataRoot(REPO_ROOT));
|
|
24628
|
+
if (!manifest || manifest.exports.included.length === 0) {
|
|
24629
|
+
const why = manifest ? "no chat/notes sources are included \u2014 re-run the wizard to add some" : "no exports-manifest.json \u2014 run the wizard (bare `polymath-society`) to approve chat/notes sources";
|
|
24630
|
+
progress.chat = { i: 0, total: 0, label: "", done: true, skipped: why };
|
|
24631
|
+
earlyHandle.setProgress(progress);
|
|
24632
|
+
chatLane.log(` (chat analysis skipped: ${why})`);
|
|
24633
|
+
return null;
|
|
24634
|
+
}
|
|
24635
|
+
chatLane.log(` chat analysis starting over your ${manifest.exports.included.length} approved source(s) \u2014 same engine as the hosted app.`);
|
|
24636
|
+
const chat2 = await runChatPipeline({
|
|
24637
|
+
repoRoot: REPO_ROOT,
|
|
24638
|
+
model: opts.model,
|
|
24639
|
+
overnight: chatOvernight,
|
|
24640
|
+
onStage: (i, total, label, llm) => {
|
|
24641
|
+
progress.chat = { ...progress.chat, i, total, label, done: false };
|
|
24642
|
+
earlyHandle.setProgress(progress);
|
|
24643
|
+
chatLane.stage(i, total, `${label}${llm ? " (AI)" : ""}`);
|
|
24644
|
+
},
|
|
24645
|
+
onLine: (line) => {
|
|
24646
|
+
harvestWithin("chat", line);
|
|
24647
|
+
chatLane.log(` ${line}`);
|
|
24648
|
+
}
|
|
24649
|
+
});
|
|
24650
|
+
progress.chat = { ...progress.chat ?? { i: 0, total: 0, label: "" }, done: true, failed: chat2.failed.length };
|
|
24651
|
+
earlyHandle.setProgress(progress);
|
|
24652
|
+
await refreshProfile();
|
|
24653
|
+
return chat2;
|
|
24654
|
+
})();
|
|
24655
|
+
const [{ failed }, chat] = await Promise.all([codingDone, chatDone]);
|
|
24656
|
+
clearInterval(liveRefresh);
|
|
24657
|
+
mbar.done();
|
|
24029
24658
|
if (failed.length) {
|
|
24030
24659
|
console.error(`
|
|
24031
|
-
\u26A0\uFE0F ${failed.length} stage(s) FAILED \u2014 the report
|
|
24660
|
+
\u26A0\uFE0F ${failed.length} coding stage(s) FAILED \u2014 the report is served WITHOUT their output:`);
|
|
24032
24661
|
for (const f of failed) console.error(` \u2022 ${f.label} (${f.script}): ${f.error}`);
|
|
24033
24662
|
console.error(` Fix: run \`serve --grade\` again \u2014 it resumes, redoing ONLY the missing work.
|
|
24034
24663
|
`);
|
|
24035
24664
|
} else {
|
|
24036
24665
|
console.error(`
|
|
24037
|
-
\u2713 coding analysis complete in ${Math.round((Date.now() - t0) / 6e4)} min
|
|
24038
|
-
`);
|
|
24666
|
+
\u2713 coding analysis complete in ${Math.round((Date.now() - t0) / 6e4)} min.`);
|
|
24039
24667
|
}
|
|
24040
|
-
if (
|
|
24041
|
-
const
|
|
24042
|
-
if (
|
|
24043
|
-
console.error(`
|
|
24044
|
-
`);
|
|
24045
|
-
} else {
|
|
24046
|
-
console.error(`Running the CHAT analysis over your ${manifest.exports.included.length} approved source(s) \u2014 same engine as the hosted app.
|
|
24047
|
-
`);
|
|
24048
|
-
const c0 = Date.now();
|
|
24049
|
-
const chat = await runChatPipeline({
|
|
24050
|
-
repoRoot: REPO_ROOT,
|
|
24051
|
-
model: opts.model,
|
|
24052
|
-
overnight: opts.overnight,
|
|
24053
|
-
onStage: (i, total, label, llm) => console.error(`
|
|
24054
|
-
\u25B8 [chat ${i}/${total}] ${label}${llm ? " (AI)" : ""}`),
|
|
24055
|
-
onLine: (line) => console.error(` ${line}`)
|
|
24056
|
-
});
|
|
24057
|
-
for (const p of chat.notIngestable) console.error(` \u26A0\uFE0F can't ingest ${p} \u2014 no importer for that source kind`);
|
|
24058
|
-
if (chat.failed.length) {
|
|
24059
|
-
console.error(`
|
|
24668
|
+
if (chat) {
|
|
24669
|
+
for (const p of chat.notIngestable) console.error(` \u26A0\uFE0F can't ingest ${p} \u2014 no importer for that source kind`);
|
|
24670
|
+
if (chat.failed.length) {
|
|
24671
|
+
console.error(`
|
|
24060
24672
|
\u26A0\uFE0F ${chat.failed.length} chat stage(s) FAILED \u2014 the chat tab is served WITHOUT their output:`);
|
|
24061
|
-
|
|
24062
|
-
|
|
24673
|
+
for (const f of chat.failed) console.error(` \u2022 ${f.label} (${f.script}): ${f.error}`);
|
|
24674
|
+
console.error(` Fix: run \`serve --grade\` again \u2014 every chat stage resumes from what's on disk.
|
|
24063
24675
|
`);
|
|
24064
|
-
|
|
24065
|
-
|
|
24066
|
-
\u2713 chat analysis complete in ${Math.round((Date.now() - c0) / 6e4)} min.
|
|
24676
|
+
} else {
|
|
24677
|
+
console.error(`\u2713 chat analysis complete in ${Math.round((Date.now() - t0) / 6e4)} min (ran alongside coding).
|
|
24067
24678
|
`);
|
|
24068
|
-
}
|
|
24069
24679
|
}
|
|
24070
24680
|
}
|
|
24681
|
+
try {
|
|
24682
|
+
await fs31.writeFile(runMarker, JSON.stringify({ startedAt: (/* @__PURE__ */ new Date()).toISOString(), done: true }));
|
|
24683
|
+
} catch {
|
|
24684
|
+
}
|
|
24685
|
+
}
|
|
24686
|
+
if (!opts.grade && !existsSync7(path37.join(DATA_ROOT, "coding", "sessions.json")) && hasPipeline(REPO_ROOT)) {
|
|
24687
|
+
console.error(`
|
|
24688
|
+
No analysis here yet \u2014 computing the instant deterministic metrics now (free, no AI)\u2026`);
|
|
24689
|
+
const d0 = Date.now();
|
|
24690
|
+
const { makeProgressBar: makeProgressBar2 } = await Promise.resolve().then(() => (init_progressBar(), progressBar_exports));
|
|
24691
|
+
const dbar = makeProgressBar2();
|
|
24692
|
+
const det = await runPipeline({
|
|
24693
|
+
repoRoot: REPO_ROOT,
|
|
24694
|
+
deterministicOnly: true,
|
|
24695
|
+
codex: opts.codex,
|
|
24696
|
+
idleGapMin: opts.idleGapMin,
|
|
24697
|
+
onStage: (i, total, label) => dbar.stage(i, total, label),
|
|
24698
|
+
onLine: (line) => dbar.log(` ${line}`)
|
|
24699
|
+
});
|
|
24700
|
+
dbar.done();
|
|
24701
|
+
if (det.failed.length) {
|
|
24702
|
+
console.error(`
|
|
24703
|
+
\u26A0\uFE0F ${det.failed.length} deterministic stage(s) FAILED \u2014 the report is served without their output:`);
|
|
24704
|
+
for (const f of det.failed) console.error(` \u2022 ${f.label} (${f.script}): ${f.error}`);
|
|
24705
|
+
} else {
|
|
24706
|
+
console.error(`
|
|
24707
|
+
\u2713 deterministic metrics ready in ${Math.round((Date.now() - d0) / 1e3)}s.
|
|
24708
|
+
`);
|
|
24709
|
+
}
|
|
24071
24710
|
}
|
|
24072
24711
|
const web = await compileCodingProfile();
|
|
24073
24712
|
const version = await pkgVersion();
|
|
24074
24713
|
const shareUrl = opts.shareUrl || process.env.PS_SHARE_URL || DEFAULT_SHARE_URL;
|
|
24075
|
-
const dataDir =
|
|
24714
|
+
const dataDir = DATA_ROOT;
|
|
24076
24715
|
const shareSections = buildShareSections(web);
|
|
24077
|
-
|
|
24716
|
+
let handle;
|
|
24717
|
+
if (earlyHandle) {
|
|
24718
|
+
earlyHandle.setProfile(web);
|
|
24719
|
+
handle = earlyHandle;
|
|
24720
|
+
} else {
|
|
24721
|
+
handle = await startServer({ profile: web, shareSections, version, shareUrl, port: opts.port, dataDir });
|
|
24722
|
+
}
|
|
24078
24723
|
const w = web;
|
|
24079
24724
|
const nSessions = w.throughput?.sessions ?? 0;
|
|
24080
24725
|
const nGraded = w.gradedSessions ?? 0;
|
|
24081
24726
|
const who = await readIdentity(dataDir);
|
|
24082
|
-
if (!
|
|
24727
|
+
if (nSessions === 0 && !existsSync7(path37.join(dataDir, "coding")) && !existsSync7(path37.join(dataDir, "engine-pilot"))) {
|
|
24083
24728
|
console.error(`
|
|
24084
24729
|
\u26A0\uFE0F ${dataDir} has no analysis artifacts \u2014 this will be an EMPTY report.`);
|
|
24085
24730
|
console.error(` Run from the directory where you ran the analysis, or set POLYMATH_DATA_DIR.`);
|
|
@@ -24091,7 +24736,7 @@ Running the full analysis on ${backend.name === "cli" ? "Claude Code" : "Codex"}
|
|
|
24091
24736
|
console.error(` ${who ? `signed in as ${who.email}` : "not signed in \u2014 feedback + sharing ask for Google sign-in in the header"}`);
|
|
24092
24737
|
console.error(` (Ctrl-C to stop)
|
|
24093
24738
|
`);
|
|
24094
|
-
if (opts.open) openBrowser(handle.url);
|
|
24739
|
+
if (opts.open && !earlyHandle) openBrowser(handle.url);
|
|
24095
24740
|
process.on("SIGINT", async () => {
|
|
24096
24741
|
await handle.close();
|
|
24097
24742
|
process.exit(0);
|
|
@@ -24105,7 +24750,7 @@ Running the full analysis on ${backend.name === "cli" ? "Claude Code" : "Codex"}
|
|
|
24105
24750
|
const profile = await analyze({ codex: opts.codex, idleGapMin: opts.idleGapMin, tz: opts.tz, spanHourMin: opts.spanHourMin });
|
|
24106
24751
|
const payload = opts.cmd === "projects" ? profile.projects : opts.cmd === "flow" ? profile.flow : opts.cmd === "aggregate" ? profile.aggregate : profile;
|
|
24107
24752
|
if (opts.out) {
|
|
24108
|
-
await
|
|
24753
|
+
await fs31.writeFile(opts.out, JSON.stringify(payload, null, 2));
|
|
24109
24754
|
console.error(`wrote ${opts.cmd} \u2192 ${opts.out}`);
|
|
24110
24755
|
return;
|
|
24111
24756
|
}
|
|
@@ -24117,7 +24762,7 @@ Running the full analysis on ${backend.name === "cli" ? "Claude Code" : "Codex"}
|
|
|
24117
24762
|
}
|
|
24118
24763
|
async function pkgVersion() {
|
|
24119
24764
|
try {
|
|
24120
|
-
const pkg = JSON.parse(await
|
|
24765
|
+
const pkg = JSON.parse(await fs31.readFile(path37.join(__dirname2, "..", "package.json"), "utf-8"));
|
|
24121
24766
|
return String(pkg.version || "0.0.0");
|
|
24122
24767
|
} catch {
|
|
24123
24768
|
return "0.0.0";
|