sigrank 0.18.5 → 1.0.1

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 (80) hide show
  1. package/CHANGELOG.md +158 -0
  2. package/MCP_SERVER_DESCRIPTION.md +172 -0
  3. package/README.md +94 -41
  4. package/adapters/index.mjs +1100 -0
  5. package/adapters/tokenpull.mjs +568 -0
  6. package/adapters.mjs +1 -857
  7. package/analytics/cascade.mjs +338 -0
  8. package/cascade.mjs +1 -274
  9. package/cli.mjs +1 -1853
  10. package/connect.mjs +1 -13
  11. package/identity/connect.mjs +13 -0
  12. package/identity/keystore.mjs +231 -0
  13. package/identity/sign.mjs +106 -0
  14. package/index.mjs +47 -162
  15. package/keystore.mjs +1 -242
  16. package/lib/constants.mjs +137 -0
  17. package/lib/pkg-version.mjs +59 -0
  18. package/manifest.json +46 -0
  19. package/narrate.mjs +1 -77
  20. package/package.json +41 -16
  21. package/preflight.mjs +1 -191
  22. package/presentation/cli.mjs +1926 -0
  23. package/presentation/narrate.mjs +219 -0
  24. package/presentation/tui-themes.mjs +189 -0
  25. package/presentation/tui.mjs +3316 -0
  26. package/prompts/check-my-efficiency.md +1 -0
  27. package/prompts/compare-with-leader.md +1 -0
  28. package/prompts/simulate-improvement.md +1 -0
  29. package/proxy.mjs +492 -0
  30. package/resources/class-tiers.md +81 -0
  31. package/resources/data-policy.md +31 -0
  32. package/resources/install-guide.md +59 -0
  33. package/resources/privacy-model.md +44 -0
  34. package/resources/scoring-formula.md +24 -0
  35. package/review.mjs +263 -0
  36. package/sign.mjs +1 -106
  37. package/submit/index.mjs +297 -0
  38. package/submit/preflight.mjs +191 -0
  39. package/submit.mjs +1 -303
  40. package/tokenpull.mjs +1 -576
  41. package/tokscale_analytics.mjs +864 -0
  42. package/tools/_framing.mjs +217 -0
  43. package/tools/_helpers.mjs +253 -0
  44. package/tools/_peer-matching.mjs +361 -0
  45. package/tools/_report.mjs +262 -0
  46. package/tools/_schemas.mjs +492 -0
  47. package/tools/_verifiers.mjs +148 -0
  48. package/tools/compare-operators.mjs +80 -0
  49. package/tools/compare-self.mjs +124 -0
  50. package/tools/describe-power-user.mjs +78 -0
  51. package/tools/diagnose-cascade.mjs +192 -0
  52. package/tools/discover-peers.mjs +198 -0
  53. package/tools/enroll.mjs +119 -0
  54. package/tools/get-best-operator.mjs +59 -0
  55. package/tools/get-leaderboard.mjs +27 -0
  56. package/tools/get-operator.mjs +33 -0
  57. package/tools/index.mjs +229 -0
  58. package/tools/optimize-efficiency.mjs +170 -0
  59. package/tools/rank-paste.mjs +51 -0
  60. package/tools/rank-windows.mjs +120 -0
  61. package/tools/self-improve.mjs +423 -0
  62. package/tools/simulate-change.mjs +207 -0
  63. package/tools/submit-paste.mjs +121 -0
  64. package/tools/submit-verified.mjs +153 -0
  65. package/tools/suggest-improvements.mjs +168 -0
  66. package/tools/tokenpull-compare.mjs +123 -0
  67. package/tools/tokenpull-submit.mjs +235 -0
  68. package/tools/tokenpull.mjs +113 -0
  69. package/tools/tokscale-breakdown.mjs +119 -0
  70. package/tools/tokscale-competitive-intel.mjs +45 -0
  71. package/tools/tokscale-cost-analysis.mjs +31 -0
  72. package/tools/tokscale-developer-profile.mjs +36 -0
  73. package/tools/tokscale-device-profile.mjs +35 -0
  74. package/tools/tokscale-market-share.mjs +38 -0
  75. package/tools/tokscale-mcp-usage.mjs +33 -0
  76. package/tools/tokscale-model-trends.mjs +32 -0
  77. package/tools/watch-tokenpull.mjs +134 -0
  78. package/tools.mjs +1 -3897
  79. package/tui.mjs +4 -2650
  80. package/banner.svg +0 -7
