AI reference
The framework's AI paths, collated into one reference. The shell's claude-solve
command runs Claude Code headless against a single problem's solution files
(the claude-euler-solver skill), and claude-blog runs it against one blog
article under blogs/ (the claude-euler-blogger skill); both skills are
below. claude-api generates solution artifacts — Python and C code,
notes.html, test_cases.json — through the Claude API from the prompt
templates further down. All of them are held to the shared convention_*
guides listed in the docs index.
The claude-euler-blogger skill
Claude Euler Blogger (headless)
A skill that runs headless to write one blog page under blogs/. The claude-blog shell
command launches Claude with:
claude -p /claude-euler-blogger <tag-or-blog> [additional_prompt]
A blog collects the problems that share a tag and explains the idea behind them. Each tag has
a page at blogs/<facet>/<slug>.md; curated cross-cutting blogs live elsewhere under blogs/
(e.g. blogs/number-theory/primes.md). Claude researches the covered problems, writes the page,
commits it, refreshes its Problems section, and ends the turn. The commit stays local: the
collaborator reviews and amends the work, then pushes it themselves.
Read first — the conventions
The tag graph and the house voice are the two things to honour:
- docs/convention_tags.md — the tag system: the three facets (domain / technique / takeaway), and how a page declares the tags it covers.
- docs/convention_documentation.md — the writing voice
used in
notes.html: a "Programming Techniques" course for engineers, first person, precise, why not just what. A blog page carries that same voice, one level up: it explains the idea across many problems, not one.
The central vocabulary is blogs/tags.json (each tag's name, reference URL, and refs — the
problems/solutions that carry it). Read the exact solver command usage in
docs/commands-index.md — especially
blog, blogs,
and update-tags.
Rule — reference private problems, but never hand out their answer
Problems > 100 live under solutions/private/ and are encrypted at rest, because Project
Euler asks that solutions to problems past 100 not be published. Blog pages under blogs/ are
plaintext and public. The boundary that follows is about the answer, not the problem:
- Do name a private problem by number, summarise its statement, and explain the shared idea and the approach in your own words — that is the point of a blog page, and a page that ducks every private problem is a worse page.
- Do include a small illustrative snippet only if it cannot compute the answer — a two-line sketch of the general technique, a formula, a shape of a loop. If someone could paste it and get the number, it is too much.
- Never print a private problem's final answer, and never paste its full working solution
code or its
notes.htmlverbatim. For anything you want to quote at length, use a public problem (solutions/public/pNNNN/), whose code is already published.
When in doubt, describe the method and link the problem; the reader can open the solution themselves if they are entitled to it.
Execution model
Runs at the repository root and edits the one target page in place. solver is on PATH; run
subcommands directly (solver "blog technique/sieve-of-eratosthenes"). These Bash commands run
without confirmation; the skill also relies on Edit/Write under blogs/** and Read on the
project tree — keep .claude/settings.local.json in sync:
- bash solver *
- bash git add:* / git commit:*
- edit/write blogs/** # the article
- read ./**
Do not change cwd; every command runs from the project root, no ./ prefix.
Phase 1 — Resolve the target
The argument is one of: a <facet>/<slug> path, a bare tag slug, or a curated blog path.
- Run
solver "update-tags"first. It regenerates every page's Problems section from the current graph — so the list you write around is fresh, with each problem's title and a solved/unsolved marker baked in as of now. (You will run it again at the end.) - Resolve the argument to a file:
- a
<facet>/<slug>path →blogs/<facet>/<slug>.md; - a bare slug → look it up in
blogs/tags.json, take itsfacet, targetblogs/<facet>/<slug>.md; - any other path →
blogs/<path>.md.
- a
- Run
solver "blog <path-without-.md>"to see the tag(s) the page declares and the problems/solutions on their central legs. - Read the target file — after step 0 it always exists. It is usually a skeleton: a
<!-- tags: [...] -->comment on line 1, a<!-- status: draft -->comment under it, an# H1title, a_TODO: …_stub, and a generated Problems section delimited by<!-- problems (generated by update-tags) -->…<!-- /problems -->. That section is machine-owned and rendered — it is the reader's list of the covered problems. You replace the_TODO_stub with prose; leave the tags comment, the status comment, and the whole Problems section exactly as they are —update-tagsowns them, and the save gate refuses an edit that changes them.
The status is the page's state of writing: draft while it is a stub or half-written, final once
it is a finished article. A final status also carries the time the article was written
(<!-- status: final 2026-10-14T08:32Z -->), which update-tags stamps — see Phase 4.
blogs/articles.json (the article index, maintained by update-tags) mirrors both — the time as
the row's written. The claude-blog command refuses a final page unless it was run with
--force, so if you were launched on one, the maintainer asked for a rewrite deliberately.
If the [additional_prompt] gave an angle or constraint, factor it in without overriding the
conventions.
Phase 2 — Research the idea
- Read the tag's
referenceURL andnamefromblogs/tags.jsonto pin the concept. - From the problems on the tag's legs, read a representative handful — their
statement.html,notes.html(Problem Analysis + Solution Approach), and, the solution code — to see how the idea is actually used and where it varies. - Note the through-line: what the idea is, why it recurs across these problems, the shape it takes, and when an engineer should reach for it.
Phase 3 — Write the page
Replace the _TODO_ stub (or, for a new curated blog, create the file) with a focused article:
- Lead — one short paragraph: what this domain / technique / takeaway is, and why it keeps coming back across the problems below.
- The idea — the shared structure or method, explained once, well. Define terms; link the
central
referenceand other authoritative sources (Wikipedia, official docs, OEIS, MathWorld) inline as normal Markdown links. - How to reason about it — when it applies, what it buys, the trade-offs and pitfalls.
Do not write a problems list. The generated Problems section already lists every covered problem, with links, titles and solved markers — that is what replaces the old hand-picked "in the wild" section. Write your prose above that section; you may refer to specific problems by number in the flow of the idea (a public one when you want to quote code — see the private-problem rule), but do not duplicate the list.
Keep it tight — a blog page, not an essay. Leave the <!-- tags: [...] --> comment, the
<!-- status: … --> comment (until Phase 4 marks it final), and the whole <!-- problems … --> … <!-- /problems --> section
exactly as they are — update-tags owns them. Use GitHub-flavoured Markdown (## headings,
tables, code fences); do not put raw HTML in the page (it renders to every reader and the save
gate refuses it). A new curated page must open with its own <!-- tags: [slug, …] --> comment,
carry a <!-- status: draft --> comment under it, and include an empty
<!-- problems (generated by update-tags) --> / <!-- /problems --> pair for update-tags to
fill.
Phase 4 — Finalize (always last)
Writing the page is not delivering it. The four steps run in order — each is worth nothing without the one before it — and any of them failing is a stop-and-report:
-
Mark the page final — undated. The article is written, so change its status comment to exactly
<!-- status: final -->with no timestamp, even on a
--forcerewrite of a page that already carries one (<!-- status: final 2026-08-03T14:12Z -->→<!-- status: final -->). The refresh in step 3 stamps the current UTC time on it; that time is compared with each covered problem's solve time (solutions/problems.json) to find articles written before some of their problems were solved, so it must be the time of this writing — a stale timestamp left in place would hide exactly the problems you just drew on. Do not write a time yourself.Do this only for a page you actually finished — if you stopped short (missing research, an unresolved
update-tagsissue, a half-written section), leave itdraft, say so in the summary, and stop.finalis a claim that the page needs no more writing. -
Commit your page — before the refresh, not after:
solver "git-commit blogs message='docs(blog): <name>'"git-commitstages what its targets name, andblogsis both legs of the tag graph: your page andblogs/tags.json/blogs/articles.json, and each problem'stags.json, whichupdate-tagsrewrites when it accepts a proposed tag. One target covers the whole graph, and nothing outside those paths can ride along. Blog pages carry no solutions, so the message needs no secrecy: just say what was written, taggeddocs(blog):so the log reads at a glance.Order matters.
update-tagscommits its own output, so running it first would sweep your article into a genericchore(update-tags):commit and yourdocs(blog):message would never land. Commit first; let the refresh commit only what it itself changes.Pass the message explicitly, as above. With no
message=the command asks for one at the prompt, and headless there is nobody to ask — it exits2without committing.Do not run
solver "commit"bare: with no target it is problem-scoped — it stages asolutions/pNNNNdirectory plusproblems.json, not a blog page, so it would not commit your work at all. -
Refresh the Problems section:
solver "update-tags"— it rewrites every article's Problems section (fresh titles and solved markers), stamps yourfinalwith the current time, reconciles the graph, and updatesblogs/articles.json(where your new status lands), committing whatever it changed. Thensolver "update-tags --check"must exit0; fix any issue it names (an unknown tag in your<!-- tags: -->comment, most likely) and re-run. -
Sanity-check:
solver "blog <path>"lists the tags and problems the page now resolves to.
The phase ends at the commit. Pushing the branch and opening its pull request is the
collaborator's step (solver "git-push"), taken once they have read the page and amended
anything they want changed — so do not push, and never merge anything yourself.
Then summarise in one or two sentences (which page, and the idea you drew out) and end the turn.
Notes & failure modes to avoid
- Write about the idea across the problems, not a recap of any single solution — that is what
notes.htmlis for. - Never print a private (
> 100) problem's answer or paste its full solution code / notes; name it, summarise, and take any quotable code from a public problem (see the private-problem rule). - Do not hand-edit the
<!-- problems … -->section or the<!-- tags: -->comment's membership to force a problem in or out — fix the tags at their source (a problem'stags.json) if the mapping is wrong, thenupdate-tags. The save gate refuses edits to those regions anyway. - A non-zero
update-tags --check, or a commit failure, is a stop-and-report, not a reason to push on.
The claude-euler-solver skill
Claude Euler Solver (headless)
A skill that runs headless against a single problem's solution files. The
claude-skill shell command launches Claude with:
claude -p /claude-euler-solver <problem_number> <action> [additional_prompt]
<problem_number> selects the problem, <action> is solve or review, and
[additional_prompt] is optional free-form guidance to factor into that action.
Claude does the work, prints a short summary, and ends the turn, returning
control to the caller.
Read first — the conventions
The standards each action must meet live in the convention_*.md guides under
docs/ (each is also injected into the matching generation prompt — they are the
single source of truth). All paths are relative to the project root, which is the
working directory.
- convention_python_solution.md — Python
solve(). - convention_c_translation.md — the C port.
- convention_source_documentation.md — in-source docstrings/comments.
- convention_documentation.md —
notes.html. - convention_tags.md —
tags.json(problem/technique/takeaway tags). - convention_test_cases.md —
test_cases.json.
For exact solver command usage (aliases, flags, arguments), see
docs/commands-index.md — e.g. ls,
new, evaluate/eval,
benchmark, lint,
mark and
git-commit. The solution interface
(@runner.main / runner.h) is documented in
docs/solver-guide.md.
Execution model
The skill runs at the repository root and operates directly on the problem's
solution files.
solver is on PATH; run subcommands directly and pass the problem number
(solver "ls 42", solver "eval 42 lang=py", …). Every command takes an optional
leading problem number and otherwise defaults to the last one used, so once a step
names the problem the rest can omit it. Finishing simply means ending the turn.
Every problem's files live in its own solution directory:
- problems ≤ 100:
solutions/public/pNNNN/— plaintext. - problems > 100: the private solution tree — transparently encrypted at rest, plaintext in the working tree (the git clean/smudge filter handles it), so you read and edit them like any other file.
Run solver "ls <n>" to print the exact file paths and sizes for the problem; call
that directory the solution directory below (e.g. solutions/public/p0007/). A
solution runs directly from there, e.g.
solutions/public/p0007/p0007_s0.py <arg>... --runs=1 [--show] — the last output
line is <runs> <average> <result>.
Permissions and paths
These Bash commands run without user confirmation; the skill also relies on
Edit/Write on the solution directory and Read on the project tree (./**).
These must be granted in .claude/settings.local.json — keep the two in sync.
- bash autoflake *
- bash autopep8 *
- bash black *
- bash echo:*
- bash env
- bash flake8 *
- bash gcc *
- bash isort *
- bash ls:*
- bash mypy *
- bash pip:*
- bash python:*
- bash scripts/c/compile.sh:*
- bash scripts/git/status.sh:*
- bash scripts/linters/check.sh:*
- bash solver *
- bash stat:*
- bash solutions/** # run a solution binary/script from its directory
- edit/write solutions/** # create and edit solution files
Path convention. Every command runs from the project root. No command is
prefixed with ./ — the allowlisted paths all contain a slash, so bash runs them
relative to the cwd; PATH-resolved tools (solver, flake8, gcc, python, …)
take no path at all; a solution file runs as its solver ls-reported path
(solutions/public/pNNNN/pNNNN_sK…, no ./). Keep each invocation in this form so
it matches the allowlist — a stray ./ or cd misses the pattern and is
auto-denied in a headless run.
Phase 1 — Start
The problem number is the first argument. Locate its files and confirm they exist:
solver "ls <problem_number>"
This lists the solution directory (e.g. solutions/public/p0042/…). Confirm
statement.html is present and read it (plus any data file it references from
the directory's resources/). If the solution directory has no statement.html,
abort and report that the problem is not initialised — the shell's claude-skill
command is expected to hand this skill an existing problem.
Phase 2 — Action
Dispatch on <action>. If an [additional_prompt] was given, treat it as extra
caller guidance — an algorithm hint, a constraint, an aspect to focus on, or an
additional step to perform — and factor it in without overriding the action's
contract or the conventions.
Note: implement any required analysis/brute-force scripts in the solution directory as non-executable files. The
eval/benchmarkharness only discovers executablepNNNN_sK…files, so keeping these scratch scripts non-executable leaves them out of the run set; preserve them (do not delete them) as a record of the working.
solve
Write and verify a Python solution, translate it to C, then document and summarise:
- Understand the problem. Read the solution directory's
statement.htmland any data file it references fromresources/. - Test cases. If
test_cases.jsonis missing, create it withsolver "new <n> --tc"; then make it correct and complete per convention_test_cases.md — everydevcase has a non-nullanswer, exactly onemaincase,extraoptional. - Implement
solve(). Add a Python file withsolver "new <n> --py"if needed, then implement it per convention_python_solution.md (build sieves/caches insidesolve()for benchmark fidelity; never print after the harness line or rewrite the scaffolding). Test directly:<solution_dir>/pNNNN_sK.py <arg>... --runs=1 [--show]— the last output line is<runs> <average> <result>, and eachdevresult must equal itsanswer. Brute-force cross-check small inputs where possible. Once it is right, run themaincase and record its (sanity-checked) answer intotest_cases.json; do the same for anyextracase that is feasible to run. - Verify Python.
solver "eval <n> lang=py solution_index=K"(addallto includeextra) until the verdict iscorrect. - Translate to C.
solver "new <n> --c"adds a.csibling for each.py. Implement it per convention_c_translation.md — the same algorithm as the Python. Compile withscripts/c/compile.sh <solution_dir>/pNNNN_sK.c, then verify withsolver "eval <n> lang=c solution_index=K"untilcorrect. If a faithful C port is impractical, leave the template in place with a remark explaining why. - Document. Replace the template's placeholder module and function docstrings with the real approach. Bring the in-source docs to convention_source_documentation.md.
- Summarise. Run
solver "benchmark <n> && benchmark <n>"to record fresh timings (benchmark twice), then write/refresh the solution directory'snotes.htmlper convention_documentation.md, using the recordedresults.jsonvalues for every timing claim.notes.htmlis Problem Analysis and Solution Approach only — no techniques or takeaways sections. - Tag. Write/refresh the solution directory's
tags.jsonper convention_tags.md: the problem'sdomain, each solution index'stechniques, and anytakeaways— choosing slugs from the vocabulary inblogs/tags.jsonand proposing anything genuinely new undernew-tags. Write the file only; reconciling it into the central vocabulary is Finalize's job, aftermark, so the articles it regenerates carry this problem's solved marker.
review
Audit an existing solution and bring it up to standard. Precondition: at
least one Python solution file (pNNNN_sK.py) must exist — if none does, stop and
report that this is a solve job, not a review. Then, in order:
- C ↔ Python parity. For each solution index, read the
.pyand its.cand judge whether the C implements the same algorithm (same approach, complexity, and data structures in spirit — not line-for-line). Find unimplemented/broken C withsolver "eval <n> lang=c"(a(no solve)orincorrectverdict). Where the C is missing or has diverged, fix it per convention_c_translation.md:solver "new <n> --c"to add any missing sibling, implement, compile (scripts/c/compile.sh <solution_dir>/pNNNN_sK.c), and verify withsolver "eval <n> lang=c solution_index=K"untilcorrect. Leave a.cthat already matches its Python untouched, and do not change any algorithm. - In-source documentation. Read each
pNNNN_sK.py/.cand bring its module and function docstrings and comments up to convention_source_documentation.md. This is a documentation pass only — do not change algorithm or behaviour. Asolve()left with the template placeholder (or no docstring) is below the floor; add the missing approach-and-complexity note. notes.html. Ensureresults.jsonis present and newer than every solution source (solver "ls <n>"shows the mtimes); if it is missing or stale, runsolver "benchmark <n> && benchmark <n>"to refresh it (benchmark twice). Then bring the solution directory'snotes.htmlto convention_documentation.md, using the recordedresults.jsonvalues for every timing or comparison claim — never invent numbers. It must be Problem Analysis and Solution Approach only; if the notes still carryProgramming TechniquesorKey Takeawayssections, remove them (that content is now carried by tags).tags.json. Bring the solution directory'stags.jsonto convention_tags.md: confirm thedomainfits the problem, each solution index'stechniquesreflect that index's code, andtakeawaysare genuinely transferable — choosing slugs fromblogs/tags.jsonand proposing new ones only undernew-tags. Write the file only; Finalize reconciles it.
Phase 3 — Finalize (always last)
Files are edited in place in the solution directory, so finishing means leaving the work in a state a collaborator can review: make it clean, record it as solved, reconcile the tag graph, and commit. The four steps run in order — each one is worth nothing without the one before it — and any of them failing is a stop-and-report:
-
Lint and fix:
solver "lint <n> --auto-fix". It clears the mechanicalflake8issues automatically; fix any remainingmypy/flake8errors by hand and re-run untillint(...) → 0. If you cannot make it pass, stop and report; do not paper over it. -
Mark it solved:
solver "mark". It records the problem as solved only once the recorded results confirm it — there must be amaintest case with an answer and acorrectverdict for it inresults.json. A problem already marked is left unchanged (still exit 0). If it refuses, runsolver "benchmark <n>"to record fresh results and try again; if it still refuses, stop and report — an unconfirmed solution is not finished work. -
Reconcile the tag graph:
solver "update-tags". It promotes anynew-tagsyou proposed into the central vocabulary, rebuilds everyrefsleg from the per-problem files, and regenerates the blog articles andblogs/articles.json.After
mark, and before the commit. After, because the articles it regenerates carry each problem's solved marker — run it first and this problem still reads unsolved. Before, becauseupdate-tagscommits its own output (blogs/and every problem'stags.json, both legs together and nothing else), so letting it go first means step 4 has only your solution left to stage.Then
solver "update-tags --check"must exit0; fix whatever it names — an unknown slug or an unpromoted proposal in this problem'stags.jsonis the likely cause — and re-run. -
Commit:
solver "git-commit solution message='<message>'".One target:
solutionstages this problem's directory plussolutions/problems.json(what step 2 wrote). The tag graph needs no target here — step 3 already committed both of its legs, this problem'stags.jsonincluded.The message is a named argument (
message=…), not a positional one; pass it explicitly. Headless there is nobody to ask, sogit-commitwith nomessage=exits2without committing. Quote it as shown when it contains spaces.Keep
<message>short — a single line that does not reveal the solution approach. Use a word or two from the problem title and make it unique with a bit of personality, e.g.solver "git-commit solution message='p0042 de-coded triangles with a smile'",solver "git-commit solution message='p0042 coded triangles bites the dust'", etc. Never mention the algorithm, formula, or any hint of how it was solved.
The phase ends at the commit. Pushing the branch and opening its pull request is the
collaborator's step (solver "git-push"), taken once they have reviewed the work and
amended anything they want changed — so do not push, and never merge anything
yourself.
Then summarise the session in one or two sentences (the action, and what was found or done) and end the turn.
Notes & failure modes to avoid
- Do not change
cwd; the allowlist assumes the project root is the cwd. - Work on the problem you were handed — its files live in the solution directory
solver "ls <n>"reports; do not touch other problems. - In
solve: code against the actualtest_cases.jsoninputschema; verifydevbefore computingmain; build caches insidesolve(); never print after the harness's final line; and write the computed answer into everynullanswer. - In
solve: create any required analysis/brute-force artifacts as non-executable files in the solution directory so the harness ignores them. - In
review: do not rewrite a.cthat already matches its Python, and do not change any algorithm; keep.cfiles non-executable (only the compiled_cis+x). Take only the corrective steps the audit actually requires — a solution that is already in parity, documented, and summarised is a valid "nothing to do". - In Finalize: a non-zero
lintexit, or an unfixable lint error, is a stop-and-report, never a reason to push on. The same goes for the three steps after it — a refusedmark, a non-zeroupdate-tags --check, or a failed commit stop the phase and get reported as they came back. Never work around one: no--force, no hand-editedproblems.json, no hand-editedblogs/tags.json, no pushing or merging on the collaborator's behalf.
prompt_c.txt
You are a master C programmer translating Python Project Euler solutions to C.
## Problem
Number : $number
Title : $title
Level : $difficulty
Solved : $solved_date
## Problem statement (HTML)
$problem_content
## Existing Solution Notes (HTML)
$solution_notes
## Existing Solution files
$file_naming
$solutions
## Test cases
$test_cases
## Current benchmark results
$results
## Solution Template
Use the following C template as the structural basis for each generated file:
$solution_template
---
Generate only the files listed below. Each corresponds to the Python solution with the same index.
Use the existing solution files above for context; do not regenerate files that already exist.
Files to generate: $files_to_generate
Follow the C translation conventions below in full:
$c_translation_conventions
Apply these source documentation conventions to the in-source comments:
$source_documentation_conventions
Generation-task requirements (in addition to the conventions above):
1. Each file to generate corresponds to the Python solution with the same index; use the existing
solution files above for context and do not regenerate files that already exist.
2. Begin each file with the comment: /* Solution to Euler Problem $number: $title. */
3. Skip matplotlib and any graphical visualization code entirely.
4. If a Python solution depends on libraries with no reasonable C equivalent (anything beyond
numpy / primesieve / GMP / MPFR / OpenSSL BIGNUM, e.g. sympy or networkx), do not fabricate a
port: emit a one-line file containing only `// SKIP: <one-sentence reason>` and move to the next.
5. $house_style
6. Output each C file wrapped in delimiter lines, one after another, no other text:
// BEGIN <filename>
[c source]
// END <filename>
prompt_doc.txt
You are a meticulous software documentarian improving the in-source documentation of Project Euler solutions, written in Python and C.
## Problem
Number : $number
Title : $title
Level : $difficulty
Solved : $solved_date
## Problem statement (HTML)
$problem_content
## Existing Solution Notes (HTML)
$solution_notes
## Existing Solution files
$file_naming
$solutions
## Test cases
$test_cases
## Current benchmark results
$results
---
Re-document each of the solution files listed below in place. These files already exist above; this
is a documentation-only pass over the in-source docstrings and comments - do NOT change the
algorithm, behaviour, or any computed value.
Files to document: $files_to_generate
Apply these source documentation conventions in full:
$source_documentation_conventions
Generation-task requirements (in addition to the conventions above):
1. Re-emit every file listed in "Files to document" in full, exactly as it appears above except for
improved in-source documentation: the module docstring / top comment, the `solve()`
docstring/comment, and a one-line docstring/comment per non-trivial helper. Do not add, remove,
reorder, or otherwise alter any executable code.
2. Leave the runner scaffolding byte-for-byte untouched. For Python keep the
`#!/usr/bin/env python3.14` shebang, the `# -*- coding: utf-8 -*-` line, the
`from __future__ import annotations`, the `from solver.runners import runner` import, the
`@runner.main` decorator, and the `if __name__ == "__main__"` block exactly as above; for C keep
the `#include "runner.h"` and the `const char *solve(int argc, char *argv[])` signature.
3. Documenting must not change what the program does - each re-documented file must still compile
(C) and produce the same answers for the test cases above.
4. Keep every line at most 120 columns wide, including the docstrings and comments you add or
rewrite; the committed solutions are linted with `flake8 --max-line-length 120`, so a longer line
fails the check. Wrap long prose across multiple comment/docstring lines rather than overflowing.
5. $house_style
6. Output each file wrapped in delimiter lines, one after another, no other text. Between the
delimiters put the raw source only - do NOT wrap it in a markdown code fence (no ```c, ```python,
``` or ~~~ lines); a fence leaks stray backticks into the file and breaks compilation:
// BEGIN <filename>
[source]
// END <filename>
prompt_notes.txt
You are a master programmer and educator writing worked-solution notes for a "Programming Techniques" course.
Your audience is engineers who are learning to write efficient, well-reasoned programs.
Write with clarity, precision, and authority - in the first person ("I chose...", "My approach...", "I decided to...").
Explain not only *what* you did but *why* - every algorithmic and implementation decision should be justified
so that a person reading these notes can learn to reason the same way.
## Problem
Number : $number
Title : $title
Level : $difficulty
Solved : $solved_date
## Problem statement (HTML)
$problem_content
## Existing Solution Notes (HTML)
This section contains previously generated notes for this problem. It may be empty if notes are being
generated for the first time. If it is not empty, the notes are being regenerated - typically because
new solution files have been added or existing ones changed. Use these notes as a reference, but
write fresh notes that accurately reflect all current solutions and benchmark results below.
$solution_notes
## Solution files
$file_naming
$solutions
## Test cases
$test_cases
## Benchmark results
$results
---
Write the notes.html article following these documentation conventions in full:
$documentation_conventions
Base every timing or comparison claim on the "Benchmark results" above (the recorded `average`
values and verdicts) - never invent numbers. Output the HTML only - no preamble.
$house_style
prompt_py.txt
You are a master Python programmer writing Python solutions to Project Euler problems.
## Problem
Number : $number
Title : $title
Level : $difficulty
Solved : $solved_date
## Problem statement (HTML)
$problem_content
## Solution Notes (HTML)
$solution_notes
## Existing Solution files
$file_naming
If no solutions exist, write the first one. If solutions exist, implement a different algorithm.
$solutions
## Test cases
$test_cases
## Current benchmark results
$results
## Solution Template
Use the following Python template as the structural basis for the generated file:
$solution_template
---
Generate only the file listed below, using the existing solutions above only for context.
File to generate: $file_to_generate
Follow the Python solution conventions below in full:
$python_solution_conventions
Apply these source documentation conventions to the in-source docstrings and comments:
$source_documentation_conventions
Generation-task requirements (in addition to the conventions above):
1. The first line must be exactly: `#!/usr/bin/env python3.14`. Keep the template's harness
scaffolding - the shebang, `# -*- coding: utf-8 -*-`, `from __future__ import annotations`, the
`from solver.runners import runner` import, the `@runner.main` decorator, and the
`if __name__ == "__main__": raise SystemExit(solve())` block - byte-for-byte; implement only
`solve()` and the module-level helpers above it.
2. If existing solutions are present, implement a genuinely different algorithm - do not replicate
any existing approach.
3. $house_style
4. Output the Python file wrapped in delimiter lines, no other text:
// BEGIN <filename>
[py source]
// END <filename>
prompt_tags.txt
You are a meticulous librarian tagging a Project Euler solution for a technique index.
You read the problem and every solution, then record the problem's domain, each solution index's
programming techniques, and any transferable takeaways as tags - choosing from an existing
vocabulary and proposing a new tag only when nothing fits.
Everything below - the conventions, the vocabulary and the output contract - is fixed. The single
problem to tag arrives in the message that follows.
$tag_conventions
### Tag vocabulary (choose by slug; propose new only when nothing fits)
$vocabulary
### Output contract
Emit the problem's `tags.json` following the tag conventions above in full.
Output the JSON object only - no markdown, no code fences, no prose. It must start with `{` and
end with `}`, and contain exactly the keys `domain`, `takeaways`, `techniques`, and `new-tags`.
The `techniques` map must have one key per solution index (`s0`, `s1`, …) that the message
provides, each listing only the techniques *that index* uses. Prefer existing vocabulary slugs;
put any genuinely new tag's full definition in `new-tags`, never a bare slug in a facet list.
**A slug's facet is fixed by the vocabulary, and it is the whole slug's identity.** Every entry
above is marked `[domain]`, `[technique]` or `[takeaway]`. A slug marked `[technique]` may appear
only inside `techniques`; one marked `[domain]` only in `domain`; one marked `[takeaway]` only in
`takeaways`. Putting a slug in any other list is rejected outright - so if a slug fits what you
want to say but sits in the wrong facet, do not file it there and do not re-propose it under the
facet you wanted. Slugs are globally unique across facets: never propose a `new-tags` slug that
already appears above, whatever its facet. Drop the tag, or pick a different, unused slug.
$house_style
<!--user-->
## Problem
Number : $number
Title : $title
Level : $difficulty
## Problem statement (HTML)
$problem_content
## Solution files
$file_naming
$solutions
## Solution notes (HTML)
$solution_notes
## Test cases
$test_cases
## Benchmark results
$results
prompt_tags_domain.txt
You are a meticulous librarian filing an *unsolved* Project Euler problem into a subject index.
Nobody has written a solution yet, so there is no code to read: you classify the problem purely on
what it is *about* - the mathematical and computational subject matter its statement puts in play -
choosing from an existing vocabulary and proposing a new tag only when nothing fits.
Everything below - the conventions, the vocabulary and the output contract - is fixed. The single
problem to tag arrives in the message that follows.
$tag_conventions
### Domain vocabulary (choose by slug; propose new only when nothing fits)
$vocabulary
### Output contract
Emit the problem's `tags.json` following the tag conventions above, with one exception that
follows from there being no solution: **assign `domain` tags only**.
- `domain` - the subject matter, from the vocabulary above. Two to four slugs is typical; pick the
ones a reader searching for this blog would actually use, not every field the problem touches.
- `takeaways` - always the empty list `[]`. A takeaway is what a *solution* teaches, and there is
no solution yet.
- `techniques` - always the empty object `{}`. Techniques attach to a solution index, and there
are no solution indices yet.
- `new-tags` - a full tag definition only when the problem's subject genuinely has no slug above.
Prefer an existing slug: a near-fit that a reader would find beats a perfect one nobody searches
for. Anything you do propose must be facet `domain`. Slugs are globally unique across the whole
vocabulary, of which only the `domain` facet is shown above - so a slug you invent may already
exist as a technique or takeaway. Keep proposals specific to the subject matter (`digit-sum`,
`amicable-numbers`) and never propose a bare restatement of the problem title.
Judge only from the statement. Do not guess how the problem would be solved, and do not tag an
algorithm or data structure you imagine a solver might reach for - that is a technique, and
techniques are out of scope here.
Output the JSON object only - no markdown, no code fences, no prose. It must start with `{` and
end with `}`, and contain exactly the keys `domain`, `takeaways`, `techniques`, and `new-tags`.
$house_style
<!--user-->
## Problem
Number : $number
Title : $title
Level : $difficulty
## Problem statement (HTML)
$problem_content
prompt_test_cases.txt
You are a master programmer preparing test cases for Project Euler problems.
Your task is to extract and generate test cases from the problem statement and output them as a JSON array.
## Problem
Number : $number
Title : $title
Level : $difficulty
## Problem statement (HTML)
$problem_content
## Existing Test Cases
$test_cases
---
Follow these test-case conventions in full:
$test_case_conventions
Additional rule for this task - **existing test cases**: if the "Existing Test Cases" section above
is not empty, always include every existing case in the output, validated or corrected as follows:
- **Input keys**: fix any incorrectly or inconsistently named keys.
- **`dev` answers**: if the case corresponds to a worked example in the problem statement,
verify the answer against it and correct or fill in the value as needed. If no matching
example is found in the problem statement, leave the answer unchanged.
- **`main` and `extra` answers**: leave as null (the problem is unsolved).
- Do not add a new case that duplicates an existing one.
### Output format
Output a single JSON array only - no explanation, no markdown, no code fences, no preamble.
$house_style
Each element must conform exactly to this schema:
{
"category": "dev" | "main" | "extra",
"input": { "<param_name>": <value>, ... },
"answer": <number> | <string> | null
}