Sections 2.7 & 2.8: putting the whole skill pool in the window vs an INDEX.md with progressive disclosure, plus description rewrites (30 questions)
| File / folder | Description | Size |
|---|---|---|
| 📁 ../ | Up one level | - |
| 📁 graded/ | Subfolder | - |
| 📁 raw/ | Subfolder | - |
| 📄 README.md | 16.0 KB | |
| 📄 baseline.log | 491 B | |
| 📄 build_pool.py | 7.3 KB | |
| 📄 candidates.json | 220.6 KB | |
| 📄 candidates_baseline.json | 1.8 MB | |
| 📄 candidates_raw.json | 236.7 KB | |
| 📄 candidates_summary.json | 46.7 KB | |
| 📄 descriptions_fixed.json | 10.1 KB | |
| 📄 draft.log | 3.0 KB | |
| 📄 fix_descriptions.py | 3.5 KB | |
| 📄 grade.py | 14.0 KB | |
| 📄 index_fixed_plan.json | 1.6 KB | |
| 📄 lib.py | 9.2 KB | |
| 📄 make_tasks.py | 8.9 KB | |
| 📄 pool.json | 103.7 KB | |
| 📄 pool_text.json | 1.4 MB | |
| 📄 results.json | 23.6 KB | |
| 📄 run.py | 10.3 KB | |
| 📄 run_deepseek-v4.1-flash.log | 7.1 KB | |
| 📄 run_fixed_deepseek-v4.1-flash.log | 1.3 KB | |
| 📄 run_fixed_gemini-3.8-flash.log | 894 B | |
| 📄 run_fixed_grok-4-fast.log | 1.7 KB | |
| 📄 run_full_all_deepseek-v4.1-flash.log | 1.5 KB | |
| 📄 run_full_all_gemini-3.8-flash.log | 1.4 KB | |
| 📄 run_full_all_grok-4-fast.log | 1.3 KB | |
| 📄 run_gemini-3.8-flash.log | 7.2 KB | |
| 📄 run_grok-4-fast.log | 5.2 KB | |
| 📄 selection.json | 3.7 KB | |
| 📄 spotcheck.json | 52.5 KB | |
| 📄 spotcheck_review.json | 450 B | |
| 📄 task_cues.json | 287 B | |
| 📄 tasks.json | 28.8 KB |
This is the English re-run of the Chinese edition's experiments/2_7_skills/ (which feeds sections 2.7 and 2.8). Same design and code structure. What changed: an English skill pool, 30 newly generated English tasks, English prompts, and a different set of models (no GPT anywhere). Run date 2026-10-14. Spend for this experiment: about $34.5 (itemized in ../COSTS.md).
# 1. Build the English skill pool (no API calls). Needs local checkouts of the source repos; see build_pool.py.
.venv/bin/python experiments_en/2_8_skills/build_pool.py
# 2. Tasks: gemini drafts 2 candidates per skill, 3 models answer with no skill, hand review picks 30
op run --env-file experiments/aib.env -- .venv/bin/python -u experiments_en/2_8_skills/make_tasks.py draft
op run --env-file experiments/aib.env -- .venv/bin/python -u experiments_en/2_8_skills/make_tasks.py baseline
.venv/bin/python experiments_en/2_8_skills/make_tasks.py finalize # reads selection.json
# 3. Main runs (one line per model)
op run --env-file experiments/aib.env -- .venv/bin/python -u experiments_en/2_8_skills/run.py grok-4-fast none full_1 index index_rep2 full_all
# 4. Grade (primary judge), optional second judge, aggregate
op run --env-file experiments/aib.env -- .venv/bin/python -u experiments_en/2_8_skills/grade.py
op run --env-file experiments/aib.env -- .venv/bin/python -u experiments_en/2_8_skills/grade.py secondary
# 5. Description rewrite and re-run
.venv/bin/python experiments_en/2_8_skills/fix_descriptions.py plan
op run --env-file experiments/aib.env -- .venv/bin/python -u experiments_en/2_8_skills/fix_descriptions.py rewrite
op run --env-file experiments/aib.env -- .venv/bin/python -u experiments_en/2_8_skills/run.py grok-4-fast index_fixed
op run --env-file experiments/aib.env -- .venv/bin/python -u experiments_en/2_8_skills/grade.py && .venv/bin/python experiments_en/2_8_skills/grade.py analyze
# 6. Hand spot-check of the judge
.venv/bin/python experiments_en/2_8_skills/grade.py sample 20 # then label spotcheck_review.json by hand
.venv/bin/python experiments_en/2_8_skills/grade.py agree
All calls go through AI Builder Space, the same OpenAI-compatible API readers use.
deepseek-v4-flash) runs inside the gateway's orchestrator, which drops client-supplied tools. Its index condition therefore uses a plain-text protocol: the model replies with a line READ_SKILL: <name>, and the skill text comes back as the next user message (same as the Chinese run). The orchestrator also runs its own web searches on some prompts. 16 deepseek answers say in their own text that a search ran and returned nothing relevant, and the debug trace flagged only 1 of those 16 (results.json → meta.search_mentions). In full_all, 3 calls show double the prompt tokens (about 682K instead of 336K), which matches an extra search round. We saw no case where a search produced the answer, but this column cannot be fully trusted.now, know, today, latest, current, price, weather, recent), gemini requests fail with HTTP 400 "Requests ending with a model turn are not supported". lib.call works around it by appending one more user turn, Please respond to the message above., and records nudged=true. This applied to 3/30 questions in none/full_1/full_all, and to 29/30 index tasks (the returned skill text almost always contains "now" or "know"). It never affects the first-turn decision about which skill to open, except on those 3 questions.read_skill tool calls, as in the Chinese run. So grok is the only model on native tool calling here, and protocol and model are confounded for grok.estimated_cost_usd from the orchestrator trace, with no cache discount. Implied prices per 1M tokens (input / output): gemini 0.75 / 3.75, grok 1.25 / 2.50, deepseek about 0.15 input.Skill pool (pool.json, pool_text.json). Starts from the Chinese run's 139 skills (experiments/2_7_skills/pool.json):
grapeot/context-infrastructure-en, at the committed HEAD of the local checkout. 30 of them were mostly Chinese in the zh pool.skills_en/ folder.bestpractice_academic_paper_conversion, has no en-mirror copy and was already English.Provenance (source repo, commit, action) is recorded per skill in pool.json. After the swap, no skill is mostly Chinese and no description contains Chinese. The pool is 139 skills, 325,094 tokens (cl100k) and 1,445,885 characters, against 369,217 tokens in zh. The index is 5,316 tokens (cl100k), against 6,682 in zh. The secret scan hits only placeholders (example.com addresses, replace-with-your-... keys).
Tasks (tasks.json).
selection.json). Two questions were edited because they named the skill or CLI file (T16, T24).task_cues.json). 7 of the 30 are "no cue" questions (T06, T25 to T30). They don't name the product or tool, and several skills in the pool fit the request. Unlike zh, where the tags were added after seeing the failures, these tags were set at selection time, before any with-skill run.Conditions (one call per model per task, no history between tasks): none; full_1 (only the target skill); full_all (all 139, fixed seed-27 permutation); index (139-line index, up to 4 opens); index_rep2 (exact repeat, also the control for the rewrite); index_fixed (rewritten descriptions). We skipped full_10 and full_30 to stay in budget; the code supports them.
Grading. The judge prompt is the same as zh. No model grades itself: gemini grades deepseek and grok, and deepseek grades gemini. A second pass with the other judge (deepseek for deepseek/grok answers, gemini for gemini answers) covered all 506 answers.
results.json → cells)| model | none | only the right skill (full_1) | all 139 (full_all) | index | index re-run |
|---|---|---|---|---|---|
| deepseek-v4.1-flash | 2 | 30 | 30 | 24 | 23 |
| gemini-3.8-flash | 1 | 30 | 30 | 30 | 29 |
| grok-4-fast | 0 | 30 | 29 | 9 | 8 |
The none scores come from the task filter. Each task was failed by all three models in the baseline pass, and the 3 correct answers here are re-run noise (deepseek T07, T19; gemini T10).
| model | condition | mean prompt tokens / question | mean latency (s) | $ per 30 questions |
|---|---|---|---|---|
| deepseek-v4.1-flash | full_1 | 4,874 | 6.8 | 0.061 |
| full_all | 371,712 (median 336,479) | 7.9 | 1.712 | |
| index | 32,748 | 19.5 | 0.446 | |
| gemini-3.8-flash | full_1 | 2,630 | 7.5 | 0.119 |
| full_all | 349,907 | 9.7 | 7.944 | |
| index | 15,928 | 11.4 | 0.439 | |
| grok-4-fast | full_1 | 2,571 | 4.3 | 0.103 |
| full_all | 318,141 | 15.3 | 11.945 | |
| index | 7,925 | 7.5 | 0.311 |
Index tokens, latency and cost add up all rounds of a task. The deepseek full_all mean includes 3 calls that went through an extra gateway search round. Moving from all skills to the index cut cost by 97% for grok, 94% for gemini and 74% for deepseek. Latency fell for grok (15.3 → 7.5 s), rose slightly for gemini (9.7 → 11.4 s) and more than doubled for deepseek (7.9 → 19.5 s), because the index adds at least one round trip.
| model | index wrong | opened nothing | opened only other skills | opened target, still wrong | correct when target opened |
|---|---|---|---|---|---|
| deepseek-v4.1-flash | 6 | 5 | 1 (T26 → apple_calendar) | 0 | 24/24 |
| gemini-3.8-flash | 0 | 0 | 0 | 0 | 30/30 |
| grok-4-fast | 21 | 21 | 0 | 0 | 9/9 |
| re-run, all models | 8 + 1 + 22 | 5 / 0 / 22 | 2 / 0 / 0 | 0 / 1 / 0 | 23/23, 29/30, 8/8 |
All 27 first-run index failures were routing failures: 26 never opened a skill, and 1 opened the wrong one. When the target was opened, the answer was right 63 times out of 63 (60/61 in the re-run). Opening behaviour differs a lot by model. Gemini opened 1 to 3 skills per task (mean 1.47) and never zero. Deepseek usually opened one (mean 1.07) and none on 5 tasks. Grok opened nothing on 21/30 (22/30 in the re-run), including clearly cued questions that name Docling, OpenReview, Bilibili, Codex, Narwal or Apple Watch. It answered those from its own knowledge.
Run-to-run flips between index and index_rep2: deepseek 1 task (T07), gemini 1 (T28), grok 3 (T01, T10, T12).
| model | 23 cued | 7 no-cue |
|---|---|---|
| deepseek-v4.1-flash | 20 (19) | 4 (4) |
| gemini-3.8-flash | 23 (23) | 7 (6) |
| grok-4-fast | 9 (8) | 0 (0) |
The English counterpart of the zh Resend/Outlook example is T26. It asks about the default time zone of calendar invite / calendar update without naming Outlook, and deepseek opened apple_calendar in both runs. The zh-style Resend question itself (T27, received list --after without naming Resend) did not confuse deepseek or gemini in English: both opened the Resend skill.
Procedure as in zh. plan collects, per model, the index tasks that were wrong and never opened the target (deepseek 6, gemini 0, grok 21; 21 distinct target skills). gemini-3.8-flash then rewrote those 21 one-line descriptions from the skill body and the old line only. It never saw the tasks and was told to say when to open the skill, not what is in it. We read all 21 and made one hand edit. For codex_cli, "troubleshooting ... backend compatibility" sat too close to T09's symptom and was softened (original kept in descriptions_fixed.json → hand_edits). The rewritten lines are 184 characters on average against 170 before, and the full index grew from 5,316 to 5,378 tokens. Both versions are in English, so the language of the descriptions did not change.
| model | wrong and target not opened | correct after rewrite | correct in plain re-run (control) | passing sample still correct: rewrite | passing sample: re-run |
|---|---|---|---|---|---|
| deepseek-v4.1-flash | 6 | 1 (T15) | 0 | 8/10 (broke T07, T20) | 9/10 |
| gemini-3.8-flash | 0 | – | – | 10/10 | 10/10 |
| grok-4-fast | 21 | 2 (T01, T05) | 1 (T01) | 8/9 | 7/9 |
The rewrite recovered 1 of 6 for deepseek against 0 for the control, and 2 of 21 for grok against 1. That is within run-to-run noise. Deepseek still opened nothing on 3 of its 6 (T05, T26, T29) and opened the wrong skill on two (T28 → tavily, T09 → temporal_info_verification). Grok still opened nothing on 18 of 21. The deepseek T20 regression came from opening ai_session_export instead of skill_opencode_data, possibly because of the new "export session history" wording, or possibly noise.
results.json (correct_secondary_judge). No cell moves by more than 1.spotcheck.json and spotcheck_review.json. Agreement was 20/20. The closest calls were T20 (grok wrote --include-subagents with an invented explanation; judged wrong) and T03 none (deepseek suggested deleting "a stored token file" without the specific file; judged wrong). Both are defensible.build_pool.py → pool.json (per-skill provenance, description, CJK stats, scan hits; dropped list), pool_text.jsonlib.py (HTTP calls with gateway workarounds, English prompts, judge), make_tasks.py → candidates_raw.json, candidates.json, candidates_baseline.json, candidates_summary.json; selection.json → tasks.json, task_cues.jsonrun.py → raw/<model>__<condition>.json (answer, opened/requested skills, tokens, latency, cost, web flag, nudge flag)grade.py → graded/, results.json (cells, analysis, spotcheck, meta)fix_descriptions.py → index_fixed_plan.json, descriptions_fixed.jsonspotcheck.json, spotcheck_review.json; *.log run logs