What this skill produces
A single-page HTML (three columns) that can be opened directly in a browser:
- Left column: problem statement + dynamic console — one variable-parameter slider (e.g., line inclination angle θ / moving point parameter t) driving real-time recomputed geometric quantities (intersection coordinates, slope, dot product, chord length, area…), plus a "theoretical range bar" or "constant-value indicator".
- Middle column: step-by-step solution (formulas use KaTeX), can be collapsed with one click to give space to the board.
- Right column: 2D Canvas dynamic geometry board (conic sections + moving line/moving point + vectors + point labels + grid coordinate axes), overlaid with a pen doodle toolbar.
Form and target template /Users/wuyi/code/code2026/6/template/code_artifact.html consistent.
Dependencies (important)
Computation core lib/analytic_kernel.py depends on sympy. Before running the script, first confirm there is an interpreter that can import sympy:python3 -c "import sympy"(on this machine use /opt/homebrew/bin/python3.11,sympy 1.14)。
When a library is missing: if import raises an error (sympy or any subsequent library),first ask the user whether to install, and after agreement install it
(python3 -m pip install <库名>) or switch to an interpreter that already has the library installed;do not install directly without asking.
Below, python3 all refer to this interpreter that can run the dependencies.
Workflow
Step 1: Obtain the problem spec (three entry points unified)
Organize the problem into a structured spec (curve type and parameters, known points/conditions, requested type and objects, language).
- Text problem: extract directly.
- Image: extract by visual reading, andecho the recognized problem back to the user for confirmation(problem statement/curve/parameters/requested/language) before continuing.
- Random problem generation: choose curve + problem type, random parameters → kernel solve, use
analytic_kernel.is_clean(...)to judge whether the answer is neat; if not neat, redraw.
Output language follows the prompt language: English prompt → English webpage, Chinese → Chinese. The spec records
language。
Step 2: Use the kernel for exact computation (do not do mental math)
According to references/conventions.md 's solution recipe, call lib/analytic_kernel.py and lib/conics.py:
conics.ellipse/hyperbola/parabola/circle(...)to get the curve object (exact a,b,c, focus, vertex, directrix, asymptote,eq_latex, and for the frontend engine theboarddict)。chord_setup(conic, through)simultaneous parametric linex=my+cto get the quadratic equation in y + Vieta quantities (exact).- Target quantity:
dot_product_expr/chord_len_sq_expr/triangle_area_expr/slope_product_central… - Value range:
range_over_m(expr, horizontal_valid=?)—— including open/closed endpoint determination(key correctness point, see below). - Constant value:
is_constant_in_m(expr)。
Can self-check the kernel from the command line:
python3 lib/analytic_kernel.py # 旗舰题内置断言自检
⚠️ Endpoint open/closed = the crux of correctness: A chord through the focus; the horizontal line (x-axis, θ=0) and the vertical line (θ=90) are both valid lines, and the endpoints they attain must be counted. Example: for the ellipse MA·MB problem, the x-axis attains −3 and the vertical line attains 7/4, so the answer isclosed interval
[-3, 7/4](many study guides mistakenly write it as open(-3, 7/4])。range_over_mhas been judged accordingly, and this way the answer is consistent with the interactive tool—drag the slider to 0° and you read −3. The "axis direction" of a focal chord of a parabola is a degenerate line (intersecting at only one point), and its limiting endpoint is not counted (horizontal_valid=Falseor restrict the param range).
Step 3: Assemble data and inject into the template
📍 Output location & sole artifact (most important): delivered to the userthere is only one
.html, written tothe current working directory (Path.cwd())(unless the user explicitly specifies a path). In cwddo not leave any other files—build scripts (.py)、__pycache__, self-check screenshots (.png), and temporary files are allnot deliverables, always put them in/tmpor delete them after use. Alsoneverwrite into the skill's own directory (skills/edu-analytic-geometry/output/is an internal skill example).
The "assemble data + inject template"build script should be written to a temporary directory(e.g. /tmp/ag_build.py), and let itonly write .html
to cwd; the script assembles the lesson / steps / board data (schema see references/problem-schema.md), and
calls generate.render_html(data, out) to inject template/board.html,delete the script after running:
# 构建脚本放 /tmp(不要放 cwd):/tmp/ag_build.py
import sys; sys.dont_write_bytecode = True # 不生成 __pycache__
sys.path.insert(0, "<技能目录>/scripts")
import generate
from pathlib import Path
data = {"lesson": {...}, "steps": [...], "board": {...}}
out = Path.cwd() / "solution-<题目简述>.html" # 唯一产物,落在用户当前目录
generate.render_html(data, out)
python3 -B /tmp/ag_build.py && rm -f /tmp/ag_build.py # -B 不写字节码;跑完删临时脚本,cwd 只剩 .html
steps[*].contentthe values indirectly reference the kernel result(useK.tex(...)to output LaTeX), and the model is only responsible for organizing the explanatory text (in the target language).boarduse the curveboarddict, exact point coordinates,param、derivedconstruct the sequence,readouts、rangeBar(range problems) /constant(fixed-value problems) /answerBand(shape-parameter problems, such as eccentricity range).- Shape-parameter problems (slider = eccentricity e, etc.): when the natural dynamic quantity is the shape of the curve itself rather than a moving line/point, let the slider = that parameter,
and write the curve
a/b/c, focus, and moving-point coordinates as@paramtheexpression string(the engine redraws the curve/focus/asymptotes every frame), withstatusa readout showing the inequality status,answerBandhighlighting the answer interval on the parameter axis. See conventions "shape-parameter problems". - A template that can be copied directly:
scripts/generate.pythe 6build_*cover various interaction paradigms:ellipse_dot_range(range bar),ellipse_chord_range、ellipse_area_max、ellipse_slopeprod_const(fixed value · central symmetry),parabola_dot_const(fixed value · parabola),hyperbola_ecc_range(shape parameter: slider = e, the curve is redrawn accordingly +status+answerBand)。
registered problems are output directly (-B do not write bytecode; if no path is passed, it defaults to writing to the skill output, and when delivering to the user be sure to change it to the one under cwd .html):
python3 -B scripts/generate.py list # 列出题型
python3 -B scripts/generate.py ellipse_dot_range ./sol.html
python3 -B scripts/generate.py all ./out_dir # 全部题型
Step 4: Self-check (correctness scheme)
- kernel answer == answer card
lesson.answer== final-step displayed value == JS standard position/sweep-segment recomputed value, all four consistent (build_*has already addedassert)。 rangeBarendpoint comes from the kernel'srange_over_m;constantvalue comes from the kernel's constant value.- start a local static server (servingthe directory containing the output file, i.e. cwd) and use preview to check: no console errors, KaTeX renders correctly,
sliders recalculate in real time correctly, range bar/constant value/fixed point/trace behavior matches, brush and collapse panel work.
(When developing inside the skill repo you can use
.claude/launch.json'sag-preview, port 4601; when running elsewhere, start a temporary static server for cwd.) - Self-check screenshots are for your eyes only: the preview tool returns images directly,do not save
.pngto cwd; the local static server is read-only and does not write or produce files. Any temporary files produced by the self-check (build script.py, screenshot.png、__pycache__, etc.) must all be cleaned up before delivery.
⚠️ You must close any ports/services you opened: stop them immediately once preview ends,never leave a process occupying a port。
- opened by the preview tool:
preview_stop(pass serverId).- started directly with
http.server: when done usekill, orlsof -nP -iTCP:<port> -sTCP:LISTENto confirm it has been released.- Before delivery, confirm the port has been released before telling the user. Opening without closing = self-check incomplete.
Step 5: Delivery
The finished product is written inthe user's current working directory (cwd), named like solution-<题目简述>.html, tell the user the path,
it can be opened directly in a browser. Before delivery confirm:(1) the finished product is in cwd, not in the skill directory;(2) no local service/port opened for this preview
is left behind;(3) in cwdonly this one .htmlwas added—no .py / .png /
__pycache__ / temporary files (use git status or ls to check, delete any you find).
Extension
- Add a problem type: in
analytic_kernel.pyadd the target quantity function (written as an expression in m) + reuserange_over_m/is_constant_in_m; ingenerate.pyadd abuild_*, choose the interaction paradigm (range bar / constant value / fixed point / trace / shape parameter answerBand). Seereferences/conventions.mdrecipe table. - Add a curve:
conics.pyalready has ellipse/hyperbola/parabola/circle; the frontendboard.htmlengine already supports four types of rendering, asymptotes, and directrix direction. A new curve just needs to be added in both places. - Add an interactive construction:
board.html'sbuildSceneswitch is the construction library (line_through_angle、intersect_line_conic、point_on_conic、point_reflect、tangent_at、foot_perp…), extend as needed and register it in the schema documentation.
Directory
template/board.html— data-driven template (generic 2D renderer + parameter engine + data island__LESSON_DATA__)lib/conics.py— conic section sympy definition library (special points / LaTeX / board dict)lib/analytic_kernel.py— sympy exact solving core (simultaneous equations · Vieta · range · constant value)scripts/generate.py— injection template + 5 build_* examples + batch/single problem generationreferences/problem-schema.md— data format (board engine schema)references/conventions.md— standard forms, solution recipe table, Vieta/substitution patterns, endpoint open/closed, self-check