@motion-proto/live-tokens 0.87.1 → 0.88.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.
- package/CHANGELOG.md +11 -0
- package/package.json +1 -1
- package/src/demo/TestingLoops.svelte +100 -0
- package/src/demo/evalResults.ts +62 -0
- package/src/editor/skill-atlas/SkillAtlas.svelte +44 -65
- package/src/editor/skill-atlas/SkillValue.svelte +0 -202
- package/src/editor/skill-atlas/evalResults.ts +0 -46
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,16 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 0.88.0 — Eval results on the testing page
|
|
4
|
+
|
|
5
|
+
### Changed
|
|
6
|
+
|
|
7
|
+
- **The testing page reports the eval results.** A new Measured value
|
|
8
|
+
chapter tabulates the pick-component eval across four arms: with and
|
|
9
|
+
without the skills, and with and without the CLI. It gives the requirements
|
|
10
|
+
each arm got right, with its turns, time, and cost. The Skill Atlas loses
|
|
11
|
+
its Measured value tab, and a `#measured-value` link to the atlas now opens
|
|
12
|
+
the chapter.
|
|
13
|
+
|
|
3
14
|
## 0.87.1 — Floating parts stay above the page in sketch mode
|
|
4
15
|
|
|
5
16
|
### Fixed
|
package/package.json
CHANGED
|
@@ -1,10 +1,12 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
|
+
import { onMount } from 'svelte';
|
|
2
3
|
import CollapsibleSection from '../system/components/CollapsibleSection.svelte';
|
|
3
4
|
import Panel from '../system/components/Panel.svelte';
|
|
4
5
|
import Table from '../system/components/Table.svelte';
|
|
5
6
|
import Card from '../system/components/Card.svelte';
|
|
6
7
|
import { portal } from '../system/internal/portal';
|
|
7
8
|
import { navigate } from '../editor/core/routing/router';
|
|
9
|
+
import { pickComponentEval as result } from './evalResults';
|
|
8
10
|
|
|
9
11
|
let { homeHref = '/demo' }: { homeHref?: string } = $props();
|
|
10
12
|
|
|
@@ -14,6 +16,7 @@
|
|
|
14
16
|
{ id: 'test-runs', title: 'Testing pages and components' },
|
|
15
17
|
{ id: 'walkthrough', title: 'Build and check a page' },
|
|
16
18
|
{ id: 'reference', title: 'Rule reference' },
|
|
19
|
+
{ id: 'measured-value', title: 'Measured value' },
|
|
17
20
|
];
|
|
18
21
|
|
|
19
22
|
// Closed by default: open, the fixed panel covers the full-width figures.
|
|
@@ -21,6 +24,12 @@
|
|
|
21
24
|
|
|
22
25
|
let openRules = $state<Record<string, boolean>>({});
|
|
23
26
|
|
|
27
|
+
// The router loads this page lazily, after the browser's own jump to a hash has passed.
|
|
28
|
+
onMount(() => {
|
|
29
|
+
const id = window.location.hash.slice(1);
|
|
30
|
+
if (id) document.getElementById(id)?.scrollIntoView({ block: 'start' });
|
|
31
|
+
});
|
|
32
|
+
|
|
24
33
|
function jump(event: MouseEvent, id: string) {
|
|
25
34
|
event.preventDefault();
|
|
26
35
|
contentsOpen = false;
|
|
@@ -344,6 +353,63 @@
|
|
|
344
353
|
</div>
|
|
345
354
|
</section>
|
|
346
355
|
|
|
356
|
+
<section class="chapter" id="measured-value" aria-labelledby="measured-value-title">
|
|
357
|
+
<div class="chapter-body">
|
|
358
|
+
<h2 id="measured-value-title">Measured value</h2>
|
|
359
|
+
<p>An eval asked an agent to choose a component for {result.requirements} requirements. It ran in four arms of {result.runsPerArm} runs each: with and without the skills, and with and without the CLI. The arms chose the same components, with one miss among 144 answers, and differ in turns, time, and cost.</p>
|
|
360
|
+
<div class="eval-results">
|
|
361
|
+
<Table>
|
|
362
|
+
<table aria-label="Eval arms">
|
|
363
|
+
<thead>
|
|
364
|
+
<tr>
|
|
365
|
+
<th scope="col">Skills</th>
|
|
366
|
+
<th scope="col">CLI</th>
|
|
367
|
+
<th scope="col">Requirements right</th>
|
|
368
|
+
<th scope="col">Turns</th>
|
|
369
|
+
<th scope="col">Seconds</th>
|
|
370
|
+
<th scope="col">Cost</th>
|
|
371
|
+
</tr>
|
|
372
|
+
</thead>
|
|
373
|
+
<tbody>
|
|
374
|
+
{#each result.arms as arm (`${arm.skills}-${arm.cli}`)}
|
|
375
|
+
<tr>
|
|
376
|
+
<td>{arm.skills ? 'Yes' : 'No'}</td>
|
|
377
|
+
<td>{arm.cli ? 'Yes' : 'No'}</td>
|
|
378
|
+
<td>{arm.rowsRight}</td>
|
|
379
|
+
<td>{arm.turns}</td>
|
|
380
|
+
<td>{arm.seconds}</td>
|
|
381
|
+
<td>{arm.cost}</td>
|
|
382
|
+
</tr>
|
|
383
|
+
{/each}
|
|
384
|
+
</tbody>
|
|
385
|
+
</table>
|
|
386
|
+
</Table>
|
|
387
|
+
</div>
|
|
388
|
+
<ul class="eval-summary">
|
|
389
|
+
<li><strong>Turns:</strong> the skill saves turns only through the CLI command. Without the CLI, the skill arm takes as many turns as the agent with neither.</li>
|
|
390
|
+
<li><strong>Time and cost:</strong> the skills and the CLI each save time on their own, and together the run costs less than half as much as with neither.</li>
|
|
391
|
+
<li><strong>Accuracy:</strong> every arm scores about the same. The choices come from the entries in the component files.</li>
|
|
392
|
+
<li><strong>Change since 2026-09-20:</strong> in that run, no agent without the skills found the CLI; this time 2 of 3 did, so that arm varies from run to run.</li>
|
|
393
|
+
</ul>
|
|
394
|
+
<div class="text-columns">
|
|
395
|
+
<div>
|
|
396
|
+
<h3>Method</h3>
|
|
397
|
+
<ul>
|
|
398
|
+
<li>Cases <code>{result.cases[0]}</code> and <code>{result.cases[1]}</code>, run on {result.date} at package {result.packageVersion}.</li>
|
|
399
|
+
<li>Ten requirements with one right component, and two that nothing shipped fits.</li>
|
|
400
|
+
<li>The second case seeds the same project without the package’s <code>bin</code> folder, so the command the skill names fails. The skills are unchanged.</li>
|
|
401
|
+
<li>The runner adds the arm without skills to each case.</li>
|
|
402
|
+
<li>Each requirement has its own pattern grader, so a failure names its row.</li>
|
|
403
|
+
</ul>
|
|
404
|
+
</div>
|
|
405
|
+
<div>
|
|
406
|
+
<h3>Limits</h3>
|
|
407
|
+
<p>Three runs per arm is a small sample. The twelve requirements each have a clear answer in the entries. A harder case, where two components both fit, has not been measured.</p>
|
|
408
|
+
</div>
|
|
409
|
+
</div>
|
|
410
|
+
</div>
|
|
411
|
+
</section>
|
|
412
|
+
|
|
347
413
|
<!-- NOTES, open questions for this page:
|
|
348
414
|
- "Review by eye" (walkthrough step 7) and Figure 2's "Read the page yourself".
|
|
349
415
|
Leaning toward removing both. The create-page skill says "Open the page at
|
|
@@ -438,6 +504,11 @@
|
|
|
438
504
|
grid-column: 2 / -2;
|
|
439
505
|
}
|
|
440
506
|
|
|
507
|
+
.chapter-body > .eval-results {
|
|
508
|
+
grid-column: 2 / -2;
|
|
509
|
+
margin-block: var(--space-12) var(--space-40);
|
|
510
|
+
}
|
|
511
|
+
|
|
441
512
|
.chapter-body > .reference-groups {
|
|
442
513
|
grid-column: 2 / 11;
|
|
443
514
|
}
|
|
@@ -475,6 +546,35 @@
|
|
|
475
546
|
margin: var(--space-0) var(--space-0) var(--space-24);
|
|
476
547
|
}
|
|
477
548
|
|
|
549
|
+
.text-columns h3 {
|
|
550
|
+
font-family: var(--heading-sm-font-family);
|
|
551
|
+
font-size: var(--heading-sm-font-size);
|
|
552
|
+
font-weight: var(--heading-sm-font-weight);
|
|
553
|
+
line-height: var(--heading-sm-line-height);
|
|
554
|
+
letter-spacing: var(--heading-sm-letter-spacing);
|
|
555
|
+
margin: var(--space-0) var(--space-0) var(--space-12);
|
|
556
|
+
}
|
|
557
|
+
|
|
558
|
+
.eval-summary {
|
|
559
|
+
margin: var(--space-0) var(--space-0) var(--space-40);
|
|
560
|
+
padding-left: var(--space-24);
|
|
561
|
+
color: var(--text-secondary);
|
|
562
|
+
}
|
|
563
|
+
|
|
564
|
+
.eval-summary li + li {
|
|
565
|
+
margin-top: var(--space-12);
|
|
566
|
+
}
|
|
567
|
+
|
|
568
|
+
.text-columns ul {
|
|
569
|
+
margin: var(--space-0);
|
|
570
|
+
padding-left: var(--space-24);
|
|
571
|
+
color: var(--text-secondary);
|
|
572
|
+
}
|
|
573
|
+
|
|
574
|
+
.text-columns li + li {
|
|
575
|
+
margin-top: var(--space-8);
|
|
576
|
+
}
|
|
577
|
+
|
|
478
578
|
p,
|
|
479
579
|
li,
|
|
480
580
|
figcaption {
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
/** One arm of an eval: the same case run with or without the skills, and with or without the CLI. */
|
|
2
|
+
export interface EvalArm {
|
|
3
|
+
skills: boolean;
|
|
4
|
+
cli: boolean;
|
|
5
|
+
rowsRight: string;
|
|
6
|
+
turns: string;
|
|
7
|
+
seconds: string;
|
|
8
|
+
cost: string;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export interface EvalResult {
|
|
12
|
+
cases: string[];
|
|
13
|
+
date: string;
|
|
14
|
+
packageVersion: string;
|
|
15
|
+
runsPerArm: number;
|
|
16
|
+
requirements: number;
|
|
17
|
+
arms: EvalArm[];
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
// Recorded by hand from `npm run eval` in the live-tokens repository. The
|
|
21
|
+
// evals do not ship, so the page cannot read a result file at runtime.
|
|
22
|
+
export const pickComponentEval: EvalResult = {
|
|
23
|
+
cases: ['outcome-pick-component', 'outcome-pick-component-no-cli'],
|
|
24
|
+
date: '2026-09-22',
|
|
25
|
+
packageVersion: '0.87.1',
|
|
26
|
+
runsPerArm: 3,
|
|
27
|
+
requirements: 12,
|
|
28
|
+
arms: [
|
|
29
|
+
{
|
|
30
|
+
skills: true,
|
|
31
|
+
cli: true,
|
|
32
|
+
rowsRight: '12 of 12 in all 3 runs',
|
|
33
|
+
turns: '9 to 10',
|
|
34
|
+
seconds: '46 to 76',
|
|
35
|
+
cost: '$0.41 to $0.46',
|
|
36
|
+
},
|
|
37
|
+
{
|
|
38
|
+
skills: false,
|
|
39
|
+
cli: true,
|
|
40
|
+
rowsRight: '12 of 12 in all 3 runs; 2 of 3 found the CLI on their own',
|
|
41
|
+
turns: '15 to 17',
|
|
42
|
+
seconds: '65 to 102',
|
|
43
|
+
cost: '$0.63 to $0.74',
|
|
44
|
+
},
|
|
45
|
+
{
|
|
46
|
+
skills: true,
|
|
47
|
+
cli: false,
|
|
48
|
+
rowsRight: '12 of 12 in all 3 runs',
|
|
49
|
+
turns: '14 to 20',
|
|
50
|
+
seconds: '66 to 84',
|
|
51
|
+
cost: '$0.73 to $0.91',
|
|
52
|
+
},
|
|
53
|
+
{
|
|
54
|
+
skills: false,
|
|
55
|
+
cli: false,
|
|
56
|
+
rowsRight: '11 of 12 in one run, which missed requirement 12',
|
|
57
|
+
turns: '17 to 20',
|
|
58
|
+
seconds: '113 to 169',
|
|
59
|
+
cost: '$1.02 to $1.14',
|
|
60
|
+
},
|
|
61
|
+
],
|
|
62
|
+
};
|
|
@@ -1,9 +1,8 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
2
|
import { onMount, tick } from 'svelte';
|
|
3
|
-
import { navigate } from '../core/routing/router';
|
|
3
|
+
import { navigate, route } from '../core/routing/router';
|
|
4
4
|
import Button from '../../system/components/Button.svelte';
|
|
5
5
|
import TabBar from '../../system/components/TabBar.svelte';
|
|
6
|
-
import SkillValue from './SkillValue.svelte';
|
|
7
6
|
import SourcePane from './SourcePane.svelte';
|
|
8
7
|
import TreeCanvas from './TreeCanvas.svelte';
|
|
9
8
|
import { linkHash, linkTargets, resolveLink } from './atlasLink';
|
|
@@ -13,35 +12,23 @@
|
|
|
13
12
|
|
|
14
13
|
// `#set-type` opens that skill and `#set-type/write-the-font-pairing/voice`
|
|
15
14
|
// also selects that block, so a link can hand someone one step of one tree.
|
|
16
|
-
const VALUE_TAB = 'measured-value';
|
|
17
15
|
const firstSkill = Object.keys(skillTrees)[0];
|
|
18
16
|
|
|
19
|
-
function isValueHash(hash: string) {
|
|
20
|
-
return hash === `#${VALUE_TAB}`;
|
|
21
|
-
}
|
|
22
|
-
|
|
23
17
|
const linked = resolveLink(window.location.hash, skillTrees);
|
|
24
|
-
let active = $state(
|
|
25
|
-
isValueHash(window.location.hash) ? VALUE_TAB : (linked?.skill ?? firstSkill),
|
|
26
|
-
);
|
|
18
|
+
let active = $state(linked?.skill ?? firstSkill);
|
|
27
19
|
let selection: Selection | null = $state(linked?.target ?? null);
|
|
28
20
|
/** Which of the skill's documents the source pane shows. */
|
|
29
21
|
let doc: string = $state(SKILL_DOC);
|
|
30
22
|
|
|
31
|
-
|
|
32
|
-
let
|
|
33
|
-
let tree = $derived(skillTrees[skill]);
|
|
34
|
-
let docs = $derived(skillDocs[skill]);
|
|
23
|
+
let tree = $derived(skillTrees[active]);
|
|
24
|
+
let docs = $derived(skillDocs[active]);
|
|
35
25
|
let lines = $derived(docs[doc] ?? docs[SKILL_DOC]);
|
|
36
26
|
let siblings = $derived(Object.keys(docs).filter((name) => name !== SKILL_DOC));
|
|
37
27
|
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
})),
|
|
43
|
-
{ id: VALUE_TAB, label: 'Measured value\n1 eval' },
|
|
44
|
-
]);
|
|
28
|
+
const tabs = Object.entries(skillTrees).map(([id, t]) => ({
|
|
29
|
+
id,
|
|
30
|
+
label: `${t.title}\n${skillDocs[id][SKILL_DOC].length} lines`,
|
|
31
|
+
}));
|
|
45
32
|
|
|
46
33
|
let docTabs = $derived(
|
|
47
34
|
Object.keys(docs).map((name) => ({
|
|
@@ -65,10 +52,6 @@
|
|
|
65
52
|
}
|
|
66
53
|
|
|
67
54
|
function shareSelection() {
|
|
68
|
-
if (active === VALUE_TAB) {
|
|
69
|
-
history.replaceState(null, '', `${window.location.pathname}#${VALUE_TAB}`);
|
|
70
|
-
return;
|
|
71
|
-
}
|
|
72
55
|
const target = linkTargets(tree).find((t) => t.key === selection?.key) ?? null;
|
|
73
56
|
history.replaceState(null, '', `${window.location.pathname}${linkHash(active, target)}`);
|
|
74
57
|
}
|
|
@@ -111,10 +94,10 @@
|
|
|
111
94
|
}
|
|
112
95
|
|
|
113
96
|
function openLink(hash: string) {
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
97
|
+
// The eval report moved to the testing page; replace, so Back skips the old link.
|
|
98
|
+
if (hash === '#measured-value') {
|
|
99
|
+
history.replaceState(null, '', '/testing-loops#measured-value');
|
|
100
|
+
route.set('/testing-loops');
|
|
118
101
|
return;
|
|
119
102
|
}
|
|
120
103
|
const link = resolveLink(hash, skillTrees);
|
|
@@ -157,42 +140,38 @@
|
|
|
157
140
|
<TabBar {tabs} value={active} onchange={changeTab} />
|
|
158
141
|
</div>
|
|
159
142
|
|
|
160
|
-
|
|
161
|
-
<
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
<
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
</div>
|
|
193
|
-
</section>
|
|
194
|
-
</div>
|
|
195
|
-
{/if}
|
|
143
|
+
<div class="split">
|
|
144
|
+
<section class="pane" aria-label="{tree.id} decision tree">
|
|
145
|
+
<div class="pane-head">
|
|
146
|
+
<span class="pane-title">{tree.id}</span>
|
|
147
|
+
<span class="pane-note">{tree.nodes.length} steps</span>
|
|
148
|
+
</div>
|
|
149
|
+
<div class="pane-body" bind:this={treePane}>
|
|
150
|
+
<h2 class="tagline">{tree.tagline}</h2>
|
|
151
|
+
|
|
152
|
+
<TreeCanvas {tree} selected={selection?.key ?? null} onselect={selectTarget} onopen={openDoc} />
|
|
153
|
+
</div>
|
|
154
|
+
</section>
|
|
155
|
+
|
|
156
|
+
<section class="pane pane-source" aria-label="{tree.id} source">
|
|
157
|
+
<div class="pane-head">
|
|
158
|
+
<span class="pane-title">{tree.id}/{doc}</span>
|
|
159
|
+
<span class="pane-note">{lines.length} lines</span>
|
|
160
|
+
</div>
|
|
161
|
+
<div class="doc-tabs">
|
|
162
|
+
<TabBar tabs={docTabs} value={doc} onchange={openDoc} />
|
|
163
|
+
</div>
|
|
164
|
+
<div class="pane-body" bind:this={sourcePane}>
|
|
165
|
+
<SourcePane
|
|
166
|
+
{lines}
|
|
167
|
+
{siblings}
|
|
168
|
+
highlight={doc === SKILL_DOC ? (selection?.lines ?? null) : null}
|
|
169
|
+
onpick={selectFromLine}
|
|
170
|
+
onopen={openDoc}
|
|
171
|
+
/>
|
|
172
|
+
</div>
|
|
173
|
+
</section>
|
|
174
|
+
</div>
|
|
196
175
|
</div>
|
|
197
176
|
|
|
198
177
|
<style>
|
|
@@ -1,202 +0,0 @@
|
|
|
1
|
-
<script lang="ts">
|
|
2
|
-
import Table from '../../system/components/Table.svelte';
|
|
3
|
-
import { pickComponentEval } from './evalResults';
|
|
4
|
-
|
|
5
|
-
const result = pickComponentEval;
|
|
6
|
-
const [withSkills, without] = result.arms;
|
|
7
|
-
const difference = (withSkills.score - without.score).toFixed(2);
|
|
8
|
-
</script>
|
|
9
|
-
|
|
10
|
-
<article class="skill-value" aria-labelledby="skill-value-title">
|
|
11
|
-
<div class="measure">
|
|
12
|
-
<p class="eyebrow">Measured value</p>
|
|
13
|
-
<h2 id="skill-value-title">The skills make an agent faster. The component entries make it right.</h2>
|
|
14
|
-
<p class="lead">
|
|
15
|
-
An eval asked an agent to choose a component for twelve requirements, three times with the
|
|
16
|
-
skills loaded and three times with none. Every run that finished chose all twelve correctly,
|
|
17
|
-
in both arms. The skills changed the cost of getting there.
|
|
18
|
-
</p>
|
|
19
|
-
</div>
|
|
20
|
-
|
|
21
|
-
<div class="results">
|
|
22
|
-
<Table>
|
|
23
|
-
<table>
|
|
24
|
-
<thead>
|
|
25
|
-
<tr>
|
|
26
|
-
<th scope="col"><span class="visually-hidden">Arm</span></th>
|
|
27
|
-
<th scope="col">Score</th>
|
|
28
|
-
<th scope="col">Requirements right</th>
|
|
29
|
-
<th scope="col">Ran the catalogue command</th>
|
|
30
|
-
<th scope="col">Turns</th>
|
|
31
|
-
<th scope="col">Seconds</th>
|
|
32
|
-
</tr>
|
|
33
|
-
</thead>
|
|
34
|
-
<tbody>
|
|
35
|
-
{#each result.arms as arm (arm.label)}
|
|
36
|
-
<tr>
|
|
37
|
-
<td class="arm">{arm.label}</td>
|
|
38
|
-
<td>{arm.score.toFixed(2)}</td>
|
|
39
|
-
<td>{arm.rowsRight}</td>
|
|
40
|
-
<td>{arm.ranCatalogue}</td>
|
|
41
|
-
<td>{arm.turns}</td>
|
|
42
|
-
<td>{arm.seconds}</td>
|
|
43
|
-
</tr>
|
|
44
|
-
{/each}
|
|
45
|
-
</tbody>
|
|
46
|
-
</table>
|
|
47
|
-
</Table>
|
|
48
|
-
</div>
|
|
49
|
-
|
|
50
|
-
<div class="measure">
|
|
51
|
-
<h3>Accuracy comes from the component</h3>
|
|
52
|
-
<p>
|
|
53
|
-
Each component file carries its own entry: <code>whenToUse</code> states the condition that
|
|
54
|
-
makes it right, and <code>whenNotToUse</code> lists the conditions that rule it out, each with
|
|
55
|
-
the component to use in its place. An agent with no skills opened the component files, found
|
|
56
|
-
those entries, and made the same twelve choices, including the two requirements nothing
|
|
57
|
-
shipped fits and the destructive action that belongs in a Dialog.
|
|
58
|
-
</p>
|
|
59
|
-
|
|
60
|
-
<h3>Efficiency comes from the skill</h3>
|
|
61
|
-
<p>
|
|
62
|
-
The pick-component skill sends the agent to one command,
|
|
63
|
-
<code>npx live-tokens components --json</code>, which returns every entry at once. With the
|
|
64
|
-
skills the agent answered in {withSkills.turns} turns and under a minute. Without them it
|
|
65
|
-
never found the command, read files one at a time for {without.turns} turns, and one of its
|
|
66
|
-
three runs reached the five minute limit before it answered.
|
|
67
|
-
</p>
|
|
68
|
-
|
|
69
|
-
<h3>Method</h3>
|
|
70
|
-
<ul>
|
|
71
|
-
<li>Case <code>{result.id}</code>, run on {result.date}.</li>
|
|
72
|
-
<li>Twelve requirements: ten with one right component, two that nothing shipped fits.</li>
|
|
73
|
-
<li>Three runs per arm. The runner adds the arm without skills on its own.</li>
|
|
74
|
-
<li>
|
|
75
|
-
Each requirement has its own pattern grader, so a failure names its row. One more grader
|
|
76
|
-
checks that the agent ran the catalogue command.
|
|
77
|
-
</li>
|
|
78
|
-
<li>
|
|
79
|
-
The score is the share of graders that pass. The difference of {difference} comes from one
|
|
80
|
-
timeout and from the catalogue-command grader. No finished run chose a wrong component.
|
|
81
|
-
</li>
|
|
82
|
-
</ul>
|
|
83
|
-
|
|
84
|
-
<h3>Limits</h3>
|
|
85
|
-
<p>
|
|
86
|
-
Three runs per arm is a small sample, and one timeout moves the score a long way. The twelve
|
|
87
|
-
requirements each have a clear answer in the entries. A harder case, where two components
|
|
88
|
-
both fit, has not been measured.
|
|
89
|
-
</p>
|
|
90
|
-
</div>
|
|
91
|
-
</article>
|
|
92
|
-
|
|
93
|
-
<style>
|
|
94
|
-
/* The atlas locks to the viewport on desktop, so the report scrolls itself. */
|
|
95
|
-
.skill-value {
|
|
96
|
-
flex: 1 1 auto;
|
|
97
|
-
min-height: 0;
|
|
98
|
-
overflow-y: auto;
|
|
99
|
-
padding-bottom: var(--space-48);
|
|
100
|
-
color: var(--text-secondary);
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
.measure {
|
|
104
|
-
max-width: 70ch;
|
|
105
|
-
}
|
|
106
|
-
|
|
107
|
-
.results {
|
|
108
|
-
max-width: 110ch;
|
|
109
|
-
margin: var(--space-32) 0 var(--space-40);
|
|
110
|
-
}
|
|
111
|
-
|
|
112
|
-
.eyebrow {
|
|
113
|
-
margin: 0 0 var(--space-8);
|
|
114
|
-
font-family: var(--eyebrow-font-family);
|
|
115
|
-
font-size: var(--eyebrow-font-size);
|
|
116
|
-
font-weight: var(--eyebrow-font-weight);
|
|
117
|
-
line-height: var(--eyebrow-line-height);
|
|
118
|
-
letter-spacing: var(--eyebrow-letter-spacing);
|
|
119
|
-
text-transform: var(--eyebrow-text-transform);
|
|
120
|
-
color: var(--text-tertiary);
|
|
121
|
-
}
|
|
122
|
-
|
|
123
|
-
h2 {
|
|
124
|
-
margin: 0 0 var(--space-24);
|
|
125
|
-
font-family: var(--heading-lg-font-family);
|
|
126
|
-
font-size: var(--heading-lg-font-size);
|
|
127
|
-
font-weight: var(--heading-lg-font-weight);
|
|
128
|
-
line-height: var(--heading-lg-line-height);
|
|
129
|
-
letter-spacing: var(--heading-lg-letter-spacing);
|
|
130
|
-
color: var(--text-primary);
|
|
131
|
-
}
|
|
132
|
-
|
|
133
|
-
h3 {
|
|
134
|
-
margin: var(--space-40) 0 var(--space-12);
|
|
135
|
-
font-family: var(--heading-sm-font-family);
|
|
136
|
-
font-size: var(--heading-sm-font-size);
|
|
137
|
-
font-weight: var(--heading-sm-font-weight);
|
|
138
|
-
line-height: var(--heading-sm-line-height);
|
|
139
|
-
letter-spacing: var(--heading-sm-letter-spacing);
|
|
140
|
-
color: var(--text-primary);
|
|
141
|
-
}
|
|
142
|
-
|
|
143
|
-
.measure > h3:first-child {
|
|
144
|
-
margin-top: 0;
|
|
145
|
-
}
|
|
146
|
-
|
|
147
|
-
p,
|
|
148
|
-
li {
|
|
149
|
-
font-family: var(--body-md-font-family);
|
|
150
|
-
font-size: var(--body-md-font-size);
|
|
151
|
-
font-weight: var(--body-md-font-weight);
|
|
152
|
-
line-height: var(--body-md-line-height);
|
|
153
|
-
letter-spacing: var(--body-md-letter-spacing);
|
|
154
|
-
}
|
|
155
|
-
|
|
156
|
-
p {
|
|
157
|
-
margin: 0 0 var(--space-16);
|
|
158
|
-
}
|
|
159
|
-
|
|
160
|
-
.lead {
|
|
161
|
-
margin-bottom: 0;
|
|
162
|
-
color: var(--text-primary);
|
|
163
|
-
}
|
|
164
|
-
|
|
165
|
-
ul {
|
|
166
|
-
margin: 0;
|
|
167
|
-
padding-left: var(--space-24);
|
|
168
|
-
}
|
|
169
|
-
|
|
170
|
-
li + li {
|
|
171
|
-
margin-top: var(--space-8);
|
|
172
|
-
}
|
|
173
|
-
|
|
174
|
-
code {
|
|
175
|
-
font-family: var(--code-font-family);
|
|
176
|
-
font-size: var(--code-font-size);
|
|
177
|
-
font-weight: var(--code-font-weight);
|
|
178
|
-
line-height: var(--code-line-height);
|
|
179
|
-
letter-spacing: var(--code-letter-spacing);
|
|
180
|
-
background: var(--tint-low);
|
|
181
|
-
padding-inline: var(--space-4);
|
|
182
|
-
border-radius: var(--radius-sm);
|
|
183
|
-
/* The code face joins `--` into one dash, and a line may break between the
|
|
184
|
-
two hyphens. Either misprints a CLI flag. */
|
|
185
|
-
font-variant-ligatures: none;
|
|
186
|
-
white-space: nowrap;
|
|
187
|
-
}
|
|
188
|
-
|
|
189
|
-
.results td.arm {
|
|
190
|
-
color: var(--text-primary);
|
|
191
|
-
white-space: nowrap;
|
|
192
|
-
}
|
|
193
|
-
|
|
194
|
-
.visually-hidden {
|
|
195
|
-
position: absolute;
|
|
196
|
-
width: 1px;
|
|
197
|
-
height: 1px;
|
|
198
|
-
overflow: hidden;
|
|
199
|
-
clip-path: inset(50%);
|
|
200
|
-
white-space: nowrap;
|
|
201
|
-
}
|
|
202
|
-
</style>
|
|
@@ -1,46 +0,0 @@
|
|
|
1
|
-
/** One arm of an eval: the same case run with the skills loaded, or without them. */
|
|
2
|
-
export interface EvalArm {
|
|
3
|
-
label: string;
|
|
4
|
-
score: number;
|
|
5
|
-
rowsRight: string;
|
|
6
|
-
ranCatalogue: string;
|
|
7
|
-
turns: string;
|
|
8
|
-
seconds: string;
|
|
9
|
-
}
|
|
10
|
-
|
|
11
|
-
export interface EvalResult {
|
|
12
|
-
id: string;
|
|
13
|
-
date: string;
|
|
14
|
-
packageVersion: string;
|
|
15
|
-
runsPerArm: number;
|
|
16
|
-
requirements: number;
|
|
17
|
-
arms: [withSkills: EvalArm, without: EvalArm];
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
// Recorded by hand from `npm run eval` in the live-tokens repository. The
|
|
21
|
-
// evals do not ship, so the page cannot read a result file at runtime.
|
|
22
|
-
export const pickComponentEval: EvalResult = {
|
|
23
|
-
id: 'outcome-pick-component',
|
|
24
|
-
date: '2026-09-20',
|
|
25
|
-
packageVersion: '0.82.0, plus the unreleased catalogue entry',
|
|
26
|
-
runsPerArm: 3,
|
|
27
|
-
requirements: 12,
|
|
28
|
-
arms: [
|
|
29
|
-
{
|
|
30
|
-
label: 'With the skills',
|
|
31
|
-
score: 1,
|
|
32
|
-
rowsRight: '12 of 12 in all 3 runs',
|
|
33
|
-
ranCatalogue: '3 of 3 runs',
|
|
34
|
-
turns: '9 to 10',
|
|
35
|
-
seconds: '42 to 58',
|
|
36
|
-
},
|
|
37
|
-
{
|
|
38
|
-
label: 'Without',
|
|
39
|
-
score: 0.62,
|
|
40
|
-
rowsRight: '12 of 12 in the 2 runs that finished',
|
|
41
|
-
ranCatalogue: '0 of 3 runs',
|
|
42
|
-
turns: '15 to 16',
|
|
43
|
-
seconds: '70 to 72, and one run timed out at 300',
|
|
44
|
-
},
|
|
45
|
-
],
|
|
46
|
-
};
|