polymath-society 0.2.17 → 0.2.18

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/dist/cli.js +63 -8
  2. package/package.json +2 -2
package/dist/cli.js CHANGED
@@ -2573,6 +2573,18 @@ function makeMultiBar(out = process.stderr) {
2573
2573
  if (m) l.within = { done: Number(m[1]), total: Number(m[2]) };
2574
2574
  }
2575
2575
  repaintAround(tty ? line : `[${name17}] ${line.trimStart()}`);
2576
+ },
2577
+ // Pin the lane at 100% immediately (up-to-date gate: the report is
2578
+ // ready NOW; remaining stages are silent housekeeping and must not
2579
+ // crawl the bar through partial percentages).
2580
+ finish(label) {
2581
+ const l = lanes.get(name17) ?? { i: 0, total: 0, label: "", within: null };
2582
+ l.total = l.total || 1;
2583
+ l.i = l.total + 1;
2584
+ l.label = label;
2585
+ l.within = null;
2586
+ lanes.set(name17, l);
2587
+ repaintAround(`\u25B8 ${name17} \u2713 ${label}`);
2576
2588
  }
2577
2589
  };
2578
2590
  },
@@ -25262,6 +25274,7 @@ async function runPipeline(o) {
25262
25274
  const gate2 = await evalUpToDate(codingDir, threshold, o.regrade);
25263
25275
  if (gate2.skip) {
25264
25276
  skippedLlm = { pending: gate2.pending, threshold };
25277
+ o.onUpToDate?.();
25265
25278
  o.onLine?.(
25266
25279
  `\u2713 report is up to date \u2014 ${gate2.pending} new session(s) since the last full run (below the ${threshold}-session threshold). Skipping the AI stages; free metrics still refresh. They'll be analyzed once ${threshold}+ accumulate (POLYMATH_MIN_NEW_SESSIONS=0 or --regrade to force now).`
25267
25280
  );
@@ -25465,6 +25478,7 @@ async function runChatPipeline(o) {
25465
25478
  const report = await fs32.readFile(path37.join(dataRoot, "engine-pilot", "public-report.json"), "utf8").then((s) => JSON.parse(s)).catch(() => null);
25466
25479
  if (report?.headline && (report.spikes?.length ?? 0) > 0 && newDocs < minNewDocs) {
25467
25480
  upToDate = true;
25481
+ o.onUpToDate?.();
25468
25482
  o.onLine?.(`\u2713 chat report is up to date \u2014 ${newDocs} new doc(s) since the last full run (below the ${minNewDocs}-doc threshold), so the AI stages are skipped and the existing report is served as-is. POLYMATH_MIN_NEW_DOCS=0 forces a full run.`);
25469
25483
  }
25470
25484
  }
@@ -25578,6 +25592,18 @@ ALL analysis artifacts land under ONE data home, printed at startup:
25578
25592
  POLYMATH_DATA_DIR if set, else ./.data when it already exists, else
25579
25593
  ~/.polymath-society/data. Re-run anywhere \u2014 it resumes from that same folder.`;
25580
25594
  var round13 = (x) => Math.round(x * 10) / 10;
25595
+ async function readPriorAnalysis() {
25596
+ try {
25597
+ const agg = JSON.parse(await fs36.readFile(path41.join(DATA_ROOT, "coding", "aggregate.json"), "utf-8"));
25598
+ if (!agg.bigPicture || !String(agg.bigPicture).trim()) return null;
25599
+ const graded = (await fs36.readdir(path41.join(DATA_ROOT, "coding", "grades")).catch(() => [])).filter((f) => f.endsWith(".json")).length;
25600
+ const stat = await fs36.stat(path41.join(DATA_ROOT, "coding", "aggregate.json"));
25601
+ const when = (agg.generatedAt ?? stat.mtime.toISOString()).slice(0, 10);
25602
+ return { graded, when };
25603
+ } catch {
25604
+ return null;
25605
+ }
25606
+ }
25581
25607
  function printProfileSummary(p) {
25582
25608
  const t = p.throughput;
25583
25609
  const log = console.log;
@@ -25648,14 +25674,27 @@ async function main() {
25648
25674
  await maybePrintUpdateNotice(opts);
25649
25675
  const wantWizard = process.env.POLYMATH_WIZARD === "1" || process.env.POLYMATH_WIZARD !== "0" && process.argv.length <= 2 && !!process.stdin.isTTY && !!process.stdout.isTTY;
25650
25676
  if (wantWizard) {
25651
- const { runWizard: runWizard2 } = await Promise.resolve().then(() => (init_wizard(), wizard_exports));
25652
- const w = await runWizard2();
25653
- if (!w) return;
25654
- opts.cmd = w.cmd;
25655
- opts.grade = w.grade;
25656
- opts.overnight = w.overnight;
25657
- opts.chatOvernight = w.chatOvernight;
25658
- opts.open = w.open;
25677
+ console.error(" Checking for existing analysis\u2026");
25678
+ const prior = process.env.POLYMATH_WIZARD === "1" ? null : await readPriorAnalysis();
25679
+ if (prior) {
25680
+ console.error(` Found your finished report \u2014 ${prior.graded} graded sessions, last updated ${prior.when}.`);
25681
+ console.error(` Serving it now. The progress bars below are just a quick check for anything new \u2014`);
25682
+ console.error(` your finished analysis is never redone.`);
25683
+ console.error(` To change sources or redo setup: POLYMATH_WIZARD=1 polymath-society
25684
+ `);
25685
+ opts.cmd = "serve";
25686
+ opts.grade = true;
25687
+ opts.open = true;
25688
+ } else {
25689
+ const { runWizard: runWizard2 } = await Promise.resolve().then(() => (init_wizard(), wizard_exports));
25690
+ const w = await runWizard2();
25691
+ if (!w) return;
25692
+ opts.cmd = w.cmd;
25693
+ opts.grade = w.grade;
25694
+ opts.overnight = w.overnight;
25695
+ opts.chatOvernight = w.chatOvernight;
25696
+ opts.open = w.open;
25697
+ }
25659
25698
  }
25660
25699
  if (opts.cmd === "grade") {
25661
25700
  const backend = ensureBackend(opts.adapter);
@@ -25756,6 +25795,7 @@ Running the full analysis on ${backend.name === "cli" ? "Claude Code" : "Codex"}
25756
25795
  };
25757
25796
  mbar.setLink(earlyHandle.url);
25758
25797
  const codingLane = mbar.lane("coding");
25798
+ let codingPinned = false;
25759
25799
  const codingDone = runPipeline({
25760
25800
  repoRoot: REPO_ROOT,
25761
25801
  model: opts.model,
@@ -25764,7 +25804,14 @@ Running the full analysis on ${backend.name === "cli" ? "Claude Code" : "Codex"}
25764
25804
  codex: opts.codex,
25765
25805
  idleGapMin: opts.idleGapMin,
25766
25806
  regrade: opts.regrade,
25807
+ onUpToDate: () => {
25808
+ codingPinned = true;
25809
+ progress.coding = { i: 2, total: 1, label: "everything up to date", done: false };
25810
+ earlyHandle.setProgress(progress);
25811
+ codingLane.finish("everything up to date");
25812
+ },
25767
25813
  onStage: (i, total, label, llm) => {
25814
+ if (codingPinned) return;
25768
25815
  progress.coding = { ...progress.coding, i, total, label, done: false };
25769
25816
  earlyHandle.setProgress(progress);
25770
25817
  codingLane.stage(i, total, `${label}${llm ? " (AI)" : ""}`);
@@ -25802,11 +25849,19 @@ Running the full analysis on ${backend.name === "cli" ? "Claude Code" : "Codex"}
25802
25849
  return null;
25803
25850
  }
25804
25851
  chatLane.log(` chat analysis starting over your ${manifest.exports.included.length} approved source(s) \u2014 same engine as the hosted app.`);
25852
+ let chatPinned = false;
25805
25853
  const chat2 = await runChatPipeline({
25806
25854
  repoRoot: REPO_ROOT,
25807
25855
  model: opts.model,
25808
25856
  overnight: chatOvernight,
25857
+ onUpToDate: () => {
25858
+ chatPinned = true;
25859
+ progress.chat = { i: 2, total: 1, label: "everything up to date", done: false };
25860
+ earlyHandle.setProgress(progress);
25861
+ chatLane.finish("everything up to date");
25862
+ },
25809
25863
  onStage: (i, total, label, llm) => {
25864
+ if (chatPinned) return;
25810
25865
  progress.chat = { ...progress.chat, i, total, label, done: false };
25811
25866
  earlyHandle.setProgress(progress);
25812
25867
  chatLane.stage(i, total, `${label}${llm ? " (AI)" : ""}`);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "polymath-society",
3
- "version": "0.2.17",
3
+ "version": "0.2.18",
4
4
  "description": "Deterministic metrics from your local Claude Code / Codex agent logs — parallelism, flow, throughput, projects. Zero LLM, zero server, on-device.",
5
5
  "license": "UNLICENSED",
6
6
  "type": "module",
@@ -40,7 +40,7 @@
40
40
  "build:ts": "node scripts/bundle.mjs",
41
41
  "build:ui": "node scripts/build-ui.mjs",
42
42
  "clean": "rm -rf dist",
43
- "prepublishOnly": "npm run clean && npm run build",
43
+ "prepublishOnly": "node scripts/check-publish-version.mjs && npm run clean && npm run build",
44
44
  "start": "node dist/cli.js",
45
45
  "serve": "node dist/cli.js serve",
46
46
  "typecheck": "tsc -p tsconfig.json --noEmit",