standout 0.6.0 → 0.7.0

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 (3) hide show
  1. package/README.md +29 -6
  2. package/dist/cli.js +692 -310
  3. package/package.json +2 -1
package/dist/cli.js CHANGED
@@ -3,7 +3,7 @@ var __toBinaryNode = Uint8Array.fromBase64 || ((base64) => new Uint8Array(Buffer
3
3
 
4
4
  // src/cli.ts
5
5
  import Anthropic from "@anthropic-ai/sdk";
6
- import chalk3 from "chalk";
6
+ import chalk4 from "chalk";
7
7
  import { writeFileSync as writeFileSync2 } from "node:fs";
8
8
  import { tmpdir as tmpdir2 } from "node:os";
9
9
  import { join as join7 } from "node:path";
@@ -1608,6 +1608,449 @@ async function renderWrappedCardLocally(prefetched, theme = "dark") {
1608
1608
  return Buffer.from(png);
1609
1609
  }
1610
1610
 
1611
+ // src/endgame.ts
1612
+ import chalk from "chalk";
1613
+
1614
+ // src/wrapped/tiers.ts
1615
+ var UNICORN2 = ` ,.. /
1616
+ ,' ';
1617
+ ,,.__ _,' /'; .
1618
+ :',' ~~~~ '. '~
1619
+ ' ( ) )::,
1620
+ '. '..=----=..-~ .;'
1621
+ ' ;' :: ':. '"
1622
+ (: ': ;)
1623
+ \\\\ '" ./
1624
+ '" '"`;
1625
+ var ROCKETSHIP2 = ` .
1626
+ .'.
1627
+ |o|
1628
+ .'o'.
1629
+ |.-.|
1630
+ ' '
1631
+ ( )
1632
+ )
1633
+ ( )`;
1634
+ var WIZARD2 = ` (\\. \\ ,/)
1635
+ \\( |\\ )/
1636
+ //\\ | \\ /\\\\
1637
+ (/ /\\_#oo#_/\\ \\)
1638
+ \\/\\ #### /\\/
1639
+ \`##'`;
1640
+ var RISING_STAR2 = ` .
1641
+ ,O,
1642
+ ,OOO,
1643
+ 'oooooOOOOOooooo'
1644
+ \`OOOOOOOOOOO\`
1645
+ \`OOOOOOO\`
1646
+ OOOO'OOOO
1647
+ OOO' 'OOO
1648
+ O' 'O`;
1649
+ var CURIOUS_CAT2 = ` |\\__/,| (\`\\
1650
+ |_ _ |.--.) )
1651
+ ( T ) /
1652
+ (((^_(((/(((_/`;
1653
+ var GINGERBREAD2 = ` ,--.
1654
+ _(*_*)_
1655
+ (_ o _)
1656
+ / o \\
1657
+ (_/ \\_)`;
1658
+ var TIERS2 = [
1659
+ {
1660
+ key: "still_figuring",
1661
+ label: "STILL FIGURING IT OUT",
1662
+ min: 1,
1663
+ art: GINGERBREAD2
1664
+ },
1665
+ { key: "curious_cat", label: "CURIOUS CAT", min: 35, art: CURIOUS_CAT2 },
1666
+ { key: "rising_star", label: "RISING STAR", min: 60, art: RISING_STAR2 },
1667
+ { key: "prompt_wizard", label: "PROMPT WIZARD", min: 77, art: WIZARD2 },
1668
+ {
1669
+ key: "escape_velocity",
1670
+ label: "ESCAPE VELOCITY",
1671
+ min: 86,
1672
+ art: ROCKETSHIP2
1673
+ },
1674
+ { key: "unicorn", label: "UNICORN", min: 95, art: UNICORN2 }
1675
+ ];
1676
+ function tierForScore2(score) {
1677
+ const s = Number.isFinite(score) ? score : 0;
1678
+ for (let i = TIERS2.length - 1; i >= 0; i--) {
1679
+ if (s >= TIERS2[i].min) return TIERS2[i];
1680
+ }
1681
+ return TIERS2[0];
1682
+ }
1683
+
1684
+ // src/share-block.ts
1685
+ var TIER_EMOJI = {
1686
+ still_figuring: "\u{1F331}",
1687
+ curious_cat: "\u{1F408}",
1688
+ rising_star: "\u2B50",
1689
+ prompt_wizard: "\u{1F9D9}",
1690
+ escape_velocity: "\u{1F680}",
1691
+ unicorn: "\u{1F984}"
1692
+ };
1693
+ var SPARK_CHARS = "\u2581\u2582\u2583\u2584\u2585\u2586\u2587\u2588";
1694
+ function sparkline2(buckets) {
1695
+ const recent = buckets.slice(-6).map((b) => Math.max(0, b.duration_hours));
1696
+ if (recent.filter((h) => h > 0).length < 2) return "";
1697
+ const max = Math.max(...recent);
1698
+ if (max <= 0) return "";
1699
+ return recent.map((h) => {
1700
+ const idx = Math.min(
1701
+ SPARK_CHARS.length - 1,
1702
+ Math.round(h / max * (SPARK_CHARS.length - 1))
1703
+ );
1704
+ return SPARK_CHARS[idx];
1705
+ }).join("");
1706
+ }
1707
+ function compactCount(n) {
1708
+ if (n >= 1e9) {
1709
+ const b = n / 1e9;
1710
+ return `${b >= 10 ? Math.round(b) : b.toFixed(1).replace(/\.0$/, "")}B`;
1711
+ }
1712
+ if (n >= 1e6) {
1713
+ const m = n / 1e6;
1714
+ return `${m >= 10 ? Math.round(m) : m.toFixed(1).replace(/\.0$/, "")}M`;
1715
+ }
1716
+ if (n >= 1e3) {
1717
+ const k = n / 1e3;
1718
+ return `${k >= 10 ? Math.round(k) : k.toFixed(1).replace(/\.0$/, "")}K`;
1719
+ }
1720
+ return `${Math.round(n)}`;
1721
+ }
1722
+ function monthLabel(month) {
1723
+ const names = [
1724
+ "Jan",
1725
+ "Feb",
1726
+ "Mar",
1727
+ "Apr",
1728
+ "May",
1729
+ "Jun",
1730
+ "Jul",
1731
+ "Aug",
1732
+ "Sep",
1733
+ "Oct",
1734
+ "Nov",
1735
+ "Dec"
1736
+ ];
1737
+ const idx = Number(month.split("-")[1]) - 1;
1738
+ return names[idx] ?? month;
1739
+ }
1740
+ function firstName(name) {
1741
+ return name.trim().split(/\s+/)[0] || name;
1742
+ }
1743
+ function identityLine(ctx) {
1744
+ const p = ctx.view.proficiency;
1745
+ if (ctx.versus && p && ctx.versus.score !== null && p.score > ctx.versus.score) {
1746
+ return `I beat ${firstName(ctx.versus.name)}'s AI Wrapped \u2694\uFE0F ${p.score} vs ${ctx.versus.score}`;
1747
+ }
1748
+ if (!p) return `My AI Wrapped \xB7 ${ctx.view.archetype_label}`;
1749
+ const tier = tierForScore2(p.score);
1750
+ const emoji = TIER_EMOJI[tier.key] ?? "";
1751
+ const top = p.score_percentile != null ? ` (top ${Math.max(1, Math.round(100 - p.score_percentile))}%)` : "";
1752
+ return `My AI Wrapped \xB7 ${titleCase(tier.label)} ${emoji} \xB7 ${p.score}/100${top}`.trim();
1753
+ }
1754
+ function titleCase(label) {
1755
+ return label.toLowerCase().split(/\s+/).map((w) => w.charAt(0).toUpperCase() + w.slice(1)).join(" ");
1756
+ }
1757
+ function proofLine(ctx) {
1758
+ const parts = [];
1759
+ const spark = sparkline2(ctx.view.all_time.monthly_buckets);
1760
+ if (spark) parts.push(spark);
1761
+ const hours = Math.round(ctx.view.all_time.total_hours);
1762
+ if (hours > 0) parts.push(`${hours.toLocaleString("en-US")}h`);
1763
+ if (ctx.view.streak_days >= 3) {
1764
+ parts.push(`${ctx.view.streak_days}-day streak`);
1765
+ }
1766
+ const tokens = ctx.view.tokens.work_tokens + ctx.view.tokens.cache_tokens;
1767
+ if (tokens > 0) parts.push(`${compactCount(tokens)} tokens`);
1768
+ const current = ctx.view.proficiency?.score;
1769
+ if (ctx.previous && current != null && current > ctx.previous.score) {
1770
+ parts.push(
1771
+ `+${current - ctx.previous.score} vs ${monthLabel(ctx.previous.month)}`
1772
+ );
1773
+ }
1774
+ return parts.join(" \xB7 ");
1775
+ }
1776
+ function buildShareBlock(ctx) {
1777
+ const lines = [identityLine(ctx)];
1778
+ const proof = proofLine(ctx);
1779
+ if (proof) lines.push(proof);
1780
+ lines.push(
1781
+ ctx.challengeCode ? `beat me \u2192 npx standout beat-${ctx.challengeCode}` : `get yours \u2192 npx standout`
1782
+ );
1783
+ if (ctx.shortUrl) lines.push(ctx.shortUrl);
1784
+ return lines.join("\n");
1785
+ }
1786
+
1787
+ // src/clipboard.ts
1788
+ import { spawnSync } from "child_process";
1789
+ import { platform } from "os";
1790
+ function clipboardCandidates(osPlatform = platform(), env = process.env) {
1791
+ if (osPlatform === "darwin") return [{ cmd: "pbcopy", args: [] }];
1792
+ if (osPlatform === "win32") return [{ cmd: "clip", args: [] }];
1793
+ const tools = [];
1794
+ if (env.WAYLAND_DISPLAY) tools.push({ cmd: "wl-copy", args: [] });
1795
+ tools.push(
1796
+ { cmd: "xclip", args: ["-selection", "clipboard"] },
1797
+ { cmd: "xsel", args: ["-ib"] }
1798
+ );
1799
+ if (env.WSL_DISTRO_NAME || env.WSL_INTEROP) {
1800
+ tools.push({ cmd: "clip.exe", args: [] });
1801
+ }
1802
+ return tools;
1803
+ }
1804
+ function osc52Sequence(text) {
1805
+ const b64 = Buffer.from(text, "utf8").toString("base64");
1806
+ return `\x1B]52;c;${b64}\x07`;
1807
+ }
1808
+ function copyToClipboard(text) {
1809
+ for (const tool of clipboardCandidates()) {
1810
+ try {
1811
+ const res = spawnSync(tool.cmd, tool.args, {
1812
+ input: text,
1813
+ timeout: 3e3,
1814
+ stdio: ["pipe", "ignore", "ignore"]
1815
+ });
1816
+ if (res.status === 0) return true;
1817
+ } catch {
1818
+ }
1819
+ }
1820
+ if (process.stdout.isTTY) {
1821
+ process.stdout.write(osc52Sequence(text));
1822
+ return true;
1823
+ }
1824
+ return false;
1825
+ }
1826
+
1827
+ // src/qr.ts
1828
+ import qrcodeGenerator from "qrcode-generator";
1829
+ var QUIET_ZONE = 2;
1830
+ function qrMatrix(text) {
1831
+ const qr = qrcodeGenerator(0, "M");
1832
+ qr.addData(text);
1833
+ qr.make();
1834
+ const count = qr.getModuleCount();
1835
+ const size = count + QUIET_ZONE * 2;
1836
+ const rows = [];
1837
+ for (let y = 0; y < size; y++) {
1838
+ const row = [];
1839
+ for (let x = 0; x < size; x++) {
1840
+ const my = y - QUIET_ZONE;
1841
+ const mx = x - QUIET_ZONE;
1842
+ row.push(
1843
+ my >= 0 && my < count && mx >= 0 && mx < count ? qr.isDark(my, mx) : false
1844
+ );
1845
+ }
1846
+ rows.push(row);
1847
+ }
1848
+ return rows;
1849
+ }
1850
+ function renderQrHalfBlocks(matrix, indent = " ") {
1851
+ const lines = [];
1852
+ for (let y = 0; y < matrix.length; y += 2) {
1853
+ const top = matrix[y];
1854
+ const bottom = matrix[y + 1] ?? top.map(() => false);
1855
+ let line = indent;
1856
+ for (let x = 0; x < top.length; x++) {
1857
+ const t = !top[x];
1858
+ const b = !bottom[x];
1859
+ line += t && b ? "\u2588" : t ? "\u2580" : b ? "\u2584" : " ";
1860
+ }
1861
+ lines.push(line);
1862
+ }
1863
+ return lines.join("\n");
1864
+ }
1865
+ function qrForTerminal(url, opts = {}) {
1866
+ const isTTY = opts.isTTY ?? process.stdout.isTTY ?? false;
1867
+ if (!isTTY) return null;
1868
+ const rows = opts.rows ?? process.stdout.rows ?? 0;
1869
+ const matrix = qrMatrix(url);
1870
+ const neededRows = Math.ceil(matrix.length / 2) + 4;
1871
+ if (rows > 0 && rows < (opts.minRows ?? neededRows)) return null;
1872
+ return renderQrHalfBlocks(matrix);
1873
+ }
1874
+
1875
+ // src/wrapped-share.ts
1876
+ import open from "open";
1877
+ async function openWrapped(shareUrl) {
1878
+ await open(shareUrl);
1879
+ }
1880
+
1881
+ // src/endgame.ts
1882
+ var ACCENT = "#ad5cff";
1883
+ function firstName2(name) {
1884
+ return name.trim().split(/\s+/)[0] || name;
1885
+ }
1886
+ function buildVersusCard(view, versus) {
1887
+ const mine = view.proficiency?.score ?? null;
1888
+ const theirs = versus.score;
1889
+ const them = firstName2(versus.name);
1890
+ const myTier = mine != null ? TIER_EMOJI[tierForScore2(mine).key] ?? "" : "";
1891
+ const theirTier = versus.tier_key ? TIER_EMOJI[versus.tier_key] ?? "" : "";
1892
+ const lines = ["", chalk.bold.white(" \u2694\uFE0F THE CHALLENGE"), ""];
1893
+ if (mine != null && theirs != null) {
1894
+ const you = `you ${myTier}`.trim();
1895
+ const other = `${them} ${theirTier}`.trim();
1896
+ lines.push(
1897
+ ` ${chalk.white(you)} ${chalk.hex(ACCENT)(String(mine))} vs ${chalk.hex(ACCENT)(String(theirs))} ${chalk.white(other)}`
1898
+ );
1899
+ lines.push("");
1900
+ if (mine > theirs) {
1901
+ lines.push(
1902
+ chalk.white(` you took it. ${them} has been notified. (kidding.)`)
1903
+ );
1904
+ } else if (mine < theirs) {
1905
+ lines.push(
1906
+ chalk.white(
1907
+ ` ${theirs - mine} point${theirs - mine === 1 ? "" : "s"} behind. run it again next month \u2014 scores move.`
1908
+ )
1909
+ );
1910
+ } else {
1911
+ lines.push(chalk.white(` dead even. this demands a rematch.`));
1912
+ }
1913
+ } else {
1914
+ lines.push(chalk.white(` ${them} challenged you \u2014 challenge accepted.`));
1915
+ }
1916
+ lines.push("");
1917
+ return lines.join("\n");
1918
+ }
1919
+ function shareBlockContext(ctx) {
1920
+ return {
1921
+ view: ctx.view,
1922
+ challengeCode: ctx.challengeCode,
1923
+ shortUrl: ctx.shortUrl,
1924
+ versus: ctx.versus,
1925
+ previous: ctx.previous
1926
+ };
1927
+ }
1928
+ function xIntentUrl(block) {
1929
+ return `https://x.com/intent/post?text=${encodeURIComponent(block)}`;
1930
+ }
1931
+ function linkedInIntentUrl(block) {
1932
+ return `https://www.linkedin.com/feed/?shareActive=true&text=${encodeURIComponent(block)}`;
1933
+ }
1934
+ async function markShared(ctx) {
1935
+ if (ctx.wrappedId) {
1936
+ try {
1937
+ await markWrappedShared(ctx.wrappedId);
1938
+ } catch {
1939
+ }
1940
+ }
1941
+ }
1942
+ function waitForAction() {
1943
+ return new Promise((resolve) => {
1944
+ const stdin = process.stdin;
1945
+ stdin.setRawMode(true);
1946
+ stdin.resume();
1947
+ stdin.setEncoding("utf8");
1948
+ const onData = (data) => {
1949
+ stdin.setRawMode(false);
1950
+ stdin.pause();
1951
+ stdin.removeListener("data", onData);
1952
+ resolve(data);
1953
+ };
1954
+ stdin.on("data", onData);
1955
+ });
1956
+ }
1957
+ async function runEndgame(ctx) {
1958
+ const block = buildShareBlock(shareBlockContext(ctx));
1959
+ if (ctx.versus) {
1960
+ process.stdout.write(buildVersusCard(ctx.view, ctx.versus));
1961
+ }
1962
+ const framed = block.split("\n").map((l) => ` ${chalk.white(l)}`).join("\n");
1963
+ process.stdout.write(`
1964
+ ${framed}
1965
+
1966
+ `);
1967
+ const copied = copyToClipboard(block);
1968
+ if (copied) {
1969
+ process.stderr.write(
1970
+ chalk.hex(ACCENT)(" \u2713 copied to your clipboard \u2014 paste anywhere\n\n")
1971
+ );
1972
+ }
1973
+ if (!process.stdin.isTTY) {
1974
+ if (ctx.shareUrl) {
1975
+ process.stderr.write(
1976
+ ` your wrapped: ${ctx.shortUrl ?? ctx.shareUrl}
1977
+
1978
+ `
1979
+ );
1980
+ }
1981
+ return;
1982
+ }
1983
+ if (ctx.shortUrl) {
1984
+ const qr = qrForTerminal(`${ctx.shortUrl}?src=qr`);
1985
+ if (qr) {
1986
+ process.stdout.write(qr + "\n");
1987
+ process.stderr.write(chalk.dim(" scan to share from your phone\n\n"));
1988
+ }
1989
+ }
1990
+ const actions = [];
1991
+ if (ctx.shareUrl)
1992
+ actions.push(`${chalk.bold.white("[enter]")} open in browser`);
1993
+ actions.push(`${chalk.bold.white("[x]")} post to X`);
1994
+ actions.push(`${chalk.bold.white("[l]")} post to LinkedIn`);
1995
+ actions.push(`${chalk.bold.white("[q]")} done`);
1996
+ process.stderr.write(` ${actions.join(chalk.dim(" \xB7 "))}
1997
+ `);
1998
+ for (; ; ) {
1999
+ const key = await waitForAction();
2000
+ if (key === "" || key === "q" || key === "Q") {
2001
+ if (ctx.shortUrl) {
2002
+ process.stderr.write(`
2003
+ your wrapped: ${ctx.shortUrl}
2004
+
2005
+ `);
2006
+ }
2007
+ return;
2008
+ }
2009
+ if (key === "x" || key === "X" || key === "l" || key === "L") {
2010
+ const linkedin = key === "l" || key === "L";
2011
+ try {
2012
+ await openWrapped(
2013
+ linkedin ? linkedInIntentUrl(block) : xIntentUrl(block)
2014
+ );
2015
+ await markShared(ctx);
2016
+ process.stderr.write(
2017
+ chalk.dim(
2018
+ `
2019
+ opened ${linkedin ? "LinkedIn" : "X"} \u2014 your post is pre-filled
2020
+ `
2021
+ )
2022
+ );
2023
+ } catch {
2024
+ process.stderr.write(
2025
+ chalk.dim(
2026
+ "\n couldn't open a browser \u2014 the block is in your clipboard\n"
2027
+ )
2028
+ );
2029
+ }
2030
+ continue;
2031
+ }
2032
+ if ((key === "\r" || key === "\n") && ctx.shareUrl) {
2033
+ try {
2034
+ await openWrapped(ctx.shareUrl);
2035
+ await markShared(ctx);
2036
+ process.stderr.write(`
2037
+ opened: ${ctx.shareUrl}
2038
+
2039
+ `);
2040
+ } catch (err) {
2041
+ process.stderr.write(
2042
+ `
2043
+ couldn't open browser. open it manually: ${ctx.shareUrl}
2044
+ (${err instanceof Error ? err.message : err})
2045
+
2046
+ `
2047
+ );
2048
+ }
2049
+ return;
2050
+ }
2051
+ }
2052
+ }
2053
+
1611
2054
  // src/gather.ts
1612
2055
  import { execSync as execSync2 } from "child_process";
1613
2056
  import { existsSync as existsSync5, readFileSync as readFileSync5, statSync as statSync4 } from "fs";
@@ -1629,7 +2072,7 @@ import { createInterface } from "readline";
1629
2072
 
1630
2073
  // src/cursor.ts
1631
2074
  import { existsSync } from "fs";
1632
- import { homedir, platform } from "os";
2075
+ import { homedir, platform as platform2 } from "os";
1633
2076
  import { join } from "path";
1634
2077
 
1635
2078
  // src/redact.ts
@@ -1750,7 +2193,7 @@ var EXT_TO_LANG = {
1750
2193
  };
1751
2194
  function findCursorDb() {
1752
2195
  const home = homedir();
1753
- const os = platform();
2196
+ const os = platform2();
1754
2197
  const candidates = os === "darwin" ? [
1755
2198
  join(
1756
2199
  home,
@@ -3674,7 +4117,7 @@ import {
3674
4117
  rmSync,
3675
4118
  readFileSync as readFileSync4
3676
4119
  } from "fs";
3677
- import { homedir as homedir4, platform as platform2, tmpdir } from "os";
4120
+ import { homedir as homedir4, platform as platform3, tmpdir } from "os";
3678
4121
  import { join as join4 } from "path";
3679
4122
  import { spawn } from "child_process";
3680
4123
  var DEBUG_PORT_WAIT_MS = 1e4;
@@ -3684,7 +4127,7 @@ function wait(ms) {
3684
4127
  return new Promise((r) => setTimeout(r, ms));
3685
4128
  }
3686
4129
  function findChromeExecutable() {
3687
- const os = platform2();
4130
+ const os = platform3();
3688
4131
  const candidates = os === "darwin" ? [
3689
4132
  "/Applications/Google Chrome.app/Contents/MacOS/Google Chrome",
3690
4133
  "/Applications/Google Chrome Beta.app/Contents/MacOS/Google Chrome Beta",
@@ -3706,7 +4149,7 @@ function findChromeExecutable() {
3706
4149
  return null;
3707
4150
  }
3708
4151
  function findChromeProfileRoot() {
3709
- const os = platform2();
4152
+ const os = platform3();
3710
4153
  const home = homedir4();
3711
4154
  const candidates = os === "darwin" ? [
3712
4155
  join4(home, "Library", "Application Support", "Google", "Chrome"),
@@ -3766,7 +4209,7 @@ async function waitForDebugPort(userDataDir, timeoutMs) {
3766
4209
  return null;
3767
4210
  }
3768
4211
  async function spawnChrome(executablePath, userDataDir) {
3769
- const os = platform2();
4212
+ const os = platform3();
3770
4213
  const args = [
3771
4214
  "--headless=new",
3772
4215
  `--user-data-dir=${userDataDir}`,
@@ -4828,7 +5271,7 @@ async function gather(options = {}) {
4828
5271
  }
4829
5272
 
4830
5273
  // src/heap.ts
4831
- import { spawnSync } from "child_process";
5274
+ import { spawnSync as spawnSync2 } from "child_process";
4832
5275
  import { totalmem } from "os";
4833
5276
  function ensureHeapHeadroom() {
4834
5277
  if (process.env.STANDOUT_HEAP_BOOSTED === "1") return;
@@ -4839,7 +5282,7 @@ function ensureHeapHeadroom() {
4839
5282
  if (desiredMb <= 4096) return;
4840
5283
  const entry = process.argv[1];
4841
5284
  if (!entry) return;
4842
- const res = spawnSync(
5285
+ const res = spawnSync2(
4843
5286
  process.execPath,
4844
5287
  [`--max-old-space-size=${desiredMb}`, entry, ...process.argv.slice(2)],
4845
5288
  {
@@ -5149,8 +5592,8 @@ The JSON should follow this structure:
5149
5592
  - If you receive a pause_turn stop reason, your turn will be continued automatically \u2014 just keep going.`;
5150
5593
 
5151
5594
  // src/schedule.ts
5152
- import chalk from "chalk";
5153
- import { spawnSync as spawnSync2 } from "node:child_process";
5595
+ import chalk2 from "chalk";
5596
+ import { spawnSync as spawnSync3 } from "node:child_process";
5154
5597
  import {
5155
5598
  existsSync as existsSync6,
5156
5599
  mkdirSync as mkdirSync2,
@@ -5163,7 +5606,7 @@ import { homedir as homedir6 } from "node:os";
5163
5606
  import { join as join6 } from "node:path";
5164
5607
  var LAUNCHD_LABEL = "work.standout.monthly";
5165
5608
  var CRON_MARKER = "# standout-monthly";
5166
- var ACCENT = "#ad5cff";
5609
+ var ACCENT2 = "#ad5cff";
5167
5610
  var SLUG_RE = /^[a-z0-9][a-z0-9_-]*$/i;
5168
5611
  var FLAG_ALLOWLIST = ["--local", "--no-upload", "--terminal"];
5169
5612
  function parseScheduleArgs(args) {
@@ -5203,7 +5646,14 @@ function escapeXml(text) {
5203
5646
  function unescapeXml(text) {
5204
5647
  return text.replace(/&lt;/g, "<").replace(/&gt;/g, ">").replace(/&amp;/g, "&");
5205
5648
  }
5206
- function buildLaunchdPlist(command, logPath) {
5649
+ function buildGuardedCommand(runCommand) {
5650
+ return `STAMP="$HOME/.standout/last-refresh"; MONTH=$(date +%Y-%m); [ "$(cat "$STAMP" 2>/dev/null)" = "$MONTH" ] || { mkdir -p "$HOME/.standout"; STANDOUT_SCHEDULED=1 ${runCommand} && echo "$MONTH" > "$STAMP"; }`;
5651
+ }
5652
+ function extractRunCommand(guarded) {
5653
+ const m = guarded.match(/STANDOUT_SCHEDULED=1 (.*?) && echo "\$MONTH"/);
5654
+ return m ? m[1] : null;
5655
+ }
5656
+ function buildLaunchdPlist(guardedCommand, logPath) {
5207
5657
  return `<?xml version="1.0" encoding="UTF-8"?>
5208
5658
  <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
5209
5659
  <plist version="1.0">
@@ -5213,22 +5663,18 @@ function buildLaunchdPlist(command, logPath) {
5213
5663
  <array>
5214
5664
  <string>/bin/zsh</string>
5215
5665
  <string>-lc</string>
5216
- <string>${escapeXml(command)}</string>
5666
+ <string>${escapeXml(guardedCommand)}</string>
5217
5667
  </array>
5218
- <key>StartCalendarInterval</key>
5219
- <dict>
5220
- <key>Day</key><integer>1</integer>
5221
- <key>Hour</key><integer>10</integer>
5222
- <key>Minute</key><integer>0</integer>
5223
- </dict>
5668
+ <key>StartInterval</key><integer>3600</integer>
5224
5669
  <key>StandardOutPath</key><string>${escapeXml(logPath)}</string>
5225
5670
  <key>StandardErrorPath</key><string>${escapeXml(logPath)}</string>
5226
5671
  </dict>
5227
5672
  </plist>
5228
5673
  `;
5229
5674
  }
5230
- function buildCronLine(command, logPath) {
5231
- return `0 10 1 * * /bin/bash -lc '${command}' >> "${logPath}" 2>&1 ${CRON_MARKER}`;
5675
+ function buildCronLine(guardedCommand, logPath) {
5676
+ const escaped = guardedCommand.replace(/%/g, "\\%");
5677
+ return `0 * * * * /bin/bash -lc '${escaped}' >> "${logPath}" 2>&1 ${CRON_MARKER}`;
5232
5678
  }
5233
5679
  function stripCronEntries(crontab) {
5234
5680
  return crontab.split("\n").filter((line) => !line.includes(CRON_MARKER)).join("\n");
@@ -5261,8 +5707,25 @@ function writeOptOut() {
5261
5707
  function clearOptOut() {
5262
5708
  rmSync2(optOutPath(), { force: true });
5263
5709
  }
5710
+ function refreshStampPath() {
5711
+ return join6(stateDir(), "last-refresh");
5712
+ }
5713
+ function readRefreshStamp() {
5714
+ try {
5715
+ return readFileSync6(refreshStampPath(), "utf8").trim() || null;
5716
+ } catch {
5717
+ return null;
5718
+ }
5719
+ }
5720
+ function writeRefreshStamp() {
5721
+ mkdirSync2(stateDir(), { recursive: true });
5722
+ const now = /* @__PURE__ */ new Date();
5723
+ const month = `${now.getFullYear()}-${String(now.getMonth() + 1).padStart(2, "0")}`;
5724
+ writeFileSync(refreshStampPath(), `${month}
5725
+ `);
5726
+ }
5264
5727
  function launchctl(args) {
5265
- const res = spawnSync2("launchctl", args, { encoding: "utf8" });
5728
+ const res = spawnSync3("launchctl", args, { encoding: "utf8" });
5266
5729
  return {
5267
5730
  status: res.status,
5268
5731
  stdout: res.stdout ?? "",
@@ -5273,11 +5736,11 @@ function uid() {
5273
5736
  return process.getuid?.() ?? 0;
5274
5737
  }
5275
5738
  function readCrontab() {
5276
- const res = spawnSync2("crontab", ["-l"], { encoding: "utf8" });
5739
+ const res = spawnSync3("crontab", ["-l"], { encoding: "utf8" });
5277
5740
  return res.status === 0 ? res.stdout ?? "" : "";
5278
5741
  }
5279
5742
  function writeCrontab(content) {
5280
- const res = spawnSync2("crontab", ["-"], {
5743
+ const res = spawnSync3("crontab", ["-"], {
5281
5744
  input: content,
5282
5745
  encoding: "utf8"
5283
5746
  });
@@ -5286,10 +5749,11 @@ function writeCrontab(content) {
5286
5749
  }
5287
5750
  }
5288
5751
  function installJob(command) {
5752
+ const guarded = buildGuardedCommand(command);
5289
5753
  if (process.platform === "darwin") {
5290
5754
  const path2 = plistPath();
5291
5755
  mkdirSync2(join6(homedir6(), "Library", "LaunchAgents"), { recursive: true });
5292
- writeFileSync(path2, buildLaunchdPlist(command, schedLogPath()));
5756
+ writeFileSync(path2, buildLaunchdPlist(guarded, schedLogPath()));
5293
5757
  launchctl(["bootout", `gui/${uid()}/${LAUNCHD_LABEL}`]);
5294
5758
  const res = launchctl(["bootstrap", `gui/${uid()}`, path2]);
5295
5759
  if (res.status !== 0) {
@@ -5301,10 +5765,11 @@ function installJob(command) {
5301
5765
  mkdirSync2(stateDir(), { recursive: true });
5302
5766
  const stripped = stripCronEntries(readCrontab());
5303
5767
  const base = stripped === "" || stripped.endsWith("\n") ? stripped : stripped + "\n";
5304
- writeCrontab(base + buildCronLine(command, schedLogPath()) + "\n");
5768
+ writeCrontab(base + buildCronLine(guarded, schedLogPath()) + "\n");
5305
5769
  }
5770
+ writeRefreshStamp();
5306
5771
  }
5307
- function installedCommand() {
5772
+ function installedShellCommand() {
5308
5773
  if (process.platform === "darwin") {
5309
5774
  if (!existsSync6(plistPath())) return null;
5310
5775
  const xml = readFileSync6(plistPath(), "utf8");
@@ -5314,7 +5779,7 @@ function installedCommand() {
5314
5779
  if (process.platform === "linux") {
5315
5780
  const line = readCrontab().split("\n").find((l) => l.includes(CRON_MARKER));
5316
5781
  const m = line?.match(/-lc '([^']*)'/);
5317
- return m ? m[1] : null;
5782
+ return m ? m[1].replace(/\\%/g, "%") : null;
5318
5783
  }
5319
5784
  return null;
5320
5785
  }
@@ -5330,10 +5795,10 @@ async function installSchedule(slug, flags) {
5330
5795
  installJob(command);
5331
5796
  process.stderr.write(
5332
5797
  `
5333
- ${chalk.hex(ACCENT)("\u2713")} ${chalk.white("monthly refresh scheduled")} ${chalk.dim("(1st of each month, 10:00)")}
5334
- ` + chalk.dim(` runs: ${command}
5335
- `) + chalk.dim(` log: ${schedLogPath()}
5336
- `) + chalk.dim(" disable anytime with `npx standout schedule off`\n\n")
5798
+ ${chalk2.hex(ACCENT2)("\u2713")} ${chalk2.white("monthly refresh scheduled")} ${chalk2.dim("(first awake hour of each month)")}
5799
+ ` + chalk2.dim(` runs: ${command}
5800
+ `) + chalk2.dim(` log: ${schedLogPath()}
5801
+ `) + chalk2.dim(" disable anytime with `npx standout schedule off`\n\n")
5337
5802
  );
5338
5803
  }
5339
5804
  async function removeSchedule() {
@@ -5361,11 +5826,11 @@ async function removeSchedule() {
5361
5826
  }
5362
5827
  process.stderr.write(
5363
5828
  removed ? `
5364
- ${chalk.hex(ACCENT)("\u2713")} ${chalk.white("monthly refresh disabled")}
5365
- ` + chalk.dim(
5829
+ ${chalk2.hex(ACCENT2)("\u2713")} ${chalk2.white("monthly refresh disabled")}
5830
+ ` + chalk2.dim(
5366
5831
  " it won't be scheduled again \u2014 re-enable with `npx standout schedule`\n\n"
5367
5832
  ) : `
5368
- ${chalk.dim("no monthly schedule installed \u2014 future runs won't add one (re-enable with `npx standout schedule`)")}
5833
+ ${chalk2.dim("no monthly schedule installed \u2014 future runs won't add one (re-enable with `npx standout schedule`)")}
5369
5834
 
5370
5835
  `
5371
5836
  );
@@ -5377,19 +5842,21 @@ async function scheduleStatus() {
5377
5842
  );
5378
5843
  return;
5379
5844
  }
5380
- const command = installedCommand();
5381
- if (!command) {
5845
+ const shell = installedShellCommand();
5846
+ if (!shell) {
5382
5847
  process.stderr.write(
5383
5848
  `
5384
- ${chalk.white("no monthly schedule installed")}` + (isOptedOut() ? chalk.dim(" (opted out)") : "") + "\n" + chalk.dim(" enable with `npx standout schedule`\n\n")
5849
+ ${chalk2.white("no monthly schedule installed")}` + (isOptedOut() ? chalk2.dim(" (opted out)") : "") + "\n" + chalk2.dim(" enable with `npx standout schedule`\n\n")
5385
5850
  );
5386
5851
  return;
5387
5852
  }
5853
+ const stamp = readRefreshStamp();
5388
5854
  process.stderr.write(
5389
5855
  `
5390
- ${chalk.hex(ACCENT)("\u2713")} ${chalk.white("monthly refresh is on")} ${chalk.dim("(1st of each month, 10:00)")}
5391
- ` + chalk.dim(` runs: ${command}
5392
- `) + chalk.dim(` log: ${schedLogPath()}
5856
+ ${chalk2.hex(ACCENT2)("\u2713")} ${chalk2.white("monthly refresh is on")} ${chalk2.dim("(first awake hour of each month)")}
5857
+ ` + chalk2.dim(` runs: ${extractRunCommand(shell) ?? shell}
5858
+ `) + chalk2.dim(` log: ${schedLogPath()}
5859
+ `) + chalk2.dim(` last refreshed month: ${stamp ?? "never"}
5393
5860
  `)
5394
5861
  );
5395
5862
  if (process.platform === "darwin") {
@@ -5397,12 +5864,12 @@ async function scheduleStatus() {
5397
5864
  const exitLine = res.stdout.split("\n").find((l) => l.includes("last exit code"));
5398
5865
  if (res.status !== 0) {
5399
5866
  process.stderr.write(
5400
- chalk.dim(
5867
+ chalk2.dim(
5401
5868
  " warning: job not loaded in launchd \u2014 re-run `npx standout schedule`\n"
5402
5869
  )
5403
5870
  );
5404
5871
  } else if (exitLine) {
5405
- process.stderr.write(chalk.dim(` ${exitLine.trim()}
5872
+ process.stderr.write(chalk2.dim(` ${exitLine.trim()}
5406
5873
  `));
5407
5874
  }
5408
5875
  }
@@ -5410,35 +5877,39 @@ async function scheduleStatus() {
5410
5877
  const mtime = statSync5(schedLogPath()).mtime;
5411
5878
  const tail = readFileSync6(schedLogPath(), "utf8").trimEnd().split("\n").slice(-10);
5412
5879
  process.stderr.write(
5413
- chalk.dim(` last log activity: ${mtime.toLocaleString()}
5880
+ chalk2.dim(` last log activity: ${mtime.toLocaleString()}
5414
5881
 
5415
- `) + tail.map((l) => chalk.dim(` \u2502 ${l}
5882
+ `) + tail.map((l) => chalk2.dim(` \u2502 ${l}
5416
5883
  `)).join("")
5417
5884
  );
5418
5885
  }
5419
5886
  process.stderr.write("\n");
5420
5887
  }
5888
+ function autoRefreshNotice(headline) {
5889
+ const optOut = "npx standout schedule off";
5890
+ return `
5891
+ ${chalk2.hex(ACCENT2)("\u27F3")} ${chalk2.bold.white(headline)}
5892
+ ${chalk2.white("standout re-runs once a month so your wrapped keeps building")}
5893
+ ${chalk2.white("(because local logs only keep ~30 days of history).")}
5894
+ ${chalk2.white("opt out anytime:")} ${chalk2.hex(ACCENT2)(optOut)}
5895
+
5896
+ `;
5897
+ }
5421
5898
  async function maybeAutoInstallSchedule(slug) {
5422
5899
  try {
5900
+ if (process.env.STANDOUT_SCHEDULED === "1") return;
5423
5901
  if (!supportedPlatform() || isOptedOut()) return;
5424
5902
  const command = buildRunCommand(slug, []);
5425
- if (installedCommand() === command) {
5426
- process.stderr.write(
5427
- chalk.dim(
5428
- " monthly refresh is on \u2014 `npx standout schedule off` to disable\n\n"
5429
- )
5430
- );
5903
+ if (installedShellCommand() === buildGuardedCommand(command)) {
5904
+ writeRefreshStamp();
5905
+ process.stderr.write(autoRefreshNotice("auto-refresh is on"));
5431
5906
  return;
5432
5907
  }
5433
5908
  installJob(command);
5434
- process.stderr.write(
5435
- ` ${chalk.hex(ACCENT)("\u2713")} ${chalk.white("monthly refresh scheduled")} ${chalk.dim("(1st of each month) \u2014 disable with `npx standout schedule off`")}
5436
-
5437
- `
5438
- );
5909
+ process.stderr.write(autoRefreshNotice("auto-refresh scheduled"));
5439
5910
  } catch (error) {
5440
5911
  process.stderr.write(
5441
- chalk.dim(
5912
+ chalk2.dim(
5442
5913
  ` (couldn't schedule the monthly refresh: ${error instanceof Error ? error.message : String(error)})
5443
5914
 
5444
5915
  `
@@ -6317,7 +6788,7 @@ function computeConversation(aiUsage, line, themes) {
6317
6788
 
6318
6789
  // src/wrapped/render.ts
6319
6790
  import boxen from "boxen";
6320
- import chalk2 from "chalk";
6791
+ import chalk3 from "chalk";
6321
6792
  import gradient from "gradient-string";
6322
6793
 
6323
6794
  // src/wrapped/chrono-critters.ts
@@ -6383,76 +6854,6 @@ var MASCOTS = {
6383
6854
  / | \\ \u25BC`
6384
6855
  };
6385
6856
 
6386
- // src/wrapped/tiers.ts
6387
- var UNICORN2 = ` ,.. /
6388
- ,' ';
6389
- ,,.__ _,' /'; .
6390
- :',' ~~~~ '. '~
6391
- ' ( ) )::,
6392
- '. '..=----=..-~ .;'
6393
- ' ;' :: ':. '"
6394
- (: ': ;)
6395
- \\\\ '" ./
6396
- '" '"`;
6397
- var ROCKETSHIP2 = ` .
6398
- .'.
6399
- |o|
6400
- .'o'.
6401
- |.-.|
6402
- ' '
6403
- ( )
6404
- )
6405
- ( )`;
6406
- var WIZARD2 = ` (\\. \\ ,/)
6407
- \\( |\\ )/
6408
- //\\ | \\ /\\\\
6409
- (/ /\\_#oo#_/\\ \\)
6410
- \\/\\ #### /\\/
6411
- \`##'`;
6412
- var RISING_STAR2 = ` .
6413
- ,O,
6414
- ,OOO,
6415
- 'oooooOOOOOooooo'
6416
- \`OOOOOOOOOOO\`
6417
- \`OOOOOOO\`
6418
- OOOO'OOOO
6419
- OOO' 'OOO
6420
- O' 'O`;
6421
- var CURIOUS_CAT2 = ` |\\__/,| (\`\\
6422
- |_ _ |.--.) )
6423
- ( T ) /
6424
- (((^_(((/(((_/`;
6425
- var GINGERBREAD2 = ` ,--.
6426
- _(*_*)_
6427
- (_ o _)
6428
- / o \\
6429
- (_/ \\_)`;
6430
- var TIERS2 = [
6431
- {
6432
- key: "still_figuring",
6433
- label: "STILL FIGURING IT OUT",
6434
- min: 1,
6435
- art: GINGERBREAD2
6436
- },
6437
- { key: "curious_cat", label: "CURIOUS CAT", min: 35, art: CURIOUS_CAT2 },
6438
- { key: "rising_star", label: "RISING STAR", min: 60, art: RISING_STAR2 },
6439
- { key: "prompt_wizard", label: "PROMPT WIZARD", min: 77, art: WIZARD2 },
6440
- {
6441
- key: "escape_velocity",
6442
- label: "ESCAPE VELOCITY",
6443
- min: 86,
6444
- art: ROCKETSHIP2
6445
- },
6446
- { key: "unicorn", label: "UNICORN", min: 95, art: UNICORN2 }
6447
- ];
6448
- function tierForScore2(score) {
6449
- const s = Number.isFinite(score) ? score : 0;
6450
- for (let i = TIERS2.length - 1; i >= 0; i--) {
6451
- if (s >= TIERS2[i].min) return TIERS2[i];
6452
- }
6453
- return TIERS2[0];
6454
- }
6455
-
6456
6857
  // src/wrapped/render.ts
6457
6858
  var BOX_WIDTH = 56;
6458
6859
  var SPARK_BARS = ["\u2581", "\u2582", "\u2583", "\u2584", "\u2585", "\u2586", "\u2587", "\u2588"];
@@ -6494,8 +6895,8 @@ function hasHistogramData(view) {
6494
6895
  return view.hour_histogram.some((v) => v > 0);
6495
6896
  }
6496
6897
  function divider(label) {
6497
- return chalk2.dim(`
6498
- ${label.padEnd(48, " ")} ${chalk2.dim("[press \u21B5]")}
6898
+ return chalk3.dim(`
6899
+ ${label.padEnd(48, " ")} ${chalk3.dim("[press \u21B5]")}
6499
6900
  `);
6500
6901
  }
6501
6902
  function wrapWords(text, width) {
@@ -6533,7 +6934,7 @@ function centerBlock(art, color) {
6533
6934
  function bar2(value, max, width) {
6534
6935
  if (max === 0) return " ".repeat(width);
6535
6936
  const filled = Math.round(value / max * width);
6536
- return chalk2.hex("#ff8a00")("\u2588".repeat(filled)) + chalk2.gray("\u2591".repeat(width - filled));
6937
+ return chalk3.hex("#ff8a00")("\u2588".repeat(filled)) + chalk3.gray("\u2591".repeat(width - filled));
6537
6938
  }
6538
6939
  function compactNum(n) {
6539
6940
  const sign = n < 0 ? "-" : "";
@@ -6543,14 +6944,14 @@ function compactNum(n) {
6543
6944
  return `${sign}${abs}`;
6544
6945
  }
6545
6946
  function coloredBar(value, max, width, hex) {
6546
- if (max <= 0) return chalk2.gray("\u2591".repeat(width));
6947
+ if (max <= 0) return chalk3.gray("\u2591".repeat(width));
6547
6948
  const filled = Math.max(
6548
6949
  0,
6549
6950
  Math.min(width, Math.round(value / max * width))
6550
6951
  );
6551
- return chalk2.hex(hex)("\u2588".repeat(filled)) + chalk2.gray("\u2591".repeat(width - filled));
6952
+ return chalk3.hex(hex)("\u2588".repeat(filled)) + chalk3.gray("\u2591".repeat(width - filled));
6552
6953
  }
6553
- function sparkline2(buckets) {
6954
+ function sparkline3(buckets) {
6554
6955
  if (!buckets.length) return "";
6555
6956
  const max = Math.max(...buckets, 1);
6556
6957
  return buckets.map(
@@ -6561,7 +6962,7 @@ function sparkline2(buckets) {
6561
6962
  ).join("");
6562
6963
  }
6563
6964
  function hourlyChart(buckets, critter = null) {
6564
- const spark = sparkline2(buckets);
6965
+ const spark = sparkline3(buckets);
6565
6966
  const width = 24;
6566
6967
  const axis = new Array(width).fill(" ");
6567
6968
  for (const label of [
@@ -6576,8 +6977,8 @@ function hourlyChart(buckets, critter = null) {
6576
6977
  }
6577
6978
  }
6578
6979
  const left = [
6579
- chalk2.hex("#ad5cff")(spark.padEnd(width, " ")),
6580
- chalk2.dim(axis.join(""))
6980
+ chalk3.hex("#ad5cff")(spark.padEnd(width, " ")),
6981
+ chalk3.dim(axis.join(""))
6581
6982
  ];
6582
6983
  if (!critter) return left.map((l) => ` ${l}`);
6583
6984
  const critterLines = critter.art.split("\n");
@@ -6619,12 +7020,12 @@ function card1Open(view) {
6619
7020
  const verdict = perDay >= 6 ? "that's a second full-time job. 996 who?" : perDay >= 3 ? "basically a part-time gig with the machines." : perDay >= 1 ? "a daily habit at this point." : "just getting warmed up.";
6620
7021
  const bench = benchmarkInline(view, view.rank_summary.hours_percentile);
6621
7022
  const lines = [
6622
- chalk2.dim("YOU MANAGED"),
7023
+ chalk3.dim("YOU MANAGED"),
6623
7024
  "",
6624
7025
  bigNumber(` ${hours} session-hours`) + (bench ? ` ${bench}` : ""),
6625
7026
  "",
6626
- chalk2.white(` ${verdict}`),
6627
- chalk2.dim(" across parallel agent sessions, last 30 days")
7027
+ chalk3.white(` ${verdict}`),
7028
+ chalk3.dim(" across parallel agent sessions, last 30 days")
6628
7029
  ].join("\n");
6629
7030
  return box(lines, { borderColor: "yellow" });
6630
7031
  }
@@ -6634,7 +7035,7 @@ function cardAllTime(view) {
6634
7035
  const max = Math.max(...months.map((m) => m.duration_hours), 1);
6635
7036
  const rows = months.map((m) => {
6636
7037
  const label = monthYearShort(m.month).padEnd(6);
6637
- return ` ${chalk2.dim(label)} ${bar2(m.duration_hours, max, 20)} ${chalk2.dim(`${Math.round(m.duration_hours)}h`)}`;
7038
+ return ` ${chalk3.dim(label)} ${bar2(m.duration_hours, max, 20)} ${chalk3.dim(`${Math.round(m.duration_hours)}h`)}`;
6638
7039
  });
6639
7040
  const since = view.all_time.first_session ? new Date(view.all_time.first_session).toISOString().slice(0, 7) : "your first local log";
6640
7041
  const latest = months[months.length - 1];
@@ -6644,14 +7045,14 @@ function cardAllTime(view) {
6644
7045
  )[0];
6645
7046
  const trend = latest && prior && prior.duration_hours > 0 ? `${monthShort(latest.month)}: ${latest.duration_hours >= prior.duration_hours ? "+" : ""}${Math.round((latest.duration_hours - prior.duration_hours) / prior.duration_hours * 100)}% vs previous month` : latest && prior && latest.duration_hours > 0 ? `${monthShort(latest.month)}: active after a quiet month` : null;
6646
7047
  const lines = [
6647
- chalk2.dim("YOUR AI CODING YEAR"),
7048
+ chalk3.dim("YOUR AI CODING YEAR"),
6648
7049
  "",
6649
7050
  ` ${bigNumber(`~${Math.round(view.all_time.total_hours).toLocaleString()} hours`)} from local logs`,
6650
- ` ${chalk2.white(view.all_time.total_sessions.toLocaleString())} sessions detected since ${since}`,
6651
- ...trend ? [` ${chalk2.dim(trend)}`] : [],
7051
+ ` ${chalk3.white(view.all_time.total_sessions.toLocaleString())} sessions detected since ${since}`,
7052
+ ...trend ? [` ${chalk3.dim(trend)}`] : [],
6652
7053
  "",
6653
7054
  ...rows,
6654
- best ? ` ${chalk2.dim(`best local-log month: ${monthShort(best.month)} \xB7 ~${Math.round(best.duration_hours)}h`)}` : ""
7055
+ best ? ` ${chalk3.dim(`best local-log month: ${monthShort(best.month)} \xB7 ~${Math.round(best.duration_hours)}h`)}` : ""
6655
7056
  ].join("\n");
6656
7057
  return box(lines, { borderColor: "cyan" });
6657
7058
  }
@@ -6670,25 +7071,25 @@ function cardRhythm(view) {
6670
7071
  const isNightOwl = critter?.key === "night_owl";
6671
7072
  const subhead = isNightOwl ? "while the 9-5ers sleep, you ship." : weekendPct < 10 ? "locked in on weekdays, weekends are yours." : weekendPct >= 35 ? "weekends are just more reps for you." : peak !== null && peak < 9 ? "up before standup. menace." : "you keep your own hours.";
6672
7073
  const lines = [
6673
- chalk2.dim("WHEN YOU CODE"),
7074
+ chalk3.dim("WHEN YOU CODE"),
6674
7075
  "",
6675
7076
  ...hourlyChart(
6676
7077
  view.hour_histogram,
6677
- critter ? { art: critter.art, color: chalk2.magenta } : null
7078
+ critter ? { art: critter.art, color: chalk3.magenta } : null
6678
7079
  ),
6679
7080
  "",
6680
- ` ${chalk2.white(caption)}`,
7081
+ ` ${chalk3.white(caption)}`,
6681
7082
  "",
6682
- ` ${chalk2.white("weekdays".padEnd(9))} ${bar2(weekdayPct, 100, 20)} ${chalk2.dim(weekdayPct + "%")}`,
6683
- ` ${chalk2.white("weekends".padEnd(9))} ${bar2(weekendPct, 100, 20)} ${chalk2.dim(weekendPct + "%")}`,
7083
+ ` ${chalk3.white("weekdays".padEnd(9))} ${bar2(weekdayPct, 100, 20)} ${chalk3.dim(weekdayPct + "%")}`,
7084
+ ` ${chalk3.white("weekends".padEnd(9))} ${bar2(weekendPct, 100, 20)} ${chalk3.dim(weekendPct + "%")}`,
6684
7085
  ...weekendBench ? ["", ` ${weekendBench}`] : [],
6685
7086
  ""
6686
7087
  ];
6687
7088
  if (view.rhythm_comment) {
6688
7089
  for (const l of wrapWords(view.rhythm_comment, 47))
6689
- lines.push(chalk2.italic.white(" " + l));
7090
+ lines.push(chalk3.italic.white(" " + l));
6690
7091
  } else {
6691
- lines.push(chalk2.dim(" " + subhead));
7092
+ lines.push(chalk3.dim(" " + subhead));
6692
7093
  }
6693
7094
  return box(lines.join("\n"), { borderColor });
6694
7095
  }
@@ -6701,10 +7102,10 @@ function cardProjects(view) {
6701
7102
  if (!usageReady(view)) return "";
6702
7103
  const projects = view.top_projects.filter((p) => p.commits > 0 || p.sessions > 0).slice(0, 3);
6703
7104
  if (projects.length === 0) return "";
6704
- const lines = [chalk2.dim("YOUR TOP PROJECTS"), ""];
7105
+ const lines = [chalk3.dim("YOUR TOP PROJECTS"), ""];
6705
7106
  const c = view.contributions;
6706
7107
  if (c && c.one_liner) {
6707
- for (const l of wrapWords(c.one_liner, 50)) lines.push(chalk2.dim(l));
7108
+ for (const l of wrapWords(c.one_liner, 50)) lines.push(chalk3.dim(l));
6708
7109
  lines.push("");
6709
7110
  }
6710
7111
  projects.forEach((p, i) => {
@@ -6714,14 +7115,14 @@ function cardProjects(view) {
6714
7115
  lines.push(` ${bigNumber(`\u25B8 ${name}`)} ${TITLE_GRADIENT(count)}`);
6715
7116
  if (p.blurb)
6716
7117
  for (const l of wrapWords(p.blurb, 44))
6717
- lines.push(` ${chalk2.white(l)}`);
7118
+ lines.push(` ${chalk3.white(l)}`);
6718
7119
  } else {
6719
7120
  const namePart = `\u25B8 ${name}`;
6720
7121
  const pad = " ".repeat(Math.max(2, 24 - namePart.length));
6721
- lines.push(` ${chalk2.white(namePart)}${pad}${chalk2.dim(count)}`);
7122
+ lines.push(` ${chalk3.white(namePart)}${pad}${chalk3.dim(count)}`);
6722
7123
  if (p.blurb)
6723
7124
  for (const l of wrapWords(p.blurb, 44))
6724
- lines.push(` ${chalk2.dim(l)}`);
7125
+ lines.push(` ${chalk3.dim(l)}`);
6725
7126
  }
6726
7127
  lines.push("");
6727
7128
  });
@@ -6737,17 +7138,17 @@ function card7AINative(view) {
6737
7138
  );
6738
7139
  const streak = view.streak_days;
6739
7140
  const lines = [
6740
- chalk2.dim("YOU'RE AI-NATIVE"),
7141
+ chalk3.dim("YOU'RE AI-NATIVE"),
6741
7142
  "",
6742
- ` commits since 2024: ${chalk2.white(view.total_commits.toLocaleString())}`,
6743
- ` AI co-authored: ${chalk2.white(view.ai_assisted_commits.toLocaleString())}`,
7143
+ ` commits since 2024: ${chalk3.white(view.total_commits.toLocaleString())}`,
7144
+ ` AI co-authored: ${chalk3.white(view.ai_assisted_commits.toLocaleString())}`,
6744
7145
  "",
6745
- ` ${bar2(pct, 100, 22)} ${chalk2.white(pct + "%")}${bench ? ` ${bench}` : ""}`,
7146
+ ` ${bar2(pct, 100, 22)} ${chalk3.white(pct + "%")}${bench ? ` ${bench}` : ""}`,
6746
7147
  ...streak >= 2 ? [
6747
- ` ${chalk2.white(`${streak}-day streak`)}${chalk2.dim(", coding without missing a day.")}`
7148
+ ` ${chalk3.white(`${streak}-day streak`)}${chalk3.dim(", coding without missing a day.")}`
6748
7149
  ] : [],
6749
7150
  "",
6750
- chalk2.dim(subhead)
7151
+ chalk3.dim(subhead)
6751
7152
  ].join("\n");
6752
7153
  return box(lines, { borderColor: "yellow" });
6753
7154
  }
@@ -6760,7 +7161,7 @@ function benchmarkInline(view, percentile) {
6760
7161
  const top = topPercentNumber(percentile);
6761
7162
  if (top === null) return "";
6762
7163
  const pct = `${top}%`;
6763
- return top < 10 ? chalk2.dim("(top ") + TITLE_GRADIENT(pct) + chalk2.dim(" of users)") : chalk2.dim(`(top ${pct} of users)`);
7164
+ return top < 10 ? chalk3.dim("(top ") + TITLE_GRADIENT(pct) + chalk3.dim(" of users)") : chalk3.dim(`(top ${pct} of users)`);
6764
7165
  }
6765
7166
  function formatTokens(n) {
6766
7167
  if (n >= 1e9) return (n / 1e9).toFixed(1) + "B";
@@ -6780,24 +7181,24 @@ function cardTokens(view) {
6780
7181
  const max = Math.max(...t.by_tool.map((x) => x.tokens), 1);
6781
7182
  const toolRows = t.by_tool.length > 0 ? t.by_tool.slice(0, 3).map((x) => {
6782
7183
  const padTool = x.tool.padEnd(13, " ");
6783
- return ` ${chalk2.white(padTool)} ${bar2(x.tokens, max, 16)} ${chalk2.dim(formatTokens(x.tokens))}`;
6784
- }).join("\n") : chalk2.dim(" (no tool breakdown available)");
6785
- const deltaLine = t.multiplier_vs_prior !== null && t.multiplier_vs_prior >= 1.05 ? chalk2.hex("#ff8a00")(
7184
+ return ` ${chalk3.white(padTool)} ${bar2(x.tokens, max, 16)} ${chalk3.dim(formatTokens(x.tokens))}`;
7185
+ }).join("\n") : chalk3.dim(" (no tool breakdown available)");
7186
+ const deltaLine = t.multiplier_vs_prior !== null && t.multiplier_vs_prior >= 1.05 ? chalk3.hex("#ff8a00")(
6786
7187
  ` \u2191 ${t.multiplier_vs_prior.toFixed(1)}\xD7 vs last period`
6787
- ) : t.multiplier_vs_prior !== null && t.multiplier_vs_prior < 0.95 ? chalk2.dim(
7188
+ ) : t.multiplier_vs_prior !== null && t.multiplier_vs_prior < 0.95 ? chalk3.dim(
6788
7189
  ` \u2193 ${(1 / t.multiplier_vs_prior).toFixed(1)}\xD7 less than last period`
6789
- ) : t.total_prior_30d > 0 ? chalk2.dim(` \u2248 same as last period`) : chalk2.dim(` rolling 30-day window`);
7190
+ ) : t.total_prior_30d > 0 ? chalk3.dim(` \u2248 same as last period`) : chalk3.dim(` rolling 30-day window`);
6790
7191
  const cost = t.estimated_retail_cost_usd;
6791
- const costLine = cost > 0 ? ` ${chalk2.dim("would have cost")} ${TITLE_GRADIENT(`~$${cost.toLocaleString()}`)} ${chalk2.dim("at retail API rates")}` : "";
6792
- const cursorNote = t.cursor_estimated ? t.cursor_token_share >= 0.9 ? chalk2.dim(
7192
+ const costLine = cost > 0 ? ` ${chalk3.dim("would have cost")} ${TITLE_GRADIENT(`~$${cost.toLocaleString()}`)} ${chalk3.dim("at retail API rates")}` : "";
7193
+ const cursorNote = t.cursor_estimated ? t.cursor_token_share >= 0.9 ? chalk3.dim(
6793
7194
  " \u2248 estimated from time spent in Cursor (no local token data)"
6794
- ) : chalk2.dim(
7195
+ ) : chalk3.dim(
6795
7196
  " includes Cursor (tokens + cost estimated from active time)"
6796
7197
  ) : "";
6797
- const cachedNote = t.cache_tokens > t.work_tokens ? chalk2.dim(" thankfully, most of them were cached :)") : t.cache_tokens > 0 ? chalk2.dim(" (includes cached context, re-read each turn)") : "";
6798
- const generatedLine = t.work_tokens > 0 ? ` ${chalk2.white(formatTokens(t.work_tokens))} ${chalk2.dim("were actually generated fresh")}` : "";
7198
+ const cachedNote = t.cache_tokens > t.work_tokens ? chalk3.dim(" thankfully, most of them were cached :)") : t.cache_tokens > 0 ? chalk3.dim(" (includes cached context, re-read each turn)") : "";
7199
+ const generatedLine = t.work_tokens > 0 ? ` ${chalk3.white(formatTokens(t.work_tokens))} ${chalk3.dim("were actually generated fresh")}` : "";
6799
7200
  const lines = [
6800
- chalk2.dim("YOU BURNED THIS MANY TOKENS"),
7201
+ chalk3.dim("YOU BURNED THIS MANY TOKENS"),
6801
7202
  "",
6802
7203
  ` ${totalLine}${tokensBench ? ` ${tokensBench}` : ""}`,
6803
7204
  "",
@@ -6819,23 +7220,23 @@ function cardToolRelationship(view) {
6819
7220
  if (r.kind === "insufficient") {
6820
7221
  return "";
6821
7222
  }
6822
- const streakLine = view.streak_days >= 2 ? ` ${chalk2.white(`${view.streak_days}-day streak, coding without missing a day.`)}` : null;
7223
+ const streakLine = view.streak_days >= 2 ? ` ${chalk3.white(`${view.streak_days}-day streak, coding without missing a day.`)}` : null;
6823
7224
  if (r.kind === "switch") {
6824
7225
  const rows = r.timeline.slice(-6).map((t) => {
6825
7226
  const monthShort2 = t.month.slice(2).replace("-", "/");
6826
7227
  const filled = Math.round(t.share * 10);
6827
- const bar3 = chalk2.hex("#ff8a00")("\u2588".repeat(filled)) + chalk2.gray("\u2591".repeat(10 - filled));
6828
- const label = t.dominant === r.from_tool ? chalk2.dim(t.dominant) : chalk2.white(t.dominant);
6829
- return ` ${chalk2.dim(monthShort2)} ${bar3} ${label}`;
7228
+ const bar3 = chalk3.hex("#ff8a00")("\u2588".repeat(filled)) + chalk3.gray("\u2591".repeat(10 - filled));
7229
+ const label = t.dominant === r.from_tool ? chalk3.dim(t.dominant) : chalk3.white(t.dominant);
7230
+ return ` ${chalk3.dim(monthShort2)} ${bar3} ${label}`;
6830
7231
  });
6831
7232
  return box(
6832
7233
  [
6833
- chalk2.dim("YOU SWITCHED TOOLS"),
7234
+ chalk3.dim("YOU SWITCHED TOOLS"),
6834
7235
  "",
6835
7236
  ...rows,
6836
7237
  "",
6837
- chalk2.dim(` joined the "${r.from_tool} \u2192 ${r.to_tool}" club`),
6838
- chalk2.dim(` in ${r.switch_month}.`),
7238
+ chalk3.dim(` joined the "${r.from_tool} \u2192 ${r.to_tool}" club`),
7239
+ chalk3.dim(` in ${r.switch_month}.`),
6839
7240
  ...streakLine ? ["", streakLine] : []
6840
7241
  ].join("\n"),
6841
7242
  { borderColor: "cyan" }
@@ -6844,14 +7245,14 @@ function cardToolRelationship(view) {
6844
7245
  if (r.kind === "loyalist") {
6845
7246
  return box(
6846
7247
  [
6847
- chalk2.dim("YOU'RE A LOYALIST"),
7248
+ chalk3.dim("YOU'RE A LOYALIST"),
6848
7249
  "",
6849
7250
  ` ${bigNumber(r.tool.toUpperCase())}`,
6850
7251
  "",
6851
- chalk2.dim(
7252
+ chalk3.dim(
6852
7253
  ` ${r.sessions_count} sessions across ${r.months_count} month${r.months_count === 1 ? "" : "s"}.`
6853
7254
  ),
6854
- chalk2.dim(" no second-guessing. you knew what you wanted."),
7255
+ chalk3.dim(" no second-guessing. you knew what you wanted."),
6855
7256
  ...streakLine ? ["", streakLine] : []
6856
7257
  ].join("\n"),
6857
7258
  { borderColor: "cyan" }
@@ -6860,16 +7261,16 @@ function cardToolRelationship(view) {
6860
7261
  if (r.kind === "polyglot") {
6861
7262
  const rows = r.tools.slice(0, 4).map((t) => {
6862
7263
  const filled = Math.round(t.share * 22);
6863
- const bar3 = chalk2.hex("#ff8a00")("\u2588".repeat(filled)) + chalk2.gray("\u2591".repeat(22 - filled));
6864
- return ` ${chalk2.white(t.tool.padEnd(12, " "))} ${bar3} ${chalk2.dim(Math.round(t.share * 100) + "%")}`;
7264
+ const bar3 = chalk3.hex("#ff8a00")("\u2588".repeat(filled)) + chalk3.gray("\u2591".repeat(22 - filled));
7265
+ return ` ${chalk3.white(t.tool.padEnd(12, " "))} ${bar3} ${chalk3.dim(Math.round(t.share * 100) + "%")}`;
6865
7266
  });
6866
7267
  return box(
6867
7268
  [
6868
- chalk2.dim("YOU'RE A POLYGLOT"),
7269
+ chalk3.dim("YOU'RE A POLYGLOT"),
6869
7270
  "",
6870
7271
  ...rows,
6871
7272
  "",
6872
- chalk2.dim(" you don't pick favorites. respect."),
7273
+ chalk3.dim(" you don't pick favorites. respect."),
6873
7274
  ...streakLine ? ["", streakLine] : []
6874
7275
  ].join("\n"),
6875
7276
  { borderColor: "cyan" }
@@ -6931,17 +7332,17 @@ function cardModelsStack(view) {
6931
7332
  const column = (mm) => {
6932
7333
  if (!mm) return [];
6933
7334
  const c = modelProviderColor(mm.prov);
6934
- const hex = (s) => chalk2.hex(c)(s);
7335
+ const hex = (s) => chalk3.hex(c)(s);
6935
7336
  const cap = " " + hex("\u256D" + "\u2500".repeat(8) + "\u256E") + " ";
6936
7337
  const base = " " + hex("\u2570" + "\u2500".repeat(8) + "\u256F") + " ";
6937
7338
  const side = " " + hex("\u2502") + " ".repeat(8) + hex("\u2502") + " ";
6938
- const num3 = " " + hex("\u2502") + chalk2.bold.white(center("#" + mm.rank, 8)) + hex("\u2502") + " ";
7339
+ const num3 = " " + hex("\u2502") + chalk3.bold.white(center("#" + mm.rank, 8)) + hex("\u2502") + " ";
6939
7340
  const h = heights[mm.rank];
6940
7341
  const mid = Math.floor((h - 1) / 2);
6941
7342
  const body = [];
6942
7343
  for (let i = 0; i < h; i++) body.push(i === mid ? num3 : side);
6943
- const label = mm.rank === 1 ? bigNumber(center(mm.name)) : chalk2.white(center(mm.name));
6944
- return [label, chalk2.dim(center(mm.pct + "%")), cap, ...body, base];
7344
+ const label = mm.rank === 1 ? bigNumber(center(mm.name)) : chalk3.white(center(mm.name));
7345
+ return [label, chalk3.dim(center(mm.pct + "%")), cap, ...body, base];
6945
7346
  };
6946
7347
  const cols = [column(second), column(first), column(third)];
6947
7348
  const maxH = Math.max(...cols.map((col) => col.length));
@@ -6949,20 +7350,20 @@ function cardModelsStack(view) {
6949
7350
  (col) => Array(maxH - col.length).fill(blankCol).concat(col)
6950
7351
  );
6951
7352
  const header = ranked.length === 1 ? "YOUR MODEL & STACK" : "YOUR MODELS & STACK";
6952
- const lines = [chalk2.dim(header), ""];
7353
+ const lines = [chalk3.dim(header), ""];
6953
7354
  lines.push(
6954
- " " + [blankCol, chalk2.hex("#ffd700")(center("\u265B")), blankCol].join(" ")
7355
+ " " + [blankCol, chalk3.hex("#ffd700")(center("\u265B")), blankCol].join(" ")
6955
7356
  );
6956
7357
  for (let r = 0; r < maxH; r++)
6957
7358
  lines.push(" " + [padded[0][r], padded[1][r], padded[2][r]].join(" "));
6958
7359
  lines.push("");
6959
7360
  lines.push(
6960
- ` top pick: ${chalk2.white(first.name)} ${chalk2.dim(`\u2014 ${first.pct}% of sessions`)}`
7361
+ ` top pick: ${chalk3.white(first.name)} ${chalk3.dim(`\u2014 ${first.pct}% of sessions`)}`
6961
7362
  );
6962
7363
  if (view.stack_comment) {
6963
7364
  lines.push("");
6964
7365
  for (const l of wrapWords(view.stack_comment, 46))
6965
- lines.push(chalk2.italic.white(" " + l));
7366
+ lines.push(chalk3.italic.white(" " + l));
6966
7367
  }
6967
7368
  return box(lines.join("\n"), { borderColor: "magenta" });
6968
7369
  }
@@ -6973,25 +7374,25 @@ function cardCodeFootprint(view) {
6973
7374
  const netLabel = `${f.net >= 0 ? "+" : ""}${compactNum(f.net)}`;
6974
7375
  const subhead = f.label === "Cleaner" ? "you delete more than you add. the slop stops with you." : f.label === "Shipper" ? `${f.additive_ratio >= 0 ? Math.round(f.additive_ratio * 100) : 0}% of your churn is brand-new code.` : "you rework as much as you write. nothing ships half-baked.";
6975
7376
  const lines = [
6976
- chalk2.dim("YOUR CODE FOOTPRINT"),
7377
+ chalk3.dim("YOUR CODE FOOTPRINT"),
6977
7378
  "",
6978
7379
  ` ${bigNumber(f.label.toUpperCase())}`,
6979
7380
  "",
6980
- ` ${chalk2.green("+ " + compactNum(f.lines_added).padEnd(7))} ${coloredBar(f.lines_added, max, 22, "#22c55e")} ${chalk2.dim("added")}`,
6981
- ` ${chalk2.red("- " + compactNum(f.lines_deleted).padEnd(7))} ${coloredBar(f.lines_deleted, max, 22, "#ef4444")} ${chalk2.dim("deleted")}`,
7381
+ ` ${chalk3.green("+ " + compactNum(f.lines_added).padEnd(7))} ${coloredBar(f.lines_added, max, 22, "#22c55e")} ${chalk3.dim("added")}`,
7382
+ ` ${chalk3.red("- " + compactNum(f.lines_deleted).padEnd(7))} ${coloredBar(f.lines_deleted, max, 22, "#ef4444")} ${chalk3.dim("deleted")}`,
6982
7383
  "",
6983
- ` ${chalk2.white("net " + netLabel)} ${chalk2.dim("lines since 2024")}`
7384
+ ` ${chalk3.white("net " + netLabel)} ${chalk3.dim("lines since 2024")}`
6984
7385
  ];
6985
7386
  if (f.median_commit_size > 0)
6986
7387
  lines.push(
6987
- ` ${chalk2.dim(`typical commit ~${compactNum(f.median_commit_size)} lines \xB7 biggest ${compactNum(f.biggest_commit_size)}`)}`
7388
+ ` ${chalk3.dim(`typical commit ~${compactNum(f.median_commit_size)} lines \xB7 biggest ${compactNum(f.biggest_commit_size)}`)}`
6988
7389
  );
6989
7390
  lines.push("");
6990
7391
  if (f.line) {
6991
7392
  for (const l of wrapWords(f.line, 47))
6992
- lines.push(chalk2.italic.white(" " + l));
7393
+ lines.push(chalk3.italic.white(" " + l));
6993
7394
  } else {
6994
- lines.push(chalk2.dim(" " + subhead));
7395
+ lines.push(chalk3.dim(" " + subhead));
6995
7396
  }
6996
7397
  return box(lines.join("\n"), { borderColor: "green" });
6997
7398
  }
@@ -7002,20 +7403,20 @@ function cardConcurrency(view) {
7002
7403
  const longest = days >= 1.5 ? `${days.toFixed(0)} days` : `${Math.round(c.longest_session_hours)}h`;
7003
7404
  const bench = benchmarkInline(view, view.rank_summary.avg_agents_percentile);
7004
7405
  const lines = [
7005
- chalk2.dim("HOW MANY AGENTS YOU JUGGLE"),
7406
+ chalk3.dim("HOW MANY AGENTS YOU JUGGLE"),
7006
7407
  "",
7007
- ` ${bigNumber(`~${c.open_tab_avg}`)} ${chalk2.white("agents open at once")}${bench ? ` ${bench}` : ""}`,
7408
+ ` ${bigNumber(`~${c.open_tab_avg}`)} ${chalk3.white("agents open at once")}${bench ? ` ${bench}` : ""}`,
7008
7409
  "",
7009
- ` ${chalk2.white("peak".padEnd(14))} ${chalk2.dim(`${c.open_tab_peak} at once`)}`,
7010
- ` ${chalk2.white("longest tab".padEnd(14))} ${chalk2.dim(`${longest} open`)}`,
7011
- ` ${chalk2.white("2+ active".padEnd(14))} ${chalk2.dim(`${Math.round(c.active_juggle_pct * 100)}% of your coding time`)}`,
7410
+ ` ${chalk3.white("peak".padEnd(14))} ${chalk3.dim(`${c.open_tab_peak} at once`)}`,
7411
+ ` ${chalk3.white("longest tab".padEnd(14))} ${chalk3.dim(`${longest} open`)}`,
7412
+ ` ${chalk3.white("2+ active".padEnd(14))} ${chalk3.dim(`${Math.round(c.active_juggle_pct * 100)}% of your coding time`)}`,
7012
7413
  ""
7013
7414
  ];
7014
7415
  if (c.line) {
7015
7416
  for (const l of wrapWords(c.line, 47))
7016
- lines.push(chalk2.italic.white(" " + l));
7417
+ lines.push(chalk3.italic.white(" " + l));
7017
7418
  } else {
7018
- lines.push(chalk2.dim(" a one-agent setup could never."));
7419
+ lines.push(chalk3.dim(" a one-agent setup could never."));
7019
7420
  }
7020
7421
  return box(lines.join("\n"), { borderColor: "blue" });
7021
7422
  }
@@ -7032,22 +7433,22 @@ function cardTalk(view) {
7032
7433
  const c = view.conversation;
7033
7434
  const v = view.collaboration;
7034
7435
  if ((!c || c.total_prompts < 10) && !v) return "";
7035
- const lines = [chalk2.dim("HOW YOU TALK"), ""];
7436
+ const lines = [chalk3.dim("HOW YOU TALK"), ""];
7036
7437
  if (c?.line) {
7037
7438
  for (const l of wrapWords(c.line, 47))
7038
- lines.push(chalk2.italic.white(" " + l));
7439
+ lines.push(chalk3.italic.white(" " + l));
7039
7440
  lines.push("");
7040
7441
  }
7041
7442
  if (v) {
7042
7443
  lines.push(` ${bigNumber(v.style_label)}`);
7043
7444
  if (v.summary)
7044
7445
  for (const l of wrapWords(v.summary, 47))
7045
- lines.push(chalk2.white(" " + l));
7446
+ lines.push(chalk3.white(" " + l));
7046
7447
  const sigs = [
7047
7448
  ["reads", v.signals.fact_checking],
7048
7449
  ["drives", v.signals.autonomy]
7049
7450
  ].filter(([, t]) => t).map(
7050
- ([label, t]) => ` ${chalk2.dim(label.padEnd(8))} ${chalk2.white(briefSignal(t))}`
7451
+ ([label, t]) => ` ${chalk3.dim(label.padEnd(8))} ${chalk3.white(briefSignal(t))}`
7051
7452
  );
7052
7453
  if (sigs.length > 0) {
7053
7454
  lines.push("");
@@ -7057,11 +7458,11 @@ function cardTalk(view) {
7057
7458
  if (c) {
7058
7459
  lines.push("");
7059
7460
  lines.push(
7060
- ` ${chalk2.white(c.total_prompts.toLocaleString())} ${chalk2.dim("prompts")} \xB7 ${chalk2.white(Math.round(c.question_ratio * 100) + "%")} ${chalk2.dim("questions")} \xB7 ${chalk2.white("~" + c.avg_prompt_chars)} ${chalk2.dim("chars")}`
7461
+ ` ${chalk3.white(c.total_prompts.toLocaleString())} ${chalk3.dim("prompts")} \xB7 ${chalk3.white(Math.round(c.question_ratio * 100) + "%")} ${chalk3.dim("questions")} \xB7 ${chalk3.white("~" + c.avg_prompt_chars)} ${chalk3.dim("chars")}`
7061
7462
  );
7062
7463
  if (c.themes.length > 0)
7063
7464
  lines.push(
7064
- ` ${chalk2.dim("recurring: " + c.themes.slice(0, 4).join(", "))}`
7465
+ ` ${chalk3.dim("recurring: " + c.themes.slice(0, 4).join(", "))}`
7065
7466
  );
7066
7467
  }
7067
7468
  return box(lines.join("\n"), { borderColor: "magenta" });
@@ -7073,13 +7474,13 @@ function cardProficiency(view) {
7073
7474
  if (!p) {
7074
7475
  return box(
7075
7476
  [
7076
- chalk2.dim(" you are\u2026"),
7477
+ chalk3.dim(" you are\u2026"),
7077
7478
  "",
7078
- chalk2.hex("#ff8a00")(mascot),
7479
+ chalk3.hex("#ff8a00")(mascot),
7079
7480
  "",
7080
7481
  ` ${archetype}`,
7081
7482
  "",
7082
- ` ${chalk2.italic.white(`"${view.zinger}"`)}`
7483
+ ` ${chalk3.italic.white(`"${view.zinger}"`)}`
7083
7484
  ].join("\n"),
7084
7485
  { borderColor: "yellow" }
7085
7486
  );
@@ -7087,27 +7488,33 @@ function cardProficiency(view) {
7087
7488
  const scoreTop = topPercentNumber(p.score_percentile ?? null);
7088
7489
  const sampleSize = view.rank_summary.sample_size;
7089
7490
  const cohort = scoreTop != null && sampleSize > 0 ? `top ${scoreTop}% of ${sampleSize.toLocaleString()} users` : view.cohort_size > 0 ? `among ${view.cohort_size.toLocaleString()} users so far` : "";
7090
- const metricRow = (label, value) => value === null ? null : ` ${chalk2.white(label.padEnd(12))} ${bar2(value, 100, 10)} ${chalk2.dim(String(value))}`;
7491
+ const metricRow = (label, value) => value === null ? null : ` ${chalk3.white(label.padEnd(12))} ${bar2(value, 100, 10)} ${chalk3.dim(String(value))}`;
7091
7492
  const bars = [
7092
7493
  metricRow("intensity", p.intensity),
7093
7494
  metricRow("consistency", p.consistency),
7094
- p.craft_bonus > 0 ? ` ${chalk2.white("craft".padEnd(12))} ${chalk2.hex("#ff8a00")(`+${p.craft_bonus}`)} ${chalk2.dim("clean prompting")}` : null
7495
+ p.craft_bonus > 0 ? ` ${chalk3.white("craft".padEnd(12))} ${chalk3.hex("#ff8a00")(`+${p.craft_bonus}`)} ${chalk3.dim("clean prompting")}` : null
7095
7496
  ].filter((r) => r !== null);
7096
7497
  const zingerLines = wrapWords(`"${view.zinger}"`, INNER_WIDTH).map(
7097
- (l) => centerText(l, chalk2.italic.white)
7498
+ (l) => centerText(l, chalk3.italic.white)
7098
7499
  );
7099
7500
  const commentLines = p.comment ? wrapWords(p.comment, INNER_WIDTH - 4).map(
7100
- (l, i) => i === 0 ? ` ${chalk2.hex("#ff8a00")(">")} ${chalk2.white(l)}` : ` ${chalk2.white(l)}`
7501
+ (l, i) => i === 0 ? ` ${chalk3.hex("#ff8a00")(">")} ${chalk3.white(l)}` : ` ${chalk3.white(l)}`
7101
7502
  ) : [];
7102
7503
  const tier = tierForScore2(p.score);
7504
+ const nextTier = TIERS2[TIERS2.findIndex((t) => t.key === tier.key) + 1];
7505
+ const nextTierLine = nextTier ? centerText(
7506
+ `${nextTier.min - p.score} pts to ${nextTier.label.toLowerCase()}`,
7507
+ chalk3.hex("#ad5cff")
7508
+ ) : null;
7103
7509
  const lines = [
7104
- centerBlock(tier.art, chalk2.hex("#ff8a00")),
7510
+ centerBlock(tier.art, chalk3.hex("#ff8a00")),
7105
7511
  "",
7106
7512
  centerText(`\u2500\u2500 ${tier.label} \u2500\u2500`, bigNumber),
7107
7513
  centerText(`${p.score} / 100`, bigNumber),
7108
- cohort ? centerText(cohort, chalk2.dim) : null,
7514
+ cohort ? centerText(cohort, chalk3.dim) : null,
7515
+ nextTierLine,
7109
7516
  "",
7110
- centerText(view.archetype_label, chalk2.bold.hex("#ad5cff")),
7517
+ centerText(view.archetype_label, chalk3.bold.hex("#ad5cff")),
7111
7518
  ...zingerLines,
7112
7519
  "",
7113
7520
  ...bars,
@@ -7145,7 +7552,7 @@ async function renderWrappedAll(view) {
7145
7552
  " " + TITLE_GRADIENT.multiline("\u2591\u2592\u2593 YOUR AI WRAPPED \u2593\u2592\u2591") + "\n"
7146
7553
  );
7147
7554
  process.stdout.write(
7148
- chalk2.dim(` ${view.name.toLowerCase()} \xB7 last 30 days
7555
+ chalk3.dim(` ${view.name.toLowerCase()} \xB7 last 30 days
7149
7556
 
7150
7557
  `)
7151
7558
  );
@@ -7247,7 +7654,8 @@ async function createWrapped(args) {
7247
7654
  const body = JSON.stringify({
7248
7655
  profile,
7249
7656
  submission_id: args.submissionId ?? void 0,
7250
- group: args.group ?? void 0
7657
+ group: args.group ?? void 0,
7658
+ challenge: args.challenge ?? void 0
7251
7659
  });
7252
7660
  const bodyKb = Math.round(bytesAfter / 1024);
7253
7661
  let created = null;
@@ -7316,16 +7724,14 @@ async function createWrapped(args) {
7316
7724
  id: created.id,
7317
7725
  share_url: created.share_url,
7318
7726
  view,
7319
- group: created.group ?? null
7727
+ group: created.group ?? null,
7728
+ challenge_code: created.challenge_code ?? null,
7729
+ short_url: created.short_url ?? null,
7730
+ versus: created.versus ?? null,
7731
+ previous: created.previous ?? null
7320
7732
  };
7321
7733
  }
7322
7734
 
7323
- // src/wrapped-share.ts
7324
- import open from "open";
7325
- async function openWrapped(shareUrl) {
7326
- await open(shareUrl);
7327
- }
7328
-
7329
7735
  // src/cli.ts
7330
7736
  var MAX_TURNS = 40;
7331
7737
  function profileChatEnabled() {
@@ -7368,18 +7774,18 @@ var MODE_OPTIONS = [
7368
7774
  function renderModeMenu(selected) {
7369
7775
  const out = [
7370
7776
  "",
7371
- chalk3.white(" How do you want to run Standout?"),
7777
+ chalk4.white(" How do you want to run Standout?"),
7372
7778
  ""
7373
7779
  ];
7374
7780
  MODE_OPTIONS.forEach((opt, i) => {
7375
7781
  const active = i === selected;
7376
- const pointer = active ? chalk3.hex("#ad5cff")("\u276F ") : " ";
7377
- const title = active ? chalk3.bold.white(opt.title) + chalk3.dim(opt.tag) : chalk3.dim(opt.title + opt.tag);
7782
+ const pointer = active ? chalk4.hex("#ad5cff")("\u276F ") : " ";
7783
+ const title = active ? chalk4.bold.white(opt.title) + chalk4.dim(opt.tag) : chalk4.dim(opt.title + opt.tag);
7378
7784
  out.push(`${pointer}${title}`);
7379
- for (const line of opt.lines) out.push(chalk3.dim(` ${line}`));
7785
+ for (const line of opt.lines) out.push(chalk4.dim(` ${line}`));
7380
7786
  out.push("");
7381
7787
  });
7382
- out.push(chalk3.dim(" \u2191/\u2193 to move \xB7 enter to select"));
7788
+ out.push(chalk4.dim(" \u2191/\u2193 to move \xB7 enter to select"));
7383
7789
  return out.join("\n");
7384
7790
  }
7385
7791
  async function chooseMode() {
@@ -7482,8 +7888,8 @@ function startLoadingLine(label) {
7482
7888
  let frame = 0;
7483
7889
  const render = () => {
7484
7890
  const dots = frames[frame % frames.length];
7485
- const accent = chalk3.hex("#ad5cff")(dots);
7486
- const text = chalk3.white(label);
7891
+ const accent = chalk4.hex("#ad5cff")(dots);
7892
+ const text = chalk4.white(label);
7487
7893
  process.stderr.write(`\r\x1B[2K ${accent} ${text}`);
7488
7894
  frame += 1;
7489
7895
  };
@@ -7494,54 +7900,6 @@ function startLoadingLine(label) {
7494
7900
  process.stderr.write("\r\x1B[2K");
7495
7901
  };
7496
7902
  }
7497
- async function askLine(prompt) {
7498
- if (!process.stdin.isTTY) return "y";
7499
- return new Promise((resolve) => {
7500
- const iface = createInterface3({
7501
- input: process.stdin,
7502
- output: process.stderr
7503
- });
7504
- iface.question(prompt, (ans) => {
7505
- iface.close();
7506
- resolve(ans.trim());
7507
- });
7508
- });
7509
- }
7510
- async function maybeShareWrapped(wrapped) {
7511
- if (!process.stdin.isTTY) {
7512
- process.stderr.write(` your wrapped: ${wrapped.share_url}
7513
-
7514
- `);
7515
- return;
7516
- }
7517
- const ans = await askLine(
7518
- chalk3.white(" press enter to see your ai wrapped ")
7519
- );
7520
- process.stderr.write("\n");
7521
- const shared = !ans || ans.toLowerCase() !== "n";
7522
- if (!shared) {
7523
- process.stderr.write(` your wrapped: ${wrapped.share_url}
7524
-
7525
- `);
7526
- return;
7527
- }
7528
- process.stderr.write(" opening your wrapped...\n");
7529
- try {
7530
- await openWrapped(wrapped.share_url);
7531
- await markWrappedShared(wrapped.id);
7532
- process.stderr.write(` opened: ${wrapped.share_url}
7533
-
7534
- `);
7535
- } catch (err) {
7536
- process.stderr.write(
7537
- ` couldn't open browser. open it manually: ${wrapped.share_url}
7538
- `
7539
- );
7540
- process.stderr.write(` (${err instanceof Error ? err.message : err})
7541
-
7542
- `);
7543
- }
7544
- }
7545
7903
  async function renderLocalTerminal(prefetched) {
7546
7904
  const view = aggregateView({
7547
7905
  profile: prefetched,
@@ -7620,23 +7978,30 @@ async function runLocal() {
7620
7978
  " (Your terminal can't show inline images \u2014 open the saved card below.)\n"
7621
7979
  );
7622
7980
  }
7623
- const post = encodeURIComponent(
7624
- "Check out my AI Wrapped \u{1F916} \u2014 get yours: npx standout"
7625
- );
7626
- process.stderr.write(
7627
- `
7981
+ process.stderr.write(`
7628
7982
  Saved card: ${file}
7629
-
7630
- Share it:
7631
- X: https://x.com/intent/post?text=${post}
7632
- LinkedIn: https://www.linkedin.com/feed/?shareActive=true&text=${post}
7633
-
7634
- (Rendered on your machine \u2014 nothing left your computer.)
7983
+ `);
7984
+ await runEndgame({
7985
+ view: aggregateView({
7986
+ profile: prefetched,
7987
+ computed: {},
7988
+ share_url: ""
7989
+ }),
7990
+ wrappedId: null,
7991
+ shareUrl: null,
7992
+ shortUrl: null,
7993
+ challengeCode: null,
7994
+ versus: null,
7995
+ previous: null,
7996
+ localOnly: true
7997
+ });
7998
+ process.stderr.write(
7999
+ ` (Rendered on your machine \u2014 nothing left your computer.)
7635
8000
 
7636
8001
  `
7637
8002
  );
7638
8003
  }
7639
- async function runAgent(jobId) {
8004
+ async function runAgent(jobId, challengeCode) {
7640
8005
  if (profileChatEnabled()) {
7641
8006
  ensureInteractive("The interactive profile chat");
7642
8007
  }
@@ -7676,7 +8041,8 @@ async function runAgent(jobId) {
7676
8041
  const wrapped2 = await createWrapped({
7677
8042
  profile: prefetched2,
7678
8043
  submissionId: null,
7679
- group: jobId ?? null
8044
+ group: jobId ?? null,
8045
+ challenge: challengeCode ?? null
7680
8046
  });
7681
8047
  return { wrapped: wrapped2, prefetched: prefetched2 };
7682
8048
  } catch {
@@ -7703,7 +8069,17 @@ async function runAgent(jobId) {
7703
8069
  `
7704
8070
  );
7705
8071
  }
7706
- await maybeShareWrapped(wrapped);
8072
+ await maybeAutoInstallSchedule(jobId);
8073
+ await runEndgame({
8074
+ view: wrapped.view,
8075
+ wrappedId: wrapped.id,
8076
+ shareUrl: wrapped.share_url,
8077
+ shortUrl: wrapped.short_url,
8078
+ challengeCode: wrapped.challenge_code,
8079
+ versus: wrapped.versus,
8080
+ previous: wrapped.previous,
8081
+ localOnly: false
8082
+ });
7707
8083
  } else {
7708
8084
  process.stderr.write(
7709
8085
  " (couldn't generate wrapped right now. continuing profile setup.)\n\n"
@@ -7861,18 +8237,24 @@ async function main() {
7861
8237
  await startMcpServer();
7862
8238
  return;
7863
8239
  }
7864
- const jobId = args.find((a) => !a.startsWith("-"));
8240
+ const positional = args.filter((a) => !a.startsWith("-"));
8241
+ const challengeCode = positional.find((a) => a.startsWith("beat-"));
8242
+ const jobId = positional.find((a) => !a.startsWith("beat-"));
7865
8243
  printBanner();
7866
8244
  let mode;
7867
8245
  if (localOnly) mode = "local";
7868
- else if (jobId) mode = "full";
8246
+ else if (jobId || challengeCode) mode = "full";
7869
8247
  else mode = await chooseMode();
7870
8248
  if (mode === "local") {
8249
+ if (challengeCode) {
8250
+ process.stderr.write(
8251
+ " (challenges need the full run to rank you \u2014 skipping the versus in local mode)\n"
8252
+ );
8253
+ }
7871
8254
  await runLocal();
7872
8255
  } else {
7873
8256
  if (jobId) process.env.STANDOUT_JOB_ID = jobId;
7874
- await runAgent(jobId);
7875
- await maybeAutoInstallSchedule(jobId);
8257
+ await runAgent(jobId, challengeCode);
7876
8258
  }
7877
8259
  }
7878
8260
  main().catch((error) => {