polymath-society 0.2.5 → 0.2.7

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/web/app.js CHANGED
@@ -7279,7 +7279,7 @@ var require_jsx_runtime = __commonJS({
7279
7279
  });
7280
7280
 
7281
7281
  // web/entry.tsx
7282
- var import_react10 = __toESM(require_react(), 1);
7282
+ var import_react11 = __toESM(require_react(), 1);
7283
7283
  var import_client = __toESM(require_client(), 1);
7284
7284
 
7285
7285
  // ../../components/CodeAnalysisView.tsx
@@ -7855,8 +7855,30 @@ function FeedbackSection({
7855
7855
  const api = (0, import_react2.useContext)(FeedbackCtx);
7856
7856
  const ref = (0, import_react2.useRef)(null);
7857
7857
  const [text, setText] = (0, import_react2.useState)("");
7858
+ const [quick, setQuick] = (0, import_react2.useState)("idle");
7858
7859
  const status = api?.statusOf(sectionKey);
7859
7860
  if (!isLocalRuntime()) return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_jsx_runtime2.Fragment, { children });
7861
+ const sendNow = async () => {
7862
+ const t = text.trim();
7863
+ if (!t || quick === "sending") return;
7864
+ setQuick("sending");
7865
+ try {
7866
+ const r = await fetch("/api/feedback/submit", {
7867
+ method: "POST",
7868
+ headers: { "Content-Type": "application/json" },
7869
+ body: JSON.stringify({ reportKind, sectionKey, sectionLabel: label, feedback: t, context: "", evidence: {} })
7870
+ });
7871
+ if (!r.ok) {
7872
+ setQuick("error");
7873
+ return;
7874
+ }
7875
+ setQuick("sent");
7876
+ setText("");
7877
+ setTimeout(() => setQuick("idle"), 4e3);
7878
+ } catch {
7879
+ setQuick("error");
7880
+ }
7881
+ };
7860
7882
  const startGather = () => {
7861
7883
  if (!api) return;
7862
7884
  api.gather({
@@ -7922,13 +7944,22 @@ function FeedbackSection({
7922
7944
  {
7923
7945
  value: text,
7924
7946
  onChange: (e) => setText(e.target.value),
7925
- placeholder: "What's wrong, harsh, missed, or right about this read? Say it however you want \u2014 nothing is sent until you preview and approve it.",
7947
+ onKeyDown: (e) => {
7948
+ if (e.key === "Enter" && !e.shiftKey) {
7949
+ e.preventDefault();
7950
+ void sendNow();
7951
+ }
7952
+ },
7953
+ placeholder: "What's wrong, harsh, missed, or right about this read? Say it however you want \u2014 Enter sends your words right away.",
7926
7954
  className: "min-h-[52px] w-full resize-y rounded-lg border border-line bg-paper px-3 py-2 text-[13px] leading-relaxed text-ink placeholder:text-faint focus:border-accent focus:outline-none"
7927
7955
  }
7928
7956
  ),
7929
- text.trim() && /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "mt-2 flex items-center gap-2.5", children: [
7930
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("button", { onClick: startGather, className: "rounded-lg bg-accent px-3 py-1.5 text-[12px] font-semibold text-white", children: "Gather evidence" }),
7931
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "text-[11px] text-faint", children: "stays on this machine \u2014 review & send later, all at once" })
7957
+ quick === "sent" && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className: "mt-1.5 text-[12px] font-medium text-emerald-600", children: "\u2713 Sent \u2014 thank you. Got more? Just keep writing." }),
7958
+ quick === "error" && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className: "mt-1.5 text-[12px] text-red-600", children: "Couldn't send \u2014 check you're signed in (top right) and try again." }),
7959
+ text.trim() && /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "mt-2 flex flex-wrap items-center gap-2.5", children: [
7960
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("button", { onClick: () => void sendNow(), disabled: quick === "sending", className: "rounded-lg bg-accent px-3.5 py-1.5 text-[12px] font-semibold text-white disabled:opacity-50", children: quick === "sending" ? "Sending\u2026" : "Send" }),
7961
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "text-[11px] text-faint", children: "sends your words + this section's name, instantly" }),
7962
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("button", { onClick: startGather, className: "rounded-lg border border-line px-3 py-1.5 text-[11.5px] text-muted transition-colors hover:text-ink", title: "Runs a local audit of what the analysis missed for this section \u2014 takes minutes, previewed before anything extra is sent", children: "Deep audit first" })
7932
7963
  ] })
7933
7964
  ] })
7934
7965
  ] })
@@ -8175,6 +8206,11 @@ function ReportChatSidebar({ endpoint = "/api/coding/chat" } = {}) {
8175
8206
  window.addEventListener("keydown", onKey);
8176
8207
  return () => window.removeEventListener("keydown", onKey);
8177
8208
  }, []);
8209
+ (0, import_react3.useEffect)(() => {
8210
+ const close = () => setOpen(false);
8211
+ window.addEventListener("polymath:close-ask-drawer", close);
8212
+ return () => window.removeEventListener("polymath:close-ask-drawer", close);
8213
+ }, []);
8178
8214
  const send = async (text) => {
8179
8215
  const t = text.trim();
8180
8216
  if (!t || busy) return;
@@ -8279,7 +8315,7 @@ function ReportChatSidebar({ endpoint = "/api/coding/chat" } = {}) {
8279
8315
 
8280
8316
  // ../../lib/calibration/index.ts
8281
8317
  var DEFAULT_CALIBRATION = {
8282
- version: "2026-07-12.2",
8318
+ version: "2026-07-14.2",
8283
8319
  // = RUBRIC_FINGERPRINT of the shipped npm rubric (packages/coding-analyzer/
8284
8320
  // src/grade/criteria.ts). A unit test fails loud when the rubric changes
8285
8321
  // without this being updated (and re-pushed to the server).
@@ -8368,7 +8404,7 @@ var DEFAULT_CALIBRATION = {
8368
8404
  }
8369
8405
  ],
8370
8406
  codingTiers: {
8371
- push: { median: 300, sigma: 1.121, tag: "estimated \u2014 log-normal fit", source: "Anthropic 2026 Claude Code study (400k sessions): median engaged user ~8 prompts/day at ~35 words \u2014 ~300 directed words/day; tail shape from its actions-per-prompt distribution. AVERAGE over substantial days, cumulative not spiky." },
8407
+ push: { median: 300, sigma: 0.91, tag: "estimated \u2014 log-normal fit", source: "Anthropic 2026 Claude Code study (400k sessions): median engaged user ~8 prompts/day at ~35 words \u2014 ~300 directed words/day; tail: a 1-in-1,000 user AVERAGES ~5k directed words/day (near-daily heavy dictation, clearly below the ~10k single-day record). AVERAGE over substantial days, cumulative not spiky." },
8372
8408
  focus: { median: 0.08, sigma: 0.559, tag: "estimated \u2014 proxy-anchored", source: "median: Anthropic 20h/week engaged-user figure implies ~1h/day of true rapid exchange against an 8h working day; ceiling anchored to the ~4h/day deep-work limit (45% share = 1-in-1,000). AVERAGE share, cumulative not spiky." },
8373
8409
  orchestration: { tag: "estimated \u2014 behavior bands", source: "no published concurrency distribution exists; ceiling anchored to the Claude Code lead's documented 10-15 parallel sessions" }
8374
8410
  },
@@ -8401,12 +8437,18 @@ var DEFAULT_CALIBRATION = {
8401
8437
  line: "the Claude Code lead runs 10\u201315 sessions at once; his #1 tip is 3\u20135 git worktrees in parallel"
8402
8438
  },
8403
8439
  throughput: {
8404
- // Top-0.1% words/day reference lines, anchored to the throughput ladder
8405
- // (THROUGHPUT_LADDER in throughput.ts): score 10 "world-class sustained" =
8406
- // 9k/day, score 11 "superhuman ceiling" = 12k/day. Calibrated to the person's
8407
- // own anchors, not a wild guess but still a target, not a measured population.
8408
- topAvgWordsPerDay: 9e3,
8409
- topPeakWordsPerDay: 12e3,
8440
+ // Two DIFFERENT kinds of line (2026-07-14.2): topAvg is a PERCENTILE
8441
+ // claim — what a 1-in-1,000 user AVERAGES over substantial days (5k/day:
8442
+ // near-daily heavy dictation; a measured top dictating power user
8443
+ // averages ~3.9k). topPeak is NOT a percentileit is the CEILING
8444
+ // reference, the wildest single days on record (~10k: a 14-16h
8445
+ // launch-day marathon), rendered as "wildest single days", never
8446
+ // "top X% peak". An avg-percentile and a peak-percentile can't both be
8447
+ // shown at a same-ish value (avg≈peak reads broken — user call), and a
8448
+ // peak PERCENTILE line is unknowable anyway; the record framing is
8449
+ // honest and keeps the visual gap.
8450
+ topAvgWordsPerDay: 5e3,
8451
+ topPeakWordsPerDay: 1e4,
8410
8452
  benchLabel: "top 0.1%",
8411
8453
  // No published "words typed/day" for heavy users — the real story is OUTPUT.
8412
8454
  loopsHeadline: ">1,000,000 lines of Rust at 99.8% tests passing",
@@ -9864,9 +9906,9 @@ function ThroughputScatterPanel({ data, coaching, minDate }) {
9864
9906
  ] })
9865
9907
  ] }),