@@ -0,0 +1,219 @@
1
+ /**
2
+ * narrate.mjs — deterministic prose "card" for a cascade result.
3
+ *
4
+ * Uses the 10 build archetype composition classifier, synced with the app's
5
+ * lib/analytics/build-archetypes.ts. Every operator lands in exactly one
6
+ * archetype that describes their operating shape — not their rank.
7
+ *
8
+ * Classification precedence (first match wins):
9
+ * 1. CONVERGENT — P80+ on all 3 axes (leverage + velocity + construction)
10
+ * 2. KINETIC — velocity >= 0.80
11
+ * 3. Construction — construction >= 0.02 (BUILDER / RECURSIVE / AMPLIFIER)
12
+ * 4. Reuse depth — else (INPUT-BOUND / PRIMING / CONTEXTUAL / DEEP READER / ARCHIVIST)
13
+ *
14
+ * The three derived dimensions:
15
+ * leverage = cache_read / input
16
+ * velocity = output / input
17
+ * construction = cache_write / cache_read
18
+ *
19
+ * Token-only. No network, no randomness.
20
+ */
21
+
22
+ // Safe formatters: never emit NaN/Infinity/undefined into the card.
23
+ const safeNum = (n) => (Number.isFinite(Number(n)) ? Number(n) : null);
24
+ const comma = (n, dec) => {
25
+ const v = safeNum(n);
26
+ return v !== null
27
+ ? v.toLocaleString("en-US", {
28
+ minimumFractionDigits: dec,
29
+ maximumFractionDigits: dec,
30
+ })
31
+ : "—";
32
+ };
33
+ const plain = (n, dec) => {
34
+ const v = safeNum(n);
35
+ return v !== null ? v.toFixed(dec) : "—";
36
+ };
37
+
38
+ // P80 thresholds calibrated from HCM cut (1,586 operators).
39
+ const CONVERGENT_T = { levP80: 74.6, velP80: 0.34, constrP80: 0.0431 };
40
+ const VEL_KINETIC = 0.8;
41
+ const LEV_INPUT_BOUND = 5;
42
+ const LEV_PRIMING = 10;
43
+ const LEV_CONTEXTUAL = 15;
44
+ const LEV_DEEP_READER = 23;
45
+ const CONSTR_ACTIVE = 0.02;
46
+ const LEV_BUILDER = 30;
47
+ const LEV_RECURSIVE = 50;
48
+
49
+ /** Classify an operator's cascade into one of 10 build archetypes.
50
+ * Returns { key, name, family, familyLabel, blurb }. */
51
+ export function classifyArchetype(cascade) {
52
+ const v = safeNum(cascade.velocity);
53
+ const l = safeNum(cascade.leverage);
54
+ const cw = cascade.pillars ? Number(cascade.pillars.cacheCreate) : NaN;
55
+ const cr = cascade.pillars ? Number(cascade.pillars.cacheRead) : NaN;
56
+ const input = cascade.pillars ? Number(cascade.pillars.input) : NaN;
57
+
58
+ // Derive construction = cache_write / cache_read
59
+ const constr = Number.isFinite(cr) && cr > 0 && Number.isFinite(cw) ? cw / cr : 0;
60
+ const lev = l ?? 0;
61
+ const vel = v ?? 0;
62
+
63
+ // 1. CONVERGENT — all three axes elevated (P80+)
64
+ if (
65
+ lev > CONVERGENT_T.levP80 &&
66
+ vel > CONVERGENT_T.velP80 &&
67
+ constr > CONVERGENT_T.constrP80
68
+ ) {
69
+ return {
70
+ key: "convergent",
71
+ name: "CONVERGENT",
72
+ family: "convergence",
73
+ familyLabel: "Convergence",
74
+ blurb:
75
+ "Deep reuse, active construction, and high generation rise together. A rare composition where all three operating axes are elevated without the usual tradeoffs.",
76
+ };
77
+ }
78
+
79
+ // 2. KINETIC — generation breakout
80
+ if (vel >= VEL_KINETIC) {
81
+ return {
82
+ key: "kinetic",
83
+ name: "KINETIC",
84
+ family: "generation",
85
+ familyLabel: "Generation",
86
+ blurb:
87
+ "Generation has broken out. Output approaches or exceeds fresh input, making transmission the defining feature of the composition.",
88
+ };
89
+ }
90
+
91
+ // 3. Construction branch — active context construction
92
+ if (constr >= CONSTR_ACTIVE) {
93
+ if (lev >= LEV_RECURSIVE) {
94
+ return {
95
+ key: "amplifier",
96
+ name: "AMPLIFIER",
97
+ family: "construction",
98
+ familyLabel: "Active Construction",
99
+ blurb:
100
+ "Deep reuse and active construction are operating together at scale. Existing context produces new work that expands the context available for future cycles.",
101
+ };
102
+ }
103
+ if (lev >= LEV_BUILDER) {
104
+ return {
105
+ key: "recursive",
106
+ name: "RECURSIVE",
107
+ family: "construction",
108
+ familyLabel: "Active Construction",
109
+ blurb:
110
+ "New context is being built on top of an already substantial reusable base. Construction and reuse are now feeding the same operating loop.",
111
+ };
112
+ }
113
+ return {
114
+ key: "builder",
115
+ name: "BUILDER",
116
+ family: "construction",
117
+ familyLabel: "Active Construction",
118
+ blurb:
119
+ "Active context construction has begun. The system is creating material for future reuse while leverage is still developing.",
120
+ };
121
+ }
122
+
123
+ // 4. Reuse depth branch — passive (construction < 0.02)
124
+ if (lev >= LEV_DEEP_READER) {
125
+ return {
126
+ key: "archivist",
127
+ name: "ARCHIVIST",
128
+ family: "reuse",
129
+ familyLabel: "Reuse Depth",
130
+ blurb:
131
+ "Extreme reuse of accumulated context. A deep context library carries the system while new construction remains limited.",
132
+ };
133
+ }
134
+ if (lev >= LEV_CONTEXTUAL) {
135
+ return {
136
+ key: "deep-reader",
137
+ name: "DEEP READER",
138
+ family: "reuse",
139
+ familyLabel: "Reuse Depth",
140
+ blurb:
141
+ "Strong accumulated context is carrying the workflow. The operator draws deeply from retained context while creating relatively little new context.",
142
+ };
143
+ }
144
+ if (lev >= LEV_PRIMING) {
145
+ return {
146
+ key: "contextual",
147
+ name: "CONTEXTUAL",
148
+ family: "reuse",
149
+ familyLabel: "Reuse Depth",
150
+ blurb:
151
+ "Retained context is now materially supporting the workflow. Reuse is established, while active construction remains limited.",
152
+ };
153
+ }
154
+ if (lev >= LEV_INPUT_BOUND) {
155
+ return {
156
+ key: "priming",
157
+ name: "PRIMING",
158
+ family: "reuse",
159
+ familyLabel: "Reuse Depth",
160
+ blurb:
161
+ "Reuse is beginning to form. Prior context is returning, but the system has not yet developed deep leverage.",
162
+ };
163
+ }
164
+ return {
165
+ key: "input-bound",
166
+ name: "INPUT-BOUND",
167
+ family: "reuse",
168
+ familyLabel: "Reuse Depth",
169
+ blurb:
170
+ "Fresh input still carries most of the workload. Little prior context is returning, so each cycle depends heavily on new input.",
171
+ };
172
+ }
173
+
174
+ /**
175
+ * Given a cascade result ({ velocity, leverage, dev10x, pillars, class }) and an
176
+ * optional subject name, return "**CLASS.** <archetype blurb with context>".
177
+ * Deterministic — same numbers in → same card out.
178
+ */
179
+ export function narrate(cascade, name = "This operator") {
180
+ const klass = cascade.class || cascade.klass || "UNCLASSED";
181
+ const v = safeNum(cascade.velocity);
182
+ const l = safeNum(cascade.leverage);
183
+ const cw = cascade.pillars ? Number(cascade.pillars.cacheCreate) : NaN;
184
+
185
+ // Handle non-compounding (stateless pipe) as a special case before the
186
+ // archetype classifier — cascade.mjs leaves dev10x null when cacheCreate is 0.
187
+ const nonCompounding =
188
+ cascade.dev10x == null || !(cw > 0) || v === null || l === null;
189
+
190
+ if (nonCompounding) {
191
+ const leverageStr =
192
+ l !== null
193
+ ? `Leverage ${comma(l, 1)}x comes from reuse alone.`
194
+ : "Leverage is undefined (no fresh input recorded).";
195
+ const dev10xNote =
196
+ cascade.dev10x == null
197
+ ? " 10xDEV is undefined — the compounding loop has not formed yet."
198
+ : "";
199
+ const body =
200
+ `${name} runs a stateless pipe — no cache commits, so the cascade can't form. ` +
201
+ `High read volume, but nothing is being built forward. ${leverageStr}${dev10xNote}`;
202
+ return `**${klass}.** ${body}`;
203
+ }
204
+
205
+ // Classify into one of 10 build archetypes
206
+ const arch = classifyArchetype(cascade);
207
+
208
+ // Build the card with archetype name, family, and context-specific numbers
209
+ const levStr = l !== null ? `${comma(l, 0)}x leverage` : "undefined leverage";
210
+ const velStr = v !== null ? `${plain(v, 2)}x generation` : "undefined generation";
211
+ const cr = cascade.pillars ? Number(cascade.pillars.cacheRead) : NaN;
212
+ const constrStr = `construction ${plain(Number.isFinite(cr) && cr > 0 ? cw / cr : 0, 4)}`;
213
+
214
+ const body =
215
+ `${name} is ${arch.name} — ${arch.blurb} ` +
216
+ `${levStr}, ${velStr}, ${constrStr}.`;
217
+
218
+ return `**${klass}.** ${body}`;
219
+ }
@@ -0,0 +1,189 @@
1
+ // tui-themes.mjs — centralized ANSI color palette with multiple themes
2
+ //
3
+ // Tokscale-inspired: all colors live in one module, render code references
4
+ // them through `currentTheme`. Supports dark (default), light, high-contrast,
5
+ // and monochrome themes for accessibility.
6
+ //
7
+ // Usage in tui.mjs:
8
+ // import { currentTheme as c, setTheme } from "./tui-themes.mjs";
9
+ // // c.gold, c.cyan, c.reset, etc. — same interface as the old `c` object
10
+ //
11
+ // CLI:
12
+ // node tui.mjs --theme dark # default
13
+ // node tui.mjs --theme light # light terminal
14
+ // node tui.mjs --theme high-contrast # visually impaired
15
+ // node tui.mjs --theme monochrome # colorblind
16
+
17
+ const ESC = "\x1b[";
18
+
19
+ export const THEMES = {
20
+ // ── Dark (default) — current palette, designed for dark terminals ──
21
+ // green uses 256-color 77 (#5fd75f) for WCAG AA compliance on dark bg (9.0:1).
22
+ // Standard ANSI 32 (#5a8a5a) only achieves 4.1:1 — below the 4.5:1 threshold.
23
+ dark: {
24
+ name: "dark",
25
+ reset: `${ESC}0m`,
26
+ bold: `${ESC}1m`,
27
+ dim: `${ESC}2m`,
28
+ gold: `${ESC}33m`,
29
+ boldGold: `${ESC}1;33m`,
30
+ cyan: `${ESC}36m`,
31
+ boldCyan: `${ESC}1;36m`,
32
+ green: `${ESC}38;5;77m`, // brighter green #5fd75f (9.0:1 on dark — was ANSI 32 at 4.1:1)
33
+ red: `${ESC}38;5;203m`, // brighter red #ff5f5f (5.6:1 on dark — was ANSI 31 at 4.46:1, just below AA)
34
+ white: `${ESC}97m`,
35
+ boldWhite: `${ESC}1;97m`,
36
+ magenta: `${ESC}35m`,
37
+ blue: `${ESC}34m`,
38
+ bgDim: `${ESC}48;5;236m`,
39
+ bgCyan: `${ESC}48;5;23m`,
40
+ // Medal backgrounds (256-color) — gold/silver/bronze podium tints
41
+ medalBg: { 1: 220, 2: 250, 3: 130 },
42
+ medalFg: `${ESC}38;5;232m`, // dark text on medal bg
43
+ },
44
+
45
+ // ── Light — dark text on light/white terminals ──
46
+ // Uses 256-color codes (38;5;N) with darker shades that pass WCAG AA (4.5:1)
47
+ // on white backgrounds. Standard ANSI 33/36/32/31/35/34 render as pastel
48
+ // shades that fail contrast on white — these 256-color variants fix that.
49
+ light: {
50
+ name: "light",
51
+ reset: `${ESC}0m`,
52
+ bold: `${ESC}1m`,
53
+ dim: `${ESC}38;5;242m`, // medium gray (4.5:1 on white — passes AA for large text)
54
+ gold: `${ESC}38;5;130m`, // dark orange-gold #af5f00 (4.7:1 — yellow can't pass AA on white, this is the closest)
55
+ boldGold: `${ESC}1;38;5;130m`, // bold dark orange-gold (4.7:1)
56
+ cyan: `${ESC}38;5;24m`, // dark cyan #005f87 (7.0:1)
57
+ boldCyan: `${ESC}1;38;5;24m`, // bold dark cyan (7.0:1)
58
+ green: `${ESC}38;5;28m`, // dark green #008700 (4.7:1)
59
+ red: `${ESC}38;5;124m`, // dark red #af0000 (7.4:1)
60
+ white: `${ESC}30m`, // BLACK text on light bg (21:1)
61
+ boldWhite: `${ESC}1;30m`, // bold black
62
+ magenta: `${ESC}38;5;90m`, // dark magenta #870087 (8.8:1)
63
+ blue: `${ESC}38;5;19m`, // dark blue #0000af (13.0:1)
64
+ bgDim: `${ESC}48;5;250m`, // light grey bg for active tab
65
+ bgCyan: `${ESC}48;5;194m`, // light teal bg for active tab
66
+ medalBg: { 1: 220, 2: 250, 3: 130 },
67
+ medalFg: `${ESC}38;5;232m`,
68
+ },
69
+
70
+ // ── High contrast — bold everything, no dim, maximum readability ──
71
+ highContrast: {
72
+ name: "high-contrast",
73
+ reset: `${ESC}0m`,
74
+ bold: `${ESC}1m`,
75
+ dim: `${ESC}0;37m`, // NO dim — full brightness white instead
76
+ gold: `${ESC}1;33m`, // bold gold
77
+ boldGold: `${ESC}1;33m`,
78
+ cyan: `${ESC}1;36m`, // bold cyan
79
+ boldCyan: `${ESC}1;36m`,
80
+ green: `${ESC}1;32m`, // bold green
81
+ red: `${ESC}1;31m`, // bold red
82
+ white: `${ESC}1;97m`, // bold bright white
83
+ boldWhite: `${ESC}1;97m`,
84
+ magenta: `${ESC}1;35m`, // bold magenta
85
+ blue: `${ESC}1;34m`, // bold blue
86
+ bgDim: `${ESC}48;5;238m`, // slightly lighter dark bg
87
+ bgCyan: `${ESC}48;5;24m`, // slightly lighter teal bg
88
+ medalBg: { 1: 220, 2: 250, 3: 130 },
89
+ medalFg: `${ESC}1;38;5;232m`,
90
+ },
91
+
92
+ // ── Monochrome — bold/normal only, no color (colorblind-safe) ──
93
+ monochrome: {
94
+ name: "monochrome",
95
+ reset: `${ESC}0m`,
96
+ bold: `${ESC}1m`,
97
+ dim: `${ESC}2m`, // dim is fine in monochrome (it's weight, not color)
98
+ gold: `${ESC}1m`, // bold only (no color)
99
+ boldGold: `${ESC}1m`,
100
+ cyan: `${ESC}0m`, // normal weight
101
+ boldCyan: `${ESC}1m`, // bold
102
+ green: `${ESC}0m`, // normal
103
+ red: `${ESC}1m`, // bold (errors stand out by weight)
104
+ white: `${ESC}0m`, // normal
105
+ boldWhite: `${ESC}1m`, // bold
106
+ magenta: `${ESC}0m`, // normal
107
+ blue: `${ESC}0m`, // normal
108
+ bgDim: `${ESC}7m`, // reverse video for active tab (no color)
109
+ bgCyan: `${ESC}7m`, // reverse video
110
+ medalBg: {}, // no medal colors in monochrome
111
+ medalFg: `${ESC}1m`, // bold for medal winners
112
+ },
113
+ };
114
+
115
+ export let currentTheme = THEMES.dark;
116
+
117
+ export function setTheme(name) {
118
+ if (THEMES[name]) {
119
+ currentTheme = THEMES[name];
120
+ }
121
+ return currentTheme;
122
+ }
123
+
124
+ export function getThemeNames() {
125
+ return Object.keys(THEMES);
126
+ }
127
+
128
+ // ── Platform color map ─────────────────────────────────────────────────────
129
+ // Each platform gets a distinct 256-color code so platforms are visually
130
+ // distinguishable in the cascade table, token composition bars, board, and
131
+ // watch tabs. The colors are chosen for distinguishability on dark terminals
132
+ // (the default theme). For light theme, darker 256-color variants are used.
133
+ // Monochrome theme returns no color (bold only) — colorblind-safe.
134
+ //
135
+ // Color assignments (dark theme 256-color codes):
136
+ // claude = 75 (blue-cyan)
137
+ // codex = 114 (green)
138
+ // amp = 179 (orange)
139
+ // gemini = 129 (purple-magenta)
140
+ // kimi = 213 (pink)
141
+ // qwen = 68 (steel blue)
142
+ // goose = 142 (olive)
143
+ // kilo = 166 (dark orange)
144
+ // hermes = 96 (plum)
145
+ // droid = 167 (salmon)
146
+ // codebuff = 72 (teal-green)
147
+ // copilot = 33 (bright blue)
148
+ // openclaw = 136 (gold-brown)
149
+ // pi = 177 (light purple)
150
+ // omp = 220 (gold — the "oh my pi" platform gets gold)
151
+ // opencode = 60 (slate)
152
+ // devin = 30 (teal)
153
+ // proxy = 245 (gray — synthetic passthrough)
154
+ // other = 245 (gray — catch-all)
155
+
156
+ const PLATFORM_COLORS_DARK = {
157
+ claude: 75, codex: 114, amp: 179, gemini: 129, kimi: 213,
158
+ qwen: 68, goose: 142, kilo: 166, hermes: 96, droid: 167,
159
+ codebuff: 72, copilot: 33, openclaw: 136, pi: 177, omp: 220,
160
+ opencode: 60, devin: 30, proxy: 245, other: 245,
161
+ };
162
+
163
+ // Light theme: darker shades of the same hues for contrast on white
164
+ const PLATFORM_COLORS_LIGHT = {
165
+ claude: 24, codex: 28, amp: 130, gemini: 54, kimi: 90,
166
+ qwen: 19, goose: 100, kilo: 130, hermes: 54, droid: 124,
167
+ codebuff: 23, copilot: 19, openclaw: 130, pi: 90, omp: 130,
168
+ opencode: 19, devin: 23, proxy: 242, other: 242,
169
+ };
170
+
171
+ /**
172
+ * Returns a paint function for the given platform name, theme-aware.
173
+ * Usage: `const pc = platformColor("claude"); pc("claude")` → colored string.
174
+ * Falls back to the theme's cyan for unknown platforms.
175
+ */
176
+ export function platformColor(platform) {
177
+ const themeName = currentTheme.name;
178
+ // Monochrome: no color, just bold (colorblind-safe)
179
+ if (themeName === "monochrome") {
180
+ return (s) => `${currentTheme.bold}${s}${currentTheme.reset}`;
181
+ }
182
+ const map = themeName === "light" ? PLATFORM_COLORS_LIGHT : PLATFORM_COLORS_DARK;
183
+ const code = map[platform];
184
+ if (code == null) {
185
+ // Unknown platform — fall back to cyan
186
+ return (s) => `${currentTheme.cyan}${s}${currentTheme.reset}`;
187
+ }
188
+ return (s) => `${ESC}38;5;${code}m${s}${currentTheme.reset}`;
189
+ }