atris 3.74.23 → 3.74.25

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.
@@ -0,0 +1,179 @@
1
+ 'use strict';
2
+
3
+ // The Atris Rating: one number, 25 to 99, for how much real work a teammate
4
+ // finishes. 99 means 99 of every 100. Each time a teammate halves its misses
5
+ // it gains about 6 points, so the top is the hardest climb: going from 96 to
6
+ // 99 percent finished is worth about 12.
7
+ //
8
+ // One scale rates two things. An engine gets its number from the combine
9
+ // below: real tasks graded by the tests that shipped with them. A member
10
+ // gets its number from the jobs it lands in its own workspace (gm-season).
11
+
12
+ const { modelLabel } = require('./roster-models');
13
+
14
+ const TOP = 99;
15
+ const FLOOR = 25;
16
+ const STEP = 6;
17
+
18
+ // Every rating starts from half a finish and half a miss, so a short perfect
19
+ // run cannot reach the top: 3 of 3 rates 76, and it takes about 60 in a row
20
+ // to rate 99. null when nothing has been tried.
21
+ function atrisRating(finished, tries) {
22
+ const all = Number(tries);
23
+ const done = Number(finished);
24
+ if (!Number.isFinite(all) || all <= 0 || !Number.isFinite(done)) return null;
25
+ const share = (Math.min(Math.max(done, 0), all) + 0.5) / (all + 1);
26
+ const raw = TOP - STEP * (Math.log2(TOP) - Math.log2(share / (1 - share)));
27
+ return Math.max(FLOOR, Math.min(TOP, Math.round(raw)));
28
+ }
29
+
30
+ // The combine: Loop Bench, tasks from the atris repos (javascript from the
31
+ // CLI, python from the backend), each graded by the hidden tests that shipped
32
+ // with its fix, run in Claude Code on the builder prompt Atris kept. unseen
33
+ // tasks were held out of every prompt change, so the prompt was never tuned
34
+ // on them. finished adds each task's pass rate over its tries; time and price
35
+ // count each task once too. broke counts tries that passed their own tests
36
+ // but broke another one. The file is what evals/loopbench/combine.py in
37
+ // atrisos-backend prints, copied as is, so re-rating is one copy.
38
+ function freeze(value) {
39
+ if (value && typeof value === 'object') {
40
+ for (const inner of Object.values(value)) freeze(inner);
41
+ Object.freeze(value);
42
+ }
43
+ return value;
44
+ }
45
+
46
+ const COMBINE = freeze(require('./atris-rating-combine.json'));
47
+
48
+ const MONTHS = ['January', 'February', 'March', 'April', 'May', 'June', 'July',
49
+ 'August', 'September', 'October', 'November', 'December'];
50
+
51
+ // "2026-10-29" -> "October 2026"
52
+ function monthOf(date) {
53
+ const [year, month] = String(date || '').split('-').map(Number);
54
+ return year && month >= 1 && month <= 12 ? `${MONTHS[month - 1]} ${year}` : '';
55
+ }
56
+
57
+ const RATED = monthOf(COMBINE.rated);
58
+
59
+ // One engine's card: the overall and four parts, each on the same scale.
60
+ function engineCard(row) {
61
+ return {
62
+ model: row.model,
63
+ label: modelLabel(row.model),
64
+ ovr: atrisRating(row.finished, row.tasks),
65
+ finished: row.finished,
66
+ tasks: row.tasks,
67
+ python: atrisRating(row.python.finished, row.python.tasks),
68
+ javascript: atrisRating(row.javascript.finished, row.javascript.tasks),
69
+ unseen: atrisRating(row.unseen.finished, row.unseen.tasks),
70
+ clean: atrisRating(row.tries - row.broke, row.tries),
71
+ parts: { python: row.python, javascript: row.javascript, unseen: row.unseen },
72
+ tries: row.tries,
73
+ broke: row.broke,
74
+ minutes_cap: row.minutes_cap,
75
+ median_minutes: row.median_minutes,
76
+ cost_per_finish: row.cost_per_finish,
77
+ };
78
+ }
79
+
80
+ // Every rated engine, best first.
81
+ function combineCards() {
82
+ return COMBINE.engines.map(engineCard).sort((a, b) => b.ovr - a.ovr || a.label.localeCompare(b.label));
83
+ }
84
+
85
+ // The card for a model id, a label, or a family word that names one engine;
86
+ // null for a model the combine has not rated.
87
+ function combineCardFor(name) {
88
+ const text = String(name || '').trim().toLowerCase().replace(/\s+/g, ' ');
89
+ if (!text) return null;
90
+ const cards = combineCards();
91
+ const exact = cards.find((card) => card.model === text || card.label === text);
92
+ if (exact) return exact;
93
+ const family = cards.filter((card) => card.label.split(' ')[0] === text);
94
+ return family.length === 1 ? family[0] : null;
95
+ }
96
+
97
+ function finishedText(value) {
98
+ return Number.isInteger(value) ? String(value) : String(Math.round(value * 10) / 10);
99
+ }
100
+
101
+ function priceText(dollars) {
102
+ if (typeof dollars !== 'number') return '-';
103
+ return dollars < 1 ? `${Math.round(dollars * 100)}¢` : `$${dollars.toFixed(2)}`;
104
+ }
105
+
106
+ function minutesText(minutes) {
107
+ return typeof minutes === 'number' ? `${minutes.toFixed(1)} min` : '-';
108
+ }
109
+
110
+ const SCALE_LINES = Object.freeze([
111
+ 'how much real work a teammate finishes, 25 to 99. 99 means 99 of every 100.',
112
+ 'each halving of misses is worth about 6 points, so the top is the hardest climb.',
113
+ ]);
114
+
115
+ // The league table: every rated engine, best first.
116
+ function renderCombine(cards = combineCards()) {
117
+ const caps = [...new Set(cards.map((card) => card.minutes_cap))];
118
+ const capLine = caps.length > 1
119
+ ? cards.filter((card) => card.minutes_cap !== Math.min(...caps)).map((card) => `${card.label} gets ${card.minutes_cap} minutes a task`).join(', ') + `, the others ${Math.min(...caps)}.`
120
+ : `every engine gets ${caps[0]} minutes a task.`;
121
+ const lines = [
122
+ 'atris rating',
123
+ ...SCALE_LINES,
124
+ '',
125
+ `the combine: ${COMBINE.tasks} atris tasks, each graded by the tests that shipped with it`,
126
+ '',
127
+ ` ${'ovr'.padEnd(5)}${'engine'.padEnd(12)}${'finished'.padEnd(12)}${'py'.padEnd(4)}${'js'.padEnd(4)}${'unseen'.padEnd(8)}${'clean'.padEnd(7)}${'time'.padEnd(9)}price`,
128
+ ];
129
+ for (const card of cards) {
130
+ lines.push(` ${String(card.ovr).padEnd(5)}${card.label.padEnd(12)}${`${finishedText(card.finished)} of ${card.tasks}`.padEnd(12)}${String(card.python).padEnd(4)}${String(card.javascript).padEnd(4)}${String(card.unseen).padEnd(8)}${String(card.clean).padEnd(7)}${minutesText(card.median_minutes).padEnd(9)}${priceText(card.cost_per_finish)}`);
131
+ }
132
+ const top = cards[0];
133
+ lines.push(
134
+ '',
135
+ top && top.ovr >= TOP ? `${top.label} is a 99.` : 'no engine is a 99 yet.',
136
+ 'py, js: python and javascript tasks. unseen: ones the prompt was never tuned on.',
137
+ 'clean: tries that broke no other test. time: median to finish.',
138
+ 'price: per finished task, pay-per-use.',
139
+ capLine,
140
+ `${COMBINE.bench}, ${RATED}. one engine: atris rating <engine>`,
141
+ );
142
+ return lines.join('\n');
143
+ }
144
+
145
+ // One engine's card.
146
+ function renderCard(card) {
147
+ const head = `${card.label}, builder`;
148
+ const part = (name, value, text) => ` ${name.padEnd(13)}${String(value).padEnd(5)}${text}`;
149
+ return [
150
+ `${head}${' '.repeat(Math.max(2, 44 - head.length))}${card.ovr} ovr`,
151
+ '',
152
+ part('python', card.python, `${finishedText(card.parts.python.finished)} of ${card.parts.python.tasks} tasks`),
153
+ part('javascript', card.javascript, `${finishedText(card.parts.javascript.finished)} of ${card.parts.javascript.tasks} tasks`),
154
+ part('unseen', card.unseen, `${finishedText(card.parts.unseen.finished)} of ${card.parts.unseen.tasks} tasks the Atris prompt was never tuned on`),
155
+ part('clean', card.clean, `broke another test on ${card.broke} of ${card.tries} tries`),
156
+ '',
157
+ ` finished ${finishedText(card.finished)} of ${card.tasks} tasks, ${minutesText(card.median_minutes)} median, ${card.minutes_cap} minute cap`,
158
+ ` ${priceText(card.cost_per_finish)} per finished task on pay-per-use`,
159
+ ` ${COMBINE.bench}, ${RATED}, ${card.tries} tries graded by each task's shipped tests`,
160
+ ].join('\n');
161
+ }
162
+
163
+ // What the boot team line adds after a build engine, like " (86 ovr)", or ''
164
+ // for a model the combine has not rated.
165
+ function bootRatingText(model) {
166
+ const card = model ? combineCards().find((c) => c.model === String(model).trim()) : null;
167
+ return card ? ` (${card.ovr} ovr)` : '';
168
+ }
169
+
170
+ module.exports = {
171
+ COMBINE,
172
+ SCALE_LINES,
173
+ atrisRating,
174
+ bootRatingText,
175
+ combineCardFor,
176
+ combineCards,
177
+ renderCard,
178
+ renderCombine,
179
+ };
package/lib/gm-bet.js CHANGED
@@ -4573,8 +4573,8 @@ function createBetDesk(deps) {
4573
4573
 
4574
4574
  // The team page: every member on the team, one row each. role is a few
4575
4575
  // words from its MEMBER.md. ovr is the board's own rating (atris gm
4576
- // --board): 60 to 99 from the share of finished jobs that landed in the
4577
- // last 30 days, "new" with 1 or 2 finished, and two dots with none
4576
+ // --board): the Atris Rating, 25 to 99, of the finished jobs that landed
4577
+ // in the last 30 days, "new" with 1 or 2 finished, and two dots with none
4578
4578
  // finished in that window (a first claim alone is not a rating) or no
4579
4579
  // task list to read. engine is the tool and the exact model the roster
4580
4580
  // gives the member (atris engine roster), two dots when no model is
package/lib/gm-season.js CHANGED
@@ -10,6 +10,7 @@
10
10
 
11
11
  const fs = require('fs');
12
12
  const path = require('path');
13
+ const { atrisRating } = require('./atris-rating');
13
14
 
14
15
  const HOUR_MS = 60 * 60 * 1000;
15
16
  const DAY_MS = 24 * HOUR_MS;
@@ -49,17 +50,18 @@ function tally(outcomes) {
49
50
  return out;
50
51
  }
51
52
 
52
- // round(60 + 39 * landed / finished), rookie under 3 finished jobs. This is
53
+ // The Atris Rating of landed over finished (lib/atris-rating.js): 25 to 99,
54
+ // where 99 means 99 of every 100, rookie under 3 finished jobs. This is
53
55
  // stricter than the website rule (kept / graded) on purpose: drops and
54
56
  // abandoned jobs count.
55
57
  function ovr(outcomes) {
56
58
  const { landed, finished } = tally(outcomes);
57
59
  if (finished < ROOKIE_FINISHED) return null;
58
- return Math.round(60 + 39 * landed / finished);
60
+ return atrisRating(landed, finished);
59
61
  }
60
62
 
61
63
  // Each member's rating over one window of plays, the board's own numbers:
62
- // ovr is 60 to 99, or null for a rookie under 3 finished. A member with no
64
+ // ovr is 25 to 99, or null for a rookie under 3 finished. A member with no
63
65
  // plays in the window is not in the map.
64
66
  function memberRatings(outcomes = []) {
65
67
  const groups = new Map();
@@ -3,7 +3,7 @@
3
3
  const knownCommands = ['init', 'guide', 'doctor', 'doc-health', 'install', 'workspace', 'log', 'logs', 'later', 'idea', 'done', 'wish', 'ask', 'approve', 'stop', 'ready', 'check', 'drill', 'dream', 'now', '99', 'goal', 'wtf', 'founder', 'orb', 'radar', 'who', 'stream', 'ctop', 'launchpad', 'status', 'analytics', 'revisions', 'visualize', 'brain', 'brainstorm', 'autopilot', 'run', 'plan', 'do', 'review', 'release',
4
4
  'activate', '_activate', 'agent', 'team', 'chat', 'fast', 'ax', 'console', 'serve', 'login', 'logout', 'whoami', 'switch', 'use', 'accounts', '_resolve', '_profile-email', '_switch-session', 'shell-init', 'update', 'upgrade', 'version', 'help', 'next', 'atris',
5
5
  'clean', 'close', 'harvest', 'verify', 'recover', 'search', 'scout', 'skill', 'member', 'codex-goal', 'app', 'apps', 'learn', 'lesson', 'taste', 'teach', 'plugin', 'experiments', 'bench', 'router', 'tree', 'receipt', 'proof', 'openclaw', 'pull', 'push', 'watch', 'cloud', 'live', 'align', 'terminal', 'computer', 'diff', 'business', 'sync', 'youtube', 'x-search',
6
- 'ingest', 'query', 'lint', 'loop', 'pulse', 'task', 'mission', 'decide', 'campaign', 'agents', 'probe', 'worktree', 'land', 'caretaker', 'autoland', 'drive', 'aeo', 'slop', 'voice', 'strings', 'write', 'security-review', 'secure', 'deck', 'site', 'theme', 'card', 'reel', 'improve', 'study', 'rainmaker', 'xp', 'play', 'gm', 'game', 'x', 'recap', 'report', 'signup', 'clarity', 'interview', 'meet', 'moves', 'unknowns', 'avail', 'scoreboard', 'sync-checkout', 'zen',
6
+ 'ingest', 'query', 'lint', 'loop', 'pulse', 'task', 'mission', 'decide', 'campaign', 'agents', 'probe', 'worktree', 'land', 'caretaker', 'autoland', 'drive', 'aeo', 'slop', 'voice', 'strings', 'write', 'security-review', 'secure', 'deck', 'site', 'theme', 'card', 'reel', 'improve', 'study', 'rainmaker', 'xp', 'play', 'gm', 'game', 'x', 'recap', 'report', 'signup', 'clarity', 'interview', 'meet', 'moves', 'unknowns', 'avail', 'scoreboard', 'scorecard', 'rating', 'sync-checkout', 'zen',
7
7
  'ci', 'github', 'vercel', 'supabase', 'linear', 'stripe', 'balance', 'usage', 'spend', 'api-key', 'agent-client', 'topup', 'buy', 'transactions', 'hire', 'hires', 'mail', 'design', 'mcp', 'gmail', 'calendar', 'twitter', 'slack', 'imessage', 'integrations', 'setup', 'clean-workspace', 'cw',
8
8
  'fork', 'browse', 'publish', 'pack', 'sleep', 'wake', 'feedback', 'errors', 'wiki', 'code-review', 'cr', 'soul', 'fleet', 'fleet-report', 'loops', 'self-improve', 'compile', 'spaceship', 'truth', 'sign', 'engine', 'engines', 'link', 'playbook', 'feed', 'brief', 'social', 'host', 'people', 'follow', 'unfollow', 'friends', 'msg', 'inbox', 'invite', 'join', 'rsi', 'pay', 'trust'];
9
9