9866
9908
  /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "mt-0.5 text-[12px] text-faint", children: [
9867
- "words per day \u2014 a proxy for focus & hard work \xB7 your days in orange (your avg = orange dashed line) \xB7 grey dashed = ",
9909
+ "words per day \u2014 a proxy for focus & hard work \xB7 your days in orange (your avg = orange dashed line) \xB7 grey dashed = the ",
9868
9910
  BEST2.throughput.benchLabel,
9869
- " \xB7 hover a dot for detail"
9911
+ " average and the wildest single days on record \xB7 hover a dot for detail"
9870
9912
  ] }),
9871
9913
  /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { ref: wrapRef, className: "relative mt-3", children: [
9872
9914
  /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { className: "overflow-x-auto", children: /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("svg", { viewBox: `0 0 ${W} ${H}`, className: "w-full min-w-[560px]", role: "img", "aria-label": "throughput by day", children: [
@@ -9876,7 +9918,7 @@ function ThroughputScatterPanel({ data, coaching, minDate }) {
9876
9918
  ] }, i)),
9877
9919
  [
9878
9920
  { v: BEST2.throughput.topAvgWordsPerDay, label: `${BEST2.throughput.benchLabel} avg` },
9879
- { v: BEST2.throughput.topPeakWordsPerDay, label: `${BEST2.throughput.benchLabel} peak` }
9921
+ { v: BEST2.throughput.topPeakWordsPerDay, label: "wildest days on record" }
9880
9922
  ].map((ref, i) => /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("g", { children: [
9881
9923
  /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("line", { x1: L, x2: W - R, y1: y(ref.v), y2: y(ref.v), className: "stroke-ink/40", strokeWidth: 1, strokeDasharray: "4 3" }),
9882
9924
  /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("text", { x: W - R, y: y(ref.v) - 4, textAnchor: "end", className: "fill-muted", fontSize: 9, children: [
@@ -11816,38 +11858,359 @@ function SharePublic({ editing, onToggleEdit } = {}) {
11816
11858
  ] });
11817
11859
  }
11818
11860
 
11861
+ // ../../components/PublicCodingPageShare.tsx
11862
+ var import_react10 = __toESM(require_react());
11863
+ var import_jsx_runtime11 = __toESM(require_jsx_runtime());
11864
+ var THINKING = "__polymath_public_page_thinking__";
11865
+ var rarity = (topPct2) => Math.min(11.2, 5 + 2 * Math.log10(50 / Math.max(0.01, topPct2)));
11866
+ function Radar2({ axes }) {
11867
+ const withPct = axes.filter((a) => a.topPct != null);
11868
+ if (!withPct.length) return null;
11869
+ const cx = 170, cy = 150, R = 104;
11870
+ const pt = (i, r, n2) => {
11871
+ const a = Math.PI * 2 * i / n2 - Math.PI / 2;
11872
+ return [cx + r * Math.cos(a), cy + r * Math.sin(a)];
11873
+ };
11874
+ const n = withPct.length;
11875
+ const ring = (f) => withPct.map((_, i) => pt(i, R * f, n).join(",")).join(" ");
11876
+ const poly = withPct.map((a, i) => pt(i, R * 0.96 * rarity(a.topPct) / 11.2, n).join(",")).join(" ");
11877
+ return /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("svg", { viewBox: "-75 -14 490 330", width: "100%", style: { maxWidth: 490 }, "aria-label": "ability radar", children: [
11878
+ [0.33, 0.66, 1].map((f) => /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("polygon", { points: ring(f), fill: "none", stroke: "var(--line, #e7e2d9)" }, f)),
11879
+ withPct.map((_, i) => {
11880
+ const [x, y] = pt(i, R, n);
11881
+ return /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("line", { x1: cx, y1: cy, x2: x, y2: y, stroke: "var(--line, #e7e2d9)" }, i);
11882
+ }),
11883
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("polygon", { points: poly, fill: "rgba(180,95,63,.14)", stroke: "#b45f3f", strokeWidth: 2 }),
11884
+ withPct.map((a, i) => {
11885
+ const [x, y] = pt(i, R * 0.96 * rarity(a.topPct) / 11.2, n);
11886
+ return /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("circle", { cx: x, cy: y, r: 3, fill: "#b45f3f" }, i);
11887
+ }),
11888
+ withPct.map((a, i) => {
11889
+ const [x, y] = pt(i, R + 24, n);
11890
+ const anchor = Math.abs(x - cx) < 10 ? "middle" : x > cx ? "start" : "end";
11891
+ const above = y < cy;
11892
+ return /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("text", { x, y: above ? y - 8 : y + 4, textAnchor: anchor, fontSize: 11, fill: "#6b6257", children: [
11893
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("tspan", { x, children: a.label }),
11894
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("tspan", { x, dy: 14, fontWeight: 700, fill: "#1a1714", children: [
11895
+ "Top ",
11896
+ a.topPct,
11897
+ "%"
11898
+ ] })
11899
+ ] }, i);
11900
+ })
11901
+ ] });
11902
+ }
11903
+ function buildChips(page) {
11904
+ const specific = [];
11905
+ for (const ax of page.axes) {
11906
+ for (const m of ax.moments) {
11907
+ const snippet = m.what.length > 46 ? `${m.what.slice(0, 46).trim()}\u2026` : m.what;
11908
+ if (m.quote) specific.push(`Remove the "${snippet}" example in ${ax.label} (${m.date})`);
11909
+ else specific.push(`Find different evidence than "${snippet}" for ${ax.label} (${m.date})`);
11910
+ }
11911
+ }
11912
+ const general = [
11913
+ "Hide the swear words in any quote",
11914
+ "Don't show the specific project names",
11915
+ "Get more evidence for the Taste claim"
11916
+ ];
11917
+ return [...specific.slice(0, 2), ...general].slice(0, 3);
11918
+ }
11919
+ function AxisCard({ axis, hidden, onToggle }) {
11920
+ return /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("div", { className: `rounded-xl border border-line p-3 transition-opacity ${hidden ? "bg-canvas opacity-45" : "bg-paper"}`, children: [
11921
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("div", { className: "flex items-center justify-between gap-2", children: [
11922
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("span", { className: "text-[12.5px] font-semibold text-ink", children: [
11923
+ axis.label,
11924
+ " ",
11925
+ axis.topPct != null && /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("span", { className: "text-accent", children: [
11926
+ "Top ",
11927
+ axis.topPct,
11928
+ "%"
11929
+ ] })
11930
+ ] }),
11931
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("button", { onClick: onToggle, className: "rounded-full border border-line px-2.5 py-0.5 text-[10.5px] text-muted transition-colors hover:text-ink", children: hidden ? "Include" : "Hide" })
11932
+ ] }),
11933
+ !hidden && /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)(import_jsx_runtime11.Fragment, { children: [
11934
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("div", { className: "mt-1.5 text-[13px] font-semibold text-ink", children: axis.claim }),
11935
+ axis.read && /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("div", { className: "mt-1 text-[12px] leading-relaxed text-muted", children: axis.read }),
11936
+ axis.numbers.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("div", { className: "mt-2 flex flex-wrap gap-4", children: axis.numbers.map((n, i) => /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("div", { children: [
11937
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("div", { className: "font-serif text-[18px] text-ink", children: n.big }),
11938
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("div", { className: "text-[10.5px] text-muted", children: n.lab })
11939
+ ] }, i)) }),
11940
+ axis.moments.map((m, i) => /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("div", { className: "mt-2 border-t border-dashed border-line pt-2 text-[12px] leading-relaxed", children: [
11941
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("span", { className: "mr-1.5 text-[10.5px] text-faint", children: m.date }),
11942
+ m.what,
11943
+ m.quote && /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("div", { className: "mt-0.5 italic text-muted", children: [
11944
+ "\u201C",
11945
+ m.quote,
11946
+ "\u201D"
11947
+ ] })
11948
+ ] }, i)),
11949
+ axis.edge && /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("div", { className: "mt-2 border-t border-dashed border-line pt-2 text-[11.5px] text-muted", children: [
11950
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("b", { className: "text-ink", children: "Honest edge: " }),
11951
+ axis.edge
11952
+ ] })
11953
+ ] })
11954
+ ] });
11955
+ }
11956
+ function PublicCodingPageShare({ identity, canAuth }) {
11957
+ const [open, setOpen] = (0, import_react10.useState)(false);
11958
+ const [page, setPage] = (0, import_react10.useState)(null);
11959
+ const [loading, setLoading] = (0, import_react10.useState)("idle");
11960
+ const [error, setError] = (0, import_react10.useState)(null);
11961
+ const [hiddenAxes, setHiddenAxes] = (0, import_react10.useState)(/* @__PURE__ */ new Set());
11962
+ const [msgs, setMsgs] = (0, import_react10.useState)([]);
11963
+ const [busy, setBusy] = (0, import_react10.useState)(false);
11964
+ const [sent, setSent] = (0, import_react10.useState)(false);
11965
+ const [chatReport, setChatReport] = (0, import_react10.useState)(null);
11966
+ const [includeChat, setIncludeChat] = (0, import_react10.useState)(true);
11967
+ const openModal = async () => {
11968
+ setOpen(true);
11969
+ setError(null);
11970
+ setSent(false);
11971
+ setLoading("checking");
11972
+ try {
11973
+ window.dispatchEvent(new Event("polymath:close-ask-drawer"));
11974
+ } catch {
11975
+ }
11976
+ try {
11977
+ const r = await fetch("/api/public-coding-page").then((r2) => r2.json());
11978
+ setPage(r.page ?? null);
11979
+ setChatReport(r.chatReport ?? null);
11980
+ } catch {
11981
+ setError("couldn't load your report");
11982
+ }
11983
+ setLoading("idle");
11984
+ };
11985
+ const generate = async () => {
11986
+ setLoading("generating");
11987
+ setError(null);
11988
+ try {
11989
+ const r = await fetch("/api/public-coding-page/generate", { method: "POST" }).then((r2) => r2.json());
11990
+ if (r.page) setPage(r.page);
11991
+ else setError(r.error || "generation failed");
11992
+ } catch {
11993
+ setError("generation failed \u2014 try again");
11994
+ }
11995
+ setLoading("idle");
11996
+ };
11997
+ const send = async (text) => {
11998
+ const t = text.trim();
11999
+ if (!t || busy || !page) return;
12000
+ const base = [...msgs, { role: "user", content: t }];
12001
+ setMsgs([...base, { role: "assistant", content: THINKING }]);
12002
+ setBusy(true);
12003
+ try {
12004
+ const r = await fetch("/api/public-coding-page/edit", {
12005
+ method: "POST",
12006
+ headers: { "content-type": "application/json" },
12007
+ body: JSON.stringify({ page, messages: base })
12008
+ }).then((r2) => r2.json());
12009
+ if (r.page) setPage(r.page);
12010
+ setMsgs((m) => {
12011
+ const c = [...m];
12012
+ c[c.length - 1] = { role: "assistant", content: r.reply || r.error || "Done." };
12013
+ return c;
12014
+ });
12015
+ } catch {
12016
+ setMsgs((m) => {
12017
+ const c = [...m];
12018
+ c[c.length - 1] = { role: "assistant", content: "Something went wrong \u2014 try again." };
12019
+ return c;
12020
+ });
12021
+ }
12022
+ setBusy(false);
12023
+ };
12024
+ const shareWithPolymath = async () => {
12025
+ if (!page) return;
12026
+ setLoading("sending");
12027
+ setError(null);
12028
+ const toSend = { ...page, axes: page.axes.filter((a) => !hiddenAxes.has(a.key)) };
12029
+ try {
12030
+ const r = await fetch("/api/public-coding-page/share", {
12031
+ method: "POST",
12032
+ headers: { "content-type": "application/json" },
12033
+ body: JSON.stringify({ page: toSend, includeChat: includeChat && !!chatReport })
12034
+ }).then((r2) => r2.json());
12035
+ if (r.ok) setSent(r.includedChat ? "both" : "coding");
12036
+ else setError(r.error || "couldn't send");
12037
+ } catch {
12038
+ setError("couldn't send \u2014 try again");
12039
+ }
12040
+ setLoading("idle");
12041
+ };
12042
+ return /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)(import_jsx_runtime11.Fragment, { children: [
12043
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("button", { onClick: openModal, className: "rounded-full bg-ink px-3.5 py-1.5 text-[12px] font-medium text-paper transition-opacity hover:opacity-85", children: "Share report" }),
12044
+ open && /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("div", { className: "fixed inset-0 z-[60] flex items-center justify-center bg-black/30 p-4", onClick: () => setOpen(false), children: /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("div", { className: "flex max-h-[88vh] w-full max-w-[900px] flex-col rounded-2xl border border-line bg-canvas p-5 shadow-xl", onClick: (e) => e.stopPropagation(), children: [
12045
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("h2", { className: "font-serif text-[23px] leading-snug text-ink", children: "We'll get you intros and opportunities based on how good you are." }),
12046
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("div", { className: "mt-1.5 text-[14px] font-semibold text-ink", children: [
12047
+ "Your ",
12048
+ chatReport ? "coding + chat profile" : "coding profile",
12049
+ " \u2014 review before sharing"
12050
+ ] }),
12051
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("div", { className: "mt-0.5 mb-3 text-[11.5px] text-faint", children: "Not a public page. Sending it goes privately to Polymath for opportunity-matching \u2014 nothing gets a public link." }),
12052
+ loading === "checking" && /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("div", { className: "py-10 text-center text-[13px] text-muted", children: "Loading\u2026" }),
12053
+ error && /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("div", { className: "mb-2 rounded-xl bg-amber-50 px-3 py-2 text-[12px] text-amber-800", children: error }),
12054
+ !page && loading !== "checking" && /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("div", { className: "rounded-xl border border-dashed border-line p-8 text-center", children: [
12055
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("div", { className: "text-[13px] text-muted", children: "You haven't generated your coding profile yet." }),
12056
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("button", { onClick: generate, disabled: loading === "generating", className: "mt-3 rounded-full bg-ink px-4 py-1.5 text-[12px] font-medium text-paper disabled:opacity-50", children: loading === "generating" ? "Generating\u2026 (this reads your sessions, ~1-2 min)" : "Generate my report" })
12057
+ ] }),
12058
+ page && /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("div", { className: "grid min-h-0 flex-1 gap-4 md:grid-cols-[1fr_300px]", children: [
12059
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("div", { className: "min-h-0 space-y-3 overflow-y-auto pr-1", children: [
12060
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("div", { className: "text-[11px] font-semibold uppercase tracking-[0.1em] text-faint", children: "Coding profile" }),
12061
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("div", { className: "rounded-xl border border-line bg-paper p-3.5 font-serif text-[15px] leading-relaxed text-ink", children: page.verdict }),
12062
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("div", { className: "flex justify-center", children: /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(Radar2, { axes: page.axes }) }),
12063
+ page.axes.map((a) => /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(AxisCard, { axis: a, hidden: hiddenAxes.has(a.key), onToggle: () => setHiddenAxes((s) => {
12064
+ const n = new Set(s);
12065
+ n.has(a.key) ? n.delete(a.key) : n.add(a.key);
12066
+ return n;
12067
+ }) }, a.key)),
12068
+ page.moreNumbers.map((sec, i) => /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("div", { className: "rounded-xl border border-line bg-paper p-3", children: [
12069
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("div", { className: "text-[12.5px] font-semibold text-ink", children: sec.section }),
12070
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("div", { className: "mt-1.5 grid grid-cols-2 gap-x-4 gap-y-1 text-[12px]", children: sec.stats.map((s, j) => /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("div", { className: "flex items-baseline justify-between gap-2", children: [
12071
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("span", { className: "text-faint", children: s.lab }),
12072
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("span", { className: "font-medium text-ink", children: s.big })
12073
+ ] }, j)) })
12074
+ ] }, i)),
12075
+ chatReport && /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)(import_jsx_runtime11.Fragment, { children: [
12076
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("div", { className: "flex items-center justify-between gap-2 pt-2", children: [
12077
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("h3", { className: "font-serif text-[19px] text-ink", children: "Your chat profile" }),
12078
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("button", { onClick: () => setIncludeChat((v) => !v), className: "rounded-full border border-line px-2.5 py-0.5 text-[10.5px] text-muted transition-colors hover:text-ink", children: includeChat ? "Exclude from send" : "Include in send" })
12079
+ ] }),
12080
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("div", { className: "text-[10.5px] text-faint", children: "Sent with the coding profile. This is exactly the version from the Public report tab \u2014 edit it there." }),
12081
+ includeChat ? /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("div", { className: "rounded-xl border border-line bg-paper p-3", children: /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(PublicReportView, { r: chatReport }) }) : /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("div", { className: "rounded-xl border border-dashed border-line bg-canvas p-3 text-[12px] text-muted", children: "Excluded \u2014 only the coding profile will be sent." })
12082
+ ] })
12083
+ ] }),
12084
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("div", { className: "flex min-h-0 flex-col rounded-xl border border-line bg-paper p-3", children: [
12085
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("div", { className: "text-[12.5px] font-semibold text-ink", children: "Change it by talking to it" }),
12086
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("div", { className: "mt-0.5 text-[10.5px] text-faint", children: "Redact anything, or ask it to find different evidence. It can't invent achievements or change any number." }),
12087
+ msgs.length === 0 && /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("div", { className: "mt-2 flex flex-col gap-1.5", children: buildChips(page).map((c, i) => /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("button", { onClick: () => send(c), disabled: busy, className: "text-left rounded-lg border border-line bg-canvas px-2.5 py-1.5 text-[10.5px] leading-snug text-muted transition-colors hover:text-ink disabled:opacity-40", children: c }, i)) }),
12088
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("div", { className: "mt-2 min-h-0 flex-1 space-y-1.5 overflow-y-auto", children: msgs.map((m, i) => /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("div", { className: m.role === "user" ? "flex justify-end" : "flex justify-start", children: m.content === THINKING ? /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(ThinkingBubble, {}) : /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("div", { className: `max-w-[90%] rounded-xl px-2.5 py-1 text-[11.5px] leading-relaxed ${m.role === "user" ? "bg-ink text-paper" : "bg-canvas text-ink"}`, children: m.content }) }, i)) }),
12089
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(ChatInput, { busy, onSend: send })
12090
+ ] })
12091
+ ] }),
12092
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("div", { className: "mt-3 flex items-center justify-end gap-2 border-t border-line pt-3", children: sent ? /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("span", { className: "text-[12.5px] font-medium text-emerald-600", children: [
12093
+ "\u2713 Sent to Polymath \u2014 ",
12094
+ sent === "both" ? "coding + chat profile, " : "",
12095
+ "private, not a public page."
12096
+ ] }) : /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)(import_jsx_runtime11.Fragment, { children: [
12097
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("button", { onClick: () => setOpen(false), className: "rounded-full px-3.5 py-1.5 text-[12px] text-muted transition-colors hover:text-ink", children: "Cancel" }),
12098
+ identity ? /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("button", { onClick: shareWithPolymath, disabled: !page || loading === "sending", className: "rounded-full bg-ink px-4 py-1.5 text-[12px] font-medium text-paper transition-opacity hover:opacity-85 disabled:opacity-50", children: loading === "sending" ? "Sending\u2026" : "Share with Polymath for opportunities" }) : canAuth ? /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("a", { href: "/auth/login", target: "_blank", rel: "noreferrer", className: "rounded-full bg-ink px-4 py-1.5 text-[12px] font-medium text-paper", children: "Sign in with Google to share" }) : null
12099
+ ] }) })
12100
+ ] }) })
12101
+ ] });
12102
+ }
12103
+ function ThinkingBubble() {
12104
+ return /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("div", { className: "polymath-edit-thinking max-w-[92%] rounded-2xl border border-line bg-canvas px-3 py-2 text-[11px] text-muted shadow-sm", children: [
12105
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("span", { className: "polymath-edit-thinking__bar", "aria-hidden": "true" }),
12106
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("span", { className: "relative inline-flex items-center gap-2", children: [
12107
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("span", { className: "font-medium text-ink", children: "Checking evidence" }),
12108
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("span", { className: "inline-flex items-center gap-1", "aria-label": "editing", children: [
12109
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("span", {}),
12110
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("span", {}),
12111
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("span", {})
12112
+ ] })
12113
+ ] }),
12114
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("style", { children: `
12115
+ .polymath-edit-thinking {
12116
+ position: relative;
12117
+ overflow: hidden;
12118
+ }
12119
+ .polymath-edit-thinking__bar {
12120
+ position: absolute;
12121
+ inset: 0;
12122
+ background: linear-gradient(90deg, transparent, rgba(180, 95, 63, 0.10), transparent);
12123
+ transform: translateX(-110%);
12124
+ animation: polymath-edit-scan 1.45s ease-in-out infinite;
12125
+ }
12126
+ .polymath-edit-thinking span[aria-label="editing"] span {
12127
+ width: 4px;
12128
+ height: 4px;
12129
+ border-radius: 999px;
12130
+ background: currentColor;
12131
+ opacity: .35;
12132
+ animation: polymath-edit-dot 1.05s ease-in-out infinite;
12133
+ }
12134
+ .polymath-edit-thinking span[aria-label="editing"] span:nth-child(2) { animation-delay: .15s; }
12135
+ .polymath-edit-thinking span[aria-label="editing"] span:nth-child(3) { animation-delay: .30s; }
12136
+ @keyframes polymath-edit-scan {
12137
+ 0% { transform: translateX(-110%); }
12138
+ 55%, 100% { transform: translateX(110%); }
12139
+ }
12140
+ @keyframes polymath-edit-dot {
12141
+ 0%, 80%, 100% { opacity: .30; transform: translateY(0); }
12142
+ 40% { opacity: .95; transform: translateY(-2px); }
12143
+ }
12144
+ @media (prefers-reduced-motion: reduce) {
12145
+ .polymath-edit-thinking__bar,
12146
+ .polymath-edit-thinking span[aria-label="editing"] span {
12147
+ animation: none;
12148
+ }
12149
+ }
12150
+ ` })
12151
+ ] });
12152
+ }
12153
+ function ChatInput({ busy, onSend }) {
12154
+ const [text, setText] = (0, import_react10.useState)("");
12155
+ const go = () => {
12156
+ if (text.trim()) {
12157
+ onSend(text);
12158
+ setText("");
12159
+ }
12160
+ };
12161
+ return /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("div", { className: "mt-2 flex items-end gap-1.5", children: [
12162
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
12163
+ "textarea",
12164
+ {
12165
+ value: text,
12166
+ onChange: (e) => setText(e.target.value),
12167
+ onKeyDown: (e) => {
12168
+ if (e.key === "Enter" && !e.shiftKey) {
12169
+ e.preventDefault();
12170
+ go();
12171
+ }
12172
+ },
12173
+ rows: 2,
12174
+ placeholder: "or say it your own way\u2026",
12175
+ className: "min-h-[36px] flex-1 resize-none rounded-lg border border-line bg-canvas px-2.5 py-1.5 text-[11px] text-ink outline-none focus:border-ink/40"
12176
+ }
12177
+ ),
12178
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("button", { onClick: go, disabled: busy || !text.trim(), className: "rounded-lg bg-ink px-3 py-1.5 text-[11px] font-medium text-paper disabled:opacity-40", children: busy ? "..." : "Send" })
12179
+ ] });
12180
+ }
12181
+
11819
12182
  // web/entry.tsx
11820
- var import_jsx_runtime11 = __toESM(require_jsx_runtime(), 1);
12183
+ var import_jsx_runtime12 = __toESM(require_jsx_runtime(), 1);
11821
12184
  function PublicReportTab() {
11822
- const [loaded, setLoaded] = (0, import_react10.useState)(false);
11823
- const [footprint, setFootprint] = (0, import_react10.useState)(null);
11824
- const [report, setReport] = (0, import_react10.useState)(null);
11825
- const [editing, setEditing] = (0, import_react10.useState)(false);
11826
- (0, import_react10.useEffect)(() => {
12185
+ const [loaded, setLoaded] = (0, import_react11.useState)(false);
12186
+ const [footprint, setFootprint] = (0, import_react11.useState)(null);
12187
+ const [report, setReport] = (0, import_react11.useState)(null);
12188
+ const [editing, setEditing] = (0, import_react11.useState)(false);
12189
+ (0, import_react11.useEffect)(() => {
11827
12190
  fetch("/api/public-report").then((r) => r.ok ? r.json() : null).then((d) => {
11828
12191
  setReport(d?.report ?? null);
11829
12192
  setFootprint(d?.footprint ?? null);
11830
12193
  }).catch(() => {
11831
12194
  }).finally(() => setLoaded(true));
11832
12195
  }, []);
11833
- if (!loaded) return /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("div", { className: "py-16 text-center text-[13px] text-faint", children: "Loading your public report\u2026" });
12196
+ if (!loaded) return /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("div", { className: "py-16 text-center text-[13px] text-faint", children: "Loading your public report\u2026" });
11834
12197
  if (!report) {
11835
- return /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("div", { className: "rounded-2xl border border-dashed border-line bg-paper/60 px-6 py-16 text-center", children: [
11836
- /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("h2", { className: "font-serif text-[20px] text-ink", children: "No public report yet" }),
11837
- /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("p", { className: "mx-auto mt-2 max-w-[460px] text-[13.5px] leading-relaxed text-muted", children: [
12198
+ return /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("div", { className: "rounded-2xl border border-dashed border-line bg-paper/60 px-6 py-16 text-center", children: [
12199
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("h2", { className: "font-serif text-[20px] text-ink", children: "No public report yet" }),
12200
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("p", { className: "mx-auto mt-2 max-w-[460px] text-[13.5px] leading-relaxed text-muted", children: [
11838
12201
  "Your shareable report is distilled from the full analysis. Run",
11839
12202
  " ",
11840
- /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("code", { className: "rounded bg-canvas px-1.5 py-0.5 text-[12px]", children: "polymath-analyzer serve --grade" }),
12203
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("code", { className: "rounded bg-canvas px-1.5 py-0.5 text-[12px]", children: "polymath-analyzer serve --grade" }),
11841
12204
  " ",
11842
12205
  "(or pick a full-analysis depth in the wizard) and it will appear here."
11843
12206
  ] })
11844
12207
  ] });
11845
12208
  }
11846
- return /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)(import_jsx_runtime11.Fragment, { children: [
11847
- /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(SharePublic, { editing, onToggleEdit: () => setEditing((e) => !e) }),
11848
- /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("div", { className: editing ? "grid grid-cols-1 gap-5 lg:grid-cols-[1fr_360px]" : "", children: [
11849
- /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("div", { className: "min-w-0", children: /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(PublicReportView, { r: report, footprint }) }),
11850
- editing && /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("div", { className: "lg:sticky lg:top-6 lg:h-[calc(100vh-3rem)]", children: /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(PublicReportEditor, { onUpdate: setReport }) })
12209
+ return /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(import_jsx_runtime12.Fragment, { children: [
12210
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(SharePublic, { editing, onToggleEdit: () => setEditing((e) => !e) }),
12211
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("div", { className: editing ? "grid grid-cols-1 gap-5 lg:grid-cols-[1fr_360px]" : "", children: [
12212
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("div", { className: "min-w-0", children: /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(PublicReportView, { r: report, footprint }) }),
12213
+ editing && /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("div", { className: "lg:sticky lg:top-6 lg:h-[calc(100vh-3rem)]", children: /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(PublicReportEditor, { onUpdate: setReport }) })
11851
12214
  ] })
11852
12215
  ] });
11853
12216
  }
@@ -11861,27 +12224,27 @@ function LaneRow({ name, l }) {
11861
12224
  if (l.skipped) return null;
11862
12225
  const pct = Math.round(laneFrac(l) * 100);
11863
12226
  const detail = l.done ? l.failed ? `${l.failed} stage${l.failed === 1 ? "" : "s"} failed. A rerun resumes them.` : "done \u2713" : `${l.label}${l.within ? ` \xB7 ${l.within.done}/${l.within.total}` : ""}${l.overnight ? " \xB7 heavy grading runs at 2:00 am tonight" : ""}`;
11864
- return /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("div", { className: "flex min-w-0 flex-1 basis-full items-center gap-2 sm:basis-auto", children: [
11865
- /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("span", { className: "w-12 shrink-0 text-[11.5px] font-medium text-ink", children: name }),
11866
- /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("div", { className: "h-1.5 w-24 shrink-0 overflow-hidden rounded-full bg-canvas", children: /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("div", { className: "h-full rounded-full bg-ink transition-all duration-700", style: { width: `${pct}%` } }) }),
11867
- /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("span", { className: "w-9 shrink-0 text-[12px] font-semibold tabular-nums text-ink", children: [
12227
+ return /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("div", { className: "flex min-w-0 flex-1 basis-full items-center gap-2 sm:basis-auto", children: [
12228
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("span", { className: "w-12 shrink-0 text-[11.5px] font-medium text-ink", children: name }),
12229
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("div", { className: "h-1.5 w-24 shrink-0 overflow-hidden rounded-full bg-canvas", children: /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("div", { className: "h-full rounded-full bg-ink transition-all duration-700", style: { width: `${pct}%` } }) }),
12230
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("span", { className: "w-9 shrink-0 text-[12px] font-semibold tabular-nums text-ink", children: [
11868
12231
  pct,
11869
12232
  "%"
11870
12233
  ] }),
11871
- /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("span", { className: "min-w-0 text-[11.5px] text-muted", children: detail })
12234
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("span", { className: "min-w-0 text-[11.5px] text-muted", children: detail })
11872
12235
  ] });
11873
12236
  }
11874
12237
  function PipelineProgressBanner() {
11875
- const [p, setP] = (0, import_react10.useState)(null);
11876
- const [landedSinceLoad, setLandedSinceLoad] = (0, import_react10.useState)(false);
11877
- (0, import_react10.useEffect)(() => {
12238
+ const [p, setP] = (0, import_react11.useState)(null);
12239
+ const [landedSinceLoad, setLandedSinceLoad] = (0, import_react11.useState)(false);
12240
+ (0, import_react11.useEffect)(() => {
11878
12241
  let alive = true;
11879
- const sawRunning = {};
12242
+ let baseRev = null;
11880
12243
  const poll = () => fetch("/api/progress").then((r) => r.ok ? r.json() : null).then((j) => {
11881
12244
  if (!alive || !j) return;
11882
- for (const [name, l] of Object.entries({ coding: j.coding, chat: j.chat })) {
11883
- if (l && !l.done && !l.skipped) sawRunning[name] = true;
11884
- if (l && l.done && sawRunning[name]) setLandedSinceLoad(true);
12245
+ if (typeof j.profileRev === "number") {
12246
+ if (baseRev == null) baseRev = j.profileRev;
12247
+ else if (j.profileRev > baseRev) setLandedSinceLoad(true);
11885
12248
  }
11886
12249
  setP(j);
11887
12250
  }).catch(() => {
@@ -11897,17 +12260,17 @@ function PipelineProgressBanner() {
11897
12260
  const anyRunning = visible.some(([, l]) => !l.done);
11898
12261
  const anyOvernight = visible.some(([, l]) => !l.done && l.overnight);
11899
12262
  if (!visible.length || !anyRunning && !landedSinceLoad) return null;
11900
- return /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("div", { className: "mb-4 rounded-xl border border-line bg-paper px-4 py-3 text-[12.5px] text-muted", children: [
11901
- /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("div", { className: "mb-1.5 flex items-center gap-2", children: [
11902
- anyRunning && /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("span", { className: "inline-block h-2 w-2 animate-pulse rounded-full bg-amber-500", "aria-hidden": true }),
11903
- /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("span", { className: "font-medium text-ink", children: !anyRunning ? "New results just landed." : anyOvernight ? "Part of your analysis is scheduled for 2:00 am tonight. This page fills in as stages finish." : "Your analysis is still running. This page fills in as stages finish." }),
11904
- landedSinceLoad && /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("button", { onClick: () => window.location.reload(), className: "ml-auto rounded-full bg-ink px-3 py-1 text-[11.5px] font-medium text-paper transition-opacity hover:opacity-85", children: "Load the new results" })
12263
+ return /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("div", { className: "mb-4 rounded-xl border border-line bg-paper px-4 py-3 text-[12.5px] text-muted", children: [
12264
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("div", { className: "mb-1.5 flex items-center gap-2", children: [
12265
+ anyRunning && /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("span", { className: "inline-block h-2 w-2 animate-pulse rounded-full bg-amber-500", "aria-hidden": true }),
12266
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("span", { className: "font-medium text-ink", children: !anyRunning ? "New results just landed." : anyOvernight ? "Part of your analysis is scheduled for 2:00 am tonight. This page fills in as stages finish." : "Your analysis is still running. This page fills in as stages finish." }),
12267
+ landedSinceLoad && /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("button", { onClick: () => window.location.reload(), className: "ml-auto rounded-full bg-ink px-3 py-1 text-[11.5px] font-medium text-paper transition-opacity hover:opacity-85", children: "Load the new results" })
11905
12268
  ] }),
11906
- /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("div", { className: "flex flex-wrap items-center gap-x-6 gap-y-1.5", children: visible.map(([name, l]) => /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(LaneRow, { name, l }, name)) }),
11907
- anyOvernight && /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("div", { className: "mt-2 rounded-lg bg-canvas px-3 py-2 text-[12px] text-ink", children: [
11908
- /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("span", { className: "font-medium", children: "For the overnight part to finish:" }),
11909
- /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("span", { className: "ml-2", children: "1. Keep the laptop plugged in." }),
11910
- /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("span", { className: "ml-3", children: "2. Keep the lid open. A closed lid means sleep, and the run stalls until morning." })
12269
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("div", { className: "flex flex-wrap items-center gap-x-6 gap-y-1.5", children: visible.map(([name, l]) => /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(LaneRow, { name, l }, name)) }),
12270
+ anyOvernight && /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("div", { className: "mt-2 rounded-lg bg-canvas px-3 py-2 text-[12px] text-ink", children: [
12271
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("span", { className: "font-medium", children: "For the overnight part to finish:" }),
12272
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("span", { className: "ml-2", children: "1. Keep the laptop plugged in." }),
12273
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("span", { className: "ml-3", children: "2. Keep the lid open. A closed lid means sleep, and the run stalls until morning." })
11911
12274
  ] })
11912
12275
  ] });
11913
12276
  }
@@ -11916,9 +12279,54 @@ var TABS = [
11916
12279
  { key: "chat", label: "Chat analysis" },
11917
12280
  { key: "public", label: "Public report" }
11918
12281
  ];
12282
+ function ChatTab() {
12283
+ const [state, setState] = (0, import_react11.useState)("loading");
12284
+ const [links, setLinks] = (0, import_react11.useState)([]);
12285
+ (0, import_react11.useEffect)(() => {
12286
+ fetch("/api/exports-manifest").then((r) => r.ok ? r.json() : null).then((j) => {
12287
+ setLinks(j?.links ?? []);
12288
+ setState(j?.connectedKinds?.length ? "connected" : "empty");
12289
+ }).catch(() => setState("connected"));
12290
+ }, []);
12291
+ if (state === "loading") return null;
12292
+ if (state === "connected") return /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(DetailedDataView, {});
12293
+ return /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("div", { className: "rounded-2xl border border-line bg-paper p-6", children: [
12294
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("div", { className: "font-serif text-[19px] text-ink", children: "No chat exports connected yet" }),
12295
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("p", { className: "mt-1.5 max-w-[62ch] text-[13px] leading-relaxed text-muted", children: [
12296
+ "This tab analyzes your ChatGPT, claude.ai, or Notion history the same way the Code tab analyzes your Claude Code sessions. Request an export below, then run ",
12297
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("code", { className: "rounded bg-canvas px-1.5 py-0.5 text-[12px]", children: "polymath-society" }),
12298
+ " again in your terminal \u2014 it finds the downloaded zip automatically and adds it to your report."
12299
+ ] }),
12300
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("div", { className: "mt-4 space-y-2.5", children: links.filter((l) => l.requestUrl).map((l) => /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(
12301
+ "a",
12302
+ {
12303
+ href: l.requestUrl,
12304
+ target: "_blank",
12305
+ rel: "noreferrer",
12306
+ className: "flex items-center justify-between gap-3 rounded-xl border border-line bg-canvas px-4 py-3 transition-colors hover:border-accent",
12307
+ children: [
12308
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("div", { children: [
12309
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("div", { className: "text-[13px] font-semibold text-ink", children: [
12310
+ "Request my ",
12311
+ l.label,
12312
+ " export"
12313
+ ] }),
12314
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("div", { className: "mt-0.5 text-[11.5px] text-faint", children: [
12315
+ l.buttonPath,
12316
+ " \xB7 ready in ",
12317
+ l.eta
12318
+ ] })
12319
+ ] }),
12320
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("span", { className: "shrink-0 text-[12px] font-medium text-accent", children: "Open \u2192" })
12321
+ ]
12322
+ },
12323
+ l.kind
12324
+ )) })
12325
+ ] });
12326
+ }
11919
12327
  function Shell() {
11920
- const [meta, setMeta] = (0, import_react10.useState)(null);
11921
- const [tab, setTab] = (0, import_react10.useState)(() => {
12328
+ const [meta, setMeta] = (0, import_react11.useState)(null);
12329
+ const [tab, setTab] = (0, import_react11.useState)(() => {
11922
12330
  const h = (typeof window !== "undefined" ? window.location.hash : "").replace("#", "");
11923
12331
  return h === "chat" || h === "public" ? h : "coding";
11924
12332
  });
@@ -11929,10 +12337,8 @@ function Shell() {
11929
12337
  } catch {
11930
12338
  }
11931
12339
  };
11932
- const [shareState, setShareState] = (0, import_react10.useState)("idle");
11933
- const [shareMsg, setShareMsg] = (0, import_react10.useState)("");
11934
- const [rubricNudge, setRubricNudge] = (0, import_react10.useState)(null);
11935
- (0, import_react10.useEffect)(() => {
12340
+ const [rubricNudge, setRubricNudge] = (0, import_react11.useState)(null);
12341
+ (0, import_react11.useEffect)(() => {
11936
12342
  fetch("/api/config/calibration").then((r) => r.ok ? r.json() : null).then((cal) => {
11937
12343
  if (cal?.source === "central" && cal.localRubricVersion && cal.doc?.rubricVersion && cal.localRubricVersion !== cal.doc.rubricVersion) {
11938
12344
  setRubricNudge(`A newer grading rubric is published (${cal.doc.rubricVersion} \u2014 this install has ${cal.localRubricVersion}). Update polymath-analyzer and re-grade to stay comparable.`);
@@ -11941,7 +12347,7 @@ function Shell() {
11941
12347
  });
11942
12348
  }, []);
11943
12349
  const refreshMeta = () => fetch("/meta.json").then((r) => r.ok ? r.json() : null).then(setMeta).catch(() => setMeta(null));
11944
- (0, import_react10.useEffect)(() => {
12350
+ (0, import_react11.useEffect)(() => {
11945
12351
  refreshMeta();
11946
12352
  const onFocus = () => refreshMeta();
11947
12353
  window.addEventListener("focus", onFocus);
@@ -11952,63 +12358,33 @@ function Shell() {
11952
12358
  });
11953
12359
  refreshMeta();
11954
12360
  };
11955
- const share = async () => {
11956
- if (shareState === "sharing") return;
11957
- setShareState("sharing");
11958
- setShareMsg("");
11959
- try {
11960
- const r = await fetch("/share", {
11961
- method: "POST",
11962
- headers: { "content-type": "application/json" },
11963
- body: JSON.stringify({ all: true, name: meta?.identity?.name || void 0 })
11964
- });
11965
- const j = await r.json().catch(() => ({}));
11966
- if (r.ok && j.ok) {
11967
- setShareState("shared");
11968
- setShareMsg(`Shared ${Array.isArray(j.shared) ? j.shared.length : ""} sections`);
11969
- } else {
11970
- setShareState("error");
11971
- setShareMsg(j.error || `sharing failed (${r.status})`);
11972
- }
11973
- } catch (e) {
11974
- setShareState("error");
11975
- setShareMsg(e.message || "sharing failed");
11976
- }
11977
- };
11978
12361
  const identity = meta?.identity;
11979
12362
  const canAuth = meta?.capabilities?.auth !== false;
11980
- return /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)(import_jsx_runtime11.Fragment, { children: [
11981
- /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("div", { className: "mb-6 flex flex-wrap items-center justify-between gap-3 border-b border-line pb-4", children: [
11982
- /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("div", { children: [
11983
- /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("div", { className: "text-[15px] font-semibold text-ink", children: "Your coding analysis" }),
11984
- /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("div", { className: "text-[11.5px] text-faint", children: "computed on this machine \xB7 nothing leaves it without your say-so" })
12363
+ return /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(import_jsx_runtime12.Fragment, { children: [
12364
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("div", { className: "mb-6 flex flex-wrap items-center justify-between gap-3 border-b border-line pb-4", children: [
12365
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("div", { children: [
12366
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("div", { className: "text-[15px] font-semibold text-ink", children: "Your coding analysis" }),
12367
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("div", { className: "text-[11.5px] text-faint", children: "computed on this machine \xB7 nothing leaves it without your say-so" })
11985
12368
  ] }),
11986
- /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("div", { className: "flex items-center gap-2", children: [
11987
- identity ? /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)(import_jsx_runtime11.Fragment, { children: [
11988
- /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("span", { className: "rounded-full bg-paper px-3 py-1 text-[12px] text-muted", title: identity.email, children: identity.name || identity.email }),
11989
- /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("button", { onClick: signOut, className: "rounded-full px-2 py-1 text-[11.5px] text-faint transition-colors hover:text-ink", children: "Sign out" })
11990
- ] }) : canAuth ? /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("a", { href: "/auth/login", target: "_blank", rel: "noreferrer", className: "rounded-full border border-line bg-paper px-3.5 py-1.5 text-[12px] font-medium text-ink transition-colors hover:bg-canvas", children: "Sign in with Google" }) : null,
11991
- /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
11992
- "button",
11993
- {
11994
- onClick: share,
11995
- disabled: shareState === "sharing",
11996
- className: "rounded-full bg-ink px-3.5 py-1.5 text-[12px] font-medium text-paper transition-opacity hover:opacity-85 disabled:opacity-50",
11997
- children: shareState === "sharing" ? "Sharing\u2026" : shareState === "shared" ? "Shared \u2713" : "Share report"
11998
- }
11999
- )
12369
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("div", { className: "flex items-center gap-2", children: [
12370
+ identity ? /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(import_jsx_runtime12.Fragment, { children: [
12371
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("span", { className: "rounded-full bg-paper px-3 py-1 text-[12px] text-muted", title: identity.email, children: identity.name || identity.email }),
12372
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("button", { onClick: signOut, className: "rounded-full px-2 py-1 text-[11.5px] text-faint transition-colors hover:text-ink", children: "Sign out" })
12373
+ ] }) : canAuth ? /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("a", { href: "/auth/login", target: "_blank", rel: "noreferrer", className: "inline-flex items-center gap-2 rounded-full border border-line bg-paper px-3.5 py-1.5 text-[12px] font-medium text-ink transition-colors hover:bg-canvas", children: [
12374
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("svg", { width: "14", height: "14", viewBox: "0 0 48 48", "aria-hidden": "true", children: [
12375
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("path", { fill: "#EA4335", d: "M24 9.5c3.54 0 6.71 1.22 9.21 3.6l6.85-6.85C35.9 2.38 30.47 0 24 0 14.62 0 6.51 5.38 2.56 13.22l7.98 6.19C12.43 13.72 17.74 9.5 24 9.5z" }),
12376
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("path", { fill: "#4285F4", d: "M46.98 24.55c0-1.57-.15-3.09-.38-4.55H24v9.02h12.94c-.58 2.96-2.26 5.48-4.78 7.18l7.73 6c4.51-4.18 7.09-10.36 7.09-17.65z" }),
12377
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("path", { fill: "#FBBC05", d: "M10.53 28.59c-.48-1.45-.76-2.99-.76-4.59s.27-3.14.76-4.59l-7.98-6.19C.92 16.46 0 20.12 0 24c0 3.88.92 7.54 2.56 10.78l7.97-6.19z" }),
12378
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("path", { fill: "#34A853", d: "M24 48c6.48 0 11.93-2.13 15.89-5.81l-7.73-6c-2.15 1.45-4.92 2.3-8.16 2.3-6.26 0-11.57-4.22-13.47-9.91l-7.98 6.19C6.51 42.62 14.62 48 24 48z" })
12379
+ ] }),
12380
+ "Sign in with Google"
12381
+ ] }) : null,
12382
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(PublicCodingPageShare, { identity: identity ?? null, canAuth })
12000
12383
  ] })
12001
12384
  ] }),
12002
- rubricNudge && /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("div", { className: "mb-4 rounded-xl bg-amber-50 px-4 py-2.5 text-[12.5px] text-amber-800", children: rubricNudge }),
12003
- shareMsg && /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("div", { className: `mb-4 rounded-xl px-4 py-2.5 text-[12.5px] ${shareState === "error" ? "bg-amber-50 text-amber-800" : "bg-paper text-muted"}`, children: [
12004
- shareMsg,
12005
- shareState === "error" && /sign in/i.test(shareMsg) && !identity && canAuth ? /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)(import_jsx_runtime11.Fragment, { children: [
12006
- " ",
12007
- /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("a", { href: "/auth/login", target: "_blank", rel: "noreferrer", className: "font-medium underline", children: "Sign in" })
12008
- ] }) : null
12009
- ] }),
12010
- /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(PipelineProgressBanner, {}),
12011
- /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("div", { className: "mb-6 flex items-center gap-1 rounded-full border border-line bg-paper p-1", role: "tablist", "aria-label": "Report sections", children: TABS.map((t) => /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
12385
+ rubricNudge && /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("div", { className: "mb-4 rounded-xl bg-amber-50 px-4 py-2.5 text-[12.5px] text-amber-800", children: rubricNudge }),
12386
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(PipelineProgressBanner, {}),
12387
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("div", { className: "mb-6 flex items-center gap-1 rounded-full border border-line bg-paper p-1", role: "tablist", "aria-label": "Report sections", children: TABS.map((t) => /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
12012
12388
  "button",
12013
12389
  {
12014
12390
  role: "tab",
@@ -12019,13 +12395,13 @@ function Shell() {
12019
12395
  },
12020
12396
  t.key
12021
12397
  )) }),
12022
- tab === "coding" && /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(CodeAnalysisView, {}),
12023
- tab === "chat" && /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(DetailedDataView, {}),
12024
- tab === "public" && /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(PublicReportTab, {})
12398
+ tab === "coding" && /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(CodeAnalysisView, {}),
12399
+ tab === "chat" && /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(ChatTab, {}),
12400
+ tab === "public" && /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(PublicReportTab, {})
12025
12401
  ] });
12026
12402
  }
12027
12403
  var el = document.getElementById("root");
12028
- if (el) (0, import_client.createRoot)(el).render(/* @__PURE__ */ (0, import_jsx_runtime11.jsx)(Shell, {}));
12404
+ if (el) (0, import_client.createRoot)(el).render(/* @__PURE__ */ (0, import_jsx_runtime12.jsx)(Shell, {}));
12029
12405
  /*! Bundled license information:
12030
12406
 
12031
12407
  react/cjs/react.production.min.js: