understanding-prime-env 0.1.3 → 0.1.5
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/bin/install.js +76 -38
- package/package.json +1 -1
- package/skills/understand-environment/SKILL.md +494 -0
package/bin/install.js
CHANGED
|
@@ -5,13 +5,12 @@
|
|
|
5
5
|
const fs = require('fs');
|
|
6
6
|
const path = require('path');
|
|
7
7
|
const os = require('os');
|
|
8
|
-
const readline = require('readline');
|
|
9
8
|
|
|
10
9
|
const SKILL_NAME = 'understand-prime-env';
|
|
11
10
|
const PACKAGE_ROOT = path.join(__dirname, '..');
|
|
12
11
|
const SKILL_MD_PATH = path.join(PACKAGE_ROOT, 'skills', SKILL_NAME, 'SKILL.md');
|
|
13
12
|
|
|
14
|
-
// ── helpers
|
|
13
|
+
// ── helpers ───────────────────────────────────────────────────────────────────
|
|
15
14
|
|
|
16
15
|
function readSkillRaw() {
|
|
17
16
|
return fs.readFileSync(SKILL_MD_PATH, 'utf8');
|
|
@@ -37,9 +36,64 @@ function appendOrCreate(filePath, section) {
|
|
|
37
36
|
|
|
38
37
|
function ok(msg) { console.log('\x1b[32m✓\x1b[0m ' + msg); }
|
|
39
38
|
function info(msg) { console.log('\x1b[36mℹ\x1b[0m ' + msg); }
|
|
40
|
-
function warn(msg) { console.log('\x1b[33m⚠\x1b[0m ' + msg); }
|
|
41
39
|
function fail(msg) { console.error('\x1b[31m✗\x1b[0m ' + msg); process.exit(1); }
|
|
42
40
|
|
|
41
|
+
// ── arrow-key selector ────────────────────────────────────────────────────────
|
|
42
|
+
|
|
43
|
+
function select(question, choices) {
|
|
44
|
+
return new Promise((resolve) => {
|
|
45
|
+
let cursor = 0;
|
|
46
|
+
|
|
47
|
+
const RESET = '\x1b[0m';
|
|
48
|
+
const BOLD = '\x1b[1m';
|
|
49
|
+
const ACCENT = '\x1b[35m'; // purple
|
|
50
|
+
const DIM = '\x1b[2m';
|
|
51
|
+
const UP = '\x1b[1A';
|
|
52
|
+
const CLEAR = '\x1b[2K\r';
|
|
53
|
+
|
|
54
|
+
function render(first) {
|
|
55
|
+
if (!first) {
|
|
56
|
+
// move up past all choices + question line
|
|
57
|
+
process.stdout.write(UP.repeat(choices.length + 1));
|
|
58
|
+
}
|
|
59
|
+
process.stdout.write(`${CLEAR}${BOLD}${question}${RESET}\n`);
|
|
60
|
+
choices.forEach((c, i) => {
|
|
61
|
+
const active = i === cursor;
|
|
62
|
+
const pointer = active ? `${ACCENT}❯${RESET}` : ' ';
|
|
63
|
+
const label = active ? `${BOLD}${c}${RESET}` : `${DIM}${c}${RESET}`;
|
|
64
|
+
process.stdout.write(`${CLEAR} ${pointer} ${label}\n`);
|
|
65
|
+
});
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
render(true);
|
|
69
|
+
|
|
70
|
+
process.stdin.setRawMode(true);
|
|
71
|
+
process.stdin.resume();
|
|
72
|
+
process.stdin.setEncoding('utf8');
|
|
73
|
+
|
|
74
|
+
function cleanup() {
|
|
75
|
+
process.stdin.setRawMode(false);
|
|
76
|
+
process.stdin.pause();
|
|
77
|
+
process.stdin.removeListener('data', onKey);
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
function onKey(key) {
|
|
81
|
+
if (key === '') { cleanup(); process.exit(0); } // Ctrl+C
|
|
82
|
+
if (key === '[A' || key === 'k') cursor = (cursor - 1 + choices.length) % choices.length; // up
|
|
83
|
+
if (key === '[B' || key === 'j') cursor = (cursor + 1) % choices.length; // down
|
|
84
|
+
if (key === '\r' || key === '\n') {
|
|
85
|
+
cleanup();
|
|
86
|
+
process.stdout.write('\n');
|
|
87
|
+
resolve(cursor);
|
|
88
|
+
return;
|
|
89
|
+
}
|
|
90
|
+
render(false);
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
process.stdin.on('data', onKey);
|
|
94
|
+
});
|
|
95
|
+
}
|
|
96
|
+
|
|
43
97
|
// ── installers ────────────────────────────────────────────────────────────────
|
|
44
98
|
|
|
45
99
|
function installClaude(isGlobal) {
|
|
@@ -62,10 +116,9 @@ function installCursor() {
|
|
|
62
116
|
const dest = path.join(process.cwd(), '.cursor', 'rules');
|
|
63
117
|
ensureDir(dest);
|
|
64
118
|
const outPath = path.join(dest, `${SKILL_NAME}.mdc`);
|
|
65
|
-
// Cursor MDC format: YAML front-matter + markdown body
|
|
66
119
|
const mdc = [
|
|
67
120
|
'---',
|
|
68
|
-
|
|
121
|
+
'description: understand-prime-env — generate HTML overview for a Prime Intellect verifiers environment',
|
|
69
122
|
'globs:',
|
|
70
123
|
' - "**/*.py"',
|
|
71
124
|
'alwaysApply: false',
|
|
@@ -81,7 +134,7 @@ function installCursor() {
|
|
|
81
134
|
function installWindsurf() {
|
|
82
135
|
const body = readSkillBody();
|
|
83
136
|
const outPath = path.join(process.cwd(), '.windsurfrules');
|
|
84
|
-
const section = `# understand-
|
|
137
|
+
const section = `# understand-prime-env\n\n${body}`;
|
|
85
138
|
appendOrCreate(outPath, section);
|
|
86
139
|
ok(`Windsurf → ${outPath}`);
|
|
87
140
|
}
|
|
@@ -91,7 +144,7 @@ function installCopilot() {
|
|
|
91
144
|
const dir = path.join(process.cwd(), '.github');
|
|
92
145
|
ensureDir(dir);
|
|
93
146
|
const outPath = path.join(dir, 'copilot-instructions.md');
|
|
94
|
-
const section = `# understand-
|
|
147
|
+
const section = `# understand-prime-env\n\n${body}`;
|
|
95
148
|
appendOrCreate(outPath, section);
|
|
96
149
|
ok(`GitHub Copilot → ${outPath}`);
|
|
97
150
|
}
|
|
@@ -111,7 +164,7 @@ function installZed() {
|
|
|
111
164
|
const separator = existing ? '\n\n---\n\n' : '';
|
|
112
165
|
settings.assistant = settings.assistant ?? {};
|
|
113
166
|
settings.assistant.default_context = settings.assistant.default_context ?? {};
|
|
114
|
-
settings.assistant.default_context.custom_instructions = existing + separator + `# understand-
|
|
167
|
+
settings.assistant.default_context.custom_instructions = existing + separator + `# understand-prime-env\n\n${body}`;
|
|
115
168
|
|
|
116
169
|
fs.writeFileSync(settingsPath, JSON.stringify(settings, null, 2));
|
|
117
170
|
ok(`Zed → ${settingsPath}`);
|
|
@@ -128,16 +181,16 @@ function installAll(isGlobal) {
|
|
|
128
181
|
// ── CLI ───────────────────────────────────────────────────────────────────────
|
|
129
182
|
|
|
130
183
|
const TOOLS = {
|
|
131
|
-
claude: { label: 'Claude Code',
|
|
132
|
-
cursor: { label: 'Cursor',
|
|
133
|
-
windsurf: { label: 'Windsurf',
|
|
134
|
-
copilot: { label: 'GitHub Copilot',
|
|
135
|
-
zed: { label: 'Zed',
|
|
136
|
-
all: { label: 'All of the above',fn: (g) => installAll(g) },
|
|
184
|
+
claude: { label: 'Claude Code', fn: (g) => installClaude(g) },
|
|
185
|
+
cursor: { label: 'Cursor', fn: () => installCursor() },
|
|
186
|
+
windsurf: { label: 'Windsurf', fn: () => installWindsurf() },
|
|
187
|
+
copilot: { label: 'GitHub Copilot', fn: () => installCopilot() },
|
|
188
|
+
zed: { label: 'Zed', fn: () => installZed() },
|
|
189
|
+
all: { label: 'All of the above', fn: (g) => installAll(g) },
|
|
137
190
|
};
|
|
138
191
|
|
|
139
192
|
const HELP = `
|
|
140
|
-
understand-
|
|
193
|
+
understand-prime-env installer
|
|
141
194
|
Usage: npx understanding-prime-env [tool] [options]
|
|
142
195
|
|
|
143
196
|
Tools (optional — omit for interactive prompt):
|
|
@@ -167,21 +220,8 @@ function parseArgs() {
|
|
|
167
220
|
return { tool, isGlobal };
|
|
168
221
|
}
|
|
169
222
|
|
|
170
|
-
async function prompt(question, choices) {
|
|
171
|
-
const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
|
|
172
|
-
console.log('\n' + question);
|
|
173
|
-
choices.forEach((c, i) => console.log(` ${i + 1}) ${c}`));
|
|
174
|
-
return new Promise((resolve) => {
|
|
175
|
-
rl.question('\nEnter number: ', (answer) => {
|
|
176
|
-
rl.close();
|
|
177
|
-
const idx = parseInt(answer, 10) - 1;
|
|
178
|
-
resolve(idx >= 0 && idx < choices.length ? idx : -1);
|
|
179
|
-
});
|
|
180
|
-
});
|
|
181
|
-
}
|
|
182
|
-
|
|
183
223
|
async function main() {
|
|
184
|
-
console.log('\n\x1b[1munderstand-
|
|
224
|
+
console.log('\n\x1b[1munderstand-prime-env\x1b[0m · Prime Intellect verifiers skill\n');
|
|
185
225
|
|
|
186
226
|
const { tool, isGlobal } = parseArgs();
|
|
187
227
|
|
|
@@ -190,20 +230,18 @@ async function main() {
|
|
|
190
230
|
return;
|
|
191
231
|
}
|
|
192
232
|
|
|
193
|
-
|
|
194
|
-
const
|
|
195
|
-
const labels = keys.map(k => TOOLS[k].label);
|
|
196
|
-
const idx = await prompt('Which editor / CLI tool do you want to install for?', labels);
|
|
197
|
-
if (idx === -1) { fail('Invalid selection.'); }
|
|
233
|
+
const keys = Object.keys(TOOLS);
|
|
234
|
+
const labels = keys.map(k => TOOLS[k].label);
|
|
198
235
|
|
|
236
|
+
const idx = await select('Which editor / CLI tool do you want to install for?', labels);
|
|
199
237
|
const chosen = keys[idx];
|
|
200
238
|
let global = isGlobal;
|
|
201
239
|
|
|
202
240
|
if (chosen === 'claude' || chosen === 'all') {
|
|
203
|
-
const scopeIdx = await
|
|
204
|
-
'
|
|
205
|
-
|
|
206
|
-
);
|
|
241
|
+
const scopeIdx = await select('Install scope for Claude Code:', [
|
|
242
|
+
'Global (~/.claude/skills/ — available everywhere)',
|
|
243
|
+
'Local (.claude/skills/ — this project only)',
|
|
244
|
+
]);
|
|
207
245
|
global = scopeIdx === 0;
|
|
208
246
|
}
|
|
209
247
|
|
package/package.json
CHANGED
|
@@ -0,0 +1,494 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: understand-environment
|
|
3
|
+
description: Generate a rich, self-contained HTML report that fully explains a Prime Intellect verifiers environment. Use this skill any time the user asks to understand, explain, document, visualize, or explore a verifiers environment — even if they just say "what does this environment do?", "explain this env", "give me an overview", or "generate an HTML for this environment". The skill reads the Python source files in the current directory, extracts the dataset, reward functions, rollout logic, and configuration parameters, and writes a beautiful HTML file to the environment folder.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Understand Environment
|
|
7
|
+
|
|
8
|
+
## Goal
|
|
9
|
+
|
|
10
|
+
Produce a single self-contained HTML file (`environment_overview.html`) — a **treasure map** that lets a first-timer understand any verifiers environment in under 5 minutes. Everything is visible at once, on one screen, no scrolling, no clicking required. The page answers one question: *"What is this environment training a model to do?"*
|
|
11
|
+
|
|
12
|
+
---
|
|
13
|
+
|
|
14
|
+
## Step 1 — Read the source
|
|
15
|
+
|
|
16
|
+
Read **every `.py` file** in the current directory. Also read `pyproject.toml` and `README.md` if they exist. Do not skip helper files — reward logic is often split across modules (e.g. `*_checks.py`, `*_prompts.py`).
|
|
17
|
+
|
|
18
|
+
Extract exactly three things:
|
|
19
|
+
|
|
20
|
+
### 1. The Task — what does the model see?
|
|
21
|
+
- Find 1 real example prompt from the source (a `PROMPTS` list, HuggingFace dataset, or prompt builder).
|
|
22
|
+
- Extract only the **user-facing prompt text** the model actually reads. Truncate to ~300 chars if longer.
|
|
23
|
+
- Note which file it lives in.
|
|
24
|
+
|
|
25
|
+
### 2. The Judge — what counts as a good response?
|
|
26
|
+
- Write 2–3 sentences in plain English describing how the environment scores the model. What is it rewarding? What does a high score look like vs a low score?
|
|
27
|
+
- If there is a composite formula (e.g. `R = (1−hw)×visible + hw×hidden`), include it.
|
|
28
|
+
- Note which file the reward logic lives in.
|
|
29
|
+
|
|
30
|
+
### 3. The Loop — how does one rollout execute?
|
|
31
|
+
- Identify 4–5 steps: what the model receives → what it produces → any tools/sandbox → scoring → final score.
|
|
32
|
+
- Write each step as a 2–4 word label and a single-line description.
|
|
33
|
+
- Note which file the rollout logic lives in.
|
|
34
|
+
|
|
35
|
+
---
|
|
36
|
+
|
|
37
|
+
## Step 2 — Generate the HTML
|
|
38
|
+
|
|
39
|
+
Write a single self-contained `./environment_overview.html`. No external CDN — all CSS and JS inline.
|
|
40
|
+
|
|
41
|
+
---
|
|
42
|
+
|
|
43
|
+
### Aesthetic Direction: "Cartographic"
|
|
44
|
+
|
|
45
|
+
The page looks like a **premium map artifact** — warm parchment in light mode, deep space in dark mode. Three cards feel like physical territories on the map, slightly lifted off the page. The purple accent (#a855f7) is the single modern intrusion into an otherwise scholarly palette — like a highlighted route drawn over an aged chart.
|
|
46
|
+
|
|
47
|
+
**The one thing a viewer remembers**: the parchment texture and the offset card shadows in light mode — it genuinely feels like a physical object.
|
|
48
|
+
|
|
49
|
+
---
|
|
50
|
+
|
|
51
|
+
### Theme System
|
|
52
|
+
|
|
53
|
+
All colors as CSS custom properties. Toggle swaps `data-theme="dark"` on `<html>`. Persisted via `localStorage`.
|
|
54
|
+
|
|
55
|
+
**Light theme — "Parchment" (default):**
|
|
56
|
+
```css
|
|
57
|
+
--bg-page: #f4efe4; /* warm laid paper */
|
|
58
|
+
--bg-card: #fdfaf3; /* lighter parchment for cards */
|
|
59
|
+
--bg-code: #ece6d4; /* aged paper for code blocks */
|
|
60
|
+
--border: #d6cba8; /* ink-faded edge */
|
|
61
|
+
--border-strong: #b8a87a;
|
|
62
|
+
--text-primary: #1c1410; /* dark iron-gall ink */
|
|
63
|
+
--text-secondary:#5c4f3a; /* brown ink */
|
|
64
|
+
--text-muted: #9c8b6e;
|
|
65
|
+
--accent: #a855f7; /* PI purple — the modern intrusion */
|
|
66
|
+
--accent-soft: rgba(168,85,247,0.12);
|
|
67
|
+
--shadow-card: 4px 6px 0 rgba(168,85,247,0.10), 0 2px 8px rgba(100,70,20,0.12);
|
|
68
|
+
--shadow-hover: 6px 8px 0 rgba(168,85,247,0.18), 0 4px 16px rgba(100,70,20,0.16);
|
|
69
|
+
|
|
70
|
+
/* Parchment noise texture — paste this SVG as a data URI background on body */
|
|
71
|
+
/* background-image: url("data:image/svg+xml,...") — see Noise Texture section */
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
**Dark theme — "Deep Space" (`[data-theme="dark"]`):**
|
|
75
|
+
```css
|
|
76
|
+
--bg-page: #0f0f1a;
|
|
77
|
+
--bg-card: #161627;
|
|
78
|
+
--bg-code: #1a1a2e;
|
|
79
|
+
--border: #2a2a4a;
|
|
80
|
+
--border-strong: #3d3d6b;
|
|
81
|
+
--text-primary: #e8e4f0;
|
|
82
|
+
--text-secondary:#b0a8c8;
|
|
83
|
+
--text-muted: #6b6488;
|
|
84
|
+
--accent: #a855f7;
|
|
85
|
+
--accent-soft: rgba(168,85,247,0.15);
|
|
86
|
+
--shadow-card: 0 0 0 1px rgba(168,85,247,0.15), 0 8px 32px rgba(0,0,0,0.5);
|
|
87
|
+
--shadow-hover: 0 0 0 1px rgba(168,85,247,0.3), 0 12px 40px rgba(168,85,247,0.15);
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
All elements get `transition: background-color 0.3s ease, border-color 0.3s ease, color 0.2s ease, box-shadow 0.3s ease` so the toggle animates smoothly.
|
|
91
|
+
|
|
92
|
+
---
|
|
93
|
+
|
|
94
|
+
### Noise Texture (light mode only)
|
|
95
|
+
|
|
96
|
+
Add a subtle grain to `body` in light mode using an inline SVG filter — no external file needed:
|
|
97
|
+
|
|
98
|
+
```html
|
|
99
|
+
<svg style="display:none">
|
|
100
|
+
<filter id="noise">
|
|
101
|
+
<feTurbulence type="fractalNoise" baseFrequency="0.65" numOctaves="3" stitchTiles="stitch"/>
|
|
102
|
+
<feColorMatrix type="saturate" values="0"/>
|
|
103
|
+
<feBlend in="SourceGraphic" mode="multiply"/>
|
|
104
|
+
</filter>
|
|
105
|
+
</svg>
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
Apply to body in light mode:
|
|
109
|
+
```css
|
|
110
|
+
:root body { filter: url(#noise); } /* very subtle — opacity trick below */
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
Better approach — use a pseudo-element overlay:
|
|
114
|
+
```css
|
|
115
|
+
body::before {
|
|
116
|
+
content: '';
|
|
117
|
+
position: fixed; inset: 0; pointer-events: none; z-index: 9999;
|
|
118
|
+
opacity: 0.03;
|
|
119
|
+
background-image: url("data:image/svg+xml,%3Csvg viewBox='0 0 256 256' xmlns='http://www.w3.org/2000/svg'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.9' numOctaves='4' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)'/%3E%3C/svg%3E");
|
|
120
|
+
}
|
|
121
|
+
[data-theme="dark"] body::before { opacity: 0.04; }
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
---
|
|
125
|
+
|
|
126
|
+
### Typography
|
|
127
|
+
|
|
128
|
+
```css
|
|
129
|
+
/* Display — scholarly, map-label feel */
|
|
130
|
+
--font-display: 'Palatino Linotype', 'Book Antiqua', Palatino, Georgia, serif;
|
|
131
|
+
|
|
132
|
+
/* Body — humanist, readable, not generic */
|
|
133
|
+
--font-body: 'Optima', 'Candara', 'Gill Sans', 'Segoe UI', sans-serif;
|
|
134
|
+
|
|
135
|
+
/* Code — typewriter, like coordinates on a map */
|
|
136
|
+
--font-mono: 'Courier New', 'Lucida Console', ui-monospace, monospace;
|
|
137
|
+
```
|
|
138
|
+
|
|
139
|
+
Scale:
|
|
140
|
+
- Env name: `2.2rem`, `var(--font-display)`, `font-weight: 700`, `letter-spacing: -0.02em`, color: `var(--text-primary)`
|
|
141
|
+
- Env description: `0.95rem`, `var(--font-body)`, `color: var(--text-secondary)`, `font-style: italic`
|
|
142
|
+
- Card landmark label: `0.65rem`, `var(--font-body)`, `font-weight: 700`, `letter-spacing: 0.12em`, `text-transform: uppercase`, `color: var(--accent)`
|
|
143
|
+
- Card body text: `0.875rem`, `var(--font-body)`, `line-height: 1.6`, `color: var(--text-primary)`
|
|
144
|
+
- Code: `0.8rem`, `var(--font-mono)`, `color: var(--text-primary)`
|
|
145
|
+
- Filename badge: `0.7rem`, `var(--font-mono)`, `color: var(--text-muted)`
|
|
146
|
+
|
|
147
|
+
---
|
|
148
|
+
|
|
149
|
+
### Layout
|
|
150
|
+
|
|
151
|
+
Full viewport, no scroll. CSS Grid:
|
|
152
|
+
|
|
153
|
+
```css
|
|
154
|
+
html, body { height: 100%; margin: 0; overflow: hidden; }
|
|
155
|
+
|
|
156
|
+
body {
|
|
157
|
+
display: grid;
|
|
158
|
+
grid-template-rows: auto 1fr; /* header + cards */
|
|
159
|
+
padding: 24px 28px 20px;
|
|
160
|
+
gap: 20px;
|
|
161
|
+
box-sizing: border-box;
|
|
162
|
+
background: var(--bg-page);
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
.cards {
|
|
166
|
+
display: grid;
|
|
167
|
+
grid-template-columns: 1fr 1fr 1fr;
|
|
168
|
+
gap: 18px;
|
|
169
|
+
min-height: 0; /* critical: lets grid row shrink */
|
|
170
|
+
}
|
|
171
|
+
```
|
|
172
|
+
|
|
173
|
+
---
|
|
174
|
+
|
|
175
|
+
### Header
|
|
176
|
+
|
|
177
|
+
```
|
|
178
|
+
┌─ header ──────────────────────────────────────────────────────┐
|
|
179
|
+
│ ⬡ Prime Intellect [light mode: ☀ dark mode: ☾] │
|
|
180
|
+
│ │
|
|
181
|
+
│ ifeval_goblin │
|
|
182
|
+
│ Trains a model to follow format instructions... │
|
|
183
|
+
└───────────────────────────────────────────────────────────────┘
|
|
184
|
+
```
|
|
185
|
+
|
|
186
|
+
- Top row: `⬡ Prime Intellect` in `0.7rem` caps, `var(--accent)`, `letter-spacing: 0.1em` — left. Theme toggle — right.
|
|
187
|
+
- Theme toggle: a small pill `<button>`, `background: var(--accent-soft)`, `border: 1px solid var(--border-strong)`, `border-radius: 99px`, `padding: 4px 12px`, `font-size: 0.75rem`. Shows `☀ Light` or `☾ Dark`. Hover: `background: var(--accent-soft)` stronger, no outline.
|
|
188
|
+
- Env name: large display serif below, with a 2px `var(--accent)` underline that is 40px wide and sits 4px below the baseline — does NOT span the full word. Like a map annotation mark.
|
|
189
|
+
- Description: italic, secondary color, one line beneath.
|
|
190
|
+
|
|
191
|
+
---
|
|
192
|
+
|
|
193
|
+
### Cards
|
|
194
|
+
|
|
195
|
+
Three equal-width cards. Each card is a fixed-height territory on the map.
|
|
196
|
+
|
|
197
|
+
```css
|
|
198
|
+
.card {
|
|
199
|
+
background: var(--bg-card);
|
|
200
|
+
border: 1.5px solid var(--border);
|
|
201
|
+
border-radius: 10px;
|
|
202
|
+
box-shadow: var(--shadow-card);
|
|
203
|
+
padding: 20px;
|
|
204
|
+
display: grid;
|
|
205
|
+
grid-template-rows: auto 1fr auto; /* label | content | filename */
|
|
206
|
+
min-height: 0;
|
|
207
|
+
transition: box-shadow 0.25s ease, transform 0.25s ease;
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
.card:hover {
|
|
211
|
+
box-shadow: var(--shadow-hover);
|
|
212
|
+
transform: translateY(-2px);
|
|
213
|
+
}
|
|
214
|
+
```
|
|
215
|
+
|
|
216
|
+
Each card has exactly three zones:
|
|
217
|
+
|
|
218
|
+
**Zone 1 — Landmark label** (top):
|
|
219
|
+
```
|
|
220
|
+
THE TASK THE JUDGE THE LOOP
|
|
221
|
+
━━━━━━━━ ━━━━━━━━━ ━━━━━━━━
|
|
222
|
+
```
|
|
223
|
+
Label in `0.65rem` uppercase caps + accent color. A `1px solid var(--border-strong)` rule beneath it, `margin-bottom: 14px`.
|
|
224
|
+
|
|
225
|
+
**Zone 2 — Content** (middle, `overflow: hidden`):
|
|
226
|
+
Content specific to each card — see below.
|
|
227
|
+
|
|
228
|
+
**Zone 3 — Filename badge** (bottom):
|
|
229
|
+
```
|
|
230
|
+
📍 ifeval_goblin_prompts.py
|
|
231
|
+
```
|
|
232
|
+
`font-size: 0.7rem`, `font-family: var(--font-mono)`, `color: var(--text-muted)`. A `1px solid var(--border)` rule above it, `padding-top: 10px`, `margin-top: 10px`.
|
|
233
|
+
|
|
234
|
+
---
|
|
235
|
+
|
|
236
|
+
### Card 1 — The Task
|
|
237
|
+
|
|
238
|
+
Content zone: the actual prompt text the model sees.
|
|
239
|
+
|
|
240
|
+
```css
|
|
241
|
+
.task-prompt {
|
|
242
|
+
background: var(--bg-code);
|
|
243
|
+
border-left: 3px solid var(--accent);
|
|
244
|
+
border-radius: 0 6px 6px 0;
|
|
245
|
+
padding: 12px 14px;
|
|
246
|
+
font-family: var(--font-mono);
|
|
247
|
+
font-size: 0.78rem;
|
|
248
|
+
line-height: 1.55;
|
|
249
|
+
color: var(--text-primary);
|
|
250
|
+
overflow: hidden;
|
|
251
|
+
display: -webkit-box;
|
|
252
|
+
-webkit-line-clamp: 8; /* truncate at ~8 lines */
|
|
253
|
+
-webkit-box-orient: vertical;
|
|
254
|
+
white-space: pre-wrap;
|
|
255
|
+
word-break: break-word;
|
|
256
|
+
}
|
|
257
|
+
```
|
|
258
|
+
|
|
259
|
+
If the prompt has format constraints embedded (e.g. "do not use the letter g"), highlight those phrases:
|
|
260
|
+
```html
|
|
261
|
+
<mark style="background:rgba(168,85,247,0.15); border-radius:2px; padding:0 2px;">
|
|
262
|
+
do not use the letter g
|
|
263
|
+
</mark>
|
|
264
|
+
```
|
|
265
|
+
|
|
266
|
+
---
|
|
267
|
+
|
|
268
|
+
### Card 2 — The Judge
|
|
269
|
+
|
|
270
|
+
Content zone: plain English scoring description.
|
|
271
|
+
|
|
272
|
+
```css
|
|
273
|
+
.judge-description {
|
|
274
|
+
font-family: var(--font-body);
|
|
275
|
+
font-size: 0.875rem;
|
|
276
|
+
line-height: 1.65;
|
|
277
|
+
color: var(--text-primary);
|
|
278
|
+
}
|
|
279
|
+
```
|
|
280
|
+
|
|
281
|
+
If there is a composite formula, render it below the prose in a formula block:
|
|
282
|
+
|
|
283
|
+
```css
|
|
284
|
+
.formula {
|
|
285
|
+
margin-top: 14px;
|
|
286
|
+
background: var(--accent-soft);
|
|
287
|
+
border: 1px solid var(--accent);
|
|
288
|
+
border-radius: 6px;
|
|
289
|
+
padding: 10px 14px;
|
|
290
|
+
font-family: var(--font-mono);
|
|
291
|
+
font-size: 0.78rem;
|
|
292
|
+
color: var(--accent);
|
|
293
|
+
letter-spacing: 0.02em;
|
|
294
|
+
}
|
|
295
|
+
```
|
|
296
|
+
|
|
297
|
+
If no formula exists, omit the block entirely — don't leave empty space.
|
|
298
|
+
|
|
299
|
+
---
|
|
300
|
+
|
|
301
|
+
### Card 3 — The Loop
|
|
302
|
+
|
|
303
|
+
Content zone: a static pipeline diagram.
|
|
304
|
+
|
|
305
|
+
Layout: vertical stack of step rows connected by short vertical lines (easier to fit in a card than horizontal).
|
|
306
|
+
|
|
307
|
+
```
|
|
308
|
+
● Prompt received
|
|
309
|
+
│
|
|
310
|
+
● Model generates response
|
|
311
|
+
│
|
|
312
|
+
● [Tool call / sandbox] ← only if applicable
|
|
313
|
+
│
|
|
314
|
+
● Scoring applied
|
|
315
|
+
│
|
|
316
|
+
● Final score emitted
|
|
317
|
+
```
|
|
318
|
+
|
|
319
|
+
HTML structure:
|
|
320
|
+
```html
|
|
321
|
+
<div class="pipeline">
|
|
322
|
+
<div class="step">
|
|
323
|
+
<div class="node"></div>
|
|
324
|
+
<div class="step-text">
|
|
325
|
+
<span class="step-label">Prompt received</span>
|
|
326
|
+
<span class="step-desc">64 task prompts with format constraints</span>
|
|
327
|
+
</div>
|
|
328
|
+
</div>
|
|
329
|
+
<div class="connector"></div>
|
|
330
|
+
<!-- repeat -->
|
|
331
|
+
</div>
|
|
332
|
+
```
|
|
333
|
+
|
|
334
|
+
CSS:
|
|
335
|
+
```css
|
|
336
|
+
.pipeline { display: flex; flex-direction: column; gap: 0; }
|
|
337
|
+
|
|
338
|
+
.step { display: flex; align-items: flex-start; gap: 12px; }
|
|
339
|
+
|
|
340
|
+
.node {
|
|
341
|
+
width: 10px; height: 10px; border-radius: 50%;
|
|
342
|
+
background: var(--accent); flex-shrink: 0;
|
|
343
|
+
margin-top: 4px;
|
|
344
|
+
box-shadow: 0 0 0 3px var(--accent-soft);
|
|
345
|
+
}
|
|
346
|
+
|
|
347
|
+
.connector {
|
|
348
|
+
width: 1px; height: 14px;
|
|
349
|
+
background: var(--border-strong);
|
|
350
|
+
margin-left: 4.5px; /* aligns with node center */
|
|
351
|
+
border-left: 1.5px dashed var(--border-strong);
|
|
352
|
+
}
|
|
353
|
+
|
|
354
|
+
.step-label {
|
|
355
|
+
display: block;
|
|
356
|
+
font-family: var(--font-body);
|
|
357
|
+
font-size: 0.8rem;
|
|
358
|
+
font-weight: 600;
|
|
359
|
+
color: var(--text-primary);
|
|
360
|
+
}
|
|
361
|
+
|
|
362
|
+
.step-desc {
|
|
363
|
+
display: block;
|
|
364
|
+
font-family: var(--font-body);
|
|
365
|
+
font-size: 0.72rem;
|
|
366
|
+
color: var(--text-muted);
|
|
367
|
+
line-height: 1.4;
|
|
368
|
+
margin-top: 1px;
|
|
369
|
+
}
|
|
370
|
+
```
|
|
371
|
+
|
|
372
|
+
---
|
|
373
|
+
|
|
374
|
+
### Theme Toggle JS (complete, ~15 lines)
|
|
375
|
+
|
|
376
|
+
```js
|
|
377
|
+
(function() {
|
|
378
|
+
const root = document.documentElement;
|
|
379
|
+
const btn = document.getElementById('theme-toggle');
|
|
380
|
+
const saved = localStorage.getItem('pi-env-theme');
|
|
381
|
+
if (saved) root.setAttribute('data-theme', saved);
|
|
382
|
+
function update() {
|
|
383
|
+
const isDark = root.getAttribute('data-theme') === 'dark';
|
|
384
|
+
btn.textContent = isDark ? '☀ Light' : '☾ Dark';
|
|
385
|
+
}
|
|
386
|
+
update();
|
|
387
|
+
btn.addEventListener('click', function() {
|
|
388
|
+
const next = root.getAttribute('data-theme') === 'dark' ? 'light' : 'dark';
|
|
389
|
+
root.setAttribute('data-theme', next);
|
|
390
|
+
localStorage.setItem('pi-env-theme', next);
|
|
391
|
+
update();
|
|
392
|
+
});
|
|
393
|
+
})();
|
|
394
|
+
```
|
|
395
|
+
|
|
396
|
+
---
|
|
397
|
+
|
|
398
|
+
### Page Load Animation
|
|
399
|
+
|
|
400
|
+
One single orchestrated entrance — not scattered micro-animations:
|
|
401
|
+
|
|
402
|
+
```css
|
|
403
|
+
@keyframes rise {
|
|
404
|
+
from { opacity: 0; transform: translateY(10px); }
|
|
405
|
+
to { opacity: 1; transform: translateY(0); }
|
|
406
|
+
}
|
|
407
|
+
|
|
408
|
+
.header { animation: rise 0.5s ease both; }
|
|
409
|
+
.card:nth-child(1) { animation: rise 0.5s ease 0.1s both; }
|
|
410
|
+
.card:nth-child(2) { animation: rise 0.5s ease 0.2s both; }
|
|
411
|
+
.card:nth-child(3) { animation: rise 0.5s ease 0.3s both; }
|
|
412
|
+
|
|
413
|
+
@media (prefers-reduced-motion: reduce) {
|
|
414
|
+
* { animation: none !important; }
|
|
415
|
+
}
|
|
416
|
+
```
|
|
417
|
+
|
|
418
|
+
---
|
|
419
|
+
|
|
420
|
+
### Final HTML skeleton
|
|
421
|
+
|
|
422
|
+
```html
|
|
423
|
+
<!DOCTYPE html>
|
|
424
|
+
<html lang="en">
|
|
425
|
+
<head>
|
|
426
|
+
<meta charset="UTF-8">
|
|
427
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
428
|
+
<title>[ENV_NAME] — Prime Intellect Environment</title>
|
|
429
|
+
<style>/* ALL CSS INLINE HERE */</style>
|
|
430
|
+
</head>
|
|
431
|
+
<body>
|
|
432
|
+
<!-- Noise texture SVG (hidden) -->
|
|
433
|
+
<svg style="display:none">...</svg>
|
|
434
|
+
|
|
435
|
+
<header class="header">
|
|
436
|
+
<div class="header-top">
|
|
437
|
+
<span class="pi-logo">⬡ Prime Intellect</span>
|
|
438
|
+
<button id="theme-toggle">☾ Dark</button>
|
|
439
|
+
</div>
|
|
440
|
+
<h1 class="env-name">[ENV_NAME]</h1>
|
|
441
|
+
<p class="env-desc">[ONE_SENTENCE_DESCRIPTION]</p>
|
|
442
|
+
</header>
|
|
443
|
+
|
|
444
|
+
<div class="cards">
|
|
445
|
+
<div class="card">
|
|
446
|
+
<div class="card-label">The Task</div>
|
|
447
|
+
<div class="card-content">
|
|
448
|
+
<pre class="task-prompt">[PROMPT_TEXT]</pre>
|
|
449
|
+
</div>
|
|
450
|
+
<div class="card-file">📍 [FILENAME]</div>
|
|
451
|
+
</div>
|
|
452
|
+
|
|
453
|
+
<div class="card">
|
|
454
|
+
<div class="card-label">The Judge</div>
|
|
455
|
+
<div class="card-content">
|
|
456
|
+
<p class="judge-description">[SCORING_DESCRIPTION]</p>
|
|
457
|
+
<!-- optional -->
|
|
458
|
+
<div class="formula">[FORMULA]</div>
|
|
459
|
+
</div>
|
|
460
|
+
<div class="card-file">📍 [FILENAME]</div>
|
|
461
|
+
</div>
|
|
462
|
+
|
|
463
|
+
<div class="card">
|
|
464
|
+
<div class="card-label">The Loop</div>
|
|
465
|
+
<div class="card-content">
|
|
466
|
+
<div class="pipeline">
|
|
467
|
+
<!-- step + connector pairs -->
|
|
468
|
+
</div>
|
|
469
|
+
</div>
|
|
470
|
+
<div class="card-file">📍 [FILENAME]</div>
|
|
471
|
+
</div>
|
|
472
|
+
</div>
|
|
473
|
+
|
|
474
|
+
<script>/* ALL JS INLINE HERE */</script>
|
|
475
|
+
</body>
|
|
476
|
+
</html>
|
|
477
|
+
```
|
|
478
|
+
|
|
479
|
+
---
|
|
480
|
+
|
|
481
|
+
## Step 3 — Confirm and report
|
|
482
|
+
|
|
483
|
+
After writing the file:
|
|
484
|
+
- Tell the user the full path and `open environment_overview.html`
|
|
485
|
+
- Two sentences: what the environment does and how it scores
|
|
486
|
+
|
|
487
|
+
## Anti-patterns
|
|
488
|
+
|
|
489
|
+
- Do not add any section beyond the three cards
|
|
490
|
+
- Do not add tabs, collapsibles, config tables, file maps, quick-start blocks, or score bars
|
|
491
|
+
- Do not let any card overflow or scroll — truncate content to fit
|
|
492
|
+
- Do not hallucinate prompt text, reward logic, or filenames not found in the source
|
|
493
|
+
- Do not skip helper modules — they often contain the core scoring logic
|
|
494
|
+
- Do not use Inter, Roboto, system-ui, or Space Grotesk — use the Palatino/Optima/Courier stack
|