polymath-society 0.2.21 → 0.2.22

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 +47 -7
  2. package/package.json +1 -1
package/dist/cli.js CHANGED
@@ -23745,7 +23745,8 @@ __export(reminderEmail_exports, {
23745
23745
  looksLikeEmail: () => looksLikeEmail,
23746
23746
  queueExportReminder: () => queueExportReminder,
23747
23747
  recordContact: () => recordContact,
23748
- requestEmailReminder: () => requestEmailReminder
23748
+ requestEmailReminder: () => requestEmailReminder,
23749
+ sendReportReadyNow: () => sendReportReadyNow
23749
23750
  });
23750
23751
  function centralBaseUrl() {
23751
23752
  return (process.env.PS_CENTRAL_URL || DEFAULT_CENTRAL_URL).replace(/\/+$/, "");
@@ -23778,6 +23779,20 @@ async function fetchClickedKinds(token, fetchImpl = fetch) {
23778
23779
  return [];
23779
23780
  }
23780
23781
  }
23782
+ async function sendReportReadyNow(email, token, fetchImpl = fetch) {
23783
+ if (!token) return false;
23784
+ try {
23785
+ const res = await fetchImpl(`${centralBaseUrl()}/api/reminders/send-now`, {
23786
+ method: "POST",
23787
+ headers: { "content-type": "application/json" },
23788
+ body: JSON.stringify({ email, token, kind: "report-ready" }),
23789
+ signal: AbortSignal.timeout(1e4)
23790
+ });
23791
+ return res.ok;
23792
+ } catch {
23793
+ return false;
23794
+ }
23795
+ }
23781
23796
  async function queueExportReminder(email, kinds, token = null, fetchImpl = fetch) {
23782
23797
  if (!kinds.length) return null;
23783
23798
  const hours = Math.max(...kinds.map((k) => REMINDER_HOURS[k] ?? 48));
@@ -23960,17 +23975,23 @@ var init_banner = __esm({
23960
23975
  // src/plan.ts
23961
23976
  var plan_exports = {};
23962
23977
  __export(plan_exports, {
23978
+ UNSUPPORTED_FULL_TIERS: () => UNSUPPORTED_FULL_TIERS,
23963
23979
  detectCodexPlan: () => detectCodexPlan,
23964
23980
  detectPlan: () => detectPlan,
23965
23981
  estimateLaneCosts: () => estimateLaneCosts,
23966
23982
  remainingFractions: () => remainingFractions,
23967
23983
  scheduleLanes: () => scheduleLanes,
23984
+ supportsFullAnalysis: () => supportsFullAnalysis,
23968
23985
  tierFromChatgptPlan: () => tierFromChatgptPlan,
23969
23986
  tierFromStrings: () => tierFromStrings
23970
23987
  });
23971
23988
  import { promises as fs36 } from "fs";
23972
23989
  import os9 from "os";
23973
23990
  import path42 from "path";
23991
+ function supportsFullAnalysis(tier) {
23992
+ if (process.env.POLYMATH_FORCE_FULL === "1") return true;
23993
+ return !UNSUPPORTED_FULL_TIERS.includes(tier);
23994
+ }
23974
23995
  function tierFromStrings(...hints) {
23975
23996
  for (const h of hints) {
23976
23997
  if (!h) continue;
@@ -24018,7 +24039,7 @@ async function detectPlan(home = os9.homedir()) {
24018
24039
  return { tier, label: LABEL[tier], windowUsd: WINDOW_USD[tier] };
24019
24040
  }
24020
24041
  function estimateLaneCosts(input) {
24021
- const codingUsd = Math.max(5, Math.round(input.agentLogFiles * 13e-4));
24042
+ const codingUsd = Math.max(5, Math.min(60, Math.round(input.agentLogFiles * 17e-4)));
24022
24043
  const chatUsd = input.chatIncluded ? Math.round(40 + input.exportTotalMB * 0.8) : 0;
24023
24044
  return { codingUsd, chatUsd };
24024
24045
  }
@@ -24053,7 +24074,8 @@ async function remainingFractions(dataRoot, agentLogFiles) {
24053
24074
  return { coding, chat: clamp(1 - chatDone, 0.1, 1) };
24054
24075
  }
24055
24076
  function scheduleLanes(plan, est) {
24056
- const fits = (usd) => usd <= plan.windowUsd * 0.5;
24077
+ const dayShare = plan.tier === "max_5x" || plan.tier === "gpt_team" ? 0.2 : 0.5;
24078
+ const fits = (usd) => usd <= plan.windowUsd * dayShare;
24057
24079
  const coding = fits(est.codingUsd) ? "now" : "overnight";
24058
24080
  const chat = est.chatUsd === 0 || fits(est.chatUsd) ? "now" : "overnight";
24059
24081
  return {
@@ -24067,10 +24089,11 @@ function scheduleLanes(plan, est) {
24067
24089
  chatReason: est.chatUsd === 0 ? "not planned \u2014 no chat sources included" : chat === "now" ? `runs now, alongside coding \u2014 your chat corpus is small enough` : `starts at 2:00 am tonight \u2014 a large chat corpus; this protects your daytime quota`
24068
24090
  };
24069
24091
  }
24070
- var WINDOW_USD, LABEL;
24092
+ var UNSUPPORTED_FULL_TIERS, WINDOW_USD, LABEL;
24071
24093
  var init_plan = __esm({
24072
24094
  "src/plan.ts"() {
24073
24095
  "use strict";
24096
+ UNSUPPORTED_FULL_TIERS = ["pro", "gpt_plus", "gpt_free"];
24074
24097
  WINDOW_USD = {
24075
24098
  max_20x: 300,
24076
24099
  max_5x: 75,
@@ -24487,6 +24510,17 @@ async function runWizard() {
24487
24510
  say();
24488
24511
  say(bold(" Step 3 \xB7 How deep?"));
24489
24512
  say();
24513
+ const { supportsFullAnalysis: supportsFullAnalysis2 } = await Promise.resolve().then(() => (init_plan(), plan_exports));
24514
+ if (!supportsFullAnalysis2(plan.tier)) {
24515
+ say(` ${bold("Proposed schedule")} \u2014 sized to your plan (${plan.label}):`);
24516
+ say();
24517
+ say(` ${bold("Your analysis")} runs now \u2014 everything measured from your logs: words/day, flow state, focus, projects, parallelism`);
24518
+ say(` ${bold("AI sections")} support for your plan is coming soon! Only the AI-graded sections (judgement, agency, taste, growth) won't be visible yet`);
24519
+ say();
24520
+ await ask(` Press Enter to run your analysis`).catch(() => "");
24521
+ say(dim(" On it. The report link appears right away.\n"));
24522
+ return { cmd: "serve", grade: false, overnight: false, chatOvernight: false, open: true };
24523
+ }
24490
24524
  const planBit = plan.label.includes("undetected") ? "your corpus (plan undetected \u2014 scheduling conservatively)" : `your plan (${plan.label}) and your corpus`;
24491
24525
  say(` ${bold("Proposed schedule")} \u2014 sized to ${planBit}:`);
24492
24526
  if (resumed) say(dim(" (an earlier run already processed most of this \u2014 only what's new is scheduled; nothing done is redone)"));
@@ -28400,9 +28434,15 @@ Running the full analysis on ${backend.name === "cli" ? "Claude Code" : "Codex"}
28400
28434
  try {
28401
28435
  const stored = JSON.parse(await fs38.readFile(path44.join(DATA_ROOT, "notify-email.json"), "utf8"));
28402
28436
  if (stored.email) {
28403
- const { requestEmailReminder: requestEmailReminder2 } = await Promise.resolve().then(() => (init_reminderEmail(), reminderEmail_exports));
28404
- const r = await requestEmailReminder2(stored.email, ["report-ready"], 1);
28405
- if (r.ok) codingLane.log(` \u2713 We'll also email ${stored.email} that the report is ready.`);
28437
+ const { requestEmailReminder: requestEmailReminder2, sendReportReadyNow: sendReportReadyNow2 } = await Promise.resolve().then(() => (init_reminderEmail(), reminderEmail_exports));
28438
+ const { ensureReminderState: ensureReminderState2 } = await Promise.resolve().then(() => (init_reminderState(), reminderState_exports));
28439
+ const state = await ensureReminderState2(DATA_ROOT).catch(() => null);
28440
+ if (await sendReportReadyNow2(stored.email, state?.token ?? null)) {
28441
+ codingLane.log(` \u2713 Emailed ${stored.email} \u2014 the report is ready.`);
28442
+ } else {
28443
+ const r = await requestEmailReminder2(stored.email, ["report-ready"], 0);
28444
+ if (r.ok) codingLane.log(` \u2713 We'll email ${stored.email} that the report is ready (within ~15 min).`);
28445
+ }
28406
28446
  }
28407
28447
  } catch {
28408
28448
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "polymath-society",
3
- "version": "0.2.21",
3
+ "version": "0.2.22",
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